Hi Alex,
Hello
I stumbled across a performance issue when pinning objects in memory.
Below I have two scripts that pin and unpin a byte array (or any object) 20k times.
The first script pins each time a new byte array:
[ 20000 timesRepeat: [
| array wasPinned |
array := ByteArray new.
wasPinned := array pinInMemory.
array setPinnedInMemory: wasPinned.
] ] timeToRunWithoutGC. "4284"
while the second one pins the same instance of array:
array := ByteArray new.
[ 20000 timesRepeat: [
| wasPinned |
wasPinned := array pinInMemory.
array setPinnedInMemory: wasPinned.
] ] timeToRunWithoutGC "12"
However, as you can see there is a huge performance difference between these scripts.
Is it expected or is it a bug? And if it is expected what can be happening in VM that leads to such huge performance impact? Thanks!
Alas this is expected. The Spur heap is composed of two very different regions, new space and old space. New space is a conventional eden plus two survivor semi spaces in which most objects are allocated and which is garbage collected using generation scavenging. Old space is a segmented space, garbage collected using a mark sweep compact collector. The old space compactor does not move pinned objects, sliding unpinned objects around pinned objects as it compacts. The system tries to maintain one old space segment that contains all pinned objects, but this can be defeated by pinning a few very large objects or pining many objects. The generation scavenger has no support for pinned objects.
So what the system does when asked to pin an object in new space is to allocate a copy of the object in old space with the pinned bit set, if possible in the preferred pinned object segment, and become forward the new space object to the pinned copy. Once an object is in old space all that needs to happen to pin (or unpin) an object is set (or clear) the pinned bit in the object header, which is tested by the compactor.
HTH
Eliot
_,,,^..^,,,_ (phone)