<<05-02-2013>>

00:59:44*q66 quit (Quit: Quit)
03:02:38*fowl quit (Quit: Leaving)
03:14:59*Amrykid is now known as Phalanxia
03:19:12*Phalanxia is now known as Amrykid
04:03:29*fowl joined #nimrod
05:12:58*zahary_ quit (Read error: Connection reset by peer)
05:47:50*fowl quit (Read error: Connection reset by peer)
05:50:42*fowl joined #nimrod
06:25:39*fowl quit (Ping timeout: 248 seconds)
07:04:32*Boscop quit (Read error: Connection reset by peer)
07:05:34*Boscop joined #nimrod
07:20:14*fowl joined #nimrod
08:17:04*XAMPP_ joined #nimrod
08:20:36*XAMPP quit (Ping timeout: 264 seconds)
08:21:14*Araq_ joined #nimrod
08:37:04*Boscop quit (Disconnected by services)
08:37:06*Boscop joined #nimrod
08:38:10*Araq_ quit (Quit: ChatZilla 0.9.89 [Firefox 18.0.1/20130116073211])
09:13:43*Araq_ joined #nimrod
10:22:21*Araq_ quit (Quit: ChatZilla 0.9.89 [Firefox 18.0.1/20130116073211])
10:39:58*zahary_ joined #nimrod
10:53:57*fowl quit (Quit: Leaving)
11:17:24*Araq_ joined #nimrod
11:17:36Araq_ping zahary, zahary_
11:33:59*q66 joined #nimrod
11:38:24zahary_hi Araq
11:44:43Araq_oh hi; bad connection here, as usual ...
11:45:16Araq_I've implemented Lins' algorithm for the cycle collector which basically does:
11:45:37Araq_for root: handleSingleRoot(root)
11:45:55*Araq_ quit (Read error: Operation timed out)
11:46:34*Araq_ joined #nimrod
11:47:22Araq_proc handleSingleRoot(r) = decRefGraph(r); if r.rc > 0: freeGraph(r); else: restoreRCs(r)
11:48:23Araq_where both restoreRCs() and freeGraph() only do a linear traversal over the computed graph
11:48:41Araq_so that only decRefGraph() performs the expensive graph traversal
11:49:32Araq_however, we get back the undesirable O(n²) behaviour of Lins' algorithm ...
11:51:56Araq_however, it doesn't work yet for bootstrapping so I have no numbers ...
11:53:22Araq_but I'd guess that for the compiler itself most of the cycle collector's time is spent trying to prove graphs to be dead which are alive; is that correct?
11:57:27Araq_(er, proc handleSingleRoot(r) = decRefGraph(r); if r.rc == 0: freeGraph(r); else: restoreRCs(r) of course)
12:49:27*Araq_ quit (Quit: ChatZilla 0.9.89 [Firefox 18.0.1/20130116073211])
17:34:31*zahary quit (Quit: Leaving.)
17:35:58*zahary joined #nimrod
17:39:25zaharyhi Araq, why did you decide to try Lin's algorithm? our current algorithm (the synchronous cycle collector) is supposed to be a significant improvement over Lin's
17:40:00zaharyWith Lin's, you should pay the big graph traversal price numerous times in each collection instead of just once
19:07:33Araqping zahary
19:10:04zaharyhi
19:12:22Araqwell I still think it's possible to modify Lins' algorithm so that it only takes 1 pass over the graph
19:12:51Araqyou can't do that if you traverse the whole transitive closure at once like in Bacon's algorithm
19:13:03Araqbut I may be wrong ;-)
19:13:34Araqin my pseudo-code the problem is the check 'rc(r) > 0'
19:14:06Araqunfortunately it's not true that the processed graph is dead iff rc(r) == 0
19:14:39Araq(note that I only perform the recDecRef pass in a traditional way)
19:15:17Araqhowever, the graph is dead if: for every processed node n: rc(n) == 0
19:15:32zaharyyou decref the transitive closure, then what?
19:15:32*shevy quit (Ping timeout: 248 seconds)
19:16:06AraqI keep a data structure that I called "speculative table"
19:16:36Araqwhy for every processed node stores what it's RC would be should the graph turn out to be dead
19:16:40zaharyit's a list of visited nodes
19:16:41zahary?
19:16:52Araqand the original RC should the graph turn out to be alive
19:17:02Araqyeah it's a list
19:17:22Araqwell actually it's an array that works as a hash table
19:17:30Araqbut these details don't matter
19:17:38zaharywell, the real problem is that the transitive closure is some 1 million edges in the final collections
19:17:50zaharyedge = ref
19:18:49zaharyI don't think the problem is the complexity of traversing itself, it's the mere size
19:21:09Araqhm quite possible
19:21:20Araqbut it doesn't help you have to traverse it 2-3 times
19:22:00Araqa <-> b -> c
19:22:23zaharywell, with bacon's algorithm you have 2 traversals. as far as I understand you, with Lin's you'll still have to walk over it for each root
19:22:52Araqreally, how is it 2 traversals?
19:23:00Araqdecref, incref, free
19:23:58Araqand yeah with Lins' you have to walk over each root, I some ideas how to fix that though
19:24:33Araqhowever, the real puzzle for now is: what's the condition that the traversed graph is dead?
19:24:51zaharyfreeing is somewhat cheaper, because it traverses only the dead objects
19:25:40zaharywell, what's your idea about fixing it?
19:27:27Araqwell it's only an issue if the graphs are connected
19:27:56*shevy joined #nimrod
19:27:57zaharyand they are
19:28:06Araqso when I traverse the root 'r' I may keep a bit set of processed nodes
19:28:14Araqand check if the other root is in that set
19:28:25Araqif so, I can skip that root
19:28:28Araqwell not really
19:28:30Araqunfortunately
19:29:05Araqbut it could be good enough for a start
19:29:21zaharywell, isn't that what bacon's algorithm is doing after all? it uses efficient coloring scheme to mark processed nodes
19:29:38AraqI know ;-)
19:30:38AraqI don't think I'll beat bacon's algorithm
19:30:50Araqbut I like to know whether my idea can work out
19:31:27Araqso back to the more interesting problem: a <-> b -> c <- d
19:31:39Araq'a' is processed as root
19:31:46Araq'd' keeps 'c' alive
19:32:00Araqhowever a and b are dead
19:32:27Araqso 'for every processed node n: rc(n) == 0' is wrong too
19:32:55Araqas we touch 'c' in the traversal but it's RC is 1 after the traversal
19:33:06zaharyyou are about to rediscover the markAlive pass :)
19:33:17Araqthat's what I fear ...
19:33:38Araqthat's it's not possible and *requires* a pass
19:37:32Araqthe condition 'rc(root) == 0' is wrong too: a <-> b <- e
19:38:06Araqwhould free 'a', but it's still alive
19:44:07Araqfor every inner node n: RC(n) == 0 ?
19:44:37Araqcould work
19:49:38zaharywhat is inner node here?
19:50:34Araqnodes that have at least 1 child
19:51:16Araqfrom the perseptive of the traversal
19:51:24Araq*perspective
19:51:57zaharydoesn't matter, `a` is inner node in your previous example
19:53:44Araqyeah and its RC is 0 after recDecRef
19:53:54Araqbut b's is still 1 so the graph is alive
19:54:42Araqthe point is that leaves don't matter but the rest needs to have RC == 0
19:55:07Araqof course you can't free leaves blindly should the graph be dead
19:55:47zahary© -> a <-> b <- [e]
19:56:57Araqwell?
19:57:01zahary(cycle candidate) [stack root]
19:57:31zahary`a` is inner here and it will have rc=0 after the decref, so what's the algorithms exactly?
19:57:48Araq'a' is the root?
19:57:54Araqor 'c'?
19:57:58zahary( c )
19:58:22zaharybrackets mark roots according to the legend above
19:58:31Araqok good
19:58:51Araqwell 'b' keeps it alive
19:58:59Araqas it's an inner node with RC > 0
19:59:00zaharyafter the mark alive pass, yes
19:59:16Araqno after the decref pass it's RC is 1
19:59:24Araqbefore the pass it's 2
20:00:00zaharyer, what is exactly is happening when we reach `b` in the decref pass?
20:00:14Araqwe process its children
20:00:14zaharydon't we decref the edge towards `a`?
20:00:21Araqyes
20:00:29zaharyso, a becomes 0
20:00:55zaharywe started from `c`
20:00:57Araqyeah but the condition is: for every inner node n: RC(n) == 0
20:01:08Araqand 'b' is an inner node too
20:01:38Araqbecause it has 'a' as a child
20:02:42zaharywell, how does `b` affect `a` after the decref pass? you notice that `a` is reachable from `b`?
20:03:26Araqno I notice within the decref pass that 'b' is an inner node
20:03:46Araqas 'forAllChildren' doesn't produce an empty list for it
20:04:20zaharyso? what we are discussing here is how `a` will get collected
20:04:41Araqwell 'a' is not dead in your example
20:05:42zaharyexactly, but its RC reached 0 so I'm asking what will prevent collecting it
20:07:07Araqwell the RCs will be restored after the decRefPass
20:07:11zaharyanyway, I'll be more interested if you try something more radical instead - like precise stack marking that will allow moving collectors, etc
20:07:34Araqbut I guess 'c' is dead and not collected with this rule
20:08:38Araqprecise stack marking is not necessary for a moving collector
20:08:54Araqyou have to 'pin' the objects referenced from the stack though
20:10:36zaharyit's not very interesting if you can't move short-lived objects (which are more likely to be on the stack)
20:11:49zaharybut it was just an example, tracing collector will be another
20:12:40Araqalright, well I gave up since the inner node rule doesn't work either
20:14:05Araqbtw I thought your "is bit set" template is wrong
20:14:20Araqbut then I figured you use it to conflate different colors
20:15:08Araqand then I wondered whether you can't achieve the same with fewer bits if you try to use <= for color checks
20:16:17zaharywell, there are colors and there are flags that are a bit independent from them
20:16:59zaharyI'm a bit more conservative than the original paper when it comes to dead objects. they are reusing the black color for them
20:17:08zaharyi.e. the "normal" color
20:20:18AraqI had another unrelated idea: the RC value is a probability for "the node is dead"
20:20:41Araqso instead of generations, we could try to group cycle roots by their RC value
20:20:51Araqand process nodes with a low RC value more often
20:21:50zaharywhat you mean is to use some kind of bucketing scheme when we add cycle roots?
20:22:13Araqor if we process them
20:22:50Araqif I'm not mistaken you can always process a subset of all cycle roots to find some garbage
20:23:56zaharyyou grokked why I needed this "trimming" feature, right?
20:24:18AraqI still haven't looked at it ;-)
20:24:35zaharythe problem is that I cannot free objects if they are cycle roots - I don't want to search the cycleRoots array for them, so I just mark them dead and wait for the next collection
20:24:56zaharyso if CollectCycles is disabled, cycleRoots accumulate
20:25:02Araqoh that's what you mean, yeah I know
20:25:14Araqyou could easily 'excl' cycle roots though
20:25:24Araqif you use the TCellSet for them
20:25:59zaharyyes, but my bet is that will slow things down. we should try it do to see how it will affect memory
20:26:46zaharytry it *tho* to see
20:33:24AraqI noticed that you mark the graphs referenced by stack roots alive
20:33:42Araqand don't run the cycle collector on them
20:34:30Araqhowever, it's then a small step to make the codegen register globals to the GC
20:34:41Araqand do the same for graphs referenced by globals
20:36:27zaharycould help, but this heuristic wasn't particularly successful - it hardly changed anything
20:37:07Araqwell then I'd remove it completely; it's dangerous
20:37:21zaharyhow so?
20:37:31Araqthe sweet thing about the current GC is that doesn't trace what hasn't changed
20:39:03Araqit's annoying we have to add the stack roots back to cycleRoots
20:39:14zaharyI see your point. I tried it because it was suggested in one of the papers. there is a switch to disable it iirc
20:42:11Araqso ... if we have cyclic graphs that span millions of nodes
20:42:40Araqhow can we ever deal with them in a realtime setting?
20:43:14Araqit can perform the scans incrementally
20:43:23Araqso that the deadline is never missed
20:43:44Araqbut it can only free things after the whole graph has been traversed
20:44:35Araqwhich is exactly what tracing/copying GCs offer
20:44:43zaharyunfortunately, to do that you need to be able to traverse the heap as it was when you started the traversal (heap shapshots or sliding views)
20:45:15Araqyeah that makes it even worse
20:45:38Araqbut if even we ignore that for a moment
20:45:56AraqI can't imagine this to really help in a realtime setting
20:46:26zaharywhy not?
20:46:31Araqthe nice thing about RC is that it's local and it proves things to be dead without needing the "whole picture"
20:47:32Araqso you can allocate&free within a cycle
20:48:01Araqbut with the other scheme you have a long period where you can't free
20:48:24Araqso my fear would be that it can't keep up with the mutator
20:48:44Araqit doesn't miss a deadline, but the memory usage keeps growing
20:49:44Araqso yeah, I quite like the current setting where you run the cycle collector in batch when you can afford it
20:49:47zaharyI see, but this probably won't be true for many projects
20:51:36Araqperhaps; we'll see
20:55:06Araqbtw I also thought about implementing a simple mark&sweep GC
20:55:35Araqbut the sweep phase is: "free every cell that is not marked alive"
20:56:17Araqand I'm too stupid to see how to implement that efficiently
20:56:41Araqwith the current allocator
20:57:14AraqI guess I could use another datastructure to easily traverse over *every* cell
20:57:32Araqwithout touching the whole heap
20:59:52Araqany better ideas?
21:01:16reactormonkAraq, crash once in a while and let the kernel clean up
21:01:35AraqRuby style, huh?
21:01:44reactormonkunicorn style.
21:16:33zaharywell, I think I remember seeing intrusive doubly linked lists in the original lua GC (the most naive way do it)
21:17:01zaharythe bitmap sweeping in the upcoming luajit GC sounds quite cool.
21:17:45Araqbitmap sweeping is an old hat though
21:17:50zaharyotherwise, it shouldn't be too expensive to traverse the free list for a page populating a map in temporary stack space that indicates with are the allocated slots
21:18:05zahary* which are the *
21:18:26Araqhowever Mike Pall also invented a new write barrier
21:18:33Araqwhich I don't get ;-)
21:19:13zaharyI haven't put much thought in it, but isn't it supposed to be simple?
21:20:20Araqwrite barriers are never simple :P
21:24:50Araqwell actually it's pretty easy to traverse every allocated object with the current allocator
21:25:30Araqbut most of them should be alive
21:25:46Araqand you don't want to touch these
21:27:16Araqhowever 2 TCellSets would work
21:27:16zaharythe most simple mark and sweep probably won't be competitive either
21:27:27Araqone set for the 'alive'
21:27:32Araqone set for 'allocated'
21:30:24Araqhrm I should really implement this; we could pick on a per thread basis which GC to use ...
21:34:56zaharyimplement more infrastructure for GCs - marking global roots, precise marking, etc - then we can put a competition for GC researches for the best implementation :)
21:42:15*FreeArtMan joined #nimrod
21:42:46Araqtrue :D
21:52:22dom96Instacode is pretty nice, and supports Nimrod: http://instacod.es/58918 :D
22:04:44*gradha joined #nimrod
22:10:54*FreeArtMan quit (Ping timeout: 264 seconds)
22:16:57gradhanew forum software http://www.codinghorror.com/blog/2013/02/civilized-discourse-construction-kit.html which will likely be used due to fame/inertia from stackoverflow
22:17:18gradhanot implemented in nimrod though
22:33:58q66dom96, haha nice
22:37:45dom96gradha: This new forum's popularity already makes me jealous.
22:39:19q66dom96, can one add their own language to instacode?
22:39:51dom96q66: I think it uses pygments as the backend, so you simply need to add support for it to pygments.
22:40:04q66aw, python
23:01:14*gradha quit (Quit: bbl, have youtube videos to watch)
23:21:07*XAMPP-8 joined #nimrod
23:33:47*XAMPP-8 quit (Ping timeout: 255 seconds)
23:50:09reactormonklooks like openid is officially dead
23:59:18reactormonkoh wait, they require it in the Gemfile