dmd -run speed trends

Witold Baryluk witold.baryluk at gmail.com
Thu Dec 7 16:32:32 UTC 2023


I do not use `dmd -run` too often, but recently was checking out 
Nim language, and they also do have run option, plus pretty fast 
compiler, so checked it out.

Then, I was curious about trends of `dmd -run`, and did some 
historical tracking.

The example is simple example from nim website, ported to Python 
and D. It imports `writefln`, and `std.array` (for split), 
defines a simple data only class, construct array of few objects, 
do some iterations, as well do some very small compile time 
generation, and generator (in I used foreach over delegate). It 
is very small program, with nothing interesting going on, so we 
are are mostly measuring compiler, linker, parsing few libraries 
we import, and startup times.


| x | min wall time [ms] | Notes |
| --- | ---: | --- |
| Python 3.11.6 | 31.4 |
| Nim 2.0.0 (cached) | 139.4 |
| Nim 2.0.0 (uncached) | 711.4 | cached binary removed before 
each re-run |
| gdc 13.2.0-7 | 1117.0 |
| dmd 2.106.0 | 728.1 |
| dmd 2.105.3 | 712.9 |
| dmd 2.104.2 | 728.2 |
| dmd 2.103.1 | 714.7 |
| dmd 2.102.2 | 714.0 |
| dmd 2.101.2 | 853.0 |
| dmd 2.100.2 | 842.9 |
| dmd 2.099.1 | 843.7 |
| dmd 2.098.1 | 898.1 |
| dmd 2.097.2 | 771.9 |
| dmd 2.096.1 | 729.7 |
| dmd 2.095.1 | 723.1 |
| dmd 2.094.2 | 1008 |
| dmd 2.093.1 | 1078 |
| dmd 2.092.1 | 1073 |
| dmd 2.091.1 | 790.6 |
| dmd 2.090.1 | 794.0 |
| dmd 2.089.1 | 771.1 |
| dmd 2.088.1 | 802.1 |
| dmd 2.087.1 | 790.6 |
| dmd 2.086.1 | 769.4 |
| dmd 2.085.1 | 822.6 |
| dmd 2.084.1 | 771.3 |
| dmd 2.083.1 | 784.0 |
| dmd 2.082.1 | 765.4 |
| dmd 2.081.2 | 693.0 |
| dmd 2.080.1 | 685.5 |
| dmd 2.079.1 | 650.4 |
| dmd 2.078.3 | 628.2 |
| dmd 2.077.1 | 626.3 |
| dmd 2.076.1 | 618.8 |
| dmd 2.075.1 | 589.9 |
| dmd 2.074.1 | 564.3 |
| dmd 2.073.2 | 574.3 |
| dmd 2.072.2 | 590.4 |
| dmd 2.071.2 | n/a | Linker issues |
| dmd 2.070.2 | n/a | Linker issues |
| dmd 2.069.2 | n/a | Linker issues |
| dmd 2.065.0 | n/a | Linker issues |
| dmd 2.064.0 | n/a | No std.array.split available |




Measurement error is <0.1%. (idle Linux system, performance 
governor, 240 or more repetitions, minimums taken).


So, not too bad, but not too good either.

We are not regressing too much, but things could be improved: 
Sizes of imports reduced, Compiler in general speed up, and for 
-run, some intermediate form cached on disk to speed up parsing, 
for various imports, or for the final binary.

Environment: Debian Linux amd64, Threadripper 2950X, all inputs 
and outputs in RAM on tmpfs (including compilers and libraries).

GNU ld (GNU Binutils for Debian) 2.41.50.20231202

Reference code:

```d
#!/usr/bin/env -S dmd -run

struct Person {
   string name;
   int age;
}

auto people = [
   Person("John", 45),
   Person("Kate", 30),
];

void main() {
   import std.stdio : writefln;
   foreach (person; people) {
     writefln("%s is %d years old", person.name, person.age);
   }

   static auto oddNumbers(T)(T[] a) {
     return delegate int(int delegate(ref T) dg) {
       foreach (x; a) {
         if (x % 2 == 0) continue;
         auto ret = dg(x);
         if (ret != 0) return ret;
       }
       return 0;
     };
   }

   foreach (odd; oddNumbers([3, 6, 9, 12, 15, 18])) {
     writefln("%d", odd);
   }

   static auto toLookupTable(string data) {
     import std.array : split;
     bool[string] result;
     foreach (w; data.split(';')) {
       result[w] = true;
     }
     return result;
   }

   enum data = "mov;btc;cli;xor;afoo";
   enum opcodes = toLookupTable(data);

   foreach (o, k; opcodes) {
     writefln("%s", o);
   }
}
```

```python
#!/usr/bin/env python3

import dataclasses


@dataclasses.dataclass
class Person:
     name: str
     age: int


people = [
     Person(name="John", age=45),
     Person(name="Kate", age=30),
]

for person in people:
     print(f"{person.name} is {person.age} years old")


def oddNumbers(a):
     for x in a:
         if x % 2 == 1:
             yield x


for odd in oddNumbers([3, 6, 9, 12, 15, 18]):
     print(odd)


def toLookupTable(data):
     result = set()
     for w in data.split(";"):
         result.add(w)
     return result


data = "mov;btc;cli;xor;afoo"
opcodes = toLookupTable(data)

for o in opcodes:
     print(o)
```

```nim
#!/usr/bin/env -S /home/user/nim-2.0.0/bin/nim r --warnings:off 
--hints:off

import std/strformat

type Person = object
     name: string
     age: Natural # Ensures the age is positive

let people = [
   Person(name: "John", age: 45),
   Person(name: "Kate", age: 30),
]

for person in people:
   echo(fmt"{person.name} is {person.age} years old")


iterator oddNumbers[Idx, T](a: array[Idx, T]): T =
   for x in a:
     if x mod 2 == 1:
       yield x

for odd in oddNumbers([3, 6, 9, 12, 15, 18]):
   echo odd


import macros, strutils

macro toLookupTable(data: static[string]): untyped =
   result = newTree(nnkBracket)
   for w in data.split(';'):
     result.add newLit(w)

const
   data = "mov;btc;cli;xor;afoo"
   opcodes = toLookupTable(data)

for o in opcodes:
   echo o
```



More information about the Digitalmars-d mailing list