Today I listened to this week’s IEEE Software Engineering podcast. It’s a pretty dry description of a money exchange banking system from New Zealand. But Mike Barker brought up a fine phrase. The phrase is originally from Sir Jackie Stewart, the three time Formula 1 World Driving Champion, where he talked about a driver having “Mechanical Sympathy”.
Car racers have a mental model of how a car works, what they have to do to make it go fast. We all have these mental models. Some people think that pushing on the throttle pedal makes the car go. That is your mental model of the complexities of a car, adequate for your daily drive. Push the throttle to make it go faster and push the brake pedal to make it stop. This model breaks down very quickly in snow or heavy rain, your tyres start to spin so you push the brake to stop, nature disagrees with your decision and you crash into a tree. Your model did not take into consideration friction or momentum, but in dry weather at low speed your model is adequate.
A car racer’s model of his car is far more complex. They drive their cars at the limit of their abilities, the capabilities of their car, and the limits imposed by nature. A driver knows how their car will react to their inputs. They don’t think about what to do when their car slides, whether from too high speed while cornering, snow, or rain, they just look where they want the car to go and their hands do the right thing. They don’t brake, that will just make them crash into a tree.
This will only get a driver so far. They rely on the person who built the car to adjust it perfectly. But there is no perfect, each adjustment has a range, and the proper adjustment is achieved with feedback from the driver. If the car wants to slide straight rather than cornering, use a more rigid rear sway bar. If the car breaks traction too easily, soften the springs. It is the driver who does the testing and discusses what they feel with their mechanics who then adjust the system. But if you really want to go fast, tighten the nut behind the steering wheel.
When a driver learns about his car, how it works, what an adjustment does, what the tradeoffs are, what the limits are, they can have a much better discussion with the mechanics. They work with the mechanics to adjust the vehicle to suit their style, and adjust their style to suit the car. They have mechanical sympathy: they work with the car to get the best results.
In computer server applications, it is common to create a new structure to store an incoming request. The request is then processed, then the structure is destroyed. If you want the absolute maximum throughput for your server you can avoid creating and destroying the structures and instead reuse them. This avoids garbage collection, which stops everything while it goes around joining up all of the deleted structures into free memory so it can be used again.
This is an example of mechanical sympathy in computing. The goal is maximum server throughput. By understanding what the system is doing under the covers, you can adjust their system for maximum performance. Getting a faster computer isn’t always the answer to performance problems; knowing where the performance bottlenecks are will tell you what the proper solution is. The answer could be increasing memory, getting faster disks, using a new algorithm, or it could be removing sleep statements in the code.
In embedded systems, we are chronically short of memory and use slow processors. We can avoid the processor time hit of memory allocation and release by allocating all of our variables at compile time. This also avoids the errors when not being able to allocate memory and also avoids garbage collection, not that C even has garbage collection.
A second example from the IEEE podcast, they always use circular buffers with the number of elements being a power of 2. To step through the buffer of an arbitrary size you use the modulo operator to perform the wrap. But modulo effectively does a divide and takes 10s of clock cycles. By using a power of 2 the wrap takes about 1 cycle. If you are doing this thousands of times per second, the time saving becomes significant.
I’ve seen communications buffers being sized at 256, so the simple increment of the uint8_t buffer index will naturally wrap from 255 back to 0 without using modulo. This code was very hard to understand at first, but there was a need for maximum performance on a small processor and a comment in the code described the trick for the maintenance person.
In motor racing, a driver must develop their skills and the mental model of their car to get maximum performance. But mechanical sympathy isn't just for racers, understanding the dynamics of your car can help when things literally go sideways. Improving your car over stock with things like winter tyres, better lights, new wiper blades, or checking out your rattles, keep everyday situations from becoming life threatening. Learning about a vehicle lets you unlock potential that is already there.
In computing, there are always many conflicting requirements in any system: cost, time to market, performance, usability, and maintainability. By getting a deep knowledge of the machine you can get the maximum performance that is needed without wasting your time and budget. Throwing hardware at a performance problem might not work, but figuring out what the system is doing and fixing it will work.
Now get out there and read your owner's manual - for your car, and your computer system.