Should I sacrifice readability for speed using inline code vs function calls in C# NET4?

117 Views Asked by At

I am writing a Z80 Emulator in C#, second time. First time was incredibly slow using a bunch of if statements and function calls, so I am rewriting using using switch/case instead. VS2019 C# .NET 4

For simple instruction execution there aren't many lines of code, but some instructions pretty much require tons of code and adding so much code inline makes the code difficult to read.

So I am wondering whether to use function calls for the flags, especially the ones that require a lot of code or take the line count hit for the sake of speed.

ex:

case 188:
    byteCount = 1;
    mnemonic = "CP H      ";
    dest = int.Parse(txtRegA.Text, System.Globalization.NumberStyles.HexNumber);
    src = int.Parse(txtRegH.Text, System.Globalization.NumberStyles.HexNumber);
    result = dest - src;
    // Zero Flag
    if (result == 0) { ZeroFlag.Text = "1"; } else { ZeroFlag.Text = "0"; }
    // Carry Flag
    if (dest < result) { CarryFlag.Text = "1"; } else { CarryFlag.Text = "0"; }
    SignFlag.Text = "1";
    //N Flag
    if (result > 127) { AddSubFlag.Text = "1"; } else { AddSubFlag.Text = "0"; }
    // Overflow
    //Subtract
    if ((src>127 & dest >127) | ( src< 127 & dest <127)) { POFlag.Text = "0"; } else { POFlag.Text = "1"; }
    // Add
    //if ((src > 127 & dest <= 127) | (src < 127 & dest >= 127)) { POFlag.Text = "0"; } else { POFlag.Text = "1"; }
    // Half Carry - Note: The Registers are already in HEX format
    dest = Convert.ToInt32(txtRegA.Text.Substring(4, 4));
    src = Convert.ToInt32(txtRegH.Text.Substring(4, 4));
    // Subtract
    if (dest < src) { HalfCarryFlag.Text = "1"; } else { HalfCarryFlag.Text = "0"; }
    // Add
    //result = dest + src;
    //if ((dest + src)>31) { HalfCarryFlag.Text = "1"; } else { HalfCarryFlag.Text = "1"; }
    run = true;
    break;

I am not at all sure about whether my half carry and overflow flags will work properly at all.

Not all instructions affect all flags so some in-line will be better. But, the multi-line flags...

Thoughts comments

1

There are 1 best solutions below

0
JonasH On

The golden rule of optimization is to profile first. Sometimes formulated as Premature optimization is the root of all evil:

There is no doubt that the grail of efficiency leads to abuse. Programmers waste enormous amounts of time thinking about, or worrying about, the speed of noncritical parts of their programs, and these attempts at efficiency actually have a strong negative impact when debugging and maintenance are considered. We should forget about small efficiencies, say about 97% of the time: premature optimization is the root of all evil.

Over time you tend to get a little bit better at guessing what will be slow or not. I would observe that it looks like your code is doing a few different things:

  1. Logic operations, i.e. shifts etc
  2. String operations
  3. UI updates

Each of these things are order of magnitudes different with regards to performance. Something like updating the UI is many order of magnitudes slower than a simple method call.

My recommendations would be to

  1. Start by doing some profiling, and/or benchmarking. That should give you some clues to what is slow, and familiarize yourself with the tools.
  2. Focus on organization and readability before you attempt to do any optimization. Well organized code can usually be optimized one you know what parts are actually causing problems. Trying to optimize messy code tend to just break things all over.
  3. Separate the actual emulation from things like UI. So that the actual emulation can run faster than the UI updates. You could use a one of the UI-timers to work as a clock for your emulation.
  4. Try to reduce string handling as much as possible. If you are reading values from the UI you want to parse & validate values when they change, and only then. The rest of the code should use the the parsed values.

You might also consider running the emulation on a background thread, but doing so will require your program to be thread safe. So I would only consider this if you are familiar with thread safety, or are prepared to learn about it before you attempt it.