Skip to content

GitLab

  • Projects
  • Groups
  • Snippets
  • Help
    • Loading...
  • Help
    • Help
    • Support
    • Community forum
    • Submit feedback
  • Sign in / Register
GHC
GHC
  • Project overview
    • Project overview
    • Details
    • Activity
    • Releases
  • Repository
    • Repository
    • Files
    • Commits
    • Branches
    • Tags
    • Contributors
    • Graph
    • Compare
    • Locked Files
  • Issues 4,257
    • Issues 4,257
    • List
    • Boards
    • Labels
    • Service Desk
    • Milestones
    • Iterations
  • Merge Requests 394
    • Merge Requests 394
  • Requirements
    • Requirements
    • List
  • CI / CD
    • CI / CD
    • Pipelines
    • Jobs
    • Schedules
  • Security & Compliance
    • Security & Compliance
    • Dependency List
    • License Compliance
  • Operations
    • Operations
    • Incidents
    • Environments
  • Analytics
    • Analytics
    • CI / CD
    • Code Review
    • Insights
    • Issue
    • Repository
    • Value Stream
  • Wiki
    • Wiki
  • Snippets
    • Snippets
  • Members
    • Members
  • Collapse sidebar
  • Activity
  • Graph
  • Create a new issue
  • Jobs
  • Commits
  • Issue Boards
  • Glasgow Haskell Compiler
  • GHCGHC
  • Wiki
    • Nested cpr
  • better ho cardinality

Last edited by Tobias Dammers Mar 29, 2019
Page history New page

better ho cardinality

better-ho-cardinality

It would be nice to merge the code structure improvements and notes into master, to keep my branch short. But it is based on better-ho-cardinality, and that is not suitable for merging because of unexpected regressions even in nofib and rtak. So I am investigating.

In these tests, it is related to reading and showing data. Small example:

main = (read "10" :: Int) `seq` return ()

Baseline: 49832, better-ho-cardinality: 49968. Unfortunately, the changes to, for example, GHC.Read are not small, and probably mostly benign...

Trying to minimize and isolate the problem. After some aggressive code deleting, this is where I ended up:

{-# LANGUAGE RankNTypes #-}

data P a
  = Get (Char -> P a)
  | Result a

Get f1     `mplus` Get f2     = undefined
Result x   `mplus` _          = Result x

newtype ReadP a = R (forall b . (a -> P b) -> P b)

instance Monad ReadP where
  return x  = R (\k -> k x)
  R m >>= f = R (\k -> m (\a -> let R m' = f a in m' k))

readP_to_S (R f) = f Result `seq` ()

ppp :: ReadP a -> ReadP a -> ReadP a
ppp (R f1) (R f2) = R (\k -> f1 k `mplus` f2 k)

paren :: ReadP () -> ReadP ()
paren p = p >> return ()

parens :: ReadP () -> ReadP ()
parens p = optional
 where
  optional  = ppp p mandatory
  mandatory = paren optional

foo = paren ( return () )

foo2 = ppp (parens ( return () )) (parens (return ()))

main = readP_to_S foo `seq` readP_to_S foo2 `seq` return ()

it is important that both paren and parens are used more than once; if there is only one use-site, the problem disappears (which made it hard to find). Also, most other changes prevent the increase in allocations: Removing the Monad instance and turning its methods into regular functions; adding NOINLINE annotations to paren or parens; changing foo2 to ppp foo foo; even removing the dead code that is the first line of the mplus function.

Further investigation and aggresive patch-splitting shows that the arity change is causing the regression. Pushed everything but that patch to master, that patch now lives in wip/exprArity.

Clone repository

GHC Home
GHC User's Guide

Joining In

Newcomers info
Mailing Lists & IRC
The GHC Team

Documentation

GHC Status Info
Working conventions
Building Guide
Debugging
Commentary

Wiki

Title Index
Recent Changes