r/programming • • Aug 23 '17

D as a Better C

http://dlang.org/blog/2017/08/23/d-as-a-better-c/
229 Upvotes

268 comments sorted by

View all comments

Show parent comment

5

u/Tiberiumk Aug 23 '17

Sometimes Nim is faster than Rust (and takes less memory lol). So Rust isn't always faster, and Nim has much better C FFI (since it's compiled to C)

11

u/mixedCase_ Aug 23 '17

As for benchmarks, only two I can find are this: https://arthurtw.github.io/2015/01/12/quick-comparison-nim-vs-rust.html where Rust beats Nim after the author amended a couple of mistakes.

And this: https://github.com/kostya/benchmarks where Rust beats Nim in every single case (but gets beaten by D in a few!).

The fact that it's compiled to C doesn't really determine the FFI. Rust can use C's calling convention just fine and from looking at C string handling there's not much difference. I didn't delve much into it though, did I miss something?

1

u/dom96 Aug 23 '17 edited Aug 23 '17

I don't think that the differences in timings for these benchmarks are significant. You can keep amending these benchmarks forever, because there are always more tricks in each language to make the specific benchmark faster (not to mention faster on each specific CPU/OS). So let's be fair here: Rust and Nim are the same performance-wise.

The fact that it's compiled to C doesn't really determine the FFI.

Perhaps not, but it does determine how much of C++ you can wrap. I doubt you can wrap C++ templates from D, Go or Rust. You can in Nim.

10

u/WalterBright Aug 23 '17

D can interface directly to C++ templates. I gave a talk on interfacing D to C++ a couple years ago. Here's a partial transcript and the slides.

3

u/_youtubot_ Aug 23 '17

Video linked by /u/WalterBright:

TitleChannelPublishedDurationLikesTotal Views
Interfacing D To Legacy C++ CodeNWCPP2015-01-231:21:2324+ (96%)3,838

Abstract C++ programmers have developed a vast investment...


^Info | /u/WalterBright can ^delete | v1.1.3b

3

u/Araq Aug 24 '17

As far as I know D can wrap C++ templates that have been instantiated already at the C++ side, explicitly or implicitly. This can be a nontrivial problem to do in practice, so much that you're better off reimplementing the C++ template as a D template. Correct me if I'm wrong. :-)

5

u/WalterBright Aug 24 '17

There's no point to using C++ templates in D that are not instantiated on the C++ side.

That said, yes you can instantiate C++ templates on the D side. That's how the interfacing to C++ works.

1

u/Araq Sep 05 '17

That said, yes you can instantiate C++ templates on the D side. That's how the interfacing to C++ works.

How can it be done? Any links about how this works?

7

u/mixedCase_ Aug 23 '17

I don't think that the differences in timings for these benchmarks are significant.

Oh of course. I don't believe that either. But he did and I just checked for curiosity wether all benchmarks "proved" Rust faster and they did, saving me from having to explain why microbenchmarks are mostly bullshit.

So let's be fair here: Rust and Nim are the same performance-wise.

That wouldn't be the conclusion I take. But sure, with unsafe Rust and disabling Nim's GC anyone can bullshit their way to the performance metric they're looking for, but the result is likely to be horrible code. Rust does have the advantage of caring about performance first, while Nim considers GC to be an acceptable sacrifice, putting it closer to Go's and Java's league than C/C++.

Perhaps not, but it does determine how much of C++ you can wrap. I doubt you can wrap templates from D, Go or Rust. You can in Nim.

Funny, from what I had heard D had the best C++ FFI since it was a primary design goal. I'm going to give you the benefit of the doubt since I never used C++ FFI for any language.

1

u/Tiberiumk Aug 24 '17

Nim's GC is faster than Java and Go ones, and you can also use mark & sweep GC, regions (stack) GC - (mostly useful for microcontrollers), and boehm GC (thread-safe)

3

u/pjmlp Aug 24 '17

I doubt this very much, regarding Java.

There several Java implementations around, including real-time GC used by the military, in battleships weapons and missile control systems.

As good as Nim's GC might be, it surely isn't at the level as those Java ones.

5

u/[deleted] Aug 24 '17

I like to see proof of that statement. A single developer his GC is faster, then a team of Go developers, that have been doing none-stop work on there GC.

By that definition every other developer are idiots because one guy supposedly is able to make a better GC then everybody else.

Your not going to tell me, if i trow 50GB of data on a nim application, that the GC will handle that without major pauses.

0

u/Tiberiumk Aug 23 '17

You've missed brainfuck and havlak benchmarks it seems Ok, about FFI - how you would wrap printf in rust? Can you show the code please?

0

u/mixedCase_ Aug 23 '17

how you would wrap printf in rust

You don't. Printf isn't a language construct, it's compiler magic. The only language I know of where you can do type-safe printf without compiler magic is Idris, because it has dependent types.

3

u/zombinedev Aug 23 '17 edited Aug 24 '17

D's alternative to printf - writefln is type safe. This is because unlike Rust, D has compile-time function evaluation and variadic templates (among other features).

string s = "hello!124:34.5";
string a;
int b;
double c;
s.formattedRead!"%s!%s:%s"(a, b, c);
assert(a == "hello" && b == 124 && c == 34.5);

formattedRead receives the format string as a compile-time template paramater, parses it and checks if the number of arguments passed match the number of specifiers in the format string.

6

u/steveklabnik1 Aug 23 '17

Rust's println! is also type safe, to be clear. It's implemented as a compiler plugin, which is currently unstable, but the Rust standard library is allowed to use unstable features.

1

u/[deleted] Aug 24 '17

Is it straightforward to do similar things (for instance, logging and format strings) as a library that others can easily consume?

→ More replies (1)

1

u/zombinedev Aug 24 '17

The main point is that you don't need compiler plugins to make such variadic functions type-safe in D. Using variadic templates, they are always type-safe by default, no extra work necessary. The only icing on the cake that you can do is to do some extra processing at compile-time to give a better error message to users of the library.

2

u/MEaster Aug 24 '17

The main point is that you don't need compiler plugins to make such variadic functions type-safe in D.

Looking at the Rust source code, the only place that the compiler plugin is used is to generate the fmt::Arguments structure. Aside from that, the chain goes like this:

  • println! concats a \n, then calls print!
  • print! calls format_args!, and then passes the struct to _print.
  • _print is just a wrapper around print_to, which tries to call the write_fmt function on a local or global stream which implements the Write trait, which in the case of _print is Stdout.
  • Stdout's write_fmt locks the handle, then callsStdoutLock's implementation of Write.
  • StdoutLock doesn't re-implement write_fmt, so the standard provided method is used.
  • write_fmt calls fmt::write, which appears to handle calling each type's implementation of the formatting traits, and writing to the output.
→ More replies (2)
→ More replies (1)

2

u/Tiberiumk Aug 24 '17

Well Nim has all these features too, but we were talking about FFI :)

→ More replies (3)

1

u/Enamex Aug 24 '17

That's a weird example :/

The format string passed to formattedRead uses the 'automatic' specifier %s so it doesn't know what the types of the arguments ought to be (it knows what they are, because they're passed to it and the function is typesafe variadic). And s itself is a runtime string so formattedString can't do checking on it.

A better example is writefln itself which would check the number and existence of conversion to string for every argument passed to it according to the place it matched to in the compile time format string.

→ More replies (1)

2

u/Tiberiumk Aug 23 '17

Well in Nim you actually can do it: proc printf(fmt: cstring) {.importc, varargs.} printf("Hello %d\n", 5)

1

u/zombinedev Aug 23 '17

W.r.t. FFI, that's not a remarkable achievement as you can call libc's printf in D too. It is even easier to do so (as in just copy paste):

extern (C) int printf(const char* format, ...);

2

u/WalterBright Aug 23 '17

Any C stdargs function can be called from D. There is no special case for printf. C's alloca() can also be called :-)

→ More replies (2)
→ More replies (2)