https://rogeralsing.com/2016/08/16/wire-writing-one-of-the-fastest-net-serializers/

It's interesting to compare what C# does and what people do in C# to promote speed over obviousness of implementation, with what D does by default and what's natural to do in D.

A direct comparison isn't trivial -- C# uses runtime reflection and D uses primarily compile-time.

Some specific parts that stood out to me:

* Looking up typeinfo
In D, TypeInfo is just an instance of some class that extends TypeInfo. When you write `typeof(foo)`, the compiler transforms that into a reference to the appropriate TypeInfo instance. On .NET, the primitive operation is to get a type handle for the type (done at compile time), and at runtime .NET performs a lookup based on that type handle.

* Dictionaries are slower than switch statements. Not surprising.

* Passing preallocated buffers. D has that concept baked in at this point; it's almost easier to use Appender!string than to append to a string. But this was apparently not natural in C#.

* When you are attempting to serialize millions of objects per second, virtual call overhead and uninlined functions matter. Wire uses code generation to eliminate both of these problems.

* In .NET, it's apparently not fast to create an uninitialized object. You can examine the bytecode for a function (including constructors) to determine whether a type has any code, which might include side effects, in its constructor.

In D, we can inspect the ClassInfo flags:

```D
if ((Foo.classinfo.m_flags & ClassInfo.ClassFlags.hasCtor) == 0) {
// static if is here just to ensure that this isn't compiled for types that
  // don't have a no-args ctor
  static if (is(typeof(new Foo))) {
    obj = new Foo;
    goto initialized;
  }
}
obj = hackyManualInitialization!Foo;
initialized:
```

(As an aside, I think I'm warming up to goto as an alternative to setting a flag and checking it later.)

Reply via email to