Header menu logo issie

SimulationBudget Module

How much memory a simulation may take, and of which kind. Here rather than beside the code that spends it because two different parts of the simulator spend it: GraphMerger, which expands the design into a graph, and FastCreate, which allocates the step arrays. Both come out of the same memory and GraphMerger is compiled first. Sizes are float and not int64 on purpose. Fable compiles int64 to BigInt, so every comparison here would allocate one - a poor thing to spend on deciding whether a design is too big. A float carries integers exactly to 2^53 and the largest number reached here is a few hundred GB.

Functions and values

Function or value Description

formatBytes bytes

Full Usage: formatBytes bytes

Parameters:
    bytes : float

Returns: string

A size in bytes, written the way a message should read it.

bytes : float
Returns: string

heapBytesPerComponent ports

Full Usage: heapBytesPerComponent ports

Parameters:
    ports : float

Returns: float
 What one component of an expanded design costs in heap, by how many ports it has (ports
 here is inputs plus outputs, as GraphMerger.expandedSize counts them).

 Measured rather than derived, on a hierarchy of 120,000 expanded components with one output
 port each and 2.9 ports each in all, by GC-forced usedJSHeapSize deltas at two step-array
 lengths (which separates the fixed cost from the per-step cost - the fixed part was the
 same at both lengths to within noise). What one waveform simulation retains, per component:

   the SimulationGraph            ~15 bytes - merger shares non-custom nodes between
                                  instances of a sheet, so this is two orders of magnitude
                                  down on the rest
   the FastComponents            ~990 bytes fixed - the 25-field record, its map node, the
                                  output IOArrays with their typed-array wrappers (~120 B a
                                  wrapper, measured), path strings, reducer closures
   AllWaves                      ~430 bytes a wave, at ~0.6 waves per port - the Wave
                                  record's strings, built by the waveform simulator only,
                                  but charged here because this guard cannot know which
                                  simulator is coming and the waveform one is both the
                                  heavier and the one large designs are opened in

 The step arrays themselves are NOT here - they scale with cycles, not components, and are
 StepCost's business. The formula sits ~15% above the measured total at 2.9 ports, which is
 the right side to miss on for a guard. To remeasure after changing these structures: build
 phase deltas are logged under --log=perf (FastBuild.buildFastSimulation and the createWaves
 line), and `node scripts/drive.js` + window.issieDev.simStats() gives the exact component,
 port and wave counts to divide by.
ports : float
Returns: float

heapShareOfLimit

Full Usage: heapShareOfLimit

Returns: float

Share of the V8 heap limit a simulation may take, for the expanded design and for the step arrays of buses wider than 32 bits. Not half, although half of USABLE heap is the intention. The heap limit is not usable in full: the scavenger needs its to-space free, mark-compact needs somewhere to evacuate pages to, and what a simulation puts there is millions of small objects promoted out of new space, which is the shape old space handles least well. Filling the cage makes the renderer stop responding well before the limit is reached. A third of the limit is about half of what can really be used. The two heap checks - the expanded design, and the step arrays - are made separately and each against this whole figure, so a design that passed both could in the worst case use twice it. That needs a design that is both deeply instantiated AND full of wide buses, and even then 70% of the limit is the boundary rather than past it.

Returns: float

maxHeapBytes

Full Usage: maxHeapBytes

Returns: float

The most V8 heap one simulation may take, for the expanded design and for the BigInt step arrays alike. Far smaller than the budget above, because V8's pointer compression caps the whole heap at 4GB - a limit no flag can lift, since raising it needs V8 built without pointer compression - and the model, the design, the waveforms and everything else the renderer holds come out of that same 4GB.

Returns: float

maxTypedArrayBytes

Full Usage: maxTypedArrayBytes

Returns: float

The most Uint32Array step-array memory one simulation may take: memory outside the V8 heap, so bounded by the machine rather than by anything Issie is built with. Most designs are 32 bits and under, so this is the budget that decides how long they may run. Mutable because it is a fact about the machine, discovered once at startup - see setBudgetsFromMachine. The value here is the fallback for when there is no machine to ask, which is every run of the test suite: those run under plain .NET with no Electron.

Returns: float

setBudgetsFromMachine physicalBytes heapLimitBytes

Full Usage: setBudgetsFromMachine physicalBytes heapLimitBytes

Parameters:
    physicalBytes : float
    heapLimitBytes : float

Size both budgets to the machine this is running on. Called once from renderer startup. physicalBytes comes from process.getSystemMemoryInfo, heapLimitBytes from performance.memory.jsHeapSizeLimit - the limit actually in force, whatever Main.fs asked for and whatever V8 decided to grant. Either being zero or absent leaves that budget at its fallback, so a machine that cannot answer is never told it has no memory.

physicalBytes : float
heapLimitBytes : float

typedArrayShareOfMachine

Full Usage: typedArrayShareOfMachine

Returns: float

Share of the machine's physical memory a simulation's Uint32Arrays may take. A third, because that is comfortably clear of where the allocator actually gives up: measured on a 32GB machine, Uint32Array allocation failed at 15.5GB, a little under half of physical. A third leaves the operating system, the rest of Chromium and whatever else the user has open their room, and still allows several million cycles of a real design.

Returns: float

Type something to start searching.