As part of writing the code, programmers usually write test cases, although sometimes other members of the team are assigned this task. Using the Stats tool, test cases can easily be turned into benchmarks and these benchmarks used to find "the right 10 percent".Running less code means understanding scaling and complexity. An O(n) operation scales much better than an O(n^2) operation, but both perform poorly for large values of n.It is also necessary to understand the minimum and fixed costs of an operation. Sometimes it is better to have a lower minimum cost for common cases in exchange for more complexity. This means that the operation does not scale well, but scaling may not be necessary. For example, a Dictionary does not scale well to huge databases, but it is faster than a BTree for smaller amounts of data.Understanding complexity means also understanding the complexity of base classes. Arrays are very fast, OrderedCollections are somewhat slower, and Dictionaries and Sets are very slow by comparison. Seemingly unassuming methods such as asSet can be very expensive. Turning an arbitrary collection into a set is an O(n^2) operation in the worst case. For this reason, unnecessary conversion between collection types should be avoided.The Smalltalk virtual machine is optimized for SmallIntegers. Avoiding LargeIntegers, Floats, and Fractions makes mathematical computations faster.
•
• Just send the message. Avoid perform: and Blocks. The use of respondsTo: and isKindOf: often indicate a problem in the architecture of a system.Objects are looked up in Smalltalk far more often than in other languages, due to the availability of base classes, such as Dictionaries with lookup operations. To reduce the number of lookup operations, design an object structure that gives direct access to the required object through a pointer chain of instance variables (as is done in Pascal or C). This gives a small fixed cost to the operation. For a badly hashed object, a Dictionary lookup operation is O(n) in the worst case.
• Because Symbols are guaranteed to be unique, each potentially new one must be looked up in the Smalltalk symbol table. If it is not found, it is added to the table.
• Using Dependents.Dependents are implemented using Dictionaries, which use lookup operations.The following selectors are normally resolved for low-level classes, such as SmallInteger, or are highly optimized by the compiler and virtual machine:Virtual-machine optimizations can sometimes be defeated accidentally. For example, whileTrue: is treated specially when the receiver and both arguments are Blocks. The following two code fragments do the same work, but the second one is faster:In application code that reimplements doesNotUnderstand:, both the number of message-send operations and the time to process the original message-send are increased. This happens because the original message-send operation must first fail before doesNotUnderstand: runs. In doesNotUnderstand:, handlers that forward the original message, the overhead of the handler is incurred for each forwarded message.For example, String>>#indexOf: is a primitive in most images. It is much faster than writing a loop and testing the elements for equality or using another less-optimal method, such as findFirst:.When in doubt about the speed of an operation, use the Stats tool to construct benchmarks and compare times.To find where the code is creating extra garbage, examine senders of new and new: in the code being optimized. Objects are also created by some primitives; for example, Float and LargeInteger operations (for example, +, -, /, and *).Less well known is that the virtual machine creates objects to run certain methods. Methods that contain Blocks can result in object creation (for example, MethodContext and BlockContext). Exceptions to this rule are special control constructs that appear to use Blocks, such as whileTrue:, but in fact, often do not because the Blocks are often optimized out. In code that draws graphics, the point and rectangle operations are typical sources of excess garbage.
![]() |