"Super" hoisting

/#!/JoePea joe at trusktr.io
Fri May 13 16:13:36 UTC 2016


> var x = XPool.get();

I think Brian is saying that local vars are GCed, so that solution doesn't
work (creating many local variables at 60fps)

> Or "Cython in Javascript". I think your needs can be satisfied by C/C++
addons in Node.js or WebAssembly in browser

But we want to stay in JavaScript because we like the language. Plus,
writing a framework in JavaScript has the obvious advantage that a beginner
web programmer can just start using it easily (HTML/JAvaScript is like the
gateway drug of programming nowadays so there's certain advantages to
writing a library in JS as opposed to in C or compiling to WebAssembly).

> I do not understand how having local variable should change any GC pattern
unless you are creating them in the for-loop body.

Having locals in a for-loop is the same as having locals in a function that
gets called at 60fps in an animation loop (which is the case).


On Fri, May 13, 2016 at 8:47 AM, Nicolas B. Pierron <
nicolas.b.pierron at mozilla.com> wrote:

> I do not understand how having local variable should change any GC
> pattern unless you are creating them in the for-loop body.
> Even though, Scalar Replacement optimizations (which are implemented
> in all engine?) should be able to remove these allocations once the
> optimizing JIT is reached, unless the "setFromPoint", "rotate", and
> "average" functions are not inlined.
>
>
> On Fri, May 13, 2016 at 3:09 PM, Herby Vojčík <herby at mailbox.sk> wrote:
> >
> >
> > Brian Barnes wrote:
> >>
> >> It could be, but there is a difference between:
> >>
> >> var x;
> >>
> >> and:
> >>
> >> this.x
> >
> >
> > You should probably do `var x = XPool.get();` and at the end
> `XPool.put(x);`
> > and do `XPool`s for every possible X type which you want to not GC. And
> then
> > happily use local variable, as it should be. If things are not very
> parallel
> > / reentrant, the pools will likely only contains zero / single element.
> >
> >
> >>
> >> Because you’ll get leakage from the last run, so it would probably be
> >> something that would need to be hinted, unless the engine was smart
> enough
> >> to reset everything it hoisted (which is doable) but not optimal, as you
> >> might always know that will be discarded (a really smart engine could
> >> probably figure this out.)
> >>
> >> Again, all this is to try to eliminate GC as much as possible.  It’s
> not a
> >> philosophical argument, GC has pros and cons, it’s just bad for
> performance
> >> sensitive stuff like games.  I do this all by hand now, so a super hoist
> >> would just eliminate a lot of hard to read code I’ve written!
> >>
> >> [>] Brian
> >>
> >>> On May 13, 2016, at 10:43 AM, Alan Johnson<alan at breakrs.com>  wrote:
> >>>
> >>> Sounds like a potential JS engine optimization, rather than a language
> >>> feature per se.
> >>>
> >>>
> >>>> On May 12, 2016, at 1:53 PM, Brian Barnes<ggadwa at charter.net>  wrote:
> >>>>
> >>>> Not by my testing, at least.
> >>>>
> >>>> My original example is a simple one to explain what the procedure is.
> >>>> Here’s a more complex example, from my code, from my mesh classes.
> This
> >>>> function updates the vertices in the mesh based on the position of
> the bones
> >>>> of a skeleton, it gets called every frame for every model mesh that
> can be
> >>>> seen in the scene:
> >>>>
> >>>>    updateVertexesToPoseAndPosition(view,skeleton,angle,position)
> >>>>    {
> >>>>        var n,v;
> >>>>        var bone,parentBone;
> >>>>
> >>>>            // move all the vertexes
> >>>>
> >>>>        var vIdx=0;
> >>>>        var nIdx=0;
> >>>>
> >>>>        for (n=0;n!==this.vertexCount;n++) {
> >>>>            v=this.vertexList[n];
> >>>>
> >>>>                // bone movement
> >>>>
> >>>>            bone=skeleton.bones[v.boneIdx];
> >>>>
> >>>>            this.rotVector.setFromPoint(v.vectorFromBone);
> >>>>            this.rotVector.rotate(bone.curPoseAngle);
> >>>>
> >>>>            this.rotVector.x=bone.curPosePosition.x+this.rotVector.x;
> >>>>            this.rotVector.y=bone.curPosePosition.y+this.rotVector.y;
> >>>>            this.rotVector.z=bone.curPosePosition.z+this.rotVector.z;
> >>>>
> >>>>            this.rotNormal.setFromPoint(v.normal);
> >>>>            this.rotNormal.rotate(bone.curPoseAngle);
> >>>>
> >>>>                // average in any parent movement
> >>>>
> >>>>            if (v.parentBoneIdx!==-1) {
> >>>>                parentBone=skeleton.bones[v.parentBoneIdx];
> >>>>
> >>>>
> >>>> this.parentRotVector.setFromPoint(v.vectorFromParentBone);
> >>>>                this.parentRotVector.rotate(parentBone.curPoseAngle);
> >>>>
> >>>>
> >>>>
> this.parentRotVector.x=parentBone.curPosePosition.x+this.parentRotVector.x;
> >>>>
> >>>>
> this.parentRotVector.y=parentBone.curPosePosition.y+this.parentRotVector.y;
> >>>>
> >>>>
> this.parentRotVector.z=parentBone.curPosePosition.z+this.parentRotVector.z;
> >>>>
> >>>>                this.parentRotNormal.setFromPoint(v.normal);
> >>>>                this.parentRotNormal.rotate(parentBone.curPoseAngle);
> >>>>
> >>>>                this.rotVector.average(this.parentRotVector);
> >>>>                this.rotNormal.average(this.parentRotNormal);
> >>>>            }
> >>>>
> >>>>                // whole model movement
> >>>>
> >>>>            this.rotVector.rotate(angle);
> >>>>
> >>>>            this.drawVertices[vIdx++]=this.rotVector.x+position.x;
> >>>>            this.drawVertices[vIdx++]=this.rotVector.y+position.y;
> >>>>            this.drawVertices[vIdx++]=this.rotVector.z+position.z;
> >>>>
> >>>>            this.rotNormal.rotate(angle);
> >>>>
> >>>>            this.drawNormals[nIdx++]=this.rotNormal.x;
> >>>>            this.drawNormals[nIdx++]=this.rotNormal.y;
> >>>>            this.drawNormals[nIdx++]=this.rotNormal.z;
> >>>>        }
> >>>>
> >>>>            // set the buffers
> >>>>
> >>>>        var gl=view.gl;
> >>>>        gl.bindBuffer(gl.ARRAY_BUFFER,this.vertexPosBuffer);
> >>>>
> gl.bufferData(gl.ARRAY_BUFFER,this.drawVertices,gl.DYNAMIC_DRAW);
> >>>>
> >>>>        gl.bindBuffer(gl.ARRAY_BUFFER,this.vertexNormalBuffer);
> >>>>        gl.bufferData(gl.ARRAY_BUFFER,this.drawNormals,gl.STATIC_DRAW);
> >>>>    }
> >>>>
> >>>> Notice that rotVector, rotNormal, parentRotVector, and
> parentRotNormal,
> >>>> are all “this”, i.e., globals.  They are *only* used in this
> function, no
> >>>> where else in the class.  If I put them as local variables, I get
> enormous
> >>>> GC pauses.  If I don’t, I get none (granted, I have to do this
> everywhere,
> >>>> so it’s just not this function.)
> >>>>
> >>>> The example I gave existed only to show how it would work; not a real
> >>>> example.  Here’s a real example, that shows obvious problems with
> local
> >>>> variables.  Yes, these are objects.
> >>>>
> >>>> Not that moving the objects would ONLY be something that happened at
> >>>> compile time and would be a hint; they wouldn’t be effected in the
> warm up
> >>>> runs.  You’d almost have to say that same hint would force a compile
> (which
> >>>> has it’s own problems.)
> >>>>
> >>>> [>] Brian
> >>>>
> >>>>> On May 12, 2016, at 1:33 PM, Allen Wirfs-Brock<allen at wirfs-brock.com
> >
> >>>>> wrote:
> >>>>>
> >>>>>
> >>>>>> On May 12, 2016, at 9:39 AM, Brian Barnes<ggadwa at charter.net>
> wrote:
> >>>>>>
> >>>>>> ...
> >>>>>> If I call doSomething a lot of times, I get a lot of objects to be
> >>>>>> tracked and GC’d.  Yes, I can rewrite that code to obviously
> eliminate them,
> >>>>>> but pretend there is actually something interesting happening here
> that
> >>>>>> requires those variables.  And engines can be smart enough to mark
> them and
> >>>>>> deal with them with the function ends (I don’t know if this is
> done.)
> >>>>>>
> >>>>>> What I’m thinking is some kind of class based hint that would
> “super”
> >>>>>> hoist all local function variables.  It would be sugar but it would
> >>>>>> transform it into:
> >>>>>>
> >>>>>
> >>>>>
> >>>>> Local variables like a,b,c in your example are probably the least
> >>>>> expensive construct in JS. In your example, there are no objects
> created by
> >>>>> doSomething, not state that persists after doSomething  returns, and
> no GC
> >>>>> pressure. Anything you do WRT moving such local state into object
> properties
> >>>>> is going to be more expensive.
> >>>>>
> >>>>> Allen
> >>>>>
> >>>> _______________________________________________
> >>>> es-discuss mailing list
> >>>> es-discuss at mozilla.org
> >>>> https://mail.mozilla.org/listinfo/es-discuss
> >>
> >>
> >> _______________________________________________
> >> es-discuss mailing list
> >> es-discuss at mozilla.org
> >> https://mail.mozilla.org/listinfo/es-discuss
> >
> > _______________________________________________
> > es-discuss mailing list
> > es-discuss at mozilla.org
> > https://mail.mozilla.org/listinfo/es-discuss
>
>
>
> --
> Nicolas B. Pierron
> _______________________________________________
> es-discuss mailing list
> es-discuss at mozilla.org
> https://mail.mozilla.org/listinfo/es-discuss
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20160513/2f495986/attachment-0001.html>


More information about the es-discuss mailing list