5 ms·
These "faster than C" claims are almost always embarrassing (usually involving C code that would easily win if it were as aggressively optimized as the high-lev
by haberman 14y ago
These "faster than C" claims are almost always embarrassing (usually involving C code that would easily win if it were as aggressively optimized as the high-level language) but that's almost not the point.
The real point is the larger narrative. The subtext of these posts is what we are really arguing about. So let's just duke that out directly.
High-level language fans have a point, which is that high-level languages are sometimes an better overall "bang for the buck" in developer time, and that sometimes they can be pretty fast (possibly even out-performing an un-optimized C program). Reasonable C guys aren't arguing against this. We're certainly not arguing that people should use C for everything.
But here's what high-level language fans have to understand. First of all, you depend on us. Your language runtime is (very likely) implemented in our language (possibly with a little assembly thrown in). So as much as you may like your language, it certainly does not obsolete C. C guys like me get cranky when high-level language fans imply that it does.
Second of all, a C+ASM approach will always win eventually, given enough time invested. That is because a C+ASM programmer has at his/her disposal literally every possible optimization technique that is implementable on that CPU, with no language-imposed overhead. What this means is that a higher-level language being "faster than C" is just a local maximum; the global maximum is that C is faster.
Yes, it's absolutely true that in limited development timeframes a higher-level language might still be the right choice, and in rare cases might even have better performance. But for long-term projects that want the absolute best performance, C (or C++) are still the only choice. (But maybe Rust someday).
- raverbashing 14y ago"Second of all, a C+ASM approach will always win eventually, given enough time invested. That is because a C+ASM programmer has at his/her disposal literally every possible optimization technique that is implementable on that CPU, with no language-imposed overhead. What this means is that a higher-level language being "faster than C" is just a local maximum; the global maximum is that C is faster." Exactly The C program presented is very naive. getc? ungetc? malloc inside a loop? For example, I can create a table to convert 4 characters at once instead of only one. Just as a start. Doable in haskell sure, but it would most likely not use the resources of modern processors (SSE2, AVX, etc)
- iheartc 14y agoThank you.
- ChuckMcM 14y agoI wish I could up vote this 10x. When folks were saying "Oh with HotSpotUltimateOptoMix III Java is going to be faster than C code!" or whatever the optimizer de-jour was I would sigh. We have very much reached a stage where there are computers which can dedicate way more cycles to your effort than you need to get it done in time, we can spend this "surplus" on making writing code easier, and that is a huge win. Enjoy it. Don't worry that someone could craft it in C+Asm and give the idle loop more cycles to play with, it doesn't need them.
- jacquesm 14y agoUnless of course the idle loop isn't idle. Since the end of the assembler era there has always been a trade-off: programmer time vs processor time. And programmer time is about as expensive as it was in the past, cycles have gotten cheaper and cheaper. But the cost of a cycle still isn't 0, and likely it will never be. Optimizing a chunk of code and making it perform 10 times as fast can be a huge competitive advantage when you're operating a sizeable cluster that is really working instead of idling. For one-offs and incidental use optimization of any kind is nonsense.
- ChuckMcM 14y agoI don't think we disagree. I assert both things are true: 1) There are situations in which extracting the most work out of a given compute infrastructure is the best use of ones time and effort. 2) There are situations in which optimization will only lead to additional free cycles which will go unused thus investment in such optimizations is a waste of time.
- tikhonj 14y agoJust as you're not arguing to use C for everything, people liking high-level languages aren't arguing you should never use C (or, at the very least, a similarly low-level language). Rather, the point is that using C is very often a premature optimization. It also comes with a sacrifice in terms of productivity, maintainability, safety, testability and readability. So you should certainly use C. Sometimes. And the question to ask is always: "why C?" and never "why not C?". Also, you can get quite far by doing something like generating C from a DSL embedded in OCaml or Haskell, giving you both powerful type-level features and many of the advantages of a high-level language without sacrificing low-level control of C. You could use something like CIL[1] to avoid many of C's usual pitfalls. I haven't tried this myself, but I know some people happy with that approach. [1]: http://www.cs.berkeley.edu/~necula/cil/index.html http://www.cs.berkeley.edu/~necula/cil/index.html
- haberman 14y ago> people liking high-level languages aren't arguing you should never use C Some do; the most frustrating such conversation I can remember with such a person was this: http://news.ycombinator.com/item?id=2537155 http://news.ycombinator.com/item?id=2537155 This person argued that the only way to make progress in systems programming is to ditch C as the basis of the system and linking model, in favor of something more constrained. That's the kind of talk that gets me cranky. It's precisely because C and assembly are so unconstrained that such a wide variety of programming paradigms can all be implemented efficiently and run under a single OS, and that we can so easily experiment with brand new paradigms without having to get buy-in from the VM gatekeepers.
- mpyne 14y agoActually pointers are a sore spot. Of course we have `restrict` in C (and not C++, for some strange reason) but it leaks elsewhere too, like qsort. Of course your main point still holds (you could write macros that implement your container without void* everywhere) but I feel those are the issues where a HLL is most likely to outperform a naïve C implementation (since it would take gyrations to most efficiently implement the same in C).
- dustingetz 14y agoEdit: iPhone posted to root, meant in reply to top voted comment sry! don't think that's the underlying point at all. A functional Language gives the compiler more room to optimize - the compiler has more information because a functional language let's the programmer express constraints in ways imperative languages can't - the compiler fundamentally knows more and thus can generate better machine code. The productivity benefits of HLLs are secondary to this discussion.
- jhuni 14y agoC is itself a HLL, e.g it uses a high level state model based upon mutable variables rather then direct manipulations of processor registers and hardware memory locations.
- Xurinos 14y agoI guess I will be your essay-writing dissenter. C is a high-level language with fewer features than many other languages, is not necessarily the engine behind other languages, has the problem of its programs poorly implementing a percentage of what other high level languages are capable of doing quickly and securely, and provides slow and troublesome memory allocation out-of-the-box. When comparing the speed of operations, people are rarely comparing apples to apples. And contrary to what is spattered on the boards, C is not an understandable, close-to-the-metal wrapper around assembly instructions (compilers have advanced quite a bit). I love C. It does feel fast, and I get the illusion of being close to the metal. It was one of my first languages, holding a sentimental place in my heart. Very important things are written in it. It is a high-level language with some okay abstractions. Is it underneath other high level languages? Maybe, if you mean that the compiler might be written in C in order to bootstrap the language. Of course, one could write the compiler in any language; it's all about translating programmer-friendly symbols into assembly or VM bytecode, right? And speed of compile is a different subject from speed of the compiled program. But here is the gotcha on raw performance: Your large C program poorly implements a percentage of what other high level languages are capable of doing quickly and securely. I once foolishly argued in favor of C's performance, saying that one could write a layer that supports all these nice features speedily, such as the data structures I will mention below as well as GC; by the time you do that, you might as well be using a different language. You probably implemented that layer poorly, compared to other languages with large communities pounding at and optimizing that layer. For example, when you implemented your "fast" list with the basic struct and next pointer, did you also implement the new-node creation in such a way as it still uses raw malloc(), as opposed to managing previously-malloced memory efficiently? How many implementations of a basic list do we need in C? Super large integers? Fixed-point integers? Growable arrays? Lazy/infinite lists? Trees? Hash maps? Surely you don't think these other language designers said to themselves, "Let's support hash maps and make them slow." No, they came up with a fast standard, supported by their language, sometimes complete with various configuration options to make all the tradeoff decisions on making those data structures speed-efficient or memory-efficient for reads or writes. Others, of course, subscribe to a religion, er, a specific tradeoff, such as perl's approach to {}s ("There's more than one way to do it" ... unless you are dealing with hash tables). What about all the wonderful memory management you can do in C? Aren't you closer to the metal that way, able to make basic memory allocation super speedy? Not really. This is part of the illusion. malloc() is slow enough that developers have rewritten versions of it several times. ROM-based MUDs, for example, manage their own memory, using an initial malloc, of course, but regularly using their own set of allocators and deallocators (free_string, str_dup, etc) on top of that allocation. There are these tricks and more in high level languages, including the sharing of partial structures (kinda like union but with more pointers and fewer bugs associated with those pointers), allowing for resource allocation strategies that can be "faster than C". If the argument in favor of C's speed at the end of the day is, "When we write crappy programs with buffer overrun holes, memory leaks, and no error handling, it's super fast!", we are (1) not comparing apples to apples and (2) doing ourselves and our customers a grave disservice. Let's be honest: C is no "closer to the metal" than other high level languages (http://news.ycombinator.com/item?id=3753530 http://news.ycombinator.com/item?id=3753530 and https://en.wikipedia.org/wiki/Low-level_programming_language#Relative%20meaning https://en.wikipedia.org/wiki/Low-level_programming_language...). The days of manually XORing to assign 0 to a variable are well behind us. Note... I don't mean all high-level languages. There are many very slow implementations of these languages. Programmers are getting better at this stuff in modern implementations, gcc included. And it is fair to say that there are many things other languages can do that are, when you compare apples to apples, faster than C, especially when you factor in modern JIT compilation; and they also do some things slower than a similar function in C. No, C isn't and won't be obsolete, not until people write popular OSes in other human-readable languages, complete with a body of excellent libraries. We operate in a world of legacy, working code. Edit: Looks like we both must have not read the article before replying. The author goes over many of these points.
- Snoptic 14y agoWhere possible, GHC does not compile Haskell via C anymore.