[Haskell-cafe] Re[2]: Fast Mutable Variables for the IO and ST
monads
John Meacham
john at repetae.net
Mon Feb 6 19:41:03 EST 2006
On Mon, Feb 06, 2006 at 04:19:03PM -0800, John Meacham wrote:
> On Mon, Feb 06, 2006 at 11:13:47PM +0300, Bulat Ziganshin wrote:
> > btw, i have the counter proposal - automatically convert IORefs of
> > simple types to the fast internal variables like the Int automatically
> > converted to the Int#. The same applies to automatic conversion of
> > arrays to the unboxed arrays
>
> Yeah, I have thought about doing this optimization for jhc. the only
> issue is that figuring out 'strictness' through an updatable variable
> is pretty darn tricky. It would be good if there were an IOSRef which is
> a strict IORef (this can be simulated with normal IORefs and seq) but
> with secret internal compiler support to automatically turn them into
> their unboxed equivalants.
heh. After some more thought, I realized it is not only relativly easy
for jhc to implement this optimization generally, but that it already
does! the arity raising transformation is basically an unboxing style
transformation, that will take arguments with a known heap layout and
just pass its components to functions. since suspended functions and
mutable variables are both just heap locations, the arity raising
transformation of functions incidentally does the same for IORefs.
meaning that if every update looks like this (which would be the case if
you only stored strict integer values in it)
update v1 (Prelude.Int (i::Int#))
then the arity raising will see that that heap location always has a
boxed Int#, and just drop the box, turning it into
update v1 (i::Int#)
now an interesting thing is that this transformation applies even if the
value isn't strict. take this function
foo 0 = error "is zero"
foo x = x
now, imagine you want to store (foo x) in an IORef for various calls of
foo, obviously using a strict IORef would be bad, as it might invoke the
error prematurely. in grin, the writeIORefs will end up looking like
update v1 (Ffoo (i::Int#))
Ffoo is the tag that means a suspended call to 'foo'
since there is absolutely no differenc between data constructors and
suspended functions, the same optimization applies, and you end up
turning it into a mutable fast int in the heap, even though it is not
strict...
note there are some other complications, like you need to make sure you
can identify all the use sites of said heap location so that you can
transform them too, but in practice this can be done for the majority of
heap locations I have found.
John
--
John Meacham - ⑆repetae.net⑆john⑈
More information about the Haskell-Cafe
mailing list