Skip to main content

News

Topic: Link.js v0.4.2 (Read 47371 times) previous topic - next topic

Re: [code] Query.js for Sphere
Reply #15
I wrote a slightly nasty reply to your post (I'm not hugely partial to being called an asshole), but decided against posting it. I did not mean my post which you replied to to be inflammatory.

Instead I simply want to cover two things.


  • I actually think if (!(typeof func == "function")) is incredibly ugly, partly because it looks noisy and because that's exactly what the != operator is for. In case you hadn't noticed yet, I tend to be strongly opinionated. The "incredibly ugly" is not meant to be harsh on you, simply harsh on that bit of odd code. Try to detach from your code a bit.

  • The second is your statement "I should also mention nobody wants to hear that their code is inferior." I think this is a very poor bit of reasoning and a useless statement in general. If you don't hear that your code is inferior in some way, you won't improve. One of the first things a graphic designer (or really anyone in a creative profession) learns is to kill one's work. The faster one can detach, look objectively, and realize that one's stuff is crap, the faster one gets better. That definitely applies to programming as well. Maybe it's painful to hear that one's creation has some warts, but those are simply spots that can be improved.



I'm getting irritated by your tone of voice writing. The Big Lebowski quote is simply not necessary here, nor is "apologizing" for not making something the best way possible. Sorry you didn't hear from me what you wanted. I'm not around to make you feel good about your code and have no qualms using adjectives that mean what I want.

  • Radnen
  • [*][*][*][*][*]
  • Senior Staff
  • Wise Warrior
Re: [code] Query.js for Sphere
Reply #16
Quote
I actually think if (!(typeof func == "function")) is incredibly ugly, partly because it looks noisy and because that's exactly what the != operator is for. In case you hadn't noticed yet, I tend to be strongly opinionated. The "incredibly ugly" is not meant to be harsh on you, simply harsh on that bit of odd code. Try to detach from your code a bit.


I do admit, it was stylistically not the best choice to have done that. Just today I made the same remark about code style on this page: http://msdn.microsoft.com/en-us/library/cc221403(v=vs.95).aspx, it's pretty bad! :P

Quote

The second is your statement "I should also mention nobody wants to hear that their code is inferior." I think this is a very poor bit of reasoning and a useless statement in general. If you don't hear that your code is inferior in some way, you won't improve. One of the first things a graphic designer (or really anyone in a creative profession) learns is to kill one's work. The faster one can detach, look objectively, and realize that one's stuff is crap, the faster one gets better. That definitely applies to programming as well. Maybe it's painful to hear that one's creation has some warts, but those are simply spots that can be improved.


Well the inferior part can certainly be true, think on the Lewboski quote. I'm not calling you an asshole, remember it's Walter in the quote (though by extension I'm calling you the Walter). It's the idea behind the quote. See, my code is inferior, and I see it now - to Lazy.js - and feature incomplete - compared to the others - but as it stands it's not so bad. I just think it's how you say it. So perhaps it's not that people don't want to hear their code is inferior, they do, but not in such a spartan way. I don't recall Lazy.js calling Underscore inferior.

TBH: I dreaded the day you read this and remark on it. You might think that would encourage me to write better, but not until Lazy.js I had no clue how I could have sped it up. I legitimately thought it was a rather appreciable piece of code I wrote, even for your eyes. Remember, I'm the guy who shied away from using functional programming techniques in my own code (like foreach), and you railed me on that that one time. ;)

Yet... All things considered I still don't think what I wrote is bad or inferior in any way. And I can simply ignore you this time. :)
  • Last Edit: December 30, 2013, 02:37:41 am by Radnen
If you use code to help you code you can use less code to code. Also, I have approximate knowledge of many things.

Sphere-sfml here
Sphere Studio editor here

  • N E O
  • [*][*][*][*][*]
  • Administrator
  • Senior Administrator
Re: [code] Query.js for Sphere
Reply #17
...Okay.

Can we return to civility please before I lock this topic? I have a funny feeling it's going to get out of hand again if one or both sides start taking programming style critique too seriously, and I'm reasonably sure critique can be given objectively without devolving into ad hominem.

Re: [code] Query.js for Sphere
Reply #18

This is kinda useful, but IMO it's just another example of NIH syndrome in the Sphere community. It just doesn't do things as well as Underscore, Lo-Dash, or Lazy.js.


Don't take this the wrong way. This is, what I feel, the bright side of how Sphere has historically been built, and how this community has operated:

I'd argue that a certain amount of NIH is one of the things that makes this community great. On the one hand, we don't seem to fear digging in and building things from scratch, for whatever reason.
On the other hand, the whole Sphere-scene has always had a lot of what I call 'American' programming. Almost everything is built right here, for Sphere (consider that we have all our own resource file formats, Audiere and Corona, and long ago SphereScript). It might not be the best, fastest, or most efficient implementation, but we built it ourselves. Because that's what you do--an older American creed--you build things yourself.

You can waste a lot of time making things from scratch that turn out to be of lesser quality, true. But on the other hand, you can sometimes make things better. Sometimes just because you can make more assumptions about usage, sometimes because no one else seriously tried to reinvent it.

And sometimes you reinvent things just because you wanted to  :)
  • Last Edit: December 30, 2013, 10:02:54 pm by Flying Jester

  • Radnen
  • [*][*][*][*][*]
  • Senior Staff
  • Wise Warrior
Re: [code] Query.js for Sphere
Reply #19
It actually turns out you really can't use underscore, etc. in Sphere 1.5/1.6, the shallow memory threshold cuts off anything interesting. Which means yes, they may work, and especially for Lazy.js, you can't do big data in Sphere.

So... a lightweight query library like mine is actually a very good way to go in Sphere. :)

Lazy.js does not work in 1.5/1.6, it errors when writing to variables that are named keywords (due to earlier versions of ECMA). It does however work in SSFML.

Here's the interesting thing:
Code: (javascript) [Select]

var t2 = GetTime();
for (var i = 0; i < 25000; ++i) {
var d = "";
var a = Query.from([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]).map(timesten).where(even).foreach(function(i) { d += i + ", " });
}
t2 = GetTime() - t2;

var t3 = GetTime();
for (var i = 0; i < 25000; ++i) {
var c = "";
var a = Lazy([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]).map(timesten).filter(even).forEach(function(i) { c += i + ", " });
}
t3 = GetTime() - t3;

Abort("Query: " + t2 + "\nLazy: " + t3);


The output:
Query: 1190ms
Lazy: 1656ms

Lazy.js is slower. But why!? Because it's not doing what it was designed for: big data (see below for more). Anyways this does go to show my code isn't that inferior, in fact throwing around the term inferior without seeing results is kind of a wrong thing to do. It works in older versions of Sphere and is faster in SSFML. That makes my initial premise true: it is indeed efficient. But! I still think there is a way to make it go faster, and work. I'm working on an experimental version of Query.js that works like a compiler (creates a tree/sequence of the functional logic, and then performs it in one pass). I'm seeing some promising results on big data in SSFML, but it needs more work to truly be efficient. It may not be better than Lazy (that guy's a genius) but it should still be much faster.

Now, the good stuff! On this:
Code: (javascript) [Select]

var d = "";
var a = Query.from(genArray(200000)).map(timesten).where(even).foreach(function(i) { d += i + ", " });
var c = "";
var b = Lazy(genArray(200000)).map(timesten).filter(even).forEach(function(i) { c += i + ", " });


a took 500+ ms
b took 300+ ms

So on big data, Lazy wins, but in a real time action game you want to do a lot of short data fast. So... Query turns out to work faster for that. Lazy is a data thing, Query is a game thing. Now, yes, there will come a time where you want to use Query for data - item lists, npc lists, etc. - So therefore, I'm working on an implementation that will work for larger data in Sphere.

Query2 is coming along nicely. Doing the above over 200000 elements, the times are:
Query: 531ms
Lazy: 363ms
Query 2: 447ms

So, I'm in a middle-ground so far. :)
  • Last Edit: January 01, 2014, 03:22:12 am by Radnen
If you use code to help you code you can use less code to code. Also, I have approximate knowledge of many things.

Sphere-sfml here
Sphere Studio editor here

  • Radnen
  • [*][*][*][*][*]
  • Senior Staff
  • Wise Warrior
Re: [code] Query.js for Sphere
Reply #20
Query 2 is coming along nicely

One more benchmark to show how Query 2 handles stress (do a lot of work, but only request the first 3 items):
Code: (javascript) [Select]

var t1 = GetTime();
var b = Query.from(genArray(2000000)).where(even).map(timesten).where(even).take(3).foreach(add);
t1 = GetTime() - t1;

var t2 = GetTime();
var c = Lazy(genArray(2000000)).filter(even).map(timesten).filter(even).take(3).each(add);
t2 = GetTime() - t2;

var t3 = GetTime();
var a = Query2.from(genArray(2000000)).where(even).map(timesten).where(even).take(3).each(add);
t3 = GetTime() - t3;

Abort("Query: " + t1 + "\nLazy: " + t2 + "\nQuery 2: " + t3 + "\n");


Times:
Query: 3255ms
Lazy: 911
Query 2: 945

So, Query 2 here is what I'll consider on par with Lazy. The only reason it is a tad slower has to do with traversing the underlying data structure.

And here is the winner that kicks Lazy in the down-right ass:
Code: (javascript) [Select]

var t1 = GetTime();
var b = Query.from(genArray(2000000)).where(even).map(timesten).where(even).foreach(add);
t1 = GetTime() - t1;

var t2 = GetTime();
var c = Lazy(genArray(2000000)).filter(even).map(timesten).filter(even).each(add);
t2 = GetTime() - t2;

var t3 = GetTime();
var a = Query2.from(genArray(2000000)).where(even).map(timesten).where(even).each(add);
t3 = GetTime() - t3;

Abort("Query: " + t1 + "\nLazy: " + t2 + "\nQuery 2: " + t3 + "\n");


Times:
Query: 3887ms
Lazy: 2135ms
Query 2: 930ms

I... I really think I'm on to something magnificent here in how to handle large data with compiler techniques.

Thank you Alpha for motivating me. :)

Edit: The current Query 2 API (subject to immense changes):
Code: (text) [Select]

chainable:
take(n)   - take the first n results.
first(fn) - take first satisfying item, or if no function, the very first item.
map(fn)   - perform a map operation with fn.
where(fn) - perform a filter using fn as the predicate.
get(num)  - tries to get the indexed item.
uniq()    - filters out items so only a unique list remains.
last()    - grabs the last result.
-x- random()  - selects a random result. --- TODO

non-chainable:
each(fn)         - performs the query, running the results through a function.
toArray()        - perform the query, returning an array.
contains()       - performs the query, return true if it satisfies the predicate.
every(fn)        - perform the query, checking to see if all items satisfies the predicate.
reduce(fn, memo) - perform the query, reducing the results, starting at memo, or if not, the first item.


Hmm, I think I need a better sounding name than "Query 2". I'm thinking of "Dash".

Edit:
It's actually slower than Lazy right now. :/ Darn. Why: It's taking too much time to go through the chain. I'm amazed that Lazy.js is near equal to the hand-written for loop version (sometimes, faster).
  • Last Edit: January 01, 2014, 09:02:53 pm by Radnen
If you use code to help you code you can use less code to code. Also, I have approximate knowledge of many things.

Sphere-sfml here
Sphere Studio editor here

  • Radnen
  • [*][*][*][*][*]
  • Senior Staff
  • Wise Warrior
Re: [code] Query.js for Sphere
Reply #21
Update, More Performance

So, it depends on the query structure if Query 2 is faster than Lazy... But they are now mostly the same speed.

Code: (javascript) [Select]

var arr = genArray(200000); // an array: [0, 1, 2, ..., 199999];

test.addTest("Query Performance", function() {
Query2.from(arr).map(add).where(even).map(add).each(noop);
}, 10);

test.addTest("Lazy Performance", function() {
Lazy(arr).map(add).where(even).map(add).each(noop);
}, 10);

Abort(test.run());


Times:
Query: 194ms
Lazy: 197ms

But if I order them differently, sometimes Lazy wins. So I need to work on optimizing Query 2, whose 'lazy evaluator' is not it's end-all. I can do compiler-like optimizations to it, by doing different things depeding on various states, such as going to a more efficient unique checker if the input is sorted or not, etc.

Code: (javascript) [Select]

var arr = genArray(200000);

test.addTest("Query Performance", function() {
Query2.from(arr).map(timesten).where(even).each(noop);
}, 10);

test.addTest("Lazy Performance", function() {
Lazy(arr).map(timesten).where(even).each(noop);
}, 10);

Abort(test.run());


Times:
Query: 144ms
Lazy: 184ms

Code: (javascript) [Select]

var arr = genArray(200000);

test.addTest("Query Performance", function() {
Query2.from(arr).where(even).map(add).where(even).each(noop);
}, 10);

test.addTest("Lazy Performance", function() {
Lazy(arr).where(even).map(add).where(even).each(noop);
}, 10);

Abort(test.run());


Times:
Query: 140ms
Lazy: 110ms

I just realized, Query 2 has a really fast mapper!

Code: (javascript) [Select]

var arr = genArray(200000);

test.addTest("Query1 Performance", function() {
Query.from(arr).map(add).map(add).map(add).where(even).map(add).foreach(noop);
}, 5);

test.addTest("Query2 Performance", function() {
Query2.from(arr).map(add).map(add).map(add).where(even).map(add).each(noop);
}, 1);

test.addTest("Lazy Performance", function() {
Lazy(arr).map(add).map(add).map(add).where(even).map(add).each(noop);
}, 1);

Abort(test.run());


Times:
Query 1: 687
Query 2: 283
Lazy: 497
  • Last Edit: January 02, 2014, 02:23:46 am by Radnen
If you use code to help you code you can use less code to code. Also, I have approximate knowledge of many things.

Sphere-sfml here
Sphere Studio editor here

Re: [code] Query.js for Sphere
Reply #22
Is that the best you've got?

Code: [Select]

function even(n) { return n % 2 == 0 }
function add1(n) { return n + 1 }
function div3(n) { return n / 3 }
function isInt(n) { return Math.floor(n) == n }
function noop() { }

var t1 = GetTime()
Query.from(range(500000)).where(even).map(add1).map(div3).where(isInt).foreach(noop)
t1 = GetTime() - t1

var t2 = GetTime()
Lazy(range(500000)).filter(even).map(add1).map(div3).filter(isInt).each(noop)
t2 = GetTime() - t2

var t3 = GetTime()
For(range(500000)).filter(even).map(add1).map(div3).filter(isInt).each(noop)
t3 = GetTime() - t3


Query: 2029ms
Lazy.js: 2225ms
For.js: 1488ms

Yes I'm doing black magic.

Incidentally, I'm surprised how fast Query manages to be. I guess I was a bit hard on it initially.


Thank you Alpha for motivating me. :)

You're welcome. Your progress has motivated me to try some stuff too. :)
As you can see, I've started on my own version as well. It's 1AM here and I need to get some sleep, but I'll post about it tomorrow.
  • Last Edit: January 04, 2014, 02:57:21 am by alpha123

  • Radnen
  • [*][*][*][*][*]
  • Senior Staff
  • Wise Warrior
Re: [code] Query.js for Sphere
Reply #23
I started testing Query2 in an actual JS environment (Google Chrome) and you wouldn't believe the speeds:

On map -> where, Query2 is about 6 times faster than Lazy.
Query 2: 34ms
Lazy: 214ms

On where -> map, Query2 is about 3 times faster than Lazy.
Query 2: 46ms
Lazy: 123ms

HINT: Query 2 turns map-where and where-map into a single "instruction" during it's optimizer phase (also where-where and map-map). The downside to this is the optimizer can take a while to perform, so the above was used with cached values, ie:

Code: (javascript) [Select]

var arr = genArray(25000000);

var Q = Query2.from(arr).map(add).where(even);
var L = Lazy(arr).map(add).where(even);

test.addTest("Query", function() {
var n = Q.each(noop);
}, 10);

test.addTest("Lazy", function() {
var n = L.each(noop);
}, 10);


That effectively prevents the optimizer from kicking in each time.

BTW, on take() they perform at the same speed, which is critical: you don't want to do a million things before you realize you only needed 10 items.

Soon, I'll release this to the public and get fame and glory and what-not. :P But right now it's still very rough and mad-scientist-like at places.

edit: On the pattern you had matched:
where(even) -> map(add1) -> map(div3) -> where(isInt)

I get the times on a range of 25000000 ints:

Query 2: 93ms
Lazy: 631ms
Query 1: 1210ms

Query2 is 6.7 times faster than Lazy, and 13 times faster than Query 1. :)
  • Last Edit: January 04, 2014, 06:19:22 am by Radnen
If you use code to help you code you can use less code to code. Also, I have approximate knowledge of many things.

Sphere-sfml here
Sphere Studio editor here

Re: [code] Query.js for Sphere
Reply #24
*jaw drops*

What new devilry is this?

I'm really impressed Radnen, and quite eager to see the source code of Query2.

In the latest Chrome with an array of 25000000 numbers, I get:
Query: 2137ms
Lazy.js: 826ms
For.js: 156ms

5.3x faster than Lazy.js and 13.7x faster than Query1. May the speed games begin. ;) Looks like I have some work to do. :P

For.js takes a completely different approach from Query2. It takes all the method calls and compiles a plain-JavaScript for loop from them. This, surprisingly, is actually not as much faster than Lazy.js as I thought, much less Query2. The filter -> map -> map -> filter test case I gave is actually contrived to be very advantageous to For.js. It is capable of inlining the even, add1, div3, and isInt functions right into the compiled loop. JavaScript function calls have a fairly big overhead (especially in Sphere), but I never knew just how significant it was until I tried this. Obviously it's not enough to be noticeable in normal usage, but when iterating over huge arrays I was able to shave off several hundred milliseconds.

Here's an example:
Code: [Select]

For(nums).filter(even).map(add1).map(div3).filter(isInt).each(noop)

gets compiled into
Code: [Select]

function (s, l, b, p, f, a) {
  for(;a=s[b],b<l;++b){if(!(a%2==0))continue;a=a+1;a=a/3;if(!(Math.floor(a)==a))continue;f(a,b)
}

Note the lack of any reference to even, isInt, etc. This only works for a pretty small class of functions, but they happen to be the ones usually used for map, filter, reduce, every, etc; i.e. one-statement functions that aren't closures.

Now the question remains: What on earth did you do to get 6.7x faster than Lazy.js!?

EDIT: I gave it some testing and the inlining saves around 1100ms, give or take 100. So it's definitely a big win, but now I need to find some other way to lose another ~60ms.
  • Last Edit: January 04, 2014, 12:53:22 pm by alpha123

  • N E O
  • [*][*][*][*][*]
  • Administrator
  • Senior Administrator
Re: [code] Query.js for Sphere
Reply #25

gets compiled into
Code: [Select]

function (s, l, b, p, f, a) {
  for(;a=s[b],b<l;++b){if(!(a%2==0))continue;a=a+1;a=a/3;if(!(Math.floor(a)==a))continue;f(a,b)
}



I already see a couple optimizations there, unless there's something above Sphere's JS that makes (!(a%2==0)) faster than (a%2!==0) or (a&1>0).


  • The aforementioned a%2 optimization
  • add1 becoming ++a instead of a=a+1
  • Replacing Math.floor(a)==a with (a|0)==a (or === if one wants to truly be pedantic)


For div3 I've personally never seen a significantly measurable difference between a=a/3 and a=a*0.333333333333333333333333333333333 (or however many digits a double can go until precision is lost) so that one may be in its most optimized form.

In JS, I subscribe to the FBNil school of optimization ;)

Re: [code] Query.js for Sphere
Reply #26


  • The aforementioned a%2 optimization
  • add1 becoming ++a instead of a=a+1
  • Replacing Math.floor(a)==a with (a|0)==a (or === if one wants to truly be pedantic)



Can't say for Sphere's JS, but in V8 ++a and a++ are identical performance in almost every regard.
I would assume that a>>0 is faster than Math.floor(a), if only because of asm.js.

Re: [code] Query.js for Sphere
Reply #27
@NEO: The reason it doesn't perform those is because those would require actually parsing the inlined functions. Currently it simply tokenizes them and does some very basic parsing to verify that they're safe to inline. It then does a little more parsing to replace variable names, but never at any point generates a proper AST. I could consider that, especially since in the end I'll likely be creating an AST of some sort from the method calls to then compile to the for loop. I currently think full parsing of functions would add significant overhead for relatively small gain, but if anyone can think of some really useful optimizations that involve rewriting the input to higher-order functions I could implement a parser and compiler.

Your first optimization is actually implemented now, because I restructured a bit of the compilation so that it avoids the continue altogether by wrapping the rest of the code in a non-negated if statement. The example now compiles to
Code: [Select]

function (s, l, b, p, f, a) {
  for(;a=s[b],b<l;++b){if(a%2==0){a=a+1;a=a/3;if(Math.floor(a)==a){f(a,b)}}
}

mainly because it's shorter (invoking the Function constructor has high overhead, so the less I feed it the better) and simpler (one less operation).

I believe n|0 is the fastest Math.floor()-type thing, but none of the bitwise hacks are quite equivalent to Math.floor() with regard to negative numbers. So it couldn't do that type of optimization automatically, although isInt() could be written with n|0 and For.js would still happily inline it.

I have been paying more attention than usual (i.e. none) to FBNil's School of Micro-Optimizations for this, because it's meant to be blazing fast even in Sphere 1.5. Still, I think at this point I'm likely to get bigger gains by doing less work, not by doing work faster. Whatever Radnen is doing, I imagine it's aggressively delaying evaluation to avoid doing much work. For.js does not do as much of that currently. His architecture lends itself more to that sort of thing; For.js would need some restructuring and probably a proper optimizing compiler to achieve that level. At the moment it relies mainly on clever and bizarre things like decompiling and inlining functions. Which if I may say so is pretty darn sick, but has only very small gains from this point and is of limited utility anyway since it's only possible for a few functions.

  • Radnen
  • [*][*][*][*][*]
  • Senior Staff
  • Wise Warrior
Re: [code] Query.js for Sphere
Reply #28
Alpha123: I had the exact same idea, but then I realized how much trouble it would be to create a feature complete thing like Lazy. Also, it's kinda like cheating. :P

My trick is to back out of execution when you no longer need it. I use the function stack frame heavily. My Where()'s are not as fast as Lazy's, but my WhereMap()'s are faster than Lazy's, it's on longer queries I get faster. I think for that instance your code may be faster than mine. It has, after all far more optimization potential, but at the expense of a lot of creator-struggle.

Oh, and in Sphere Query2 at least works, but it is flawed: Sphere's JS has bad stack-frame performance, so much so it can be worse that Query at times. So a for-loop generator like yours is perhaps the only best option. But in a good environment like Chrome, it's starting to be clear just how much faster than Lazy my code is by witnessing the speed gains from their more powerful stack frame handling.
  • Last Edit: January 04, 2014, 03:48:23 pm by Radnen
If you use code to help you code you can use less code to code. Also, I have approximate knowledge of many things.

Sphere-sfml here
Sphere Studio editor here

Re: [code] Query.js for Sphere
Reply #29

Alpha123: I had the exact same idea, but then I realized how much trouble it would be to create a feature complete thing like Lazy. Also, it's kinda like cheating. :P

In order to reasonably achieve feature-completeness and extensibility, For.js actually uses two types of methods: the ones that are compiled into the loop, like map() and filter()--these are the ones that have to be fast. For other, less common methods it simply calls out to regular functions, although that is not completed yet I had a prototype that was capable of it so it's at least doable.
I thought it would be a relatively easy way to get good performance too, until I was barely beating (and often losing to) Lazy.js even in Sphere 1.6. xP Then I got out the bag of JS black magic. I'm still amazed by how much function inlining boosts performance, even in a modern environment like Chrome. With function inlining off it's consistently ~200ms slower than Lazy.js on the 25m element array. Whatever Lazy.js does, it's very, very good. Since function inlining is fundamentally rather limited I need to come up with some more general optimizations to beat it, let alone Query2. Cheating is hard. :(

Quote

My trick is to back out of execution when you no longer need it.

I'm wondering if I can pull something like this off with aggressive usage of break and continue. The data flow in Query2 makes this a lot easier for you, I think.

Quote

It has, after all far more optimization potential, but at the expense of a lot of creator-struggle.

I think yours has more potential for algorithmic optimizations which are usually more effective. On the other hand, my type of inlining is simply not possible in your system, and it's a big win for the common case.
Oddly enough For.js is only around ~550 lines right now, and I think at least 30% of that is documentation and comments explaining what the heck I'm doing. Granted, the API is very small, but the core parts are in place. The creator-struggle hasn't bitten me quite yet (although perhaps the fact that at least 30% of the code is comments means it actually has...).

Quote

Oh, and in Sphere Query2 at least works, but it is flawed: Sphere's JS has bad stack-frame performance, so much so it can be worse that Query at times. So a for-loop generator like yours is perhaps the only best option. But in a good environment like Chrome, it's starting to be clear just how much faster than Lazy my code is by witnessing the speed gains from their more powerful stack frame handling.

Could you try trampolining the function calls to avoid creating extra stack frames? I'm not quite sure how your code works, but people have been able to sort of implement tail-call optimization that way. Emulating the stack in JS is rather expensive though, so you'd have to weight the benefits against some possibly large overhead.
  • Last Edit: January 04, 2014, 04:23:22 pm by alpha123