So what goes on under the covers with memory management. Smalltalk MT has several different mechanisms and to really make a system perform we need to have an idea of how they work.
Firstly let us examine Object Memory. In the Transcript type
MemoryManager statatistics
and display the result. You will see 8 entries and the Private Heap. These 9
entries are the Object memory. In a new image the result will look something
like this:
1 : 25 kB 0 % free 28 kB committed
3839 kB reserved 3839 kB maximum [03bbf020~03f7f010]
2 : 24 kB 0 % free 28 kB committed 3839 kB reserved 3839 kB maximum
[037ff040~03bbf020]
3 : 5 kB 1 % free 8 kB committed 3839 kB reserved 3839 kB
maximum [0343f080~037ff040]
4 : 8 kB 1 % free 12 kB committed 3839 kB reserved 3839 kB maximum
[0307f100~0343f080]
5 : 7 kB 3 % free 8 kB committed 3839 kB reserved 3839 kB
maximum [02cbf200~0307f100]
6 : 12 kB 4 % free 12 kB committed 3839 kB reserved 3839 kB maximum
[028ff400~02cbf200]
7 : 15 kB 6 % free 16 kB committed 3839 kB reserved 3839 kB maximum
[0253f800~028ff400]
8 : 16 kB 12 % free 16 kB committed 3838 kB reserved 3838 kB maximum
[02180000~0253f800]
Private Heap : 18.1 KB (8 objects)
Object memory is broken up by object size. The first region stores objects of size 8 bytes. The actual size is 16 bytes since every object has an 8 byte header. The second region contains objects of size 16. The third region contains objects of size 32, the fourth objects of size 64, the fifth objects of size 128, the sixth objects of size 256, the seventh objects of size 512 and the eighth objects of size 1024. Objects larger than this are stored in the private heap. Please note that the percentage free does NOT mean how much space is free in this region. It means the size of the free space list in the region after Garbage Collection.
So how are these regions allocated? In a default images (i.e. as you received it) the Smalltalk Heap Reserve is set to 30 Mb. You can confirm this by looking in Image Properties (Transcript Tools menu) in the 'Smalltalk Memory Settings' in the box 'Heap Reserve'. This means that each region is equally allocated 3.75 Mb (i.e. 30 / 8).
Now take a look at the class MemoryManager and the class method HeapSizes:. This method allows you to explicitly set the memory for each region (see the code in the comment of this method). If you set the regions explicitly, the Heap Reserve figure will be automatically updated (just the sum of the 8 regions). Conversely if you set the Heap Reserve figure in Image Properties then the regions will be automatically allocated memory (Heap Reserve / 8).
Now I am going to show you the difference in speed between using a region and using the private heap. This test is going to allocate 30000 objects in region 1 vs. in the private heap. First we have to do a little calculation. If we are going to use region 1 then we must create objects of 8 bytes of less. Let us use objects of size 8 bytes (an 8 byte ByteArray). The memory requirement will be 30000*(8 + 8) where the first 8 is the object size and the second 8 is the object header. This is a memory requirement of 480,000 bytes so we will set region 1 to 1 Mb (regions are allocated in Mb).
Here is the code to set the regions:
| rgHeapSizes |
rgHeapSizes := WordArray new: ST_NUM_SPACES+1.
rgHeapSizes at: 1 put: 1 * 1024 *1024.
rgHeapSizes at: 2 put: 0 * 1024 *1024.
rgHeapSizes at: 3 put: 0 * 1024 *1024.
rgHeapSizes at: 4 put: 0 * 1024 *1024.
rgHeapSizes at: 5 put: 0 * 1024 *1024.
rgHeapSizes at: 6 put: 0 * 1024 *1024.
rgHeapSizes at: 7 put: 0 * 1024 *1024.
rgHeapSizes at: 8 put: 0 * 1024 *1024.
rgHeapSizes at: 9 put: -1. /* max count in private heap */
MemoryManager heapSizes: rgHeapSizes
After executing this, check the Image Properties and you will see that in the 'Smalltalk Memory Settings' the Heap Reserve will show 1 Mb. By executing this method we have allocated 1 Mb for 8 byte objects and zero to all other sizes except the Private Heap. Thus all objects larger than 8 bytes will be allocated on the Private Heap. To make this memory model stick you must SAVE& EXIT and RESTART. When you reload Smalltalk MT, the new memory model will be in effect. Confirm this with MemoryManager statistics.
Now we can run our test.
a := Array new: 30000.
Time millisecondsToRun: [1 to: 30000 do: [:index| a at: index put: (ByteArray
new: 8)]]
The array itself will be allocated in the private heap (size will be ~30000 * 4 bytes each which you can see with MemoryManager statistics). The array contents will be allocated in region 1 because they are 8 bytes each. Display the results of the second line. For me this line executes in 24 milliseconds. A MemoryManager statistics now shows that region 1 has a size of 495 kB (very close to our calculation of 480 Kb above - the overhead is rounding from bytes to Mb).
BTW, if you perform the second a few more times, you will eventually see the percentage free will increase from 0 to ~56% as the garbage collector frees up slots in region 1.
Now lets run the same test but using the private heap instead (this would occur in practice if the regions had not been made big enough). To do this we need to set the 'Smalltalk Memory Settings' 'Heap Reserve' to zero. This will set all regions to zero and force object allocation into the private heap. After doing this, SAVE& EXIT and RESTART. Now run the same test as above. For me the second line runs in about 15.5 seconds. I tried running the test with more than 30000 objects but things take far too long. This extra time is because of Windows allocations in the private heap and for our little test the second result was 643 times longer than the first!
From this you should be able to see that region size allocation can have a serious effect on the time taken for object allocation. I would be interested in results you obtain from the tests above. mailto:DAnderson@Genify.com
For certain object models the memory model can significantly affect performance. Object region memory is the fastest for allocation and Garbage collection. One way to tune your object model is to set the Heap Reserve to a large value (e.g. 300Mb - remember that this is Virtual Memory not Physical Memory). Then load your object model. MemoryManager statistics will now show you which regions you are using most. You can then customize the regions to suit your object model.
The bigger your Object allocation (standard allocation) the larger the area that the Garbage Collector must scan to detect unreferenced objects. In my case I have a 140 Mb Stock and Option model that I build early on and none of these objects get deleted. I really don't want the Garbage collector to waste time scanning this memory. To rectify this I allocated a number of objects with heapAlloc instead of new. These objects are out of the scope of the Garbage Collector and will not be scanned. If you want to get rid of one of these objects, you must send them heapFree to explicitly deallocate them.