{"action":"created","issue":{"url":"https://api.github.com/repos/ocsigen/eliom/issues/262","repository_url":"https://api.github.com/repos/ocsigen/eliom","labels_url":"https://api.github.com/repos/ocsigen/eliom/issues/262/labels{/name}","comments_url":"https://api.github.com/repos/ocsigen/eliom/issues/262/comments","events_url":"https://api.github.com/repos/ocsigen/eliom/issues/262/events","html_url":"https://github.com/ocsigen/eliom/issues/262","id":133834629,"number":262,"title":"Memory Management with Client-Side React","user":{"login":"paurkedal","id":144070,"avatar_url":"https://avatars.githubusercontent.com/u/144070?v=3","gravatar_id":"","url":"https://api.github.com/users/paurkedal","html_url":"https://github.com/paurkedal","followers_url":"https://api.github.com/users/paurkedal/followers","following_url":"https://api.github.com/users/paurkedal/following{/other_user}","gists_url":"https://api.github.com/users/paurkedal/gists{/gist_id}","starred_url":"https://api.github.com/users/paurkedal/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/paurkedal/subscriptions","organizations_url":"https://api.github.com/users/paurkedal/orgs","repos_url":"https://api.github.com/users/paurkedal/repos","events_url":"https://api.github.com/users/paurkedal/events{/privacy}","received_events_url":"https://api.github.com/users/paurkedal/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":1,"created_at":"2016-02-15T22:38:05Z","updated_at":"2016-02-16T00:59:50Z","closed_at":null,"body":"Apologise for a somewhat long issue posting, I believe it's a tough issue.\r\n\r\nFirst, I think writing user interfaces with FRP is a bliss, though as far as I'm aware, there is a hard-to-handle memory management issue due to the lack of weak references in the JavaScript standard.  In particular WeakMap is not sufficient to implement weak references needed for FRP.  Weak references have been [proposed](http://wiki.ecmascript.org/doku.php?id=strawman:weak_references), but there are security concerns about opening a side-channels between different agents, see e.g. [this discussion](http://mozilla.6506.n7.nabble.com/What-is-the-status-of-Weak-References-td271746.html).  The issue was also [briefly discussed on the ocsigen list](https://sympa.inria.fr/sympa/arc/ocsigen/2014-10/msg00005.html) some time ago.\r\n\r\nI attach a contrived example which shows the issue.  Open e.g. `/reactive_mm/40` and click around while watching the memory consumption.  Watching the memory consumption takes a bit patience, so I added a counter of the number of leaf signals which were updated.  As can be seen this never decreases, so naturally the updates start to slow down after repeatedly switching pages without reloading the app.\r\n\r\nWhat can be done to mitigate the issue?  Ideally one would come up with a secure proposal for weak references, and lobby for its inclusion in an upcoming JavaScript standard.  That's hard work, and will take time.  For the time being, it would at least be nice with some advice in the documentation.\r\n\r\nDaniel Bünzli mentioned a workaround in the mailing list posed cited above:  When calling `stop ~strong:true` on a signal or event, will detach it from its dependencies, and trigger the same operation recursively for each dependent signal which becomes unused.  This is a working solution for user-created react signals, though it's not very convenient for complex applications.  Also, I don't think this option is currently available for signals embedded in the DOM via `Eliom_content.Html5.R` and friends.\r\n\r\nI have one proposal which may just work.  It only applies where leaf signals are tired to the DOM, but I think that covers the most important use of react on the client side.  The idea is to use the DOM document as a GC root for the signals.  To avoid changes to the react library, one could first implement finalizers for DOM nodes, and used these to perform strong stops on signals which were created via the Eliom `R` modules.  These stops would then cascade to user-created react elements depended on by DOM nodes, while other react elements where left to manual tidying.\r\n\r\nOne issue would be that a strong stop can inadvertently stop a signal which is still to be used. Maybe it's possible to schedule the DOM-finalizers in-between the page (re-)construction work, to avoid this from happening for locally referenced signals, though I'm not sure how Lwt is tied to the event loop, so it might need some though.  React elements stored in globals would still be subject to accidental stops though.\r\n\r\n[reactive_mm.eliom.txt](https://github.com/ocsigen/eliom/files/131548/reactive_mm.eliom.txt)\r\n"},"comment":{"url":"https://api.github.com/repos/ocsigen/eliom/issues/comments/184461089","html_url":"https://github.com/ocsigen/eliom/issues/262#issuecomment-184461089","issue_url":"https://api.github.com/repos/ocsigen/eliom/issues/262","id":184461089,"user":{"login":"vasilisp","id":4950946,"avatar_url":"https://avatars.githubusercontent.com/u/4950946?v=3","gravatar_id":"","url":"https://api.github.com/users/vasilisp","html_url":"https://github.com/vasilisp","followers_url":"https://api.github.com/users/vasilisp/followers","following_url":"https://api.github.com/users/vasilisp/following{/other_user}","gists_url":"https://api.github.com/users/vasilisp/gists{/gist_id}","starred_url":"https://api.github.com/users/vasilisp/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/vasilisp/subscriptions","organizations_url":"https://api.github.com/users/vasilisp/orgs","repos_url":"https://api.github.com/users/vasilisp/repos","events_url":"https://api.github.com/users/vasilisp/events{/privacy}","received_events_url":"https://api.github.com/users/vasilisp/received_events","type":"User","site_admin":false},"created_at":"2016-02-16T00:59:50Z","updated_at":"2016-02-16T00:59:50Z","body":">  Also, I don't think this option is currently available for signals embedded in the DOM via Eliom_content.Html5.R and friends.\r\n\r\nIndeed, we do not expose the strong stops for the signals used inside `Eliom_content.Html5.R`. But this is within our control, and I think we should expose them somehow.\r\n\r\n>  The idea is to use the DOM document as a GC root for the signals. To avoid changes to the react library, one could first implement finalizers for DOM nodes, and used these to perform strong stops on signals which were created via the Eliom R modules.\r\n\r\nCorrect me if I am wrong, but I don't think there is a direct way to implement finalizers in JS. That would be another vector for observing the GC behavior, I guess. At best, we can observe when a node gets removed from the DOM tree, which is not the same, because the programmer may be planning to put it back. Nevertheless, it may be acceptable in practice to impose the constraint that `R` nodes get attached to the DOM once, and once they go away, we stop the signals."}}