At first this post might seem off-topic, but it's a post that I've been planning to write for a long time because, even if it might seem a bit of fluffy fun, it reinforces one of the most important tools at your disposal.
Instrumentation in your code is pure gold when it comes to analysing performance.
Without instrumentation you're flying blind and, although most people in the Oracle community are familiar with the importance of instrumentation via the Wait Interface, 10046 trace files, ASH data, the PL/SQL Profiler and so on, I wanted to discuss a very early example of my own experience with instrumentation to illustrate that this stuff has been around for a long time!
I learnt this lesson when I was around 17 years old (which means, erm 29 years ago or so). When I first started developing commercial games for the ZX Spectrum, some of the most important questions I had to ask where things like ...
"Which part of the code is taking the most time". (i.e. I needed an activity profile to focus my tuning efforts in the right places.)
"When I'm re-drawing this object on the screen, is the refresh raster running across that area of the TV screen at the same time?" (i.e. Are objects going to flicker?)
The objective was to have as much of the screen refresh code run in the period between when the raster hit the bottom of the TV screen (which triggured the interrupt that we'd hook into via an interrupt service handler) and when it hit the top of the area that the Spectrum actually used for display*. When things happened and how long they took was absolutely critical to the speed and smoothness of the game experience.
Answering these questions might be a bit trickier than you think though! If you're writing Z80 machine code, your entire application might run in less than 1/100 of a second. I know that, because one of mine did. So any instrumentation you add to your code had better :-
1) Have a very small overhead.
2) Be non-intrusive.
3) Give you just the information that you need and no more.
As with many things in the assembly language world, the solution turned out to be an extremely primitive but effective one. As a strong clue, take a look at this video AFTER MUTING YOUR SOUND (unless you want your ears to bleed). Old Spectrum users will recognise those yellow and blue alternating lines as the Spectrum loads data. It turns out that they are really easy to produce by using an OUT instruction to port FE, using the lowest 3 bits to set the border colour. (There are a lot more technical details buried in this FAQ!)
So, by using a single lightweight instruction to change the border colour at key points in the application, you could see a visual profile of how long different bits of your application were taking to run and when they stopped and started, relative to when the Spectrum was redrawing the TV display. With 8 colours available, it was just about possible to work out a high level activity profile of your application. The profile would change as the application had to perform more work on certain screen refreshes so you could see when you were running close to those dreaded flickering graphics!
Simple, cool, elegant and extremely useful. A response time profile updated 50 times a second for the cost of a few Z80 OUT instructions
That's why I'll always be respectful of the challenges that the authors of the Wait Interface, ASH, DTrace and the like have overcome. Low-level instrumentation has to be effective and lightweight.
Instrumentation - you know it makes sense!
* When you have this knowledge, it makes you see Spectrum games in a new light. That's why programmers liked big information and score areas at the *top* of the screen - because it gave them more time to draw objects before the raster on the TV screen reached them!