[Agda] memory eagerness
Wolfram Kahl
kahl at cas.mcmaster.ca
Mon May 6 22:20:00 CEST 2013
On Mon, May 06, 2013 at 10:33:16PM +0400, Sergei Meshveliani wrote:
> [...]
> The longest one has about 250 lines of a proper source code.
>
> And it needs more than 6 Gb memory to type check:
>
> agda -c -i . -i $agdaStLib +RTS -K200m -M8000m -RTS Main.agda
>
> (-M6000m is not enough).
>
(How much memory does your machine have?
If it has only 8G, don't do -M8000m!
``kill -STOP'' your firefox, and run
agda +RTS -S -M6.5G -H6.5G -K200M -RTS ...
With -S you see what is happening; with -H you force the whole
space to be there for the heap from the beginning,
avoiding gazillions of tiny allocations and garbage collections.
Also run htop (http://htop.sourceforge.net) to see what else is going on.
In extreme cases, don't start X; instead work in the console
using possibly
http://jfbterm.sourceforge.jp/
The J Framebuffer Terminal/Multilingual Enhancement with UTF-8 support
to be able to give perhaps 7.4G to Agda...
)
Agda typechecking performs a lot of evaluation/reduction,
and the current reduction engine that is used for this
does not implement the degree of sharing you might expect.
Sharing happens when interface files are written,
but not while a single module is checked.
For that reason, sometimes it makes sense to split a
two-definition module into two one-definition modules...
> [...]
>
> Concerning the style, I see the following points.
>
>
> 1. Record vs ordinary module
> ------------------------------
>
> For example, the record Group
> has a parameter : UpMonoid c l
> and a single field totalInversion : ...
>
> There are also several related auxiliary functions
> (defined via the parameter and field totalInversion)
> and their proved lemmata:
> division, proof for inv (x * y) == (inv y) * (inv x),
> for inv (inv x) == x, and such.
>
> And I put all them into this very record, so that it exports them
> (because a record is also a module).
>
> Their code size is about 20 times larger than the proper Group
> record part. And it can grow further several times, because
> there are many useful lemmata about groups.
>
> I think, so far, that this is a natural style. Is it?
I consider this natural, too, and followed this style for a long time.
But recently I had to remove large chunks of such code into separate modules
to get my developments typechecked (in 12G...).
> Another design may be:
> to create
> module Group-related (G : Group ...)
> where
> ...
>
> and move there the above Group related items, so that the proper
> Group record will become a small code.
> Will this approach save much space in the type-check?
It did in my case.
I also have what in your case is ``Group-related'' in a separate file,
and actually have multiple such modules for different topics.
>
> 2. open, open - public
> ----------------------
>
> There are many levels in this record hierarchy (may be, 15-20).
> I apply `open' and `open - public' in order to have a shorter
> path from the top level to an operation on a lower level.
> For example, the path to reach _+_ from Field is
> EuclideanRing --> IntegralRing --> RingWithOne -->
> CommutativeRing --> Ring --> Ringoid --> _+_
>
> I do not know, may be something large is copied due to this
> nested `open' declarations
> -- ?
For re-exporting interfaces from local modules, it seems that
open X public
is mostly harmless, but
open X public using (a ; b ; c)
is definitely not harmless, and
open X public hiding (a ; b ; c)
is almost certainly not harmless, either.
I found it useful to keep that in mind when constructing
my interfaces --- if ``X'' is large,
name the pieces you will want to re-export separately,
and compose X from these pieces.
Hope this helps!
Wolfram
More information about the Agda
mailing list