5 ms·
All of these "fast as C" claims about modern, high-level Python-like languages (be they statically typed and natively compiled) are missing the point. It is mos
by bluetomcat 10y ago
All of these "fast as C" claims about modern, high-level Python-like languages (be they statically typed and natively compiled) are missing the point. It is mostly the minimalistic and terse programming style that C encourages that makes C programs performant. You avoid allocations wherever possible, you write your own custom allocators and memory pools for frequently allocated objects, you avoid copying stuff as much as possible. You craft your own data structures suited for the problem at hand, rather than using the standard "one size fits all" ones. Compare that to the "new this, new that" style of programming that's prevalent today.
- progman 10y agoThere actually is one high-level Python-like language that really is almost "as fast as C". http://nim-lang.org http://nim-lang.org I am using it for years already, and it is really performant, somewhere between C and Rust. I am still wondering why so few people use it. Benchmark: https://github.com/kostya/benchmarks https://github.com/kostya/benchmarks Nim vs Rust: http://arthurtw.github.io/2015/01/12/quick-comparison-nim-vs-rust.html http://arthurtw.github.io/2015/01/12/quick-comparison-nim-vs... Performance discussion: http://forum.nim-lang.org/t/2261 http://forum.nim-lang.org/t/2261 Embedded Nim: https://hookrace.net/blog/nim-binary-size/ https://hookrace.net/blog/nim-binary-size/ Nim on LLVM: https://github.com/arnetheduck/nlvm https://github.com/arnetheduck/nlvm
- def- 10y ago> I am still wondering why so few people use it. While Nim is my favorite language, I can understand that it has a small userbase, for these reasons: 1. No major backer like Google for Go or Mozilla for Rust 2. No killer feature like "memory safety and performance without GC" for Rust, instead a mix of all the reasonable down-to-earth features I want in a programming language 3. Some unique decisions instead of what you're used to from other languages, for example partial case sensitivity
- untothebreach 10y agoI used both nim (back when it was still nimrod) and rust for a while, before eventually settling on rust. I tried to give nim a chance, and was told that "they will grow on you" ("they" being the things you mentioned that were "unique decisions instead of what you're used to from other languages"). They never did, and though I got used to avoiding the problems I initially had with them, the language just never "felt good" to me.
- valarauca1 10y ago4. The fact that operator order is changed by the amount of white space between symbols 2+2 * 5 = 20 2 + 2 * 5 = 12
- adrusi 10y agoIf you're consistent about how you space your infix operators, this will have no impact on your code. If you put space around some operators and not around others, in a way that doesn't correspond to precedence, you're going to confuse anyone who reads your code, in any language.
- valarauca1 10y agoBeing confused by code is no excuse for code not doing what ya know... every other programming language has done for the past 50 years. I get that trying new things, but somethings are pretty well agreed upon.
- xutopia 10y agodamn... I actually like that a lot!
- qu4z-2 10y agoI like it for distinguishing homonym operators, but not for the precedence stuff they seem to have there. I'd like something like this though: let a = 10; a / 5 output> 2 let b = pwd(); b/temp output> Directory<"~/temp"> b / 2 error> b:Directory does not implement method "divide(:number)" a/temp error> a:int does not implement method "get(:string)"
- bluetomcat 10y agoShameless plug: is it considered totally uncool in 2016 for one to be developing a memory-unsafe, manual MM, non-OO, thread-denying language that preserves most of the C semantics? https://github.com/bbu/quaint-lang https://github.com/bbu/quaint-lang
- lmm 10y agoYes. Memory unsafety doesn't work.
- exDM69 10y agoNo, definitely not! I'd be very interested in a language that is roughly as low level as C, but has some obvious warts "fixed" while still being able to run on bare metal or with a minimal runtime system. I also don't care about a standard lib as long as I can call open(), close(), read(), write(), socket(), etc. Native threads is another requirement for me. Things I'd like to see in a language: - compile to native executable - type inference - module system without header files - easy to call into native C code, and export functions so they can be called from C or any other language - first class SIMD structures (this is missing from Rust!), so that you don't have to duplicate code for sin4f and sin8f (which would be line-by-line equal, except types) - perhaps some kind of modern polymorphism (ie. not class based OOP) - can target GPUs via LLVM or SPIR-V - memory safety is optional, but nice to have. I'd be mostly interested in using this kind of language for GPU kernels and tight inner loops, where you wouldn't be allocating anyways I have a bunch of design ideas and prototypes in my drawer waiting for a lot of free time and inspiration appearing. I like my tools sharp, even if it means there's going to be blood occasionally.
- bluetomcat 10y agoMy next big endeavour with Quaint will be to create a clean module and linking system (without header files or any textual inclusions). Each source file will be transformed to a corresponding unit which contains code, data and exported type definitions. The linker would then merge these units and produce a native executable that runs your program in the self-hosted VM which will be a part of that executable. Pure native compilation or LLVM integration is too much of a hassle for me at this point. One of the virtues of the language would also be the direct correspondence between the HLL code and the emitted VM instructions, without any optimisation passes. This makes it much easier to reason about code performance and to write code which performs consistently and predictably (albeit a bit slower).
- 3pt14159 10y agoI love and use Nim (in production). I wrote about why I don't think it's gained wide adoption in a previous post here: https://news.ycombinator.com/item?id=11960814 https://news.ycombinator.com/item?id=11960814 The only thing I would add would be that compared to Ruby, Nim still takes you quite a while to put something together, so defaulting to Ruby isn't necessarily a great idea.
- steveklabnik 10y agoJust a small note for anyone reading the "Nim vs Rust" post; today, regex! is much slower than Regex::new.
- hetman 10y agoAll the benchmarks you posted suggest that Rust is faster than Nim, not the other way around. Did you have something else in mind?
- steveklabnik 10y agoA lot of them did show the other way, then came to Rust people's attention and improvements were submitted. As well as both languages' implementations changing over time.
- Veedrac 10y agoThe first benchmark ("Nim vs Rust") I looked at says > Rust regex! runs faster than Regex which is a very old claim - Regex should now be much faster than regex! ever was. Any pre-1.0 Rust benchmarks are probably wrong (to be fair, most benchmarks are probably wrong anyway).
- progman 10y ago> You avoid allocations wherever possible If you don't have to write cutting-edge games or embedded software for tiny systems, why do you have to care about allocations at all? Today's systems and RAM's are so fast that garbage collections don't really matter in most cases. Consider SBCL (compiled Common Lisp) which is almost as performant as Java and C++. http://benchmarksgame.alioth.debian.org/u64q/lisp.html http://benchmarksgame.alioth.debian.org/u64q/lisp.html I used to develop software in C and C++ for many years, and a garbage collector was the thing I wanted the most. GC-free programming is unnecessarily tough in most cases, except you desperately need it for games and embedded systems.
- bluetomcat 10y agoYou must worry about allocations anytime you write CPU-bound software which wants to maximise the output per clock cycle. Granted, most software isn't like that, but it's certainly not only games and embedded software on tiny systems.
- adrianN 10y agoBecause allocating something on the stack means adding a something to a pointer and puts the object somewhere that is likely to be in the cache during the function and allocating something on the heap usually takes a tree traversal and puts the object far away from the other stuff you might be using. Also, using numbers from a benchmark game is not representative of the performance of real world applications. If you look at the code, you'll find that it's written in a style that avoids heap objects and GC wherever possible. Forcing heap allocation is what makes Java slightly slower than C in many cases.
- wott 10y ago> If you don't have to write cutting-edge games or embedded software for tiny systems, why do you have to care about allocations at all? Today's systems and RAM's are so fast What? RAM is not fast at all, the latencies have almost not improved in 20 years (compared to the improvement of other subsystems like the CPU, of course).
- GFK_of_xmaspast 10y agoRAII and smart pointers go a long way towards eliminating the need for GC in c++.
- piaste 10y agoNitpick: everything you say is probably correct, but such performant C programming is also the very opposite of a "minimalistic and terse style". Which one is more minimalistic, 'new Foo' or a collection of various custom-tuned allocation methods? Which one is more terse, 'myList.Where(foo).Select(bar).Aggregate(baz)' or an explicit for loop?
- bluetomcat 10y agoIt is minimalistic in the sense that the language provides a narrow set of primitives and a skilled programmer combines these primitives in the most sensible way to solve the problem at hand. Higher level stuff in most other languages is much more generic. Indeed, it may not be minimalistic in terms of the code size.
- wott 10y ago> All of these "fast as C" claims about modern, high-level Python-like languages (be they statically typed and natively compiled) are missing the point. It is mostly the minimalistic and terse programming style that C encourages that makes C programs performant. You avoid allocations wherever possible, you write your own custom allocators and memory pools for frequently allocated objects, you avoid copying stuff as much as possible. You craft your own data structures suited for the problem at hand, rather than using the standard "one size fits all" ones. Compare that to the "new this, new that" style of programming that's prevalent today. Exactly! I cannot agree more. I have a small test program I port to different languages to test the length of the code and the speed of the program. Of course it only represents a single use case. * C is first, of course. * twice as slow, come Pascal, D and... Crystal! * x3 to x5, come Nim, Go, C++ (and Unicon). * x6 to x9, come Tcl, Perl, BASIC (and Awk). * x15 to x30, come Little, Falcon, Ruby and Python. * x60 to x90, come Pike, C#, Bash. * x600 to x1000, come Perl6 and Julia. This list looks byzantine, I know :-) The trends I can get out of it: * the last 2 are languages with JIT compilation, and that's horrid for short programs. * the "old" interpreted (or whatever you name it nowadays) languages (Tcl, Perl) are not so bad compared to compiled languages, and much faster than "modern" one (Ruby, Python). (Again, this is only valid for my specific use.) * compiled languages should all end up in the same ballpark, shouldn't they? Well, they don't. The more they offer nice data structures, the more you use them. The more they have some kind of functional style (I mean the tendency to create new variables all the time instead of modifying existing ones) the more you allocate and create and copy loads of data. In the end, being readable and idiomatic in those languages means being lazy and inefficient, but what's the point of using those languages if don't use what they offer? C forces you to use proper data structures and not re-use existing ones. It comes naturally. What is unnatural in C is to copy again and again the data, it is simpler to modify the existing one and work on the right parts of it, not to pass the whole chunks every time you need one single bit. In more evolved languages, compilation won't save you by doing some hypothetical magic tricks, it cannot remove the heavy continuous data copying and moving you instructed your program to do. And that is what made the difference in speed between C on one side, and D, C++, Go on the other side.
- hetman 10y agoI'm curious where Rust fits in on your hierarchy with their emphasis on "zero cost abstractions". Of course that's more a lofty ideal than reality but it means that at least in some cases it does much better than C++. Is it a long program? Something that could be posted in a Github Gist maybe?