Live data from Hacker News

Speed Without Wizardry

fitzgeraldnick.com

1–10 of 72 posts

Re: Speed Without Wizardry

#2
The simple rule I have found for achieving superior performance in high level languages, particularly JavaScript is to simply do less. It isn't that simple though.

Doing less really means less code totally at the current compilation target, essentially feeding fewer total instructions to the compiler. This means no frameworks and minimal abstractions. It means having a clear appreciation for the APIs you are writing to. It means minimizing use of nested loops, which exponentially increase statement count.

Sometimes caching groups of instructions in functions can allow for cleaner code with a positive performance impact.

V8 cannot compile arithmetic assignment operators, which it calls left-side expressions, so you can see a rapid speed boost in V8 when you replace something like a += 1 with a = a + 1.

The side benefit of less code is generally clearer and cleaner code to read. There isn't any wizardry or black magic. No tricks or super weapon utilities.

As an example I wrote a new diff algorithm last year that I thought was really fast. https://news.ycombinator.com/item?id=13983085 This algorithm is only fast because it does substantially less than other algorithms. I only wrote it because I could not wrap my head around the more famous Myers' O(ND) algorithm. A side benefit, in this case, of doing less is an algorithm that produces substantially more accurate results.

Re: Speed Without Wizardry

#3

The simple rule I have found for achieving superior performance in high level languages, particularly JavaScript is to simply do less . It isn't that simple though. Doing less really means less code totally at the current compilation target, essentially feeding fewer total instructions to the compiler. This means no frameworks and minimal abstractions. It means having a clear appreciation for the APIs you are writing…

> V8 cannot compile arithmetic assignment operators, which it calls left-side expressions, so you can see a rapid speed boost in V8 when you replace something like a += 1 with a = a + 1.

Is there a reason it can't? I'm not familiar with Javascript, but aren't the two expressions equivalent?

Re: Speed Without Wizardry

#4
post #3

The simple rule I have found for achieving superior performance in high level languages, particularly JavaScript is to simply do less . It isn't that simple though. Doing less really means less code totally at the current compilation target, essentially feeding fewer total instructions to the compiler. This means no frameworks and minimal abstractions. It means having a clear appreciation for the APIs you are writing…

> V8 cannot compile arithmetic assignment operators, which it calls left-side expressions, so you can see a rapid speed boost in V8 when you replace something like a += 1 with a = a + 1. Is there a reason it can't? I'm not familiar with Javascript, but aren't the two expressions equivalent?

The two expressions are equivalent. V8 cannot compile that logic into optimized bytecode due to a violation in its code engine that conflicts with other optimization logic. So instead of fast compiled code the code in the local scope of that expression is slow string interpreted code.

https://github.com/vhf/v8-bailout-reasons

Re: Speed Without Wizardry

#5
post #3

Earlier quoted context omitted.

> V8 cannot compile arithmetic assignment operators, which it calls left-side expressions, so you can see a rapid speed boost in V8 when you replace something like a += 1 with a = a + 1. Is there a reason it can't? I'm not familiar with Javascript, but aren't the two expressions equivalent?

The two expressions are equivalent. V8 cannot compile that logic into optimized bytecode due to a violation in its code engine that conflicts with other optimization logic. So instead of fast compiled code the code in the local scope of that expression is slow string interpreted code. https://github.com/vhf/v8-bailout-reasons

Do you have a source that cites the += example? I can't seem to find it on the page you linked.

Re: Speed Without Wizardry

#6

The simple rule I have found for achieving superior performance in high level languages, particularly JavaScript is to simply do less . It isn't that simple though. Doing less really means less code totally at the current compilation target, essentially feeding fewer total instructions to the compiler. This means no frameworks and minimal abstractions. It means having a clear appreciation for the APIs you are writing…

> "It means minimizing use of nested loops, which exponentially increase statement count."

Nesting two loops has an n^2 cost and nesting 3 levels deep costs n^3. At no point does it ever cost 2^n or any x^n.

It's polynomial, not exponential.

Re: Speed Without Wizardry

#7
post #3

Earlier quoted context omitted.

> V8 cannot compile arithmetic assignment operators, which it calls left-side expressions, so you can see a rapid speed boost in V8 when you replace something like a += 1 with a = a + 1. Is there a reason it can't? I'm not familiar with Javascript, but aren't the two expressions equivalent?

The two expressions are equivalent. V8 cannot compile that logic into optimized bytecode due to a violation in its code engine that conflicts with other optimization logic. So instead of fast compiled code the code in the local scope of that expression is slow string interpreted code. https://github.com/vhf/v8-bailout-reasons

That list is for CrankShaft which has been replaced by TurboFan > 6 months ago. If you continue to experience slowdowns please file a bug and it can be investigated.

Re: Speed Without Wizardry

#8
> This is a factor of 4 improvement!

This is a common mistake. It should read, "This is a factor of 3 improvement!"

x+x+x+x is an improvement over x of 3x not of 4x. The improvement factor is 3.

Re: Speed Without Wizardry

#9
post #5

Earlier quoted context omitted.

The two expressions are equivalent. V8 cannot compile that logic into optimized bytecode due to a violation in its code engine that conflicts with other optimization logic. So instead of fast compiled code the code in the local scope of that expression is slow string interpreted code. https://github.com/vhf/v8-bailout-reasons

Do you have a source that cites the += example? I can't seem to find it on the page you linked.

I remember seeing the cause of this specific case mentioned in a slide deck by one of the V8 engineers. I don't remember where online it is. I was to validate this performance limitation more than a year ago through self-testing in my personal code.

As titzer mentioned this issue may no longer exist. I would have to run additional tests to independently make an assessment with the current V8.

Re: Speed Without Wizardry

#10

The simple rule I have found for achieving superior performance in high level languages, particularly JavaScript is to simply do less . It isn't that simple though. Doing less really means less code totally at the current compilation target, essentially feeding fewer total instructions to the compiler. This means no frameworks and minimal abstractions. It means having a clear appreciation for the APIs you are writing…

> "It means minimizing use of nested loops, which exponentially increase statement count." Nesting two loops has an n^2 cost and nesting 3 levels deep costs n^3. At no point does it ever cost 2^n or any x^n. It's polynomial, not exponential.

Before I begin just let me say I am not a mathematician. I program so that I don't have to do complex math.

I know in reality the frequency of iterations varies considerably but for simplicity of discussion let's remove variability.

Say we have a loop with 1000 iterations. That is at minimum 1000 statements in the loop body plus expression overhead from the loop itself. If this loop is nested once with a same sized loop there are now 1,000,000 iterations plus some expression overhead per iteration. If it is nested twice deep there are now 1 billion iterations.

That example is exponential of 1000. Given that there is overhead associated with operation of a loop it is actually greater than exponential. It may not be quite so dramatic as a logarithmic growth curve though.

I completely concede that in reality loops vary in iteration count and so nested loops aren't likely perfectly exponential unless their iteration counts are identical. The increase of iterations from nesting loops does increase more dramatically than a simple multiplicative operation as the depth of loop nesting increases, such that the growth of total iterations is a curve on a graph. A polynomial growth operation when graphed should present a straight diagonal line without the presence of a third variable.

Post reply on HN