Hacker News new | ask | show | jobs
by cmpitg 4000 days ago
Perhaps a bit off-topic but serious question. I don't understand whenever someone says language A is next to bare metal? What does a language have anything to do with bare metal or performance? Isn't it the compiler/interpreter that performance is about?
4 comments

If you pry open your computer and look through a microscope, you won't see any closures or lambdas. You won't see any private class members, much less any kind of inheritance or dynamic types. You won't see any microchips dedicated to try/catch/throw, you certainly won't see an 'exec' circuit. You won't see any kind of DOM, shadow or not.
I don't think it has anything to do the relationship between the language and its (compiler/interpreter) performance. Besides, the subset of a large number or programming language could be considered bare metal, right? If so, why mentioning bare metal at all?
Most things you do in a language like C, have direct counterparts in the physical machine. If you get into stuff like game hacking, you can literally "see" these things through whatever RAM-hacking tool you're using.

Dereference a pointer? That translates to a tiny fragment of machine code for "dereference pointer".

Create a lambda? That translates to a big blob of machine code for "set up this bunch of paperwork that will be used to painstakingly emulate a lambda".

And what does it have anything to do with C++ compared to any other language X? The bare-metal characteristics could be created as a subset of any non-safe non-garbage-collected language.
You're right. I think someone else already pointed out asm.js as a good example.

Of course, it won't happen magically: someone has to go to the effort of defining the subset and building the compiler for it.

You can't expect the general-purpose compiler to automatically be as optimal as possible just because a program happens to use the subset. For example, the program might be being compiled into something like a java .class file meant for importing to a less conservative calling program. This would be incompatible with putting those bare metal optimizations in the .class file.

It's about how much the language intrinsically prevents the compiler from optimising the output. Think Javascript versus asm.js, same language, one is just a subset of the other, completely different performance outcomes for the JIT compiler.
Languages like C and C++ compile down directly to machine code, and the resulting machine code is run from then on the bare metal without any further translation.

Interpreted languages such as Python or Ruby (or languages that run on a VM, like Java) go through an interpretation step _every time_ they are run that translates them down to machine language.

This gives compiled languages an inherent advantage in terms of runtime performance; programs written in these languages don't have the overhead of translating to machine code at runtime. This is typically why people advocate "next to bare metal" as having better performance.

That's technically true, but I think it has more to do with the programming model. 

In C and (sort of) C++ you can deal with actual bytes in actual memory locations. You can find the exact memory address of a data structure, and you can read or write directly to that location.

You can even prod the compiler to suggest that it uses real hardware registers for variables.

You can also control how memory is allocated and released.

In most languages an array is just an array. You usually don't care where it is in memory.

In functional languages you concentrate more on designing symbolic operations, and the fact that there's real memory under there somewhere is almost irrelevant.

But C/C++ are bare-metal-ish. In assembler you work directly with memory, but you can control program flow. You can jump/branch to any address in memory. Sometimes you can even overwrite your own code.

C/C++ won't let you do that.

As a former assembler guy, I find that C++ is the worst of both worlds. You get the cognitive overhead of dealing with memory management and pointer arithmetic and iterators, but the options for not working with them when you don't want to are limited - so it's hard to concentrate on the functional level, and you do a lot of the work the compiler/interpreter would usually do, but without the "do whatever you want" freedom of assembler.

That said, it's a about the implementation not the language itself. The phrase is technically incorrect, right? One could write a compiler that compiles Python or Ruby down to machine language without the interpretation overhead, and not necessarily faster or slower than their original interpreters, or other C/C++ compilers.
If the language defers explicitness until runtime then there's nothing a compiler or interpreter can do to get rid of the overhead.

With things like a JIT it can see it at runtime, but that's still overhead to handle the detection and the bail-out situations.

I agree on the overhead. There are information available only at run-time that could be (and actually has been, in case of interpreter like PicoLisp) used to have better optimization compared to compiled code. It isn't technically faster or slower.

Edited: Correct my bad grammar.