top | item 8883791

A Quick Comparison of Nim vs. Rust

221 points| arthurtw | 11 years ago |arthurtw.github.io | reply

90 comments

order
[+] andybak|11 years ago|reply
It's feels like a shame to me that the one Python maxim that Nim has chosen to reject is "there should be one and preferably only one way to do it" - from this flows so much of the other goodness of the Python ecosystem. I worry that some of the metaprogramming magic that Nim allows will result in the loss of that feeling that I can view source on almost any 3rd party Python code and immediately feel like I can follow what's going on. Maybe community standards can help restrain this somewhat.

Also:

> mapWidth, mapwidth and map_width all map to the same name

Why or why? Editors and IDEs now need Nim-aware search code!?

[+] baldfat|11 years ago|reply
> "there should be one and preferably only one way to do it"

In my very humble opinion this idiom is amazing at the start of a language and then it handcuffs it and that is why we have Python 2 or Python 3 issues.

I use to use Python for statistical work and about 2 years ago I switched to R. R is VERY flexible and seen a huge change over the last 5 or so years. It has changed for me especially in the last 6 months with changes in what libraries I use. Using dplyr and other libraries my code is night and day different. We now have piping with %>% that changes me code completely and makes it MUCH more readable and quick to write code. I don't see anything like this happening quickly in Python.

[+] okasaki|11 years ago|reply
On the other hand, it's quite convenient if you can't remember the exact name and it saves you a look-up e.g. quick_sort vs quicksort vs quickSort - either work
[+] idlewan|11 years ago|reply
It allows you to use your own style everywhere, instead of relying on the specific styles of the library you used (so you don't end up in your code with camelCase AND snake_case).

It's definitely unusual, but I think it works quite well.

[+] girvo|11 years ago|reply
`nimgrep` is a tool that comes with it to help with that. It's actually pretty useful, especially when dealing with wrappers over C libraries (I'm looking at you, SDL2...)
[+] ot|11 years ago|reply
> It’s mysterious that Rust’s release version with -i ran slightly faster, though.

That's actually not surprising: a large fraction of time is spent in the map lookup, which in Rust is implemented as a B-tree, thus lookup time is (mildly) dependent on the map size. If keys are lowercased before inserting them, the map ends up having fewer elements.

The Nim version uses instead hash tables, whose lookup time is near-constant (that is, excluding memory hierarchy effects).

[+] dbaupp|11 years ago|reply
> That's actually not surprising: a large fraction of time is spent in the map lookup

This was not the case in my benchmarks: the Rust spent 60% of its time doing regex matches, 25% allocating strings and less than 6% manipulating the map.

[+] AYBABTME|11 years ago|reply
This seems an odd choice to me (default to B-Tree instead of hash map). I'd expect a sorted map to be a special case, not a general one. Do you happen to know the rationale?

Not criticizing, just curious.

[+] arthurtw|11 years ago|reply
That should explain it. I’ve removed the line as it’s no more mysterious...
[+] skrebbel|11 years ago|reply
I like how articles like this help elevate Nim's status. To me, deep inside, Rust always felt like this grand high-stakes project, by wise people at this big experienced company Mozilla, and Nim felt like a hobby project that got out of hand. That's an entirely unfair judgment of course, but I bet more people feel that way. I like that Nim is starting to get the attention it deserves.
[+] arthurtw|11 years ago|reply
Yes, I think Nim deserves more attention, and that’s part of the reason I wrote this article.
[+] pcwalton|11 years ago|reply
The first benchmark is primarily a comparison of Nim's PEG package to Rust's libregex package. The two have very different algorithms, and libregex is optimized to avoid exponential blowup on pathological regexes. It's missing a fallback to the backtracking algorithm at present.

Using rust-pcre would probably mitigate this problem.

[+] burntsushi|11 years ago|reply
I was still pretty surprised that `regex` was getting killed. It turns out, I think, that `\w+` in Rust is Unicode friendly, but it's not in Nim. In cases where most matches fail, checking the full spectrum of Unicode "word" characters becomes pretty expensive (although it is at least doing a binary search on contiguous ranges of characters: https://github.com/rust-lang/regex/blob/master/src/vm.rs#L23...). When I switched `\w+` to `[a-zA-Z0-9_]+` in the Rust program, I saw a ~60% performance increase.

> and libregex is optimized to avoid exponential blowup on pathological regexes. It's missing a fallback to the backtracking algorithm at present.

Maybe. RE2/C++ doesn't do any backtracking AFAIK, but it appears near the top of any benchmark I think.

[+] gfasdgsfd|11 years ago|reply
I'd guess that pulling that try-catch out of the loop would make things go much faster. Nim doesn't use 0-overhead exceptions, so setjmp needs to be called each time the try-catch is entered.

You should also use the re module, PEGs is not nearly as optimized as PCRE.

[+] arthurtw|11 years ago|reply
I’ll try that later, though the Nim version is fast enough after using -d:release flag.
[+] _pmf_|11 years ago|reply
From what I have read, Nim has a much better cross-compilation story (i.e. it delegates to the available C cross-compilation toolchain instead of requiring the Nim compiler and toolchain to be compiled for the cross target).

Rust, as I understand, requires the Rust compiler to be compiled for the cross-target; is this correct?

[+] dbaupp|11 years ago|reply
The compiler does not need to be compiled for the cross-target to just run binaries, just the standard library like C; but, once they exist, running the compiler directly with `rustc --target=...` and using the dependency/build manager cargo `cargo build --target=...` both work fine.

Of course, it is harder to obtain cross-compiled versions of the Rust standard library at the moment, so what you say is likely true.

[+] andrewchambers|11 years ago|reply
llvm has pretty good cross compiler support, So I don't know.
[+] dom96|11 years ago|reply
Are you just using --opt:speed to compile the Nim examples? For maximum performance you should be using -d:release.
[+] mrob|11 years ago|reply
-d:release disables bounds checking, so the Rust examples would have to be modified for unchecked indexing for a fair comparison.
[+] arthurtw|11 years ago|reply
Oh, my bad. The numbers differ a lot (2~2.5x faster). I’ve updated the article.
[+] TylerE|11 years ago|reply
I'm starting to really wish there was a GC-free (or at least) GC optional version of Nim. Nim with Rust's memory semantics would just be the best of everything.
[+] Ygg2|11 years ago|reply
Well, that's kinda the point. If there was a better way to have to achieve GC-free semantics, Rust would have taken it.

As for optional GC, didn't D haven't something along those lines?

[+] skariel1|11 years ago|reply
Optional gc is tricky, as you would need all libraries written this way
[+] vbit|11 years ago|reply
I believe you can turn off the GC for Nim. Then you're just limited to libraries that don't rely on the GC, and fully manual memory management.
[+] hamstergene|11 years ago|reply
Why don't you run GC_fullCollect() at the end of Nim programs? You may unknowingly be comparing a program which actively runs destructors and frees memory with one that basically leaks everything (because GC does not happen to be triggered).
[+] nim_user|11 years ago|reply
Nim needs to move it's discussions to a mailing list if the authors want to gain more serious developers onboard.

Polling a poorly implemented web forum speaks leaps and bounds about the kind of attitude you need to have to discuss, develop or debug issues around the Nim toolchain.

This is something that Nim developers can instantly do to boost the attractiveness of the language.

Please, do this.

[+] ilaksh|11 years ago|reply
The web forum is better than 90% of the forums out there. It is very fast, looks great, has syntax highlighting and a fast search. How could you possibly think that a mailing list is better? What is this, 1981? I hate mailing lists. The github issues is where a lot of serious discussion goes on and if you give github your email and contribute or subscribe you can get spammed with every single issue discussion like me. Anyway I think the highest bandwidth most advanced option is sometimes IRC which of course Nim has too.
[+] girvo|11 years ago|reply
> about the kind of attitude you need to have to discuss, develop or debug issues around the Nim toolchain

Well, it's the kind of attitude that let me contribute to the language, and fix bugs despite being rather new to it all, so I'll be honest and say that I think it's quite good. Aside from that, the IRC channel is always super busy and amazingly helpful. I think a mailing-list is a good thing, sure, but it's not the be-all-end-all, in my humble opinion.

[+] dom96|11 years ago|reply
Can you point me to these serious developers who would be using Nim or contributing to Nim if a Nim mailing list existed? If I have proof that these developers exist then I may actually implement it.
[+] errordeveloper|11 years ago|reply
I really wouldn't consider it reasonable comparison, when one language has a sufficient compiler that is written in itself for most part, and the other still only compiles to C.
[+] ziotom78|11 years ago|reply
Why should such comparison be unreasonable? The fact that a compiler internally produces C/Assembly/Brainfuck/whatever code to produce the final binary should be relevant only for computer science theorists, not for the majority of the users out there (like me).

Also, I find one of your statements quite contradictory: by saying that Rust's compiler "is written in itself", you seem to imply that Nim is not. But this is not true: Nim's compiler is almost 100% pure Nim.

(Last but not least: to me it seems not true that Nim "only compiles to C", as it provides multiple backends. See here: http://nim-lang.org/backends.html .)

[+] beagle3|11 years ago|reply
rust uses LLVM (a C++ library) as a backend; nim uses clang (a compiled C++ executable) as a backend. While there are differences, neither is clearly superior.

Generally, the LLVM route will be faster/more compact when compared to Clang. However, nim can just as easily use gcc, or MSVC, or tcc, which rust cannot. Especially with respect to tcc, this means a stand-alone all-inclusive nim compiler executable can quite easily be constructed and will probably be ~1MB, whereas the comparable standalone rust compiler rustc executable is likely to clock in at 20MB. And you know what? That makes no difference in today's world.

Edit: made it explicit that I am talking about the compiler itself (which was the subject of the parent post I was replying to).

I estimated that the rustc will be 20MB based on my experience with linking LLVM statically in the past - I have not tried it recently, nor have I built rustc. I might be way off. Kibwen says his rust compiler clocks at 8MB - so it appears I am way off (or maybe comparing an unstripped executable to a stripped one)

To be clear to child comment: I did NOT intend to claim that writing something in C will provide a 95% reduction of code size.

[+] NateDad|11 years ago|reply
Go's compiler was entirely C until just recently... What does it matter? It's hard to write a compiler in a language that doesn't exist yet, and one you have the language, why bother with a rewrite?
[+] rayiner|11 years ago|reply
Rust compiles to LLVM, which is a big chunk of C++ code.
[+] lmm|11 years ago|reply
It'd be good to see how these new languages compare to established ones that offer similar features - maybe OCaml and Haskell.