Don Stewart

donsbot.wordpress.com · Personal blog · on HN since 2009

Don Stewart writes about Haskell performance, GHC's LLVM backend, stream fusion, and functional programming in practice.

What HN saysHN links it for the posts on making Haskell as fast as C and evolving faster programs through compiler optimization flags.
40HN people shared it
30linked it in comments
48stories submitted
933story points
6 years agolast shared
2009people per year2026

Most-shared posts

  1. 1
  2. 2
    Reviving the Gofer Standard Prelude (2009)
    4 people · 9 points · first shared 2009 · discussion on HN
  3. 3
    Smoking fast Haskell code using GHC's new LLVM codegen
    3 people · 63 points · first shared 2010 · 19 comments on HN
  4. 4
    Evolving Faster Haskell Programs (now with LLVM)
    3 people · 63 points · first shared 2010 · 4 comments on HN
  5. 5
    Fusion makes functional programming fun
    3 people · 37 points · first shared 2010 · 41 comments on HN
  6. 6
    Back to old tricks, or, baby steps in Rust
    2 people · 173 points · first shared 2020 · 54 comments on HN
  7. 7
  8. 8
    Multicore Programming in Haskell Now
    2 people · 58 points · first shared 2009 · 24 comments on HN
  9. 9
  10. 10
    Very fast, scalable mutable maps and hashes for Haskell
    2 people · 31 points · first shared 2009 · 27 comments on HN
  11. 11
    Practical Haskell: Scripting With Types
    2 people · 8 points · first shared 2010 · 2 comments on HN
  12. 12
    Evolving faster Haskell programs
    2 people · 5 points · first shared 2009 · discussion on HN
  13. 13
    Visualising the Haskell Universe
    2 people · 4 points · first shared 2009 · discussion on HN
  14. 14
    Haskell Package Popularity Rankings : August 2009
    2 people · 3 points · first shared 2009 · discussion on HN
  15. 15

What HN people wrote when they linked it

dbaupp · 2012-06-21
Reddit is very large: there are almost certainly subreddits for that sort of stuff. As an example, /r/Haskell[1] is fairly technical (it is frequented by people such as dons[2] and gwern[3], and presumably they would've moved on from r/haskell if it became overly banal). (Also, a brief googling turns up /r/startups[4], but I've got no idea of its standard of discourse.) [1]: http://www.reddit.com/r/haskell [2]: http://donsbot.wordpress.com/ [3]: http://www.gwern.net/ [3]: http://www.reddit.com/r/startups
pohl · 2010-10-30
It looks like LLVM does have a stack protector pass: https://llvm.org/svn/llvm-project/cfe/tags/Apple/clang-54.1/clang/lib/… As for non-default optimizations, this passage from the following article best explains how much there is for you to explore: Which LLVM passes to use, and which order to run them, with what analysis in between, is a huge search problem, though. There are roughly 200 optimization and analysis flags, and these, mostly, can be run in any order, any number of times. If we want to run say, twenty of the passes (about what -O3 does), that’s what, about 10^46 arrangements! http://donsbot.wordpress.com/2010/03/01/evolving-faster-haskell-progra…
jmillikin · 2010-03-03
If you need to do any sort of benchmarking for Haskell libraries, I can't recommend Criterion (and Neil Brown's package Progression[1]) enough. It handles all the details for lazy evaluation (NF vs WHNF, pure vs IO, etc) quietly behind the scenes, and uses a well-designed statistics analysis library to calculate the final numbers. Don Stewart has written a short introduction, Modern Benchmarking in Haskell[2]. It's worth mentioning that Criterion can be used for anything that can be called via the FFI -- I'm using it for benchmarking Python libraries, for example. [1] http://hackage.haskell.org/package/progression [2] http://donsbot.wordpress.com/2010/02/23/modern-benchmarking-in-haskell…
jongraehl · 2009-07-03
I first saw this suggested at http://donsbot.wordpress.com/2009/03/09/evolving-faster-haskell-progra… - he references prior work (see "best paper" in bold) by http://www.cis.udel.edu/~cavazos/index.php?page=publications The ctuning site has a timeline that extends many years back, so I'm not suggesting it's "me too" material. In (lossy) heuristic search, it's common to automatically tune a handful of parameters (with difficult to predict outcome that may depend on the specific data set) to find a good setting for a given valuation of time spent vs. search error.
delhanty · 2017-06-14
> .. you can write vastly more complicated programs that are, say, 80% as fast as hand-optimized C for only 10% of the effort of hand-optimized C. Computer Language Benchmarks of GHC versus C don't seem to be close to matching your 80% as fast claim [1]. Also, the 10% of the effort of hand-optimized C bit - seem to recall there was a caveat - "if you happen to Don Stewart" [2]. The following is just my vague, uninformed impression, but Haskell and Go seem to be opposite ends of a spectrum, with Rust somewhere in between: Haskell: good for expert individuals and small teams. The language is highly sophisticated and the compiler is rather slow. At heart, it's a research language, so the direction might not always suit production use. If you contract out to a Haskell development shop, who do you turn to with your Haskell code-base if things don't work out? Go: designed by Google for their use-case - large teams of commodity programmers. It's very quick to onboard programmers - they can be productive and non-dangerous quickly. The language is very simple and the compiler is very quick - which is again good for scaling large teams. [1] https://benchmarksgame.alioth.debian.org/u64q/compare.php?lang=ghc&… [2] https://donsbot.wordpress.com/2008/05/06/write-haskell-as-fast-as-c-ex…
jgg · 2014-05-11
The pretentious view that Haskell's core is a mathematical structure familiar to mathematicians is wrong. Haskell borrows concepts from category theory (a "field" so abstract from most math that most mathematicians don't need but a handful of its concepts) to label typeclasses, and those typeclasses don't always follow from their namesake. Further, Haskell could exist and keep its property of referential transparency without the the 'mathematical' structures or their names. Here's a version of Haskell without monads: http://donsbot.wordpress.com/2009/01/31/reviving-the-gofer-standard-pr… Monads, functors, arrows, etc. are more aesthetic than fundamental to the core nature of Haskell. They're just a bookish (and sometimes bureaucratic, IMO) design choice. What I mean by that, is that the language designers took a concept (referential transparency) and built an understandable structure, but beside and aside from this, made a bunch of nested, derived typeclasses of dubious value or purpose. Sometimes I look at a Haskell library and have a more academic version of the, "Why the fuck is this a class?" moment. I'd like to comment tangentially that Haskell is almost the OOP/Java of the 2010's - the programming community claims that it makes your code "safer", and in some sense it very much does, but its features are being perverted and overhyped while its caveats are being forgotten.
jfoutz · 2012-01-20
Argument from authority is not much of an argument, but dons is intensely focused on ghc performance, here's an easy to google example. http://donsbot.wordpress.com/2010/02/21/smoking-fast-haskell-code-usin… It's not to hard for you to go get benchmark numbers in haskell, check out http://www.serpentine.com/blog/2009/09/29/criterion-a-new-benchmarking… or read about how snap does its benchmarking. As for erlang, there's a lot of papers about reliability. I'm not saying the performance isn't there, it's just not a focus of the erlang community. You'll have a much tougher time figuring out instruction counts for a given function in erlang. Given that erlang is interpreted, without a major focus on performance, it seems unlikely erlang would be quicker. This is just - what i perceive as - the general consensus. I'd love for you to generate some numbers to prove me wrong.
ecyrb · 2011-05-08
Somewhat related, Don's site: http://donsbot.wordpress.com/
nilkn · 2020-07-11
Well, of course. Rust is not designed around immutable data structures. There are going to be differences because it's simply not the same language. This [0] example, written by a notable Haskeller, illustrates what I mean pretty well and also touches on what you just pointed out. It's also very consistent with my own experience. [0]: https://donsbot.wordpress.com/2020/07/04/back-to-old-tricks-or-baby-st…
lallysingh · 2016-12-02
https://donsbot.wordpress.com/2007/11/29/use-those-extra-cores-and-bea… This was a simple fib(), not a map(), but I think the point still stands pretty well.
harpocrates · 2016-12-01
Another thing to keep in mind is that with everything being immutable you end up with a pure language. Once that happens, the compiler starts being able to perform some really nice rewrites of your code really easily. The problem is that this is all or nothing - unless your language is actually pure you can't do this. See this blog post for more <https://donsbot.wordpress.com/2008/06/04/haskell-as-fast-as-c-working-…
eru · 2016-07-25
XMonad comes with quite a few QuickCheck properties. See https://donsbot.wordpress.com/2007/05/17/roll-your-own-window-manager-… and https://donsbot.wordpress.com/2007/05/01/roll-your-own-window-manager-… for some readable introduction. One might consider proving the properties instead of just checking them with a few thousand random examples.
boothead · 2016-02-04
I was talking about banks. I work for one where we build stuff on top of essentially this paper: http://research.microsoft.com/en-us/um/people/simonpj/Papers/financial… We're even hiring: https://donsbot.wordpress.com/2016/01/18/haskell-developer-roles-at-st…
hepta · 2015-10-23
Stream fusion (in Haskell) is the removal of intermediate lists created when you chain multiple list functions (map, filter, fold, etc). https://donsbot.wordpress.com/2008/06/04/haskell-as-fast-as-c-working-…
windlep · 2015-04-26
I meant more that languages with an iterator/generator usually have similar constant space usage. That is a drastic oversimplification of stream fusion and fails to mention other practical outcomes as you mention, along with a variety of optimizations. I found this posting a little more approachable to seeing the various optimizations possible with stream fusion: https://donsbot.wordpress.com/2008/06/04/haskell-as-fast-as-c-working-…
wetmore · 2015-04-25
The bank Standard Chartered[1] uses it, and instead of GHC they use their own compiler. There's some more info in this job posting[2]. [1] http://en.wikipedia.org/wiki/Standard_Chartered [2] https://donsbot.wordpress.com/2014/08/17/haskell-development-job-at-st…
jefffoster · 2010-12-12
Acovea (http://www.coyotegulch.com/products/acovea/) is a genetic algorithm for analysing the performance of code with various optimization flags. There's a practical example of this being used on a Haskell program at http://donsbot.wordpress.com/2010/03/01/evolving-faster-haskell-progra…
plesn · 2010-08-18
This is the original dons' blog post (easier to read on the web than slides) : http://donsbot.wordpress.com/2007/03/10/practical-haskell-shell-script… An interesting read !
mbrubeck · 2009-08-09
There's a pretty big collection of games (of varying maturity and complexity) at the Haskell Wiki, including a couple of tetrises [1]. One of them, Frag [2], is a pretty cool 3D first-person shooter. It's one of the most popular current downloads from Hackage [3]. The source code [4] is well-factored and uses functional reactive programming (FRP) to model time and user input/output. 1. http://www.haskell.org/haskellwiki/Applications_and_libraries/Games 2. http://www.haskell.org/haskellwiki/Frag 3. http://donsbot.wordpress.com/2009/08/06/haskell-package-popularity-ran… 4. http://code.haskell.org/frag/src/ (Darcs 'get' enabled)
agentultra · 2018-07-31
> There's no wrapper, and "interface" is misleading True. I used a convenient lie to make a point. If you're interested in learning Monads you should definitely learn it from a proper source like Haskell from First Principles [0], an online course, or someone who really knows what they're talking about. As I only alluded to and others have pointed out: there's nothing about monads that's inherently sequential or having to do with ordering operations. That's just how the language defined the interpretation of the IO monad. And it also happens that this is the primary topic of concern of TFA. You might even come to realize that much of what a Monad isn't contradicts the entire premise of TFA... Haskell doesn't even need the IO monad and could implement IO other ways just fine [1]. [0] https://haskellbook.com [1] https://donsbot.wordpress.com/2009/01/31/reviving-the-gofer-standard-p…
mrkgnao · 2017-06-19
Good compilers don't keep immutable things immutable at runtime, but turn uses of clean high-level functional code into tight C-like loops. https://donsbot.wordpress.com/2010/02/21/smoking-fast-haskell-code-usi… It's been seven years since: that's GHC 6.13, and GHC 8.2.1 is being released soon. Performance is even better now as long as laziness doesn't bite you (which is much less rare than people think). > you won't be able to convince him that a standard recursive-descent parser is 10x simpler to write and read I don't know what a "compile-time parser" is, but someone used to a good parser combinator library is going to be difficult to convince. http://www.haskellforall.com/2017/06/translating-c-parser-to-haskell.h… It reads like the formal spec of the language. Hand-writing recursive descent parsers isn't fun (given a sufficiently complex grammar) and expecting people to accept it as the One True Practical Non-Ivory Tower Way (and expressing dismay at not being able to convince them otherwise) is suggestive of monoculture, the kind that prides itself on copying code and using wrappers over the two or three first-class data structures that exist in the language for everything.
chriswarbo · 2016-11-29
Just watched the talk. The technique the author's discovered is called "supercompilation" (note: this is distinct from "superoptimisation", mentioned in sibling comments). The idea is to use an evaluation strategy which works at compile time, reducing statically-known expressions whilst shuffling around unknown values symbolically to preserve the semantics. The result ends up folding constants, inlining, unrolling, etc. automatically, just like the examples in the talk. Whilst supercompilation can be slow, the main criticism is that resulting code is quite large, due to the amount of inlining. The main difference between supercompilers and the technique discussed in the talk is that supercompilation is provably correct: it doesn't rely on testing or placing exhaustiveness requirements on the user. I don't think it's necessary to sacrifice correctness; the speaker mentioned the use of guards in JITs, and how he avoids them for speed, but I think that since we're performing such extensive rewriting of the code anyway, many redundant guards can be supercompiled-away, and those remaining can be shunted to the start of the program, so that no branches appear in the hot path. The allusions to the scientific method seem to be about properties/invariants, and potential counterexamples to them. I'm all for finding and sharing properties of programs, both conjectured and proven, although I don't like the idea of assuming the conjectures are true. I've looked into this in Haskell,…
jules · 2014-01-18
Since the other comments are platitudes, I'll try to give some concrete information. Well implemented purely functional data structures are usually anywhere from just as fast to about 20x slower. If the imperative version is tree like, the cost for lookups in the functional version is the same, but the cost for updating is a bit higher because a path needs to be copied rather than just 1 node modified in place. For a data structure like an unordered map, you can use a hash table backed by an array for the imperative version, but you'll have to use a tree for the purely functional one. This can cause about a 10x-20x slowdown. For example in this post http://donsbot.wordpress.com/2009/09/26/very-fast-scalable-mutable-map… Haskell's Data.Map is compared with Judy arrays, and found to be 11x slower. Judy arrays themselves are about 2x slower than a basic hash table http://preshing.com/20130107/this-hash-table-is-faster-than-a-judy-arr… Is this slow? Perhaps, but in most cases the difference is smaller. Compare this to the speed of Ruby vs C, that can easily be a 100x difference yet people use Ruby a lot because of productivity reasons.
axman6 · 2013-11-21
It's quite interesting to see essencially the ideas used in stream fusion [1] to produce practically the same results produced in Haskell, avoiding allocations and often making it much easier for the compiter ro produce vectorised code. At least that's what it looks like to me, correct me if I'm wrong. Edit: [3] has a good exlanation of how stream fusion works, and it should make it clearer why the linked code appears to be doing the same thing. see also here[2] for a further paper on stream fusion being used to produce vectorised code. I've linked to the reddit comments because there's some useful discussion there too. [1] http://citeseer.ist.psu.edu/viewdoc/summary?doi=10.1.1.104.7401 [2] http://www.reddit.com/r/haskell/comments/1br0ls/haskell_beats_c_using_… [3] http://donsbot.wordpress.com/2008/06/04/haskell-as-fast-as-c-working-a…
jrockway · 2010-03-05
Pure functional programming's core delusion is pretty clear as well: all state is immutable. There is no "state" in functional programming, there is function application. Your program is a function from some value (inputs) to some value (the result). You write that program by composing various smaller programs with operators like (.) and (>>=) (or if you like being generic, (>>>)). There is no data, there is just function application. So then, "state" becomes an imaginary concept that sometimes makes things easier to think about; if there is a sequence of computations that logically operate on the same "thing", then you call that "thing" the state. The State monad is nothing but syntax sugar that lets you very explicitly pretend that there is a such thing as state; something you can "get" at and "put" into as needed. This abstraction, BTW, is no different than state in any other language (which is why it comes up so much in hastily-written Haskell programs; you can just cut-n-paste from C and change the spelling of some keywords), except instead of "get" and "put", you just use variable names and "=". Otherwise, exactly the same concept and semantics, and very similar syntax everywhere. In procedural languages, state is important because the procedures abstract CPU instructions, which operate on little boxes called "registers". But in functional programming, your program is not a list of things to do to a register, it's just functions. So state is not really…
mightybyte · 2015-06-24

Keyboard shortcuts

/Search
j kNext / previous blog
EnterOpen selected blog
vVisit the blog site
fFollow / unfollow
lSwitch grid / list view
dSwitch dark mode
g hHome
g pTop posts
g tTopics
g fFollowing
g lLiked
g yHistory
g qFAQ
EscBack / close