|
|
Donner SVG 0.8.0-pre
SVG editor and embeddable C++20 engine.
|
Per-frame attribution of retained bytes by category (the single-canvas presenter work). More...
Classes | |
| struct | donner::MemoryAttributionSample |
| One frame's view of where the process's bytes are. More... | |
| struct | donner::MemoryStageSample |
| Net allocator movement attributed to each stage. More... | |
| class | donner::ScopedHeapDelta |
| Brackets one stage of the frame and attributes the allocator movement across it. More... | |
Namespaces | |
| namespace | donner |
| Top-level Donner namespace, which is split into different sub-namespaces such as donner::svg and donner::css. | |
Enumerations | |
| enum class | donner::MemoryCategory : std::uint8_t { donner::CompositorSegmentBitmaps = 0 , donner::CompositorSegmentTextures = 1 , donner::CompositorLayerBitmaps = 2 , donner::CompositorLayerTextures = 3 , donner::RenderResultTiles = 4 , donner::WorkerFrameSnapshot = 5 , donner::PresentationTiles = 6 , donner::PresentationOverviewTiles = 7 , donner::PresentationRetired = 8 , donner::LayerThumbnails = 9 } |
| A subsystem that retains or allocates pixel-scale memory. Kept small and stable: values are published to the stats surface as array indices. More... | |
| enum class | donner::MemoryStage : std::uint8_t { donner::WorkerRenderFrame = 0 , donner::WorkerBuildPreview = 1 , donner::WorkerFinalSnapshot = 2 , donner::WorkerOther = 3 , donner::AppPollResult = 4 , donner::AppUiFrame = 5 , donner::AppHostFrame = 6 , donner::AppInput = 7 } |
| A bracketed stage of the frame, measured by what it does to the allocator rather than by what a subsystem says it holds. More... | |
Functions | |
| const char * | donner::MemoryCategoryName (MemoryCategory category) |
| Stable short names for MemoryCategory, indexed by the enum value. Used as the key set of the published stats object so a reader does not have to keep an index table in sync. | |
| void | donner::SetRetainedBytes (MemoryCategory category, std::uint64_t bytes) |
Publish bytes as the current retained total for category, replacing whatever the category last published. | |
| void | donner::SetEntryCount (MemoryCategory category, std::uint64_t count) |
Publish count as the current live object count for category. | |
| void | donner::AddTransientBytes (MemoryCategory category, std::uint64_t bytes) |
Add bytes to the frame's allocation flow for category. | |
| MemoryAttributionSample | donner::SampleMemoryAttribution () |
| Read every counter, fold the per-frame flows into their high waters, and open a new frame window. Call once per frame from the publishing thread. | |
| MemoryAttributionSample | donner::PeekMemoryAttribution () |
| Read every counter without closing the frame window. | |
| const char * | donner::MemoryStageName (MemoryStage stage) |
| Stable short names for MemoryStage, indexed by the enum value. | |
| MemoryStageSample | donner::SampleMemoryStages () |
| Read the stage counters and open a new frame window for them. | |
| AllocTag | donner::AllocTagForStage (MemoryStage stage) |
The AllocTag that names the same part of the frame as stage, so a stage bracket and a large-block tag never disagree about what to call it. | |
Variables | |
| constexpr std::size_t | donner::kMemoryCategoryCount = 10 |
| Number of distinct MemoryCategory values. | |
| constexpr std::size_t | donner::kMemoryStageCount = 8 |
| Number of distinct MemoryStage values. | |
Per-frame attribution of retained bytes by category (the single-canvas presenter work).
The browser editor links with -sMAXIMUM_MEMORY=512MB. When linear memory reaches that ceiling emscripten_resize_heap fails and the module aborts, so "how many bytes does a frame retain, and in which subsystem" is a correctness question in the browser, not a tuning question. A single emscripten_get_heap_size() number cannot answer it: linear memory is a high-water mark that never shrinks, so it reports the worst instant since boot without saying which subsystem produced it.
This probe splits that number three ways:
Two kinds of counter, because two kinds of growth need different questions asked of them:
Counters are process-wide atomics rather than thread-locals: the render thread owns the compositor categories and the app thread owns the presentation categories, and the publisher must read both.
| struct donner::MemoryAttributionSample |
One frame's view of where the process's bytes are.
| Class Members | ||
|---|---|---|
| uint64_t | entryCounts[kMemoryCategoryCount] = {} | Live object count per category (textures, tiles), where the owner tracks one. |
| uint64_t | mallocArenaBytes = 0 | Total space the allocator has taken from the system, from mallinfo. |
| uint64_t | mallocFreeBytes = 0 | Bytes in the allocator's free lists, from mallinfo. |
| uint64_t | mallocLiveBytes = 0 | Bytes in allocated malloc blocks, from mallinfo; 0 where unavailable. |
| uint64_t | mallocLiveHighWaterBytes = 0 | Highest mallocLiveBytes seen since boot. |
| uint64_t | retainedBytes[kMemoryCategoryCount] = {} | Current retained bytes per category, indexed by MemoryCategory. |
| uint64_t | retainedHighWaterBytes[kMemoryCategoryCount] = {} | Highest retainedBytes seen since boot, per category. |
| uint64_t | totalRetainedBytes = 0 | Sum of retainedBytes across categories. |
| uint64_t | totalRetainedHighWaterBytes = 0 | Highest totalRetainedBytes seen since boot. |
| uint64_t | transientBytes[kMemoryCategoryCount] = {} | Bytes allocated during the frame just closed, per category. |
| uint64_t | transientHighWaterBytes[kMemoryCategoryCount] = {} | Highest single-frame transientBytes seen since boot, per category. |
| uint64_t | wasmHeapBytes = 0 | wasm linear memory size in bytes; 0 where the platform has no such notion. |
| uint64_t | wasmHeapHighWaterBytes = 0 | Highest wasmHeapBytes seen since boot. |
| struct donner::MemoryStageSample |
Net allocator movement attributed to each stage.
| Class Members | ||
|---|---|---|
| int64_t | cumulativeNetBytes[kMemoryStageCount] = {} | Net live-heap change since boot, per stage. A stage that is in balance hovers near zero however long the session runs; a stage that retains climbs without bound, and this is the number that names it. |
| uint64_t | entries[kMemoryStageCount] = {} | Times the stage was entered since boot. |
| int64_t | maxNetBytes[kMemoryStageCount] = {} | Largest single-entry net growth seen for the stage, in bytes. |
| int64_t | netBytes[kMemoryStageCount] = {} | Net live-heap change during the frame just closed, per stage. Negative means the stage freed more than it allocated. |