Skip to main content

PublishCache

Struct PublishCache 

Source
pub struct PublishCache {
    pub panes: Option<(u64, Arc<PanesRenderState>)>,
    pub modes: Option<(u64, Arc<ModesRenderState>)>,
    pub buffer_locals: Option<(u64, Arc<BufferLocalsRenderState>)>,
    pub resolved_opts: Option<(u64, Arc<ResolvedOptionsRenderState>)>,
    pub buffers: Option<(u64, Arc<BuffersRenderState>)>,
    pub tabs: Option<(u64, Arc<TabsRenderState>)>,
    pub publish_batch_depth: u32,
    pub publish_pending: bool,
    pub last_paint_revision: u64,
}
Expand description

Perf plan B.4: identity-preserving sub-state cache.

Editor::build_render_state rebuilds every sub-state Arc from scratch on every publish today. Most publishes don’t touch most sub-states (cursor moves, scroll, etc. only update active_document), so the inner allocations and deep clones for the rest are wasted.

This struct lives behind Editor::publish_cache (a std::sync::Mutex<PublishCache> because Editor is shared as Arc<Editor> and therefore must be Sync). The mutex is uncontested in practice — only build_render_state takes the lock, and only the actor thread calls it.

Each slot pairs a u64 version (captured from the corresponding Versioned<T> field on Editor at the moment the cached Arc was built) with the cached Arc<SubState>. On the next publish, if the field’s current version matches the cached version, the cached Arc is reused (same Arc identity preserved across the publish — Arc::ptr_eq returns true). Otherwise the slot is rebuilt and the new (version, Arc) pair is stored.

Targeted sub-states:

B.4.a (5 subs):

  • panes — full sub-state Arc. Mutates on pane_tree.split_active / close_active / set_active / tab swap; otherwise stable.
  • modes — full sub-state Arc. Mutates on activate_mode / deactivate_mode; otherwise stable.
  • buffer_locals — full sub-state Arc. Mutates on the few buffer_locals.entry(...).or_default() / .insert / .remove sites; otherwise stable. Largest savings because the per-entry clone deep-walks the typed-map.

(ML.3c retired the lsp_progress inner-Arc cache with RenderState.lsp.progress; DR.2 retired the sibling pane_highlights_map cache.)

B.4.b (3 subs):

  • buffers — full Arc<BuffersRenderState>. Keyed on buffer_uris.version() alone. The inner registry field is Arc<Mutex<...>>-backed so the SAME registry handle inside a reused Arc still sees current state — no version dependency on registry mutations needed for this sub-state’s cache hit/miss decision. Saves the buffer_uris.clone() HashMap allocation per no-op publish.
  • tabs — full Arc<TabsRenderState>. Composite key over tabs.version() (tab list shape) + active_tab (per-publish read) + pane_tree.version() (active pane’s buffer) + buffers.version() (label-resolving names). Saves the build_tabs_render_state walk per no-op publish.

Fields§

§panes: Option<(u64, Arc<PanesRenderState>)>§modes: Option<(u64, Arc<ModesRenderState>)>§buffer_locals: Option<(u64, Arc<BufferLocalsRenderState>)>§resolved_opts: Option<(u64, Arc<ResolvedOptionsRenderState>)>

PI.4: keyed on Editor::resolved_options_version.

§buffers: Option<(u64, Arc<BuffersRenderState>)>

Perf plan B.4.b: keyed on buffer_uris.version() only.

§tabs: Option<(u64, Arc<TabsRenderState>)>

Perf plan B.4.b: keyed on a composite of tabs.version(), active_tab, pane_tree.version(), buffers.version(). The composite is encoded into one u64 via a small fold so the cache slot shape stays uniform with the other entries.

§publish_batch_depth: u32

Slice I.4 (publish coalescing): depth of the in-flight dispatch / handle_effect batch. While > 0, intermediate publish_render_state() calls (from chained setters, ensure_cursor_visible, maybe_reparse_syntax, …) suppress their build/store/wake and instead set publish_pending; the single real publish fires once when the outermost batch unwinds. Collapses ~6 whole-world publishes per keystroke to 1 (and 12 worker wakes to 2). Lives here (not on Editor) because PublishCache is Default-derived and already the actor’s single publish-side lock — no new Editor construction churn, and build_render_state already takes this lock.

§publish_pending: bool

A suppressed publish occurred during the current batch; flushed once when the batch depth returns to 0.

§last_paint_revision: u64

§12 paint gate: the RenderState::paint_revision of the last real (un-suppressed) publish. publish_render_state compares the freshly-built revision against this; a change means a render-visible non-cell surface moved off-keystroke, so the actor fires paint_request. Lives here (not on Editor) for the same reason as the cache slots: PublishCache is Default-derived and already the actor’s single publish-side lock, so no Editor construction churn. u64::MAX would be a valid revision, so this starts at 0 and the first publish (revision rarely 0) paints — a harmless extra first frame.

Implementations§

Source§

impl PublishCache

Source

pub fn clear(&mut self)

Reset every slot. Useful in tests that want a clean baseline; production code never needs this (a version mismatch already triggers rebuild).

Trait Implementations§

Source§

impl Debug for PublishCache

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Default for PublishCache

Source§

fn default() -> PublishCache

Returns the “default value” for a type. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
§

impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

§

impl<T> Downcast for T
where T: Any,

§

fn into_any(self: Box<T>) -> Box<dyn Any>

Convert Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>. Box<dyn Any> can then be further downcast into Box<ConcreteType> where ConcreteType implements Trait.
§

fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>

Convert Rc<Trait> (where Trait: Downcast) to Rc<Any>. Rc<Any> can then be further downcast into Rc<ConcreteType> where ConcreteType implements Trait.
§

fn as_any(&self) -> &(dyn Any + 'static)

Convert &Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &Any’s vtable from &Trait’s.
§

fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)

Convert &mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &mut Any’s vtable from &mut Trait’s.
§

impl<T> DowncastSync for T
where T: Any + Send + Sync,

§

fn into_any_arc(self: Arc<T>) -> Arc<dyn Any + Send + Sync> ⓘ

Convert Arc<Trait> (where Trait: Downcast) to Arc<Any>. Arc<Any> can then be further downcast into Arc<ConcreteType> where ConcreteType implements Trait.
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self> ⓘ

Instruments this type with the provided [Span], returning an Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self> ⓘ

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
§

impl<T> IntoMaybeUndefined<T> for T

§

fn into_maybe_undefined(self) -> MaybeUndefined<T>

Converts this value into a three-state builder argument.
§

impl<T> IntoOption<T> for T

§

fn into_option(self) -> Option<T>

Converts this value into an optional builder argument.
§

impl<T> Pointable for T

§

const ALIGN: usize

The alignment of pointer.
§

type Init = T

The type for initializers.
§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
§

impl<T> Pointee for T

§

type Pointer = u32

§

fn debug( pointer: <T as Pointee>::Pointer, f: &mut Formatter<'_>, ) -> Result<(), Error>

§

impl<T> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

§

fn vzip(self) -> V

§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self> ⓘ
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a [WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self> ⓘ

Attaches the current default Subscriber to this type, returning a [WithDispatch] wrapper. Read more