|
|
Up to this address width every address gets a slot number in one flat array: 2^16 ints is
256kB, which is always affordable. Above it the address space outruns what can be
allocated and the memory is assumed to be occupied thinly.
-
Returns:
int
|
|
|
The most addresses ever written that a whole-memory read will be attempted for.
Reading a memory means one search of each slot's own writes, so it is linear in the
addresses ever written - measured at 1.3 ms for a thousand, 13.6 ms for ten thousand and
80.3 ms for a full 64K (docs/dev/ramOverTheWire.md). Four thousand is where that passes
5 ms, which is as long as a per-render read may take.
Past it a caller is told no rather than made to wait: a RAM table shows a window instead
of listing every location, and the step simulator's memory diff is not offered. This is
the bound that makes those paths cost the same whatever the memory holds - the count of
non-zero words cannot be it, because finding that out is the walk being avoided.
-
Returns:
int
|
|
|
Up to this address width an address still fits a uint32 and the trie can key on one.
Above it addresses arrive as bigints and the lookup falls back to a Map - a memory with
more than 4G words cannot be meaningfully simulated, so that path is a guard, not a
design.
-
Returns:
int
|
|
|
Compact once the tail is at least this long *and* at least as long as what is already
indexed. Doubling like this makes the copying amortised O(1) a write.
Waiting for a query instead, when there is nothing out of window to drop, was tried and is
worse: a tail entry carries a slot number that an indexed one does not, so leaving writes
in the tail costs 12 bytes each against 8, and on a hundred small RAMs that measured 19.9 MB
against 11.8 MB with no speed to show for it.
-
Returns:
int
|
|
|
Children per trie node. Four bits a level.
-
Returns:
int
|