20 ms·
When Haskell Is Not faster than C
- nicholassmith 14y agoNice refutation. The problem about doing language comparisons for speed is that they generally require a non-trivial example, so you have to be an excellent programmer in all the languages you've compared. Of course, language speed charts are generally as useful as PC spec charts and YouTube videos of Nürburgring laptimes when you're buying a new car.
- chii 14y agowell, what about an existing piece of software, and compare on more than just speed, but ease of maintenance (meaning, how quickly you can add features or fix a bug)? There seems to be a myriad of window managers and web frameworks. Someone should do an unbiased comparison.
- nicholassmith 14y agoSame thing again, it depends entirely on really specific domain logic. How easy it is to add a new feature on a C based web browser versus one built on Haskell is mostly useless, it just tells you how quickly one person added one feature on one specific thing. Languages aren't inherently comparable, you can get useful benchmarks but they shouldn't be taken as gospel.
- nathell 14y agoYawn. It is not possible to directly compare languages wrt speed: we only can compare the speed of their implementations and reason about the features that make a language amenable to optimizations. And we all know this. So why, despite this knowledge, do we engage in "language speed flamewars" like this? That's a valid question, and it belongs in the field of psychology of hackerhood. Does anyone have a reply to wager?
- jacquesm 14y ago> So why, despite this knowledge, do we engage in "language speed flamewars" like this? That was exactly the point. The reason why this happens is because people are - just like me - invested in their tools, they want to tell themselves they made the right choice. And then they want to tell the world the same thing. For me it doesn't matter which language is faster in a project. The parameter space that decides which language is 'right' is rarely determined by raw speed. But for those cases where raw speed is the determining factor you could do a lot worse than using C, and if you have latency requirements it is almost unavoidable on most ordinary platforms that we use.
- zxcdw 14y agoI for one find things like these extremely interesting. The more there's analysis about performance implications of certain ways of doing the task the better. The only thing I'm left missing here is to actually look into the profiling information(branches, caches, instructions per cycle etc.), especially on the compiler generated assembly to see what exact instruction sequences are to blame, and if there are ways to save cycles here or there. If only there were more things like this in the internets with deep analysis about performance of a given piece of code... :)
- jacquesm 14y agoIt was pretty long as it was... Tacking on a code generation section to show why certain things are inefficient (and the associated detour to how the standard library is implemented which would be required reading to understand all the implications) would make the article three times as long. I promised I'd have it done by Monday.
- davidw 14y ago> So why, despite this knowledge, do we engage in "language speed flamewars" like this? Because here in the real world, speed sometimes matters? And many languages are fairly closely associated with given implementations that live in the real world, and are more or less fast. These days, I mostly write Ruby because time to market is more important than having code run fast, but in its current form, it's generally a slower language than C. There, I said it! Yes, of course I really mean implementation, but realistically, there are no Ruby implementations that are faster than compiled C code.
- VeejayRampay 14y agoI still wonder to this day why Haskell programmers want their language to be loved so much. At times it feels like that kid at the playground that spends half his time telling everyone how he's the best thing since sliced bread and cries himself to sleep at night wondering why no one will play with him and his monads. Don't get me wrong, Haskell looks like a great language with obvious qualities and I don't knock anyone for using it, to each his own, it's just the never ending publicity and proselytism that really rubs me wrong. People adopt new languages, not the other way around.
- friendly_chap 14y ago> wondering why no one will play with him That's kind of a strong statement about a language which has approx. 1000 users in it's IRC chatroom.
- VeejayRampay 14y agoThe number of people present in the IRC channel is more of a sign that they have a very engaged and active community, which is a good sign for the language itself, for sure, but doesn't necessarily correlate to the general adoption of Haskell as a whole. A measure like http://www.tiobe.com/index.php/content/paperinfo/tpci/index.html http://www.tiobe.com/index.php/content/paperinfo/tpci/index.... (by no means a perfect one, quite like speed benchmarks ironically) seems to indicate that Haskell still has a long way to go before reaching "mainstream adoption". But you're right about that statement, it was intended more as a humorous jab than a statement of absolute truth :)
- sixbrx 14y agoI don't think Haskellers particularly want mainstream adoption. Adoption among library writers would suffice... :)
- Swizec 14y agoTwo things I love about Haskell. 1. It is very terse/expressive. I can look at code I haven't touched in 6 months and still understand what it's doing. Perhaps because my code is newbie code and thus somewhat simple. 2. It is the only language that brings me back to the days of Turbo Pascal when the joy of coding came from coding itself, not from building cool things. A small but vital distinction. That said, I rarely get to use Haskell. For most of my tasks javascript is better suited, but haskell has affected how I write javascript to a great extent.
- benbataille 14y agoCould everyone on HN just take a course in languages theory so we can all stop with these stupid trolls about the best languages which have been emerging for a week. Hopefully it would allow everyone to realize that a language is just some syntax and semantic and that a compiler is just a program like another. Nothing sacred here. Hell you can even do imperative programming in Haskell if you wish. Coding an interpreter to do so is not particularly difficult. With a bit of luck, everyone would understand at the same time that the compiler is building what is executed therefore the expression"speed of a language" is utter nonsense. You can only speak of the speed of the implementation which, yes, vary widely amongst compilers for the same language. So, yes, Haskell semantics encourage functional programming, C semantics imperative programming, both are Turing complete and yes GCC is currently better at optimising C code than any Haskell compiler, nothing new under the sun. Can we all go back to a normal activity now ?
- seanmcdirmid 14y agoI'm trying to translate what you are saying. All languages are Turing complete, so it doesn't matter? Do you program in assembly language then? I mean, if it doesn't matter....
- benbataille 14y ago> All languages are Turing complete, so it doesn't matter? Precisely. The whole "my language is better" argument is completely void. Syntax is mostly a matter of preference. Semantic will make the structure of your program different but in the end there is no actual difference on what you can do only on how you will do it. Once again it mostly boils down to preference. If you really need to argue about something go for my compiler/optimisation pass is better that at least does make sense. Note that there is no theoretical bound preventing an Haskell compiler to generate code equally fast than the one of a C compiler for any program. > Do you program in assembly language then? I did when I had to (quite a long time ago). While languages don't matter, compilers do when you need efficiency. While enjoying ML-based languages more, I also did some C. As I stated before, C compilers are better. Well, I even used my own little syntax-extension of C for a moment (if you don't have to share the code, you can do whatever you want with it).
- simias 14y agoThis reminds me that when I was interested in learning haskell I was completely put off by their "introduction" page on their homepage. It was a couple of years ago but it doesn't seem to have changed much: http://www.haskell.org/haskellwiki/Introduction http://www.haskell.org/haskellwiki/Introduction It looks like a very pretentious sales pitch to me. You have quotes like "Writing large software systems that work is difficult and expensive. [...] Functional programming languages, such as Haskell, can make it easier and cheaper." and a whole bunch of very vague and poorly backed up assertions. After a couple of paragraphs brainwashing you about how good functional programming is, you finally get to some code. The first code you get is (of all things) a quicksort which is not used as an introduction to the language but as a way to boast that haskell is so much better and more expressive than C. I mean, look at that C code just after it, disgusting isn't it. What they don't say is how much slower their implementation is, of course. They also give a link to a more direct (and faster) C-to-haskell version of the quicksort[1]. Hey, it's actually longer than the C version! And it uses 3 imports. And it's still slower than the original C. Oops. I wonder why they didn't put that one in the tutorial. I went back to common lisp after that, I have yet to write 1 line of haskell. TL;DR: when I want an introduction to your language, I want to know what I can do with it and how I can do it. Give me some code to chew on, show off some features. Don't spend 10 pages telling me you're the best of the best and everything else is crap. This is the kind of article I expect: http://perldoc.perl.org/perlintro.html http://perldoc.perl.org/perlintro.html [1] http://www.haskell.org/haskellwiki/Introduction/Direct_Translation http://www.haskell.org/haskellwiki/Introduction/Direct_Trans...
- amirmc 14y agoCurious to know what you think of http://ocaml.org http://ocaml.org, specifically the code example on the front page and the further examples it links to (http://ocaml.org/taste.html http://ocaml.org/taste.html)
- rtpg 14y agoFunny, I've never seen that page, I always land on Inria's page(http://caml.inria.fr/ http://caml.inria.fr/).
- sharpneli 14y agoI ran into similar issue few years ago where lack of knowledge combined with large amount of fanboyism clouded someones mind. In a popular language comparisons site there was a threading benchmark. It was simple, just start 256 threads. Haskell beat C by far. I did strace. The C benchmark actually spawned 256 threads and the Haskell one spawned 4. The response I got was that it's a builtin feature in Haskell that it uses lightweight threads internally. And because pthread doesn't do that you cannot do it in C and therefore the comparison is valid. Even though C doesn't have the concept of threading and everything must be done with an external library in anycase. I could dig the old thread up but I've given up with those. I have nothing against high level languages, I use them a lot. However I find it very weird that some true fans feel the need of creating enormously biased benchmarks and then being proud that those benchmarks show that their favourite language is the best.
- Peaker 14y agoYou could use green threads in C but you'd also need asynchronous io to work with these green threads, and an ecosystem of libraries around it. Ghc has it therefore it makes sense to use its by default green threads. In c there is no standard ecosystem around green threads therefore it is harder to write the benchmarks that way.
- sparkie 14y agoThis misses the point on why green threads are, and can be the default behavior in Haskell. It's because the purity allows it to be. Sure you can make "green threads" in C, but you as the programmer must be very careful how you use these threads. You can't go accessing some global state (or performing many different side-effects) from them freely - so you must design your code to be as "purely functional" as possible to make any sense of them. The problem is when you come to use somebody elses code - how do you know it doesn't cause side-effects, if say, you only have the object and header files? You don't, so at best you could "trial and error" until you find out that they're safe enough to use in green threads, but some bug might come back to bite you in the long run. Haskell prevents this from ever being the case, because any function which does have side-effects must clearly express the fact in it's type signature. A green thread API can therefore specify the limitations on side-effects that may occur in it.
- bborud 14y agoIf Haskell, Lisp and friends are so great for building large software systems then surely people are going to flock to them and do exactly that. And if that didn't happen, of course the proponents of these languages would sit down and try to figure out why this wasn't happening. Right?
- zxcdw 14y agoNot necessarily. Other languages will borrow ideas from these languages and that way many strengths of functional programming can be applied in everyday code. I don't think there are many people who would outright claim that functional programming doesn't have benefits at all which could be used in imperative languages too.
- Peaker 14y agoHaskellers are aware of various downsides and disadvantages to using Haskell and are actively working to improve on those. Also, the FP complete company was created to answer that exact question and cater to commercial companies who want to use Haskell. They provide training, and survey them to see what is holding them back from using Haskell, and providing them with solutions.
- wereHamster 14y agoEducation is a big part of the problem. When I attended university, we weren't even told that functional programming exists. Only later on, through one of my friends it was brought to my attention. And it's hard to change that mindset, particularly at the university I was. They are set to produce a constant stream of Java/.NET developers for the companies around them (large banks, in particular).
- PommeDeTerre 14y agoWhich university was this, and which program?
- wereHamster 14y agoThe university in Lucerne, Switzerland. Hence the reference to large banks ;)
- waxjar 14y agoI'd love to be able to reason like that about the program I'm writing. Really cool article.
- dschiptsov 14y agoPerfection is achieved not when there is nothing more to add, but when there is nothing more to remove.) When one programs a computer (in a way it suggested in TAOCP) and you know your data, your memory layout and your CPU instruction set nothing could beat it. Of course, there are tasks so massive, that a decent compiler could save lots and lots of man hours, but it is a completely different story. No Haskell (leave alone J* ) could beat a code by people who know what they do close to the metal. In some languages the code could be shorter much more readable and elegant that C, but of course, it is not Haskell, or J* . Thoughtfully crafted Common Lisp could be close to an ideal.)
- pohl 14y agoLisp's homoiconicity comes with the cost of some extra syntactic weight that Haskell doesn't have to bear. (It's also nice that "lambda" is considered so important that it's given a single character in Haskell). I'm not familiar with J*, and it seems to be difficult to search for. Do you have a reference so I can go learn about it? http://rosettacode.org/wiki/Sorting_algorithms/Quicksort#Haskell http://rosettacode.org/wiki/Sorting_algorithms/Quicksort#Has... http://rosettacode.org/wiki/Sorting_algorithms/Quicksort#Common_Lisp http://rosettacode.org/wiki/Sorting_algorithms/Quicksort#Com...
- dschiptsov 14y agoI prefer Erlang. http://rosettacode.org/wiki/Sorting_algorithms/Quicksort#Erlang http://rosettacode.org/wiki/Sorting_algorithms/Quicksort#Erl... And your illustration is particularly good for showing how much more "sane" (actually, in many ways) Erlang is. And how elegantly different Python could be. J* is my own abbreviation for Java and Javascript.)
- pohl 14y agoI prefer Erlang. Just out of curiosity, why is that? (With reference to the linked example, I mean.) Clearly they're in the same league, and so it's a close call. From my perspective, I like that Haskell reserved the single vertical bar for the list comprehension notation, so that it would be as close to familiar set-comprehension notation as possible. I also like how Haskell takes advantage of how the cons operator already implies in the pattern-matching that you're working with a list, and so the square brackets become unnecessary, whereas Erlang needs the noisy extra layer of brackets on top of the parenthesis needed for the pattern. But once languages get this elegant, it's a close comparison. They're both beautiful to my eyes.
- spookylukey 14y agoThis article starts by totally misrepresenting the original article (http://paulspontifications.blogspot.co.uk/2013/01/when-haskell-is-faster-than-c.html http://paulspontifications.blogspot.co.uk/2013/01/when-haske...) by saying that it said "Haskell beats out C when it comes to speed". If you bother to read even the TLDR of the original article you 'll find it says something completely different, which makes this article pretty poor as a response.
- jacquesm 14y agoFrom TFA: "So here is the bottom line. If you really need your code to run as fast as possible, and you are planning to spend half your development time doing profiling and optimisation, then go ahead and write it in C because no other language (except possibly Assembler) will give you the level of control you need. But if you aren't planning to do a significant amount of micro-optimisation then you don't need C. Haskell will give you the same performance, or better, and cut your development and maintenance costs by 75 to 90 percent as well." Note the 'same performance or better' in there. Maybe you missed that bit in the original article? This wasn't a large effort by any stretch of the imagination and a factor of 5 difference compared to the Haskell code isn't even in the same ballpark as "the same performance", and about a factor 10 difference with the C code listed in the original article. You'll notice no micro optimizations were done in the re-write, just some global re-arranging of the way data flows through the program. The rest is in response to the misleading title, that Haskell is 'faster' than C, faster to program, faster to debug, easier to maintain and so on while making claims about performance that are not born out by real world comparisons. Speed was the wrong thing to compare on here, and should not have been part of the original article without a serious effort to become equally proficient in both languages.
- spookylukey 14y agoCompared to the amount of optimisation that many people typically do (i.e. zero or close to zero), it was a large amount of extra work to get that performance boost. The global re-arrangements of the way data flows through the code are more difficult than many micro-optimisations, not less, so I don't understand how you can claim. And you don't have to be an expert in C to make the claim he is making, because most people are not experts in C, but might turn to it because "it's faster". It's precisely this kind of person who needs to understand that with their level of knowledge, and the amount of effort that they might put into optimisations, Haskell can be just as good or better.
- confluence 14y agoThe problem with fringe languages has always been the "all talk - no walk" nature they all seem to have. Stop telling me why you are so awesome. Just show me with shipped product. Until then it's just an intellectual circle jerk. Talk less. Ship more.
- wnewman 14y agoThere is truth in this. Certainly shipping more is good. But the situation is somewhat analogous to the perennial debate about commenting code, with "talk" playing the comment role and "ship[ped code]" playing the code role, so that your "talk less ship more" position becomes analogous to the perennial "code should be self-documenting" position. There is truth in that: to an important extent, well-designed code can be "self documenting" and thus speak for itself. Analogously, to an important extent, shipping code can work so well that its demonstrated excellence tells you something about the techniques that it uses, and thus it speaks for itself. However, it's hard to use that kind of speaking-for-itself effect to communicate some abstract issues , such as the issue of why something was done that way. Text explaining "here's why such-and-such [inheritance/functional/macro/declarative/whatever] techniques are important here" can be hard to replace with "look at the code". This problem can be quite severe for languages with extremely unusual paradigms, like the Haskell or Prolog examples that people have mentioned. Beyond that, many important issues only become significant in sizable programs, to the extent that they are imperceptible in examples less than a few pages. (This is not only an issue for language features: books like _Refactoring_ and _Large-Scale C++ Software Design_ are devoted to issues that become important with scale, and would probably be very hard to appreciate for someone who's never constructed or maintained a piece of software that required more than 5 hours of programmer time.) So if you get your mind around an entire application domain and a software system for it which is a good fit to an exotic programming language --- as, e.g., the HOL Light machine-checkable proof assistant seems to be a good fit to OCaml --- then you will very likely learn something about the strengths and weaknesses of the language and its paradigm. But some fraction of people, even perhaps some fraction of HN readers, will treat a software system like HOL Light as "tl;dr", so a 5-minute or 30-minute pitch on how the language fits the problem may be more effective in practice.
- deleted 14y ago
- JoachimSchipper 14y agoThis is cool. However, in the spirit of contributing, comparing one byte at a time is not optimally efficient. It's possible to write clever optimizations by hand, but I'd be surprised if just using https://github.com/rbdixon/glibc/blob/master/string/memchr.c https://github.com/rbdixon/glibc/blob/master/string/memchr.c doesn't cause a meaningful speedup.
- jacquesm 14y agoThe inner loop of those comparisons is indeed the spot where you can still speed up as noted in the last part of the post, the kind of optimizations that you describe are extremely effective but qualify as 'micro optimizations' and I expressly left those out because they impact readability considerably. But, you're right, if that's what it takes then so be it and then readability would have to suffer in deference to the last couple of % of speed. Maximum gain from this optimization relative to the final runtime is about 20% by my estimation. (Inner loop will step 8 bytes at the time, but will have more instructions).
- JoachimSchipper 14y agoI concur that doing this directly in your code is extremely ugly; but note that you can get this speedup by just dropping in a call to glibc's memchr(), hiding the ugliness behind a well-known interface.
- jacquesm 14y agoGood point about memchr, I missed an opportunity there. edit: because it's clearer and faster, that's a no-brainer, updating the blog post with a remark to that effect and a link to parent.
- gnuvince 14y ago> This article is in response to an earlier one comparing Haskell and C, which made the claim that Haskell beats out C when it comes to speed. Perhaps my reading comprehension of the original post is different from Jacques' (or I'm just wrong), but I don't think that the original article made such a claim. Here's the TL;DR of the original article: > TL;DR: Conventional wisdom is wrong. Nothing can beat highly micro-optimised C, but real everyday C code is not like that, and is often several times slower than the micro-optimised version would be. Meanwhile the high level of Haskell means that the compiler has lots of scope for doing micro-optimisation of its own. As a result it is quite common for everyday Haskell code to run faster than everyday C. Not always, of course, but enough to make the speed difference moot unless you actually plan on doing lots of micro-optimisation. From this, I understood that in a larger program, most programmers wouldn't be doing the kind of micro-optimizations that they do for the Benchmarks Game. I figure that most code would be written following this pattern: * Write code to follow the spec (usually without thinking too much about performance) * Run the code, and evaluate its performance * If the performance is good enough, you're done * If the performance needs to be better, run a profiler * Find the biggest bottleneck and optimize it * Re-run the code and re-evaluate its performance The original article took a micro-benchmark (a mistake in my opinion, because it's easy to micro-optimize every single detail of that code) and showed that in the case of Haskell, the first version was too slow, but that with the help of a profiler, finding the cause was easy, and the fix was trivial, while in C the profiler didn't show any problem with the code of the user, so it must be a problem in the standard library's code, and to fix it required changing the design of the program and making it more different than the spec. And I felt this was the author's real point; that to get the maximum performance from a C program, you'll need to code it not like a human would imagine it, but like a computer would, and it makes the code harder to maintain later on.
- jacquesm 14y ago> Perhaps my reading comprehension of the original post is different from Jacques' (or I'm just wrong), but I don't think that the original article made such a claim. Here's the TL;DR of the original article: The TL;DR is not representative of the whole article. It would be nice if it were but it isn't, so just reading the TL;DR is not enough, better do the short-enough;did-read version of that. Another commenter in this thread said more or less the same thing, I've responded to him here: http://news.ycombinator.com/item?id=5091270 http://news.ycombinator.com/item?id=5091270
- mistercow 14y agoThe original article did mention that switching to use lines instead of characters would probably speed things up considerably, but argued that this makes the program harder to understand, while Haskell makes the same optimizations automatically on the character-based program. And that's a fine point to make, but I do think it was a little misleading and handwavy. The proper thing to do would be to make the change and show the difference both in code and performance, and let the readers draw their own conclusions.
- jacquesm 14y agoThe 'line reader' version of the code (not shown in the article) was actually a lot easier to read than either one of these but the article was already over long. I do have that version, if anybody is interested I can add it.
- ibotty 14y agoi'm sure you have all your intermediate steps as well. i really liked an example i've seen a while ago that described an optimization process in git history. you'd simply check out the right step and have a look for yourself.
- JabavuAdams 14y agoExcellent. Documenting successive transformations on code is much more instructive than showing a final snapshot. This is one reason I really enjoyed doing live-coding when teaching programming.
- JabavuAdams 14y agoThis is a classic pattern: when advocating for one of several competing approaches, you spend more care optimizing your favourite approach than the competitors. Prof. Geoffrey Hinton specifically calls this out as a pitfall in research. It's better to compare your promising new approach versus another group's approach (not your own implementation thereof). This, assuming that the other group has deep knowledge in tuning their competing approach.
- jacquesm 14y agoI think it's only human. The standard should be that you present your case for your 'favorite' and then put out an open challenge to supporters of the opposition to do their worst.
- rtkwe 14y agoIf you're going to do a response blog post link to the original article at the beginning when you mention the original. I read the original but don't assume everyone has.
- dllthomas 14y ago"Third, a comparison on speed between Haskell and C is almost meaningless, speed is not Haskells strongest point and it would be folly to bench it against C for that particular reason." I disagree wholeheartedly. If I am choosing Haskell over C, I am giving up some (possibility of) performance. The question of how much is an important piece of information, entirely relevant to that decision. As I observed in a comment on that other post, the actual performance of both the Haskell and the C depends on the amount of effort expended to make them faster (first in general, and then possibly on a particular architecture). At the limit, the C beats the Haskell by some margin - the size of that margin is informative; but that's also not the whole story - what the margin is earlier also matters, and for a particular project, it might matter more. This is not to say that the particular benchmarks in the earlier article were good choices - I don't have a clear position on that.
- deleted 14y ago[deleted]
- sunwooz 14y agoWhat do you guys think I should learn next? I've been studying javascript/ruby and I would like to diversify what I can make. I don't want to rush learning new languages, but it's interesting to learn about paradigms that certain languages enforce. What's important to me(not in order): 1) Being an omni-platform developer 2) I only know two high-level languages, so learning a low level language will benefit me. 3) I want to get into Natural Language Processing and deep neural networks/AI, machine learning etc. 4) I'm a self-taught programmer, so the amount of good resources online/amazon is a big factor. 5) I need a fucking job. 6) I like making web applications/web games, and I would like to make native applications/games as well.
- deleted 14y ago[deleted]
- deleted 14y ago[deleted]
- ColinWright 14y agoJust a quick point. He quotes me: You can't make a computer do stuff faster, but you can make it do less work. That's not original to me, but I don't have (and haven't been able to find) a good, definitive, original source.
- neopallium 14y agoThere is a bug that causes invalid output when the input file is larger then the BLOCKLEN. Set BLOCKLEN to 4096 and run the program on the test input file [1] (compare with output file [2]), to see the problem on a smaller input file. The bug happens when read_sequence() is called with partial data saved from the last sequence, since (size == read) the first fread() will be asked for 0 bytes which causes the read loop to end early (n == 0). 1. http://benchmarksgame.alioth.debian.org/u32/iofile.php?test=revcomp&file=input http://benchmarksgame.alioth.debian.org/u32/iofile.php?test=... 2. http://benchmarksgame.alioth.debian.org/u32/iofile.php?test=revcomp&file=output http://benchmarksgame.alioth.debian.org/u32/iofile.php?test=...
- jacquesm 14y agoThat was a good catch! Serves me right for testing with the small file for correctness and testing for speed with the larger one.
- Zircom 14y agoIs there a reason "Is" and "Not" are capitalized but "faster" and "than" aren't, because it's just been bugging all day whenever I refresh the front page and look over the list for anything interesting.