HN user

glasser

243 karma

i work at meteor development group.

Posts3
Comments31
View on HN
An Analysis of vgo 8 years ago

Darcs was easy to use? Are you referring to the same darcs whose manual tried to explain concepts by making analogies to the simpler and better-understood theory of quantum mechanics?

Threadable is like Google Groups, except that whether or not the default reply-to is "all" is a user preference rather than a group preference, which made me so happy.

(There are other features too, which I entirely ignore without missing anything. In fact, other than "there are some HTML buttons in the email", which will probably also eventually have an option to turn off, our transition from our prior mailing list service was almost unnoticeable for somebody like me who didn't want to use the extra features. And that's a compliment.)

Exactly. Doing that by mistake (and then being taught to set `push.default` to upstream or simple) has been a rite of passage for engineers at my company.

Does Meteor Scale? 13 years ago

Yep, as Arunoda says I'm actively working on it right now, currently hoping for an initial release this month.

I really appreciate the work Arunoda has done on smart collections; my implementation and his package have both learned from each other. That said, there are a number of subtle race conditions involved in synchronizing queries between the oplog and the main database, and working out all the little details as carefully as possible has taken time!

Our understanding of the current level of browser support is actually in a big comment at the beginning of every file aimed at the browser we generate that has a source map :)

    If you are using Chrome, open the Developer Tools and click the gear
    icon in its lower right corner. In the General Settings panel, turn
    on 'Enable source maps'.
    
    If you are using Firefox 23, go to `about:config` and set the
    `devtools.debugger.source-maps-enabled` preference to true.
    (The preference should be on by default in Firefox 24; versions
    older than 23 do not support source maps.)

Yes, but you can statically determine whether or not eval is called.

A world-class JavaScript environment like V8 is far past "the simplest thing that is correct according to the spec".

In fact, the JavaScript spec doesn't actually define anything about garbage collection! You can create a compliant ECMAScript-262 runtime that literally never collects any garbage ever. That's certainly the simplest correct thing. But it's a bad idea!

V8 already goes to the trouble of figuring out whether or not a given variable needs to be stored in the lexical environment or not. Specifically: variables that are not used in ANY closures and where there is no eval in sight can be stored outside of the lexical environment. This is great, and better than many similar programming language environments offer.

It just would be even better if they went one step farther.

OP here. Several people have pointed out that of course I should expect a leak, since each `logIt` object is leaked. That's absolutely true; my point was just that we don't want `str` to leak.

But the original bug that led to this discovery involved a data structure that shouldn't have leaked at all. I've updated the post to show it; duplicated here since GitHub Pages seems to cache posts pretty aggressively.

    var theThing = null;
    var replaceThing = function () {
      var originalThing = theThing;
      // Define a closure that references originalThing but doesn't ever actually
      // get called. But because this closure exists, originalThing will be in the
      // lexical environment for all closures defined in replaceThing, instead of
      // being optimized out of it. If you remove this function, there is no leak.
      var unused = function () {
        if (originalThing)
          console.log("hi");
      };
      theThing = {
        longStr: new Array(1000000).join('*'),
        // While originalThing is theoretically accessible by this function, it
        // obviously doesn't use it. But because originalThing is part of the
        // lexical environment, someMethod will hold a reference to originalThing,
        // and so even though we are replacing theThing with something that has no
        // effective way to reference the old value of theThing, the old value
        // will never get cleaned up!
        someMethod: function () {}
      };
      // If you add `originalThing = null` here, there is no leak.
    };
    setInterval(replaceThing, 1000);

No, actually, you literally have to call eval as a function called eval if you want to get the local lexicals. See sections 10.4.2 and 15.1.2.1.1 of the ECMAScript standard, or try it out:

   > (function () { var x = 5; eval("console.log(x)"); })()
   5
   > (function () { var x = 5; var e = eval; e("console.log(x)"); })()
   ReferenceError: x is not defined

Right, but according to sections 10.4.2 and 15.1.2.1.1 of the ECMAScript standard, you only get lexical bindings inside your `eval` if it's literally a call to a thing called `eval`. (Which I believe is what you meant by "direct `eval`".)

So you should be able to statically determine if this is the case, and it's not here.

I don't know how to look at memory usage in other modern JS interpreters like those used in FireFox and Safari. Anyone able to check to see if they have this problem? (And if they manage to avoid the memory leaks in the first two code samples?)

To be clear: when you say "removing the call to doSomethingWithStr() doesn't change the unbounded memory growth" you do literally mean "removing the call" and not "removing the function definition", right? That matches what I see.

BTW, the original bug in the Meteor codebase wasn't a setInterval.

It was that code to replace a certain type of object (a Spark renderer) with a new instance of that object accidentally ended up with a reference to the preceding renderer in a closure assigned somewhere on it, even though that particular closure didn't actually use that reference.

So instead of replacing renderer #N with renderer #(N+1) and GCing #N, we ended up with a stream of renderers which never could be GCed... even though the reference keeping the old ones alive was literally impossible to ever use.

The surprise isn't that the memory associated with `logIt` is leaked.

The surprise is that `logIt` holds on to the giant `str` object in its environment, despite the fact that there is literally no way for the `str` variable to ever be used again.

V8 is smart enough to not make `logIt` hold on to `str` if there are no closures at all which refer to `str`. It's the introduction of the unrelated `doSomethingWithStr` closure that forces `str` into the lexical environment.

We took inspiration from the great work Tom and Mike did on Meteorite; several of 0.6.0's features are essentially versions of what Meteorite let you do, except for much more deeply integrated into the core. For now, Meteorite is still a great tool for installing packages from Atmosphere into your app... a fully integrated third-party package repository is in the works but isn't part of 0.6.0.

At the office, I do a physical variant of this: when I'm at my desk, I'm in work mode. If I want to spend time doing personal things at the office, I'll go to another area (eg a couch). If nothing else, it's easy for me to notice when I've been there for a while. And it keeps me efficient in either mode.