FAQ : Smalltalk Programming Language : Q: How can the command line improve performance?
Q: How can the command line improve performance?
A: For some applications, changing of memory related command line parameters result in more efficient use of memory and so improve performance.
How to Tune Memory
Operating System(s) 
Software Version(s): 
VisualAge 6.x, VA Smalltalk 7.0
Confused about some of the command line parameters and how to use them? Welcome aboard... you're among good company! For most of us, it is less than obvious how to use these settings. Of course, for the majority of VisualAge Smalltalk users, the default values work just fine. However, there are applications that tend to create a lot of objects that consume several hundred megabytes of memory. When this happens, it may be helpful to consider tweaking these values if you notice performance problems.
In this article I will define terms useful in the discussion of memory related command line parameters, explain the parameter switches, and give an example of how you may alter these settings to improve performance.
Before we review the parameters, here are a few definitions you should be aware of:
New Space
Stores newly created objects. New space consists of two memory segments. The system uses one segment at a time. When the system conducts a scavenge, it copies only newly created objects still in use to the idle memory segment. Then, it begins using the idle segment and stops using the other segment.
Old Space
Stores long-lived objects. Objects are long-lived if they remain in use after several scavenges. The system puts long-lived objects into old space--or tenures them--to avoid copying them each time it does a scavenge. The system reclaims long-lived objects when it does global garbage collections.
Fixed Space
Stores designated objects that the system cannot move by a garbage collection because their memory addresses have been passed to the operating system.
As a quick review, here is a description of the command line parameters:
This option sets the size of fixed space to XXXX bytes. The default is the size of the fixed space in the image when it was saved. In a newly packaged image, the default size is the actual byte size required by the image, plus a small amount.
This option sets the segment increment for allocation from the operating system to XXXX bytes. When the executable is out of memory, a new segment of XXXX bytes is allocated from the operating system. The default allocation size is 2048K.
This option sets the minimum size of free memory after a global garbage collection to XXXX bytes. The garbage collector uses this value to determine if it needs to allocate additional memory or return memory to the operating system. You use this option to specify a minimum amount of oldspace to remain free after a global garbage collection, and thus defer a garbage collection. The default minimum size is 500K.
This option sets the size of new space to XXXX bytes. The default is the size of the new space in the image when it was saved. In a newly packaged image, the default size is 256K.
This option sets the size of the largest old space to XXXX bytes. The default is the size of the old space in the image when it was saved. In a newly packaged image, the default size is the actual byte size required by the image.
An Example:
Let's say that a VisualAge Smalltalk server application that has a packaged image size of 10MB is using 300MB of memory after it is up and running for a day. (We are also assuming we have no memory leaks.) On the second day, the clients are experiencing slow response. This would seem to indicate that there are so many objects being created, used, and then deleted that scavenges and garbage collection is starting to consume more cpu cycles, effectively starving the clients from getting any work out of the server.
Some clients may even get connection failures during peak periods of garbage collection. During garbage collection, all the other Smalltalk processes are suspended as the garbage collection blocks the virtual machine. While this is happening, the incoming client requests to the server are exceeding the listenBacklog queue. Once the listening Socket running the tight loop in the accept code gets control, these requests are denied connection.
Based on the example above , in order to improve performance, you can try to tweak the following command line parameters:
1. Specify -mo250000000 -- that is about 250MB initial old space. Since the task manager reports 300MB used, and since this includes things such as the VM and associated DLLs, code cache, new space, and miscellaneous memory segments, 250MB seems like a reasonable initial size for old space.
2. Specify -mi16000000 -- that is about 16MB per memory segment. Currently, if the old space is around 250MB, you would have about 125 memory segments allocated to it by default. With this new specification, you will have only about 15 memory segments. Fewer memory segments should make life easier for garbage collection during compaction. The trade-off is that they may use slightly more memory.
3. Specify -ml8000000 -- that is about 8MB minimum free space after garbage collection. This should have the effect of reducing the number of garbage collections by hanging onto a little more memory when a garbage collection is done.
4. Specify -mn2000000 -- that is about 4MB for new space (there are 2 new spaces allocated). It is possible that with the default size of new space (256K) you are creating enough large objects, or creating objects fast enough, that "temporary" objects are surviving the scavenges and getting tenured. This then causes more work for garbage collection since they will probably just be discarded on the first garbage collection after they are tenured.
Customers can experiment by tweaking the values of -mn to find the optimum point on the size/performance curve. The other three switches probably have less "tweakability" -- setting them to a large value either helps or it doesn't.
In general, the more objects you have, the more thrashing will occur during garbage collection. Scavenges will run more often when lots of objects are being created and one of the segments in new space is full. At startUp of your application, if you are creating "static" objects that will never go away, you should consider putting them in fixed space, by sending the #makeFixed message to these objects after creating them. If the application has "long-lived" objects that will be used for a long period of time, it would be best to put these objects into old space. This will happen naturally as scavenges occur. As these long-lived objects hang around, they will be tenured (moved) to old space. You can also send #tenure to the object to put them into old space.
Some common questions to ask yourself as you work through performance issues:
1. How big should you set Old Space?
In order to figure out how big you should make old space, when you first start your application (not using the -moXXXX option) and after all the startUp code has occurred that creates the long-lived objects, check what the memory size of the running executable is at that point. As noted before, since this includes the VM and associated DLLs, code cache, new space, and miscellaneous memory segments, you can start out using something less than this. About 80% of this number would be an appropriate size to be used as an initial value to pass to the -moXXXX argument.
5. Should we explicitly set New Space size or does it grow as needed ?
New space will not grow as needed. It will start moving things to old space when it is full.
In summary, the command line parameters relating to the memory spaces are usually not used unless there is a performance issue. Hopefully, these suggestions can help.
Last modified date: 01/29/2015