Trends in Profiling Haskell

I spent some time yesterday profiling roguestar. I do this every few months just to see where things stand, and there are always two culprits at the top of, every single time:

* typeclass dictionary lookups in inner loops
* Rational

In the first case, I think the simplest solution is to INLINE the puppy. Can the ghc inliner be a little bit more aggressive when it sees dictionary lookups? Inliners are tricky business. I’m not sure I see a simple heuristic. Vaguely: leaf functions that require dictionary lookups need to be specialized.

Rational can sneak into an unsuspecting program through realToFrac, and absolutely *kills* performance.

I sit down thinking to myself, “Ok, today I’m going to streamline my Super Mumbo Jumbo Widget and get 15% faster performance,” or some such goal I set for myself. And I run the profiler and 75% of my time is being spent in fromRational . toRational.

5 thoughts on “Trends in Profiling Haskell

  1. Re dictionaries, I almost never see them in production code. Do you put {-# INLINE #-} on class methods?

    Are you able to use fromIntegral, rather than realToFrac (if you look on the GHC bug tracker, there are still cases where it must go via Integer when doing conversions with realToFrac).

    And if in doubt, compile with -O2

  2. INLINE on class methods? No, should I? That wouldn’t affect dictionary lookups, since the class method isn’t reachable until after performing it.

  3. You should consider using Data.Number.RealToFrac from the logfloat package[1]. It gives a class for defining specialized implementations of realToFrac (aka fromRational . toRational) and defines highly optimized instances for the usual suspects.

    I don’t have any fusion rules (since the optimized versions are more correct than the Prelude version, and therefore not equal to the composition), which may be where you’re issues are coming up. Though you could probably write your own if you’re not over-cautious about making sure your program transformations are exact.


  4. That’s interesting about the logfloat package. I hadn’t seen that. My concern, however, is not that I don’t know what to do with an errant realToFrac when I find it, but that I keep finding them.

    I’m imagining that there may be tens of haskell programs out there that have never been profiled, that run in twice or worse the time they should

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s