Monday, June 14, 2010

Idle = m + C1 + C2 + C3

There are a group of processor performance counters in Windows called "% Cx Time", which show the break down of processor idle time in which the processor goes into a low-power mode. Not all processors support these low-power idle states. The higher the number, the lower the power used by the processor, and the longer the latency before it can get back up running full speed again.

Thursday, June 10, 2010

CIL Constant Literals

Sometimes you'll want to create constant literals in CIL code. Most of the time you won't, but when you do, you'll need this. There are multiple ways of representing a constant, such as a constructor argument to a custom attribute, and ildasm.exe will give you something like this:
= ( DE AD BE EF )
If you want to re-write it, you know the signature (it's right next to the literal in the .il file,) so you only need to replace the single encoded binary literal into one like this:
= { string('Hello, World!') bool(true) type(int32) type([System.Xml]System.Xml.XmlDocument) }

Monday, June 07, 2010

Code Motion

The code we write in C# undergoes many changes before it is finally executed. There's the usual stuff interviews are made of: C# source is compiled to IL into a byte code representation that can be understood by the CLR. The CLR has another compiler - the JIT - which takes this byte code and turns each method into a sequence of instructions that can be understood by the hardware inside the computer. Then the hardware fetches the instructions from memory, decodes them, and executes them (fetching and writing to memory the program's data.) by driving voltages up and down across connected items inside your computer. If you thought your C# loop was executed as it's written, you're in for a treat: it's not.

The C# compiler produces different byte codes whether optimisation is turned on or off (off for DEBUG by default, which makes the emitted byte code look more like the source code, for easier pairing with the PDB files). The JIT compiler might take a loop and compile it down to a single inline sequence of instructions if they could make the execution faster. The processor might have multiple pipe lines in which it executes instruction streams in parallel (making use of the processor in times that it would otherwise have been wasting cycles waiting for the RAM or disk to send back data). Even after memory writes have been completed, they may be temporarily buffered close to the CPU rather than being expensively written directly to memory.

All of these changes are examples of code motion. To the average C# developer, most of these changes go unnoticed; on a single thread we have virtually no way of ever finding out that the instructions were actually executed out-of-order: the contract of C# guarantees these things for us. But in parallel processing with shared state, we start to witness evidence of the underlying chaos. Fields are updated after we expect - fields are updated before we expect. To limit any negative effects of code motion, the C# designers have given us the keyword, volatile. The keyword can be applied to instance/static fields (but not method local variables, as these cannot be safely accessed by multiple threads anyway - they will always live on their own thread's stack.) Read/write accesses to memory locations marked as volatile are protected by a "memory barrier". In oversimplified terms, any source code before a volatile read/write is guaranteed to have been completed before the access; similarly any source code after a volatile read/write will only be conducted after the access. To make your code ridiculously safe, you could add volatile to any updatable field (e.g. it can't be const or readonly) but you'd be losing out on all positive benefits of code motion.