links to this page:    
View this PageEdit this PageUploads to this PageHistory of this PageTop of the SwikiRecent ChangesSearch the SwikiHelp Guide
Squeak Performance Tuning
Last updated at 11:39 am UTC on 16 January 2024
There can be many different reasons for why something in Squeak might appear to be slow. (If you have more information on this subject, please add it to this page. - Doug Way)

Here are some slowness problems you may see in Squeak, along with some possible solutions (Ned Konz):

A specific operation XXX seems too slow.

Use the TimeProfileBrowser to find out why:

TimeProfileBrowser onBlock: 
[ 20 timesRepeat: [ Transcript show: 100 factorial printString ]].

Or whatever you want to do in the block. You'll see a breakdown by percent of time spent. Attack the parts that are taking the most time, if you want to speed it up.

Or, if the operation happens to be a UI operation:

Let's say that the slow operation is the act of closing a particular window in Morphic. You can start up a MessageTally by using "debug..."/"start/browse MessageTally" from the World menu. It will warn you that it is about to start the tally. After starting it, immediately do the operation (close the particular window in this case), and then quickly move your mouse to the top of the screen to end the tally. A window will now appear with the tally results, which is a hierarchy of the methods in which a significant amount of time is spent. Probably a significant chunk of the time (maybe more than 50%) is spent in the method WorldState>>interCyclePause:... this is the extra time that was spent before and after closing the window, which we can ignore. We can follow the other branch (HandMorph>>handleEvent:, etc.) down and see what the "deepest" method(s) are which are still taking a significant percentage of time, and browse the code to see if there's an obvious problem in the implementation.

Of course, after doing this profiling, if you make an enhancement which makes a common operation faster, be sure to submit your enhancement to the community. See Reporting Bugs and Fixes.

See also: MessageTally.

The Morphic UI feels sluggish in general.

Often, it's not something inherent about Morphic that is slow, but a specific operation happens to be implemented inefficiently. Use the MessageTally to find out why: from the World menu, choose debug, then choose "start/browse MessageTally". Wait for a while, or interact with Morphic for a while, then move your mouse up to the top of the screen. You'll be presented with a breakdown of where Squeak is spending most of its time. The bulk of time should be being spent in waiting for a Delay.

On Linux systems using the open source radeon driver, adding the line Option "AccelMethod" "EXA" on the Device section of the xorg.conf file, may improve the drawing speed when X is running at 24bpp.

If you have an out-of-the-box 3.x system, try killing off the SqueakEyes mouse morph on the main screen (if you're trying things out in the top project, rather than making a new one). It eats a bit of processor time.

Sometimes the UI may feel slow because graphics performance (copying bits to the screen) may be the bottleneck. If you think this might be a problem, be sure to set the screen depth in Squeak ("appearance..."/"set display depth" menu) so that it matches the screen depth of your OS... this can sometimes speed up graphics performance considerably. (Or, setting both Squeak and the OS to 8 bits (256 colors) may further speed things up.)

There are a few Preferences which can affect UI performance. (see "help..."/"preferences...") If window dragging seems slow, be sure the fastDragForMorphic preference is turned on (it is on by default). Turning off the roundedWindowCorners and roundedMenuCorners perferences can speed things up a bit on slow machines. (because displaying the rounded corners requires redisplaying the window behind them, unfortunately, for now at least)

Squeak is using most or all of the CPU on my machine.

This could be a VM problem (as a general rule, your VM version should always be as new or newer than your image version). First, use a MessageTally as described above under "the Morphic UI feels sluggish" to find out if something's eating a lot of CPU in your project. Or just open a brand new Morphic project and see how the CPU usage looks.

Under some versions of Squeak, MVC will eat a lot of CPU time if there are no windows up (i.e. in a blank project).

If you've been doing something in Squeak which may have left a rogue process running inside Squeak (which will cause high CPU usage), you can use the Process Browser to track it down.

Or if you don't mind being brutal, you can kill all non-essential processes:
Process allInstancesDo: [ :p | | rules | 
    rules := ProcessBrowser nameAndRulesFor: p.
    rules second ifTrue: [ p terminate ] "1=name, 2=safe-to-kill, 3=safe-to-debug"

Another thing that can cause high CPU usage is turning on the higherPerformance Squeak Performance Tuning. This can improve performance in Squeak, but at the cost of hogging most of the CPU of your computer.

Your Seaside/Aida/Whatever server eats up too much CPU

Please see Server Profiling.

Are there other ways to speed up overall performance of Squeak?

One feature is the higherPerformance preference (mentioned above), which can make a difference in some situations.

One project which is being worked on is J3 (third-generation JITter), which is a new VM implementation, not an interpreted VM like the current one, but not a typical just-in-time compiled VM either. Jitter results in a 2 1/2 times speedup of many operations. (As of March 2001, Mac (and PPC-Linux?) versions are available, and a Windows version is being worked on.)

Another project is Exupery which is a compiler written in Smalltalk compiling Smalltalk to machine code. It's not a JIT but it aims to be something similar. It can currently compile individual methods which will then be used instead of the interpreted ones. This done transparantly. This might be a good alternative now to writing C/Slang for tight loops and later should be more widely useful.

Sometimes, if a small bit of Smalltalk code in a tight loop is too much of a bottleneck, it may help to write a primitive to replace the section of code. See Named Primitives and Virtual Machine hacking for more info.

Maximum Squeak discusses various advanced topics related to getting maximum performance out of Squeak.

General tips for writing efficient code in Squeak

Reducing runtime

How to find bottlenecks in your code?

[10 factorial] bench. --> '12,700,000 per second. 78.5 nanoseconds per run. 0 % GC time.' 
[10 factorial] benchFor: 1 second. --> '11,400,000 per second. 87.9 nanoseconds per run. 0 % GC time.' 

What are some common strategies for low-level optimization of methods?

  1. Get familiar with Squeak bytecode (in a browser, you can click the "source" button on the right and choose "bytecode" instead).
  2. Inline frequently used methods: E.g., the compiler will usually inline ifTrue: sends so no regular method lookup is performed and no BlockClosure is created during the execution. However, this won't work in special situations such as cascades. As another example,
    a and: [b] and: [c]
    is not inlined while
    a and: [b and: [c]]
  3. Use quick return methods: A method that just has a single return of an instance variable or self, true, false, nil, -1, 0, 1, or 2 is compiled using a primitive and faster than a normal method (see CompiledMethod>>#longPrintOn:indent:). On the other hand, lazy getters such as
    ^ plonk ifNil: [plonk := Dictionary new]
    are slower.
  4. Avoid particular slow instructions such as thisContext (which will require the VM to create Context objects for the entire stack, as this happens on-demand only - see class comment) or the creation of blocks (except for blocks as part of inlined message sends, see inlining above).
  5. Be aware of slow primitives (they are not always clearly visible in the MessageTally). For instance, elementsForwardIdentityTo: is faster than sending becomeForward: repeatedly many times.

array := (1 to: 1000) asArray.
digits := (1 to: 10) asArray.

[array do: [:ea |
	digits do: [:digit |
		| sum |
		sum := digit + ea]]] bench. --> '5,660 per second. 177 microseconds per run. 5.33893 % GC time.'

[array do: [:ea |
	| sum |
	digits do: [:digit |
		sum := digit + ea]]] bench. --> '5,300 per second. 189 microseconds per run. 6.7 % GC time.'

How can I reduce the load on The Squeak Garbage Collector (GC)?


Reducing memory consumption

Reducing memory consumption not only allows you to open more programs on your machine at the same time, but also 1) reduces stress in The Squeak Garbage Collector, which will avoid occasional freezes in your image, and 2) avoids page faults when the RAM is full and the operating system has to swap out/in memory to/from the disk, which will likewise make your computer slow or temporarily freeze the VM.

Avoid memory leaks (keeping objects longer in the memory than necessary):

Why has my object not yet been GC'ed?

Useful Links