Works for me. On Mon, Aug 31, 2015 at 10:14 PM, Johan Tibell <johan.tib...@gmail.com> wrote:
> Works for me. > > On Mon, Aug 31, 2015 at 3:50 PM, Ryan Yates <fryguy...@gmail.com> wrote: > >> Any time works for me. >> >> Ryan >> >> On Mon, Aug 31, 2015 at 6:11 PM, Ryan Newton <rrnew...@gmail.com> wrote: >> > Dear Edward, Ryan Yates, and other interested parties -- >> > >> > So when should we meet up about this? >> > >> > May I propose the Tues afternoon break for everyone at ICFP who is >> > interested in this topic? We can meet out in the coffee area and >> congregate >> > around Edward Kmett, who is tall and should be easy to find ;-). >> > >> > I think Ryan is going to show us how to use his new primops for combined >> > array + other fields in one heap object? >> > >> > On Sat, Aug 29, 2015 at 9:24 PM Edward Kmett <ekm...@gmail.com> wrote: >> >> >> >> Without a custom primitive it doesn't help much there, you have to >> store >> >> the indirection to the mask. >> >> >> >> With a custom primitive it should cut the on heap root-to-leaf path of >> >> everything in the HAMT in half. A shorter HashMap was actually one of >> the >> >> motivating factors for me doing this. It is rather astoundingly >> difficult to >> >> beat the performance of HashMap, so I had to start cheating pretty >> badly. ;) >> >> >> >> -Edward >> >> >> >> On Sat, Aug 29, 2015 at 5:45 PM, Johan Tibell <johan.tib...@gmail.com> >> >> wrote: >> >>> >> >>> I'd also be interested to chat at ICFP to see if I can use this for my >> >>> HAMT implementation. >> >>> >> >>> On Sat, Aug 29, 2015 at 3:07 PM, Edward Kmett <ekm...@gmail.com> >> wrote: >> >>>> >> >>>> Sounds good to me. Right now I'm just hacking up composable accessors >> >>>> for "typed slots" in a fairly lens-like fashion, and treating the >> set of >> >>>> slots I define and the 'new' function I build for the data type as >> its API, >> >>>> and build atop that. This could eventually graduate to >> template-haskell, but >> >>>> I'm not entirely satisfied with the solution I have. I currently >> distinguish >> >>>> between what I'm calling "slots" (things that point directly to >> another >> >>>> SmallMutableArrayArray# sans wrapper) and "fields" which point >> directly to >> >>>> the usual Haskell data types because unifying the two notions meant >> that I >> >>>> couldn't lift some coercions out "far enough" to make them vanish. >> >>>> >> >>>> I'll be happy to run through my current working set of issues in >> person >> >>>> and -- as things get nailed down further -- in a longer lived medium >> than in >> >>>> personal conversations. ;) >> >>>> >> >>>> -Edward >> >>>> >> >>>> On Sat, Aug 29, 2015 at 7:59 AM, Ryan Newton <rrnew...@gmail.com> >> wrote: >> >>>>> >> >>>>> I'd also love to meet up at ICFP and discuss this. I think the >> array >> >>>>> primops plus a TH layer that lets (ab)use them many times without >> too much >> >>>>> marginal cost sounds great. And I'd like to learn how we could be >> either >> >>>>> early users of, or help with, this infrastructure. >> >>>>> >> >>>>> CC'ing in Ryan Scot and Omer Agacan who may also be interested in >> >>>>> dropping in on such discussions @ICFP, and Chao-Hong Chen, a Ph.D. >> student >> >>>>> who is currently working on concurrent data structures in Haskell, >> but will >> >>>>> not be at ICFP. >> >>>>> >> >>>>> >> >>>>> On Fri, Aug 28, 2015 at 7:47 PM, Ryan Yates <fryguy...@gmail.com> >> >>>>> wrote: >> >>>>>> >> >>>>>> I completely agree. I would love to spend some time during ICFP >> and >> >>>>>> friends talking about what it could look like. My small array for >> STM >> >>>>>> changes for the RTS can be seen here [1]. It is on a branch >> somewhere >> >>>>>> between 7.8 and 7.10 and includes irrelevant STM bits and some >> >>>>>> confusing naming choices (sorry), but should cover all the details >> >>>>>> needed to implement it for a non-STM context. The biggest surprise >> >>>>>> for me was following small array too closely and having a word/byte >> >>>>>> offset miss-match [2]. >> >>>>>> >> >>>>>> [1]: >> >>>>>> >> https://github.com/fryguybob/ghc/compare/ghc-htm-bloom...fryguybob:ghc-htm-mut >> >>>>>> [2]: https://ghc.haskell.org/trac/ghc/ticket/10413 >> >>>>>> >> >>>>>> Ryan >> >>>>>> >> >>>>>> On Fri, Aug 28, 2015 at 10:09 PM, Edward Kmett <ekm...@gmail.com> >> >>>>>> wrote: >> >>>>>> > I'd love to have that last 10%, but its a lot of work to get >> there >> >>>>>> > and more >> >>>>>> > importantly I don't know quite what it should look like. >> >>>>>> > >> >>>>>> > On the other hand, I do have a pretty good idea of how the >> >>>>>> > primitives above >> >>>>>> > could be banged out and tested in a long evening, well in time >> for >> >>>>>> > 7.12. And >> >>>>>> > as noted earlier, those remain useful even if a nicer typed >> version >> >>>>>> > with an >> >>>>>> > extra level of indirection to the sizes is built up after. >> >>>>>> > >> >>>>>> > The rest sounds like a good graduate student project for someone >> who >> >>>>>> > has >> >>>>>> > graduate students lying around. Maybe somebody at Indiana >> University >> >>>>>> > who has >> >>>>>> > an interest in type theory and parallelism can find us one. =) >> >>>>>> > >> >>>>>> > -Edward >> >>>>>> > >> >>>>>> > On Fri, Aug 28, 2015 at 8:48 PM, Ryan Yates <fryguy...@gmail.com >> > >> >>>>>> > wrote: >> >>>>>> >> >> >>>>>> >> I think from my perspective, the motivation for getting the type >> >>>>>> >> checker involved is primarily bringing this to the level where >> >>>>>> >> users >> >>>>>> >> could be expected to build these structures. it is reasonable >> to >> >>>>>> >> think that there are people who want to use STM (a context with >> >>>>>> >> mutation already) to implement a straight forward data structure >> >>>>>> >> that >> >>>>>> >> avoids extra indirection penalty. There should be some places >> >>>>>> >> where >> >>>>>> >> knowing that things are field accesses rather then array >> indexing >> >>>>>> >> could be helpful, but I think GHC is good right now about >> handling >> >>>>>> >> constant offsets. In my code I don't do any bounds checking as >> I >> >>>>>> >> know >> >>>>>> >> I will only be accessing my arrays with constant indexes. I >> make >> >>>>>> >> wrappers for each field access and leave all the unsafe stuff in >> >>>>>> >> there. When things go wrong though, the compiler is no help. >> >>>>>> >> Maybe >> >>>>>> >> template Haskell that generates the appropriate wrappers is the >> >>>>>> >> right >> >>>>>> >> direction to go. >> >>>>>> >> There is another benefit for me when working with these as >> arrays >> >>>>>> >> in >> >>>>>> >> that it is quite simple and direct (given the hoops already >> jumped >> >>>>>> >> through) to play with alignment. I can ensure two pointers are >> >>>>>> >> never >> >>>>>> >> on the same cache-line by just spacing things out in the array. >> >>>>>> >> >> >>>>>> >> On Fri, Aug 28, 2015 at 7:33 PM, Edward Kmett <ekm...@gmail.com >> > >> >>>>>> >> wrote: >> >>>>>> >> > They just segfault at this level. ;) >> >>>>>> >> > >> >>>>>> >> > Sent from my iPhone >> >>>>>> >> > >> >>>>>> >> > On Aug 28, 2015, at 7:25 PM, Ryan Newton <rrnew...@gmail.com> >> >>>>>> >> > wrote: >> >>>>>> >> > >> >>>>>> >> > You presumably also save a bounds check on reads by >> hard-coding >> >>>>>> >> > the >> >>>>>> >> > sizes? >> >>>>>> >> > >> >>>>>> >> > On Fri, Aug 28, 2015 at 3:39 PM, Edward Kmett < >> ekm...@gmail.com> >> >>>>>> >> > wrote: >> >>>>>> >> >> >> >>>>>> >> >> Also there are 4 different "things" here, basically >> depending on >> >>>>>> >> >> two >> >>>>>> >> >> independent questions: >> >>>>>> >> >> >> >>>>>> >> >> a.) if you want to shove the sizes into the info table, and >> >>>>>> >> >> b.) if you want cardmarking. >> >>>>>> >> >> >> >>>>>> >> >> Versions with/without cardmarking for different sizes can be >> >>>>>> >> >> done >> >>>>>> >> >> pretty >> >>>>>> >> >> easily, but as noted, the infotable variants are pretty >> >>>>>> >> >> invasive. >> >>>>>> >> >> >> >>>>>> >> >> -Edward >> >>>>>> >> >> >> >>>>>> >> >> On Fri, Aug 28, 2015 at 6:36 PM, Edward Kmett < >> ekm...@gmail.com> >> >>>>>> >> >> wrote: >> >>>>>> >> >>> >> >>>>>> >> >>> Well, on the plus side you'd save 16 bytes per object, which >> >>>>>> >> >>> adds up >> >>>>>> >> >>> if >> >>>>>> >> >>> they were small enough and there are enough of them. You >> get a >> >>>>>> >> >>> bit >> >>>>>> >> >>> better >> >>>>>> >> >>> locality of reference in terms of what fits in the first >> cache >> >>>>>> >> >>> line of >> >>>>>> >> >>> them. >> >>>>>> >> >>> >> >>>>>> >> >>> -Edward >> >>>>>> >> >>> >> >>>>>> >> >>> On Fri, Aug 28, 2015 at 6:14 PM, Ryan Newton >> >>>>>> >> >>> <rrnew...@gmail.com> >> >>>>>> >> >>> wrote: >> >>>>>> >> >>>> >> >>>>>> >> >>>> Yes. And for the short term I can imagine places we will >> >>>>>> >> >>>> settle with >> >>>>>> >> >>>> arrays even if it means tracking lengths unnecessarily and >> >>>>>> >> >>>> unsafeCoercing >> >>>>>> >> >>>> pointers whose types don't actually match their siblings. >> >>>>>> >> >>>> >> >>>>>> >> >>>> Is there anything to recommend the hacks mentioned for >> fixed >> >>>>>> >> >>>> sized >> >>>>>> >> >>>> array >> >>>>>> >> >>>> objects *other* than using them to fake structs? (Much to >> >>>>>> >> >>>> derecommend, as >> >>>>>> >> >>>> you mentioned!) >> >>>>>> >> >>>> >> >>>>>> >> >>>> On Fri, Aug 28, 2015 at 3:07 PM Edward Kmett >> >>>>>> >> >>>> <ekm...@gmail.com> >> >>>>>> >> >>>> wrote: >> >>>>>> >> >>>>> >> >>>>>> >> >>>>> I think both are useful, but the one you suggest requires >> a >> >>>>>> >> >>>>> lot more >> >>>>>> >> >>>>> plumbing and doesn't subsume all of the usecases of the >> >>>>>> >> >>>>> other. >> >>>>>> >> >>>>> >> >>>>>> >> >>>>> -Edward >> >>>>>> >> >>>>> >> >>>>>> >> >>>>> On Fri, Aug 28, 2015 at 5:51 PM, Ryan Newton >> >>>>>> >> >>>>> <rrnew...@gmail.com> >> >>>>>> >> >>>>> wrote: >> >>>>>> >> >>>>>> >> >>>>>> >> >>>>>> So that primitive is an array like thing (Same pointed >> type, >> >>>>>> >> >>>>>> unbounded >> >>>>>> >> >>>>>> length) with extra payload. >> >>>>>> >> >>>>>> >> >>>>>> >> >>>>>> I can see how we can do without structs if we have >> arrays, >> >>>>>> >> >>>>>> especially >> >>>>>> >> >>>>>> with the extra payload at front. But wouldn't the general >> >>>>>> >> >>>>>> solution >> >>>>>> >> >>>>>> for >> >>>>>> >> >>>>>> structs be one that that allows new user data type defs >> for >> >>>>>> >> >>>>>> # >> >>>>>> >> >>>>>> types? >> >>>>>> >> >>>>>> >> >>>>>> >> >>>>>> >> >>>>>> >> >>>>>> >> >>>>>> >> >>>>>> On Fri, Aug 28, 2015 at 4:43 PM Edward Kmett >> >>>>>> >> >>>>>> <ekm...@gmail.com> >> >>>>>> >> >>>>>> wrote: >> >>>>>> >> >>>>>>> >> >>>>>> >> >>>>>>> Some form of MutableStruct# with a known number of words >> >>>>>> >> >>>>>>> and a >> >>>>>> >> >>>>>>> known >> >>>>>> >> >>>>>>> number of pointers is basically what Ryan Yates was >> >>>>>> >> >>>>>>> suggesting >> >>>>>> >> >>>>>>> above, but >> >>>>>> >> >>>>>>> where the word counts were stored in the objects >> >>>>>> >> >>>>>>> themselves. >> >>>>>> >> >>>>>>> >> >>>>>> >> >>>>>>> Given that it'd have a couple of words for those counts >> >>>>>> >> >>>>>>> it'd >> >>>>>> >> >>>>>>> likely >> >>>>>> >> >>>>>>> want to be something we build in addition to MutVar# >> rather >> >>>>>> >> >>>>>>> than a >> >>>>>> >> >>>>>>> replacement. >> >>>>>> >> >>>>>>> >> >>>>>> >> >>>>>>> On the other hand, if we had to fix those numbers and >> build >> >>>>>> >> >>>>>>> info >> >>>>>> >> >>>>>>> tables that knew them, and typechecker support, for >> >>>>>> >> >>>>>>> instance, it'd >> >>>>>> >> >>>>>>> get >> >>>>>> >> >>>>>>> rather invasive. >> >>>>>> >> >>>>>>> >> >>>>>> >> >>>>>>> Also, a number of things that we can do with the 'sized' >> >>>>>> >> >>>>>>> versions >> >>>>>> >> >>>>>>> above, like working with evil unsized c-style arrays >> >>>>>> >> >>>>>>> directly >> >>>>>> >> >>>>>>> inline at the >> >>>>>> >> >>>>>>> end of the structure cease to be possible, so it isn't >> even >> >>>>>> >> >>>>>>> a pure >> >>>>>> >> >>>>>>> win if we >> >>>>>> >> >>>>>>> did the engineering effort. >> >>>>>> >> >>>>>>> >> >>>>>> >> >>>>>>> I think 90% of the needs I have are covered just by >> adding >> >>>>>> >> >>>>>>> the one >> >>>>>> >> >>>>>>> primitive. The last 10% gets pretty invasive. >> >>>>>> >> >>>>>>> >> >>>>>> >> >>>>>>> -Edward >> >>>>>> >> >>>>>>> >> >>>>>> >> >>>>>>> On Fri, Aug 28, 2015 at 5:30 PM, Ryan Newton >> >>>>>> >> >>>>>>> <rrnew...@gmail.com> >> >>>>>> >> >>>>>>> wrote: >> >>>>>> >> >>>>>>>> >> >>>>>> >> >>>>>>>> I like the possibility of a general solution for >> mutable >> >>>>>> >> >>>>>>>> structs >> >>>>>> >> >>>>>>>> (like Ed said), and I'm trying to fully understand why >> >>>>>> >> >>>>>>>> it's hard. >> >>>>>> >> >>>>>>>> >> >>>>>> >> >>>>>>>> So, we can't unpack MutVar into constructors because of >> >>>>>> >> >>>>>>>> object >> >>>>>> >> >>>>>>>> identity problems. But what about directly supporting >> an >> >>>>>> >> >>>>>>>> extensible set of >> >>>>>> >> >>>>>>>> unlifted MutStruct# objects, generalizing (and even >> >>>>>> >> >>>>>>>> replacing) >> >>>>>> >> >>>>>>>> MutVar#? That >> >>>>>> >> >>>>>>>> may be too much work, but is it problematic otherwise? >> >>>>>> >> >>>>>>>> >> >>>>>> >> >>>>>>>> Needless to say, this is also critical if we ever want >> >>>>>> >> >>>>>>>> best in >> >>>>>> >> >>>>>>>> class >> >>>>>> >> >>>>>>>> lockfree mutable structures, just like their Stm and >> >>>>>> >> >>>>>>>> sequential >> >>>>>> >> >>>>>>>> counterparts. >> >>>>>> >> >>>>>>>> >> >>>>>> >> >>>>>>>> On Fri, Aug 28, 2015 at 4:43 AM Simon Peyton Jones >> >>>>>> >> >>>>>>>> <simo...@microsoft.com> wrote: >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> At the very least I'll take this email and turn it >> into a >> >>>>>> >> >>>>>>>>> short >> >>>>>> >> >>>>>>>>> article. >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> Yes, please do make it into a wiki page on the GHC >> Trac, >> >>>>>> >> >>>>>>>>> and >> >>>>>> >> >>>>>>>>> maybe >> >>>>>> >> >>>>>>>>> make a ticket for it. >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> Thanks >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> Simon >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> From: Edward Kmett [mailto:ekm...@gmail.com] >> >>>>>> >> >>>>>>>>> Sent: 27 August 2015 16:54 >> >>>>>> >> >>>>>>>>> To: Simon Peyton Jones >> >>>>>> >> >>>>>>>>> Cc: Manuel M T Chakravarty; Simon Marlow; ghc-devs >> >>>>>> >> >>>>>>>>> Subject: Re: ArrayArrays >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> An ArrayArray# is just an Array# with a modified >> >>>>>> >> >>>>>>>>> invariant. It >> >>>>>> >> >>>>>>>>> points directly to other unlifted ArrayArray#'s or >> >>>>>> >> >>>>>>>>> ByteArray#'s. >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> While those live in #, they are garbage collected >> >>>>>> >> >>>>>>>>> objects, so >> >>>>>> >> >>>>>>>>> this >> >>>>>> >> >>>>>>>>> all lives on the heap. >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> They were added to make some of the DPH stuff fast >> when >> >>>>>> >> >>>>>>>>> it has >> >>>>>> >> >>>>>>>>> to >> >>>>>> >> >>>>>>>>> deal with nested arrays. >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> I'm currently abusing them as a placeholder for a >> better >> >>>>>> >> >>>>>>>>> thing. >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> The Problem >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> ----------------- >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> Consider the scenario where you write a classic >> >>>>>> >> >>>>>>>>> doubly-linked >> >>>>>> >> >>>>>>>>> list >> >>>>>> >> >>>>>>>>> in Haskell. >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> data DLL = DLL (IORef (Maybe DLL) (IORef (Maybe DLL) >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> Chasing from one DLL to the next requires following 3 >> >>>>>> >> >>>>>>>>> pointers >> >>>>>> >> >>>>>>>>> on >> >>>>>> >> >>>>>>>>> the heap. >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> DLL ~> IORef (Maybe DLL) ~> MutVar# RealWorld (Maybe >> DLL) >> >>>>>> >> >>>>>>>>> ~> >> >>>>>> >> >>>>>>>>> Maybe >> >>>>>> >> >>>>>>>>> DLL ~> DLL >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> That is 3 levels of indirection. >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> We can trim one by simply unpacking the IORef with >> >>>>>> >> >>>>>>>>> -funbox-strict-fields or UNPACK >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> We can trim another by adding a 'Nil' constructor for >> DLL >> >>>>>> >> >>>>>>>>> and >> >>>>>> >> >>>>>>>>> worsening our representation. >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> data DLL = DLL !(IORef DLL) !(IORef DLL) | Nil >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> but now we're still stuck with a level of indirection >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> DLL ~> MutVar# RealWorld DLL ~> DLL >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> This means that every operation we perform on this >> >>>>>> >> >>>>>>>>> structure >> >>>>>> >> >>>>>>>>> will >> >>>>>> >> >>>>>>>>> be about half of the speed of an implementation in >> most >> >>>>>> >> >>>>>>>>> other >> >>>>>> >> >>>>>>>>> languages >> >>>>>> >> >>>>>>>>> assuming we're memory bound on loading things into >> cache! >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> Making Progress >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> ---------------------- >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> I have been working on a number of data structures >> where >> >>>>>> >> >>>>>>>>> the >> >>>>>> >> >>>>>>>>> indirection of going from something in * out to an >> object >> >>>>>> >> >>>>>>>>> in # >> >>>>>> >> >>>>>>>>> which >> >>>>>> >> >>>>>>>>> contains the real pointer to my target and coming back >> >>>>>> >> >>>>>>>>> effectively doubles >> >>>>>> >> >>>>>>>>> my runtime. >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> We go out to the MutVar# because we are allowed to put >> >>>>>> >> >>>>>>>>> the >> >>>>>> >> >>>>>>>>> MutVar# >> >>>>>> >> >>>>>>>>> onto the mutable list when we dirty it. There is a >> well >> >>>>>> >> >>>>>>>>> defined >> >>>>>> >> >>>>>>>>> write-barrier. >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> I could change out the representation to use >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> data DLL = DLL (MutableArray# RealWorld DLL) | Nil >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> I can just store two pointers in the MutableArray# >> every >> >>>>>> >> >>>>>>>>> time, >> >>>>>> >> >>>>>>>>> but >> >>>>>> >> >>>>>>>>> this doesn't help _much_ directly. It has reduced the >> >>>>>> >> >>>>>>>>> amount of >> >>>>>> >> >>>>>>>>> distinct >> >>>>>> >> >>>>>>>>> addresses in memory I touch on a walk of the DLL from >> 3 >> >>>>>> >> >>>>>>>>> per >> >>>>>> >> >>>>>>>>> object to 2. >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> I still have to go out to the heap from my DLL and >> get to >> >>>>>> >> >>>>>>>>> the >> >>>>>> >> >>>>>>>>> array >> >>>>>> >> >>>>>>>>> object and then chase it to the next DLL and chase >> that >> >>>>>> >> >>>>>>>>> to the >> >>>>>> >> >>>>>>>>> next array. I >> >>>>>> >> >>>>>>>>> do get my two pointers together in memory though. I'm >> >>>>>> >> >>>>>>>>> paying for >> >>>>>> >> >>>>>>>>> a card >> >>>>>> >> >>>>>>>>> marking table as well, which I don't particularly need >> >>>>>> >> >>>>>>>>> with just >> >>>>>> >> >>>>>>>>> two >> >>>>>> >> >>>>>>>>> pointers, but we can shed that with the >> >>>>>> >> >>>>>>>>> "SmallMutableArray#" >> >>>>>> >> >>>>>>>>> machinery added >> >>>>>> >> >>>>>>>>> back in 7.10, which is just the old array code a a new >> >>>>>> >> >>>>>>>>> data >> >>>>>> >> >>>>>>>>> type, which can >> >>>>>> >> >>>>>>>>> speed things up a bit when you don't have very big >> >>>>>> >> >>>>>>>>> arrays: >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> data DLL = DLL (SmallMutableArray# RealWorld DLL) | >> Nil >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> But what if I wanted my object itself to live in # and >> >>>>>> >> >>>>>>>>> have two >> >>>>>> >> >>>>>>>>> mutable fields and be able to share the sme write >> >>>>>> >> >>>>>>>>> barrier? >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> An ArrayArray# points directly to other unlifted array >> >>>>>> >> >>>>>>>>> types. >> >>>>>> >> >>>>>>>>> What >> >>>>>> >> >>>>>>>>> if we have one # -> * wrapper on the outside to deal >> with >> >>>>>> >> >>>>>>>>> the >> >>>>>> >> >>>>>>>>> impedence >> >>>>>> >> >>>>>>>>> mismatch between the imperative world and Haskell, and >> >>>>>> >> >>>>>>>>> then just >> >>>>>> >> >>>>>>>>> let the >> >>>>>> >> >>>>>>>>> ArrayArray#'s hold other arrayarrays. >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> data DLL = DLL (MutableArrayArray# RealWorld) >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> now I need to make up a new Nil, which I can just >> make be >> >>>>>> >> >>>>>>>>> a >> >>>>>> >> >>>>>>>>> special >> >>>>>> >> >>>>>>>>> MutableArrayArray# I allocate on program startup. I >> can >> >>>>>> >> >>>>>>>>> even >> >>>>>> >> >>>>>>>>> abuse pattern >> >>>>>> >> >>>>>>>>> synonyms. Alternately I can exploit the internals >> further >> >>>>>> >> >>>>>>>>> to >> >>>>>> >> >>>>>>>>> make this >> >>>>>> >> >>>>>>>>> cheaper. >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> Then I can use the readMutableArrayArray# and >> >>>>>> >> >>>>>>>>> writeMutableArrayArray# calls to directly access the >> >>>>>> >> >>>>>>>>> preceding >> >>>>>> >> >>>>>>>>> and next >> >>>>>> >> >>>>>>>>> entry in the linked list. >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> So now we have one DLL wrapper which just 'bootstraps >> me' >> >>>>>> >> >>>>>>>>> into a >> >>>>>> >> >>>>>>>>> strict world, and everything there lives in #. >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> next :: DLL -> IO DLL >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> next (DLL m) = IO $ \s -> case readMutableArrayArray# >> s >> >>>>>> >> >>>>>>>>> of >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> (# s', n #) -> (# s', DLL n #) >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> It turns out GHC is quite happy to optimize all of >> that >> >>>>>> >> >>>>>>>>> code to >> >>>>>> >> >>>>>>>>> keep things unboxed. The 'DLL' wrappers get removed >> >>>>>> >> >>>>>>>>> pretty >> >>>>>> >> >>>>>>>>> easily when they >> >>>>>> >> >>>>>>>>> are known strict and you chain operations of this >> sort! >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> Cleaning it Up >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> ------------------ >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> Now I have one outermost indirection pointing to an >> array >> >>>>>> >> >>>>>>>>> that >> >>>>>> >> >>>>>>>>> points directly to other arrays. >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> I'm stuck paying for a card marking table per object, >> but >> >>>>>> >> >>>>>>>>> I can >> >>>>>> >> >>>>>>>>> fix >> >>>>>> >> >>>>>>>>> that by duplicating the code for MutableArrayArray# >> and >> >>>>>> >> >>>>>>>>> using a >> >>>>>> >> >>>>>>>>> SmallMutableArray#. I can hack up primops that let me >> >>>>>> >> >>>>>>>>> store a >> >>>>>> >> >>>>>>>>> mixture of >> >>>>>> >> >>>>>>>>> SmallMutableArray# fields and normal ones in the data >> >>>>>> >> >>>>>>>>> structure. >> >>>>>> >> >>>>>>>>> Operationally, I can even do so by just unsafeCoercing >> >>>>>> >> >>>>>>>>> the >> >>>>>> >> >>>>>>>>> existing >> >>>>>> >> >>>>>>>>> SmallMutableArray# primitives to change the kind of >> one >> >>>>>> >> >>>>>>>>> of the >> >>>>>> >> >>>>>>>>> arguments it >> >>>>>> >> >>>>>>>>> takes. >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> This is almost ideal, but not quite. I often have >> fields >> >>>>>> >> >>>>>>>>> that >> >>>>>> >> >>>>>>>>> would >> >>>>>> >> >>>>>>>>> be best left unboxed. >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> data DLLInt = DLL !Int !(IORef DLL) !(IORef DLL) | Nil >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> was able to unpack the Int, but we lost that. We can >> >>>>>> >> >>>>>>>>> currently >> >>>>>> >> >>>>>>>>> at >> >>>>>> >> >>>>>>>>> best point one of the entries of the >> SmallMutableArray# >> >>>>>> >> >>>>>>>>> at a >> >>>>>> >> >>>>>>>>> boxed or at a >> >>>>>> >> >>>>>>>>> MutableByteArray# for all of our misc. data and shove >> the >> >>>>>> >> >>>>>>>>> int in >> >>>>>> >> >>>>>>>>> question in >> >>>>>> >> >>>>>>>>> there. >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> e.g. if I were to implement a hash-array-mapped-trie I >> >>>>>> >> >>>>>>>>> need to >> >>>>>> >> >>>>>>>>> store masks and administrivia as I walk down the tree. >> >>>>>> >> >>>>>>>>> Having to >> >>>>>> >> >>>>>>>>> go off to >> >>>>>> >> >>>>>>>>> the side costs me the entire win from avoiding the >> first >> >>>>>> >> >>>>>>>>> pointer >> >>>>>> >> >>>>>>>>> chase. >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> But, if like Ryan suggested, we had a heap object we >> >>>>>> >> >>>>>>>>> could >> >>>>>> >> >>>>>>>>> construct that had n words with unsafe access and m >> >>>>>> >> >>>>>>>>> pointers to >> >>>>>> >> >>>>>>>>> other heap >> >>>>>> >> >>>>>>>>> objects, one that could put itself on the mutable list >> >>>>>> >> >>>>>>>>> when any >> >>>>>> >> >>>>>>>>> of those >> >>>>>> >> >>>>>>>>> pointers changed then I could shed this last factor of >> >>>>>> >> >>>>>>>>> two in >> >>>>>> >> >>>>>>>>> all >> >>>>>> >> >>>>>>>>> circumstances. >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> Prototype >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> ------------- >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> Over the last few days I've put together a small >> >>>>>> >> >>>>>>>>> prototype >> >>>>>> >> >>>>>>>>> implementation with a few non-trivial imperative data >> >>>>>> >> >>>>>>>>> structures >> >>>>>> >> >>>>>>>>> for things >> >>>>>> >> >>>>>>>>> like Tarjan's link-cut trees, the list labeling >> problem >> >>>>>> >> >>>>>>>>> and >> >>>>>> >> >>>>>>>>> order-maintenance. >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> https://github.com/ekmett/structs >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> Notable bits: >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> Data.Struct.Internal.LinkCut provides an >> implementation >> >>>>>> >> >>>>>>>>> of >> >>>>>> >> >>>>>>>>> link-cut >> >>>>>> >> >>>>>>>>> trees in this style. >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> Data.Struct.Internal provides the rather horrifying >> guts >> >>>>>> >> >>>>>>>>> that >> >>>>>> >> >>>>>>>>> make >> >>>>>> >> >>>>>>>>> it go fast. >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> Once compiled with -O or -O2, if you look at the core, >> >>>>>> >> >>>>>>>>> almost >> >>>>>> >> >>>>>>>>> all >> >>>>>> >> >>>>>>>>> the references to the LinkCut or Object data >> constructor >> >>>>>> >> >>>>>>>>> get >> >>>>>> >> >>>>>>>>> optimized away, >> >>>>>> >> >>>>>>>>> and we're left with beautiful strict code directly >> >>>>>> >> >>>>>>>>> mutating out >> >>>>>> >> >>>>>>>>> underlying >> >>>>>> >> >>>>>>>>> representation. >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> At the very least I'll take this email and turn it >> into a >> >>>>>> >> >>>>>>>>> short >> >>>>>> >> >>>>>>>>> article. >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> -Edward >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> On Thu, Aug 27, 2015 at 9:00 AM, Simon Peyton Jones >> >>>>>> >> >>>>>>>>> <simo...@microsoft.com> wrote: >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> Just to say that I have no idea what is going on in >> this >> >>>>>> >> >>>>>>>>> thread. >> >>>>>> >> >>>>>>>>> What is ArrayArray? What is the issue in general? Is >> >>>>>> >> >>>>>>>>> there a >> >>>>>> >> >>>>>>>>> ticket? Is >> >>>>>> >> >>>>>>>>> there a wiki page? >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> If it’s important, an ab-initio wiki page + ticket >> would >> >>>>>> >> >>>>>>>>> be a >> >>>>>> >> >>>>>>>>> good >> >>>>>> >> >>>>>>>>> thing. >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> Simon >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> From: ghc-devs [mailto:ghc-devs-boun...@haskell.org] >> On >> >>>>>> >> >>>>>>>>> Behalf >> >>>>>> >> >>>>>>>>> Of >> >>>>>> >> >>>>>>>>> Edward Kmett >> >>>>>> >> >>>>>>>>> Sent: 21 August 2015 05:25 >> >>>>>> >> >>>>>>>>> To: Manuel M T Chakravarty >> >>>>>> >> >>>>>>>>> Cc: Simon Marlow; ghc-devs >> >>>>>> >> >>>>>>>>> Subject: Re: ArrayArrays >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> When (ab)using them for this purpose, >> SmallArrayArray's >> >>>>>> >> >>>>>>>>> would be >> >>>>>> >> >>>>>>>>> very handy as well. >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> Consider right now if I have something like an >> >>>>>> >> >>>>>>>>> order-maintenance >> >>>>>> >> >>>>>>>>> structure I have: >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> data Upper s = Upper {-# UNPACK #-} >> !(MutableByteArray s) >> >>>>>> >> >>>>>>>>> {-# >> >>>>>> >> >>>>>>>>> UNPACK #-} !(MutVar s (Upper s)) {-# UNPACK #-} >> !(MutVar >> >>>>>> >> >>>>>>>>> s >> >>>>>> >> >>>>>>>>> (Upper s)) >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> data Lower s = Lower {-# UNPACK #-} !(MutVar s (Upper >> s)) >> >>>>>> >> >>>>>>>>> {-# >> >>>>>> >> >>>>>>>>> UNPACK #-} !(MutableByteArray s) {-# UNPACK #-} >> !(MutVar >> >>>>>> >> >>>>>>>>> s >> >>>>>> >> >>>>>>>>> (Lower s)) {-# >> >>>>>> >> >>>>>>>>> UNPACK #-} !(MutVar s (Lower s)) >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> The former contains, logically, a mutable integer and >> two >> >>>>>> >> >>>>>>>>> pointers, >> >>>>>> >> >>>>>>>>> one for forward and one for backwards. The latter is >> >>>>>> >> >>>>>>>>> basically >> >>>>>> >> >>>>>>>>> the same >> >>>>>> >> >>>>>>>>> thing with a mutable reference up pointing at the >> >>>>>> >> >>>>>>>>> structure >> >>>>>> >> >>>>>>>>> above. >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> On the heap this is an object that points to a >> structure >> >>>>>> >> >>>>>>>>> for the >> >>>>>> >> >>>>>>>>> bytearray, and points to another structure for each >> >>>>>> >> >>>>>>>>> mutvar which >> >>>>>> >> >>>>>>>>> each point >> >>>>>> >> >>>>>>>>> to the other 'Upper' structure. So there is a level of >> >>>>>> >> >>>>>>>>> indirection smeared >> >>>>>> >> >>>>>>>>> over everything. >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> So this is a pair of doubly linked lists with an >> upward >> >>>>>> >> >>>>>>>>> link >> >>>>>> >> >>>>>>>>> from >> >>>>>> >> >>>>>>>>> the structure below to the structure above. >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> Converted into ArrayArray#s I'd get >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> data Upper s = Upper (MutableArrayArray# s) >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> w/ the first slot being a pointer to a >> MutableByteArray#, >> >>>>>> >> >>>>>>>>> and >> >>>>>> >> >>>>>>>>> the >> >>>>>> >> >>>>>>>>> next 2 slots pointing to the previous and next >> previous >> >>>>>> >> >>>>>>>>> objects, >> >>>>>> >> >>>>>>>>> represented >> >>>>>> >> >>>>>>>>> just as their MutableArrayArray#s. I can use >> >>>>>> >> >>>>>>>>> sameMutableArrayArray# on these >> >>>>>> >> >>>>>>>>> for object identity, which lets me check for the ends >> of >> >>>>>> >> >>>>>>>>> the >> >>>>>> >> >>>>>>>>> lists by tying >> >>>>>> >> >>>>>>>>> things back on themselves. >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> and below that >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> data Lower s = Lower (MutableArrayArray# s) >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> is similar, with an extra MutableArrayArray slot >> pointing >> >>>>>> >> >>>>>>>>> up to >> >>>>>> >> >>>>>>>>> an >> >>>>>> >> >>>>>>>>> upper structure. >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> I can then write a handful of combinators for getting >> out >> >>>>>> >> >>>>>>>>> the >> >>>>>> >> >>>>>>>>> slots >> >>>>>> >> >>>>>>>>> in question, while it has gained a level of >> indirection >> >>>>>> >> >>>>>>>>> between >> >>>>>> >> >>>>>>>>> the wrapper >> >>>>>> >> >>>>>>>>> to put it in * and the MutableArrayArray# s in #, that >> >>>>>> >> >>>>>>>>> one can >> >>>>>> >> >>>>>>>>> be basically >> >>>>>> >> >>>>>>>>> erased by ghc. >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> Unlike before I don't have several separate objects on >> >>>>>> >> >>>>>>>>> the heap >> >>>>>> >> >>>>>>>>> for >> >>>>>> >> >>>>>>>>> each thing. I only have 2 now. The MutableArrayArray# >> for >> >>>>>> >> >>>>>>>>> the >> >>>>>> >> >>>>>>>>> object itself, >> >>>>>> >> >>>>>>>>> and the MutableByteArray# that it references to carry >> >>>>>> >> >>>>>>>>> around the >> >>>>>> >> >>>>>>>>> mutable >> >>>>>> >> >>>>>>>>> int. >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> The only pain points are >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> 1.) the aforementioned limitation that currently >> prevents >> >>>>>> >> >>>>>>>>> me >> >>>>>> >> >>>>>>>>> from >> >>>>>> >> >>>>>>>>> stuffing normal boxed data through a SmallArray or >> Array >> >>>>>> >> >>>>>>>>> into an >> >>>>>> >> >>>>>>>>> ArrayArray >> >>>>>> >> >>>>>>>>> leaving me in a little ghetto disconnected from the >> rest >> >>>>>> >> >>>>>>>>> of >> >>>>>> >> >>>>>>>>> Haskell, >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> and >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> 2.) the lack of SmallArrayArray's, which could let us >> >>>>>> >> >>>>>>>>> avoid the >> >>>>>> >> >>>>>>>>> card marking overhead. These objects are all small, >> 3-4 >> >>>>>> >> >>>>>>>>> pointers >> >>>>>> >> >>>>>>>>> wide. Card >> >>>>>> >> >>>>>>>>> marking doesn't help. >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> Alternately I could just try to do really evil things >> and >> >>>>>> >> >>>>>>>>> convert >> >>>>>> >> >>>>>>>>> the whole mess to SmallArrays and then figure out how >> to >> >>>>>> >> >>>>>>>>> unsafeCoerce my way >> >>>>>> >> >>>>>>>>> to glory, stuffing the #'d references to the other >> arrays >> >>>>>> >> >>>>>>>>> directly into the >> >>>>>> >> >>>>>>>>> SmallArray as slots, removing the limitation we see >> here >> >>>>>> >> >>>>>>>>> by >> >>>>>> >> >>>>>>>>> aping the >> >>>>>> >> >>>>>>>>> MutableArrayArray# s API, but that gets really really >> >>>>>> >> >>>>>>>>> dangerous! >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> I'm pretty much willing to sacrifice almost anything >> on >> >>>>>> >> >>>>>>>>> the >> >>>>>> >> >>>>>>>>> altar >> >>>>>> >> >>>>>>>>> of speed here, but I'd like to be able to let the GC >> move >> >>>>>> >> >>>>>>>>> them >> >>>>>> >> >>>>>>>>> and collect >> >>>>>> >> >>>>>>>>> them which rules out simpler Ptr and Addr based >> >>>>>> >> >>>>>>>>> solutions. >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> -Edward >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> On Thu, Aug 20, 2015 at 9:01 PM, Manuel M T >> Chakravarty >> >>>>>> >> >>>>>>>>> <c...@cse.unsw.edu.au> wrote: >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> That’s an interesting idea. >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> Manuel >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> > Edward Kmett <ekm...@gmail.com>: >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> > >> >>>>>> >> >>>>>>>>> > Would it be possible to add unsafe primops to add >> >>>>>> >> >>>>>>>>> > Array# and >> >>>>>> >> >>>>>>>>> > SmallArray# entries to an ArrayArray#? The fact that >> >>>>>> >> >>>>>>>>> > the >> >>>>>> >> >>>>>>>>> > ArrayArray# entries >> >>>>>> >> >>>>>>>>> > are all directly unlifted avoiding a level of >> >>>>>> >> >>>>>>>>> > indirection for >> >>>>>> >> >>>>>>>>> > the containing >> >>>>>> >> >>>>>>>>> > structure is amazing, but I can only currently use >> it >> >>>>>> >> >>>>>>>>> > if my >> >>>>>> >> >>>>>>>>> > leaf level data >> >>>>>> >> >>>>>>>>> > can be 100% unboxed and distributed among >> ByteArray#s. >> >>>>>> >> >>>>>>>>> > It'd be >> >>>>>> >> >>>>>>>>> > nice to be >> >>>>>> >> >>>>>>>>> > able to have the ability to put SmallArray# a stuff >> >>>>>> >> >>>>>>>>> > down at >> >>>>>> >> >>>>>>>>> > the leaves to >> >>>>>> >> >>>>>>>>> > hold lifted contents. >> >>>>>> >> >>>>>>>>> > >> >>>>>> >> >>>>>>>>> > I accept fully that if I name the wrong type when I >> go >> >>>>>> >> >>>>>>>>> > to >> >>>>>> >> >>>>>>>>> > access >> >>>>>> >> >>>>>>>>> > one of the fields it'll lie to me, but I suppose >> it'd >> >>>>>> >> >>>>>>>>> > do that >> >>>>>> >> >>>>>>>>> > if i tried to >> >>>>>> >> >>>>>>>>> > use one of the members that held a nested >> ArrayArray# >> >>>>>> >> >>>>>>>>> > as a >> >>>>>> >> >>>>>>>>> > ByteArray# >> >>>>>> >> >>>>>>>>> > anyways, so it isn't like there is a safety story >> >>>>>> >> >>>>>>>>> > preventing >> >>>>>> >> >>>>>>>>> > this. >> >>>>>> >> >>>>>>>>> > >> >>>>>> >> >>>>>>>>> > I've been hunting for ways to try to kill the >> >>>>>> >> >>>>>>>>> > indirection >> >>>>>> >> >>>>>>>>> > problems I get with Haskell and mutable structures, >> and >> >>>>>> >> >>>>>>>>> > I >> >>>>>> >> >>>>>>>>> > could shoehorn a >> >>>>>> >> >>>>>>>>> > number of them into ArrayArrays if this worked. >> >>>>>> >> >>>>>>>>> > >> >>>>>> >> >>>>>>>>> > Right now I'm stuck paying for 2 or 3 levels of >> >>>>>> >> >>>>>>>>> > unnecessary >> >>>>>> >> >>>>>>>>> > indirection compared to c/java and this could reduce >> >>>>>> >> >>>>>>>>> > that pain >> >>>>>> >> >>>>>>>>> > to just 1 >> >>>>>> >> >>>>>>>>> > level of unnecessary indirection. >> >>>>>> >> >>>>>>>>> > >> >>>>>> >> >>>>>>>>> > -Edward >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> > _______________________________________________ >> >>>>>> >> >>>>>>>>> > ghc-devs mailing list >> >>>>>> >> >>>>>>>>> > ghc-devs@haskell.org >> >>>>>> >> >>>>>>>>> > >> >>>>>> >> >>>>>>>>> > >> http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> >> >>>>>> >> >>>>>>>>> _______________________________________________ >> >>>>>> >> >>>>>>>>> ghc-devs mailing list >> >>>>>> >> >>>>>>>>> ghc-devs@haskell.org >> >>>>>> >> >>>>>>>>> >> http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs >> >>>>>> >> >>>>>>> >> >>>>>> >> >>>>>>> >> >>>>>> >> >>>>> >> >>>>>> >> >>> >> >>>>>> >> >> >> >>>>>> >> > >> >>>>>> >> > >> >>>>>> >> > _______________________________________________ >> >>>>>> >> > ghc-devs mailing list >> >>>>>> >> > ghc-devs@haskell.org >> >>>>>> >> > http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs >> >>>>>> >> > >> >>>>>> > >> >>>>>> > >> >>>>> >> >>>>> >> >>>> >> >>>> >> >>>> _______________________________________________ >> >>>> ghc-devs mailing list >> >>>> ghc-devs@haskell.org >> >>>> http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs >> >>>> >> >>> >> >> >> > >> > _______________________________________________ >> > ghc-devs mailing list >> > ghc-devs@haskell.org >> > http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs >> > >> > >
_______________________________________________ ghc-devs mailing list ghc-devs@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs