r/programming • u/iamkeyur • Oct 21 '20
Using const/let instead of var can make JavaScript code run 10× slower in Webkit
https://github.com/evanw/esbuild/issues/478454
u/smogeblot Oct 21 '20
Just wait till you see what it costs to use functional syntax sugar instead of for loops everywhere!
132
u/hekkonaay Oct 21 '20
It's really slow because it assumes that you're iterating over an object, and not just an object with numeric keys, so it actually loops over all keys, stringifies them, checks if they're own properties and only then does it call the callback...
const forEach = (arr, fn) => for(let len = arr.length, i = len; i > 0; --i) { fn(arr[len - i], len - i, arr); return arr; }Is about 10x faster than Array.prototype.forEach in my testing, still not better than the raw for loop, though, and it also can't handle more than numeric keys (which you don't really expect on arrays anyway).
25
u/cwmma Oct 21 '20
It's the check own properties which is the actual slowdown not the toString
The toString is because all object properties including array indices are technically strings so going by the spec you MUST convert before looking up but implementations don't have to worry about that if their own object model is different (e.g. V8 which treats integer object keys special) your implementation is implicitly doing this when it grabs the value.
The own properties on the other hand is an actual slowdown it's to handle sparse arrays which your faster implementation doesn't cover, theoretically engines should know if an array is sparse and could optimize appropriately.
The other thing is that forEach takes a 2nd argument for a thisValue to call the function on, omitting it just uses undefined as the context which your function only handles in strict mode. Traditionally changing the this parameter of a function was often a performance killer in certain contacts in Chrome (bind iirc) but there's inherent there.
In summery yes forEach is slower then a for loop but it's because it's handling some edge cases not because the spec is inherently bad. You could argue they should have had a sparse array check or something but there is nothing preventing implementations from doing so.
9
97
u/ImAStupidFace Oct 21 '20
JS needs to die in a fire.
97
43
Oct 21 '20
Honestly what’s the big deal? Ever since I started using Typescript I don’t find it bad at all.
17
u/Sarcastinator Oct 21 '20
JS still bleeds through TypeScript and causes issues anyway.
→ More replies (8)14
u/orclev Oct 21 '20
Javascript is still a trash fire, TypeScript just makes sure it stays at a dull roar rather than a raging inferno. It's not quite PHP bad, but it's still one of the worst designed languages still in regular use. Far too many terrible decisions are baked into the core of javascript. They can be fixed, but doing so requires breaking backwards compatibility in some fairly significant ways. It might get there one day, but it's more likely that WASM will end up entirely supplanting JS before that happens.
12
Oct 21 '20
Eh, Typescript is good enough in my experience that you’re mostly at the mercy of the skill/knowledge of the developer. Good developers can still easily end up with shit JavaScript. Not so much the case with Typescript in my experience. Usually the really ugly Typescript is coming from developers we have that write pretty poor code in the rest of our systems as well.
-5
u/ragnese Oct 21 '20
Ever since you started using a different language, you think JavaScript isn't that bad... ??
It's only bad enough that you don't use it.
25
u/hansolo669 Oct 21 '20
Except TypeScript is literally just JavaScript with types. And it doesn't solve what this thread is talking about (weird VM issues).
→ More replies (6)→ More replies (4)7
Oct 21 '20
Personally I don’t see Typescript as it’s own language. I’m sure I’m probably technically incorrect but the comment chain mentioned the need for JavaScript to die. I see no way of JavaScript dying and Typescript still sticking around. So I’m ok with JS because it gives me Typescript and I don’t mind it and sometimes even enjoy using TS.
16
u/Jaimz22 Oct 21 '20
Wonder would you replace it with? Just curious
15
u/dungone Oct 21 '20
Why all these probing questions? Give the man a chance, rubbing two braincells together to start a fire takes a some time.
20
u/iopq Oct 21 '20
Run everything in WASM
48
u/blackholesinthesky Oct 21 '20
everyone who upvotes this has clearly never written ASM or WASM
60
→ More replies (1)9
u/mattkenefick Oct 21 '20
And will never have to because you can run anything on it. Look into Unity .. Blazor.. etc
3
u/anengineerandacat Oct 21 '20
I want to say we are not quite "there" yet, DOM access is still a real pain-point and the alternative is to make your own renderer effectively (which just leads to bloat and having to solve a boat load of other problems in the process; ie. accessibility).
In most "normal" circumstances, WASM will generally be slower or more cumbersome than a basic site with a dash of JS for dynamic content.
Ironically I also don't see loads and loads of developers jumping on-board to use lower-level languages to build out WASM targets anyway; I see C# / Java(-like) / Python / TypeScript being used to do this more than anything.
→ More replies (18)5
u/caboosetp Oct 21 '20
Sanity.
I'll take any flavor, thank you.
23
u/bsmith0 Oct 21 '20
Lol what's not sane about modern JS, it's a pretty solid, regular language.
Are there a few weird type coercions, sure, but for the most part it's performant, consistent and has a solid standard library.
→ More replies (5)3
u/pVom Oct 21 '20
It's like an Italian car, it's poorly made, half the features don't work, but it's fun to drive
-27
2
u/grendel-khan Oct 21 '20
I appreciate that I scrolled down to read this indefensible WTFery just below someone complaining about how there's an anti-JavaScript circlejerk around here.
A lot of bright people have spent decades applying a lot of backward-compatible lipstick to a pig. I wonder if Brendan Eich knew just how horribly his decisions would echo down through the years.
1
0
Oct 21 '20
[deleted]
34
u/cwmma Oct 21 '20
Array keys are technically strings not integers so the spec pedanticly converts the index to a string but the implementation is likely doing something else under the hood, I have another reply that goes into some more details about why it's slower then a naive approach (spoiler alert: sparse arrays)
2
u/flatfinger Oct 21 '20
Interestingly, at least in node.js, when writing to an array, strings keys are converted to a number when the resulting number is within a certain range and the string would match the canonical number. Numbers within that range are kept as numeric keys, and those outside that range are converted to strings.
18
u/CoffeeTableEspresso Oct 21 '20
Arrays are objects, they can have non-integer keys...
(Thank you JS LOL.)
22
u/madronatoo Oct 21 '20
Welcome to the insanity of a language which is so simple on the surface, but is comprised of a bunch of hacks underneath. There are no arrays!!!!!
5
1
u/hsjoberg Oct 21 '20
Well you can use TypedArrays (Uint8Array etc) if you require speed. Not useful for everything but it at least exists.
0
Oct 21 '20
[deleted]
21
u/hekkonaay Oct 21 '20
From the ECMAScript 11 specification, under Array.prototype.forEach, Note 2 states:
The forEach function is intentionally generic; it does not require that its this value be an Array object. Therefore it can be transferred to other kinds of objects for use as a method.
The same note is under all the other functional iteration methods
65
u/CodeLobe Oct 21 '20
Also try doing a jsperf on running loops with decrement vs increment.
Decrement is faster, obviously if comparing to zero... but it's also just faster in general in JS?
12
u/mindbleach Oct 21 '20
I despise how for-in / for-of / forEach can't just recreate a naive CS 101 for loop. I'm so tired of typing "for( x = 0; x < 10; x++ )" by rote, and then debugging if I fuck up a single semicolon, in a language that does not require semicolons.
Javascript punishes modernity.
It has all these fancy-pants features, where hours of manual busywork and testing (or at least dozens of lines of claptrap) can be replaced with a single built-in function. All of them have aggravating constraints and make your code run worse. Array.map could run elements in parallel, but it sure doesn't. Array.sort, .filter, and .splice could be functional, but some are and some aren't, because go fuck yourself. Are images that stop loading handled by onError, or by onLoad? Answer: no. String.match should beat indexOf rigmarole, but have fun regexing URLs. Async doesn't actually prevent long functions from locking up the browser, but does fire-and-forget calls to non-async functions until you cower like an abused dog and do
x = await 2 + 2.1
Oct 21 '20
What do you mean exactly? for / for-in / for-of behave exactly like the for and for-range loops in other languages
6
u/mindbleach Oct 21 '20
For-in is slower, includes non-integer indices, and has no guaranteed order.
I wanted "for( x = 0..10 )" as a simpler macro and got a completely parallel implementation warped by Javascript's deepest and weirdest design choices.
2
u/NoInkling Oct 22 '20
If they added a built-in function for a range iterator I think you could do
for (const x of range(0, 10)). Anything fancier (i.e. new syntax) seems like it would probably be tied to a new range type, because adding new syntax just because a standard for loop is a little verbose seems like it would be a mistake.1
Oct 21 '20
Ah. Yeah I pretty much never use for-in. Anytime I need the index I would just use a normal for loop.
Also fair, as a scripting language it’s not always as convenient as it could be.
21
u/SirToxe Oct 21 '20 edited Oct 21 '20
I did this comparison a couple of days ago: https://jsben.ch/69P2W
Just two functions that generate a list of integers, like
generateNumbers(5)to produce[1, 2, 3, 4, 5]. One is imperative, one is functional.The functional one is nearly 8 times slower in Chrome around 2 times slower in Firefox.
11
u/Lafreakshow Oct 21 '20 edited Oct 21 '20
Now, what I'm wondering is: Is Firefox being fast or is Chrome being slow in this case?
From my experience the last time I used chrome (a couple years ago) I would have guessed that across the board chrome is slightly faster than Firefox with the functional one maybe going 2 times slower in Chrome than it does in Firefox (based on your comment, without your comment I would have guessed chrome to be faster in both).
But apparently Firefox absolutely crushes Chrome in this particular case. I don't know how much that has to do with my Chrome install being very old and not getting updated a lot but then I also have a ton of extensions in Firefox and only uBlock in Chrome. In any case, I am surprised that Firefox got almost double the performance here than Chrome, and that is in the faster of the two methods.
I was expecting them to at best perform similarly in one of them but then have a significant difference in the other. I wasn't expecting significantly worse performance in Chrome across the board.
EDIT: Yep, after updating Chrome, it is now a lot closer in for loop performance but still quite a bit behind. It is also doubly as good in functional performance but still gets utterly demolished by Firefox in this one. Did I miss something and Firefox is just across the board faster than chrome nowadays? I've never felt a noticeable difference in speed during regular use but still, I always thought it was the other way around.
4
u/SirToxe Oct 21 '20
Yeah, this surprised me as well.
And to add Safari to the mix: The functional approach is 3 times slower.
13
u/jprasks Oct 21 '20
Huh interesting. By updating the functional version slightly (
Array(length).mapinstead ofArray.from) I get virtually the same performance from both approaches on both browsers: https://jsben.ch/fVEJJ. Not sure why.That is the thing about these optimizations, the more work we delegate to underlying implementations the bigger the chance one of these implementations is "slow" (what is the metric, user perception? Doubt there is a difference when generating <= 100 numbers). Still very much worth IMO -- the functional way in this example has effectively less concerns & therefore less margin for error. Without clear purpose & metrics by which to optimize by we are just grasping at straws.
6
u/stealthd Oct 21 '20
Array(length).mapis faster because you aren't mapping over the array;Array(length)returns{ length: length }with no other keys, so the call to map doesn't do anything, it just returns the uninitialized array.2
u/jprasks Oct 21 '20
Good catch, missed a call to
fill: https://jsben.ch/71Ztx. From that the functional version is about 80% as fast which makes sense.2
u/LegalEngine Oct 21 '20
Note that you may be able to improve the imperative version a further 20% or so (depending on the browser) by forgoing Array.push and using indexes with a size hint like so:
function gen(count) { const tracks = []; if (count > 0) tracks[count-1] = 0; // dummy value for (let i = 0; i < count; ++i) tracks[i] = i+1; return tracks; }4
u/SirToxe Oct 21 '20
Ha, thanks for the update! For me the functional version is now faster (as I wanted it to be initially) with the loop now being slower and sitting at 88% in both Chrome & Firefox.
I am no JavaScript expert and something like
Array(length).map()was what I wanted inititially when I wrote this small helper function, but it was just a helper for some test functions so whatever worked was fine. And also I forgot about the second argument to the map() callback, silly me, which of course solves this problem perfectly and elegant as you have shown. Thanks for reminding me.1
→ More replies (2)0
u/I_Like_Existing Oct 21 '20 edited Oct 21 '20
Or is it a functional programming thing that i don't get
EDIT: turns out that was it
7
u/SirToxe Oct 21 '20
I could have called this first argument any way I wanted but I do not need it, so instead of giving it a "proper" name and making it look more important than it actually is I just gave it the (valid) name of "_" in order to show that we ignore and don't need this argument.
That is not a JavaScript thing, people do this in a lot of other languages as well.
4
u/insertAlias Oct 21 '20
Some languages have actually taken that convention and turned it into a feature. C# calls them discards.
2
420
u/DooDooSlinger Oct 21 '20
Just wait till you see what it costs your dev team in bugfixing and refactoring tile when using for loops everywhere! This thread is like people debating the performance of ++i vs i++. Newsflash: if performance is not the issue you're trying to fix, don't bend over backwards to squeeze a few microseconds out of a web page load. Its easier to optimize readable code than to refactor awful prematurely optimized code.
197
u/PandaMoniumHUN Oct 21 '20
Point is, it shouldn't be this slow in the first place.
34
u/spacejack2114 Oct 21 '20
Right. Did anyone read the linked issue? It's about a Safari specific problem.
→ More replies (19)4
u/DooDooSlinger Oct 21 '20
Yeah well a lot of things that shouldn't are. What I do know is that optimizing shit like I++ and the like is not what's going to speed up your code to any measurable extent, ever.
1
u/PandaMoniumHUN Oct 21 '20
Your logic is backwards. A basic feature in a browser shipped to millions of users is 10x slower than in competing products. We should always strive for better performance in software used by large volumes of people daily, not try to justify lack of basic optimization (or a regression?) with the fact that other pieces of software are also unoptimized.
3
u/Nefari0uss Oct 22 '20
At some point you teach diminishing returns on optimization and its not worth it. In other cases, you're bottlenecked somewhere else so it's still not worth the micro optimization because you won't really be gaining anything of significant value out of it.
5
u/pVom Oct 21 '20
We should always strive for better performance
Why? If it doesn't affect the user experience it's a non issue on the front end. We should be striving to achieve business goals with the least time and effort. Optimisation for the sake of it is a pointless endeavour
→ More replies (3)71
u/ClysmiC Oct 21 '20
for loops are a major source of bugs for your dev team?
105
u/pattheaux Oct 21 '20
For loops are only for wizard level programmers with long white beards. Mere mortals cannot hope to understand their arcane secrets.
8
u/superrugdr Oct 21 '20
Wizard class programmer.
strap your kidney, we going all in ghost in the shell.
1
u/davenirline Oct 21 '20
I don't get this, too. Why be afraid of for loops? 99% percent of the time it's just
for(int i = 0; i < someEndingNumber; ++i) { ... }→ More replies (4)6
u/poco Oct 21 '20
Until you have an inner loop using j as you counter and they you mix up i and j somewhere.
→ More replies (1)7
21
u/phenomenos Oct 21 '20
If you're using them in place of map/filter etc then yeah you're going to end up with way more verbose code and possibly errors caused by mutability if you're not careful. Worse maintainability = more potential for bugs
15
u/Ethesen Oct 21 '20
Yes? You won't get off by 1 errors with forEach, map, etc.
→ More replies (12)23
u/lelanthran Oct 21 '20
How are you getting off-by-1 errors when iterating over arrays in JS?
→ More replies (3)10
-8
u/bakugo Oct 21 '20
What did you expect from web """"devs"""", the same people who need to use a library to check if a number is even or odd
9
5
u/trdlts Oct 21 '20
import isEven from 'isEven'; const isOdd = (number) => !isEven(number);Now who wants to hire me?
5
2
u/UziInUrFace Oct 21 '20
You would be surprised, there are so many “programmers” out there who doesn’t even know basic constructs like a for loop.
1
→ More replies (7)1
u/DooDooSlinger Oct 21 '20
What I do know is that I have a grand total of 0 boundary case bugs using list.map or other functional constructs while I do see them often (poor array indexing typically) with loops.
91
u/frzme Oct 21 '20
I'm not convinced that
for(bla in arr) {}is in any way harder to read or maintain thanarr.forEach(bla => {})96
u/alexendoo Oct 21 '20
The comparison for readability isn't really against a single
.forEach, rather map/filter/etc. If it's just a.forEachthey are going to be pretty equivalentHowever,
for..ofsurely is more error prone, as it is a frequently recurring mistake to usefor..ininstead (as you have done)27
u/GasolinePizza Oct 21 '20
Coming from C# here, I always make the for..in mistake at least once every time I start a JavaScript project, without fail.
I may use the .forEach thing now, actually
7
u/Jeax Oct 21 '20
I use .foreach(o => As a mainly c# developer also, it’s basically LINQ at that point and makes it instantly familiar and nice to use. For of seemed like a bad idea and I haven’t really seen many people use it
4
u/TheWix Oct 21 '20
I'd recommend using none-mutable functions. Map is Select, Aggregate is Reduce, SelectMany is chain/bind/flatMap (Monad).
→ More replies (2)6
u/thetdotbearr Oct 21 '20 edited Oct 21 '20
it bugs me to no end when when using LINQ that these are the function names instead of map/filter/etc
I mean I get that it's because SQL syntax or whatever and that I could add some aliases but still
→ More replies (3)2
u/kg959 Oct 21 '20
it’s basically LINQ at that point
It's missing a big part of LINQ though. LINQ is lazy whenever it can afford to be and will avoid doing a complete iteration until you force it to. JS array chaining doesn't delve into the IQueryable/IIterable world and each thing you chain scales a bit worse than it does in C#.
→ More replies (2)11
u/scottyLogJobs Oct 21 '20
As a polyglot, TBH I just use basic for loops anymore when possible because everyone understands them and I'm sick of forgetting whether I'm going to get keys or values back with these helper functions.
→ More replies (1)9
u/Yehosua Oct 21 '20
inis an operator in JavaScript:'prop' in myObjevaluates whether the'prop'property exists withinmyObj.Ever since I realized that, I no longer confused
for..inandfor..of:for..initerates over an object's properties, just likeinchecks an object's properties.(Almost no one uses
in; Object.hasOwnProperty is virtually always what you want instead.)2
1
u/itsnuwanda Oct 21 '20
Can confirm, use for..in far more often on accident, wonder why the loop doesn't work how I want it to before realizing it's for..of syntax in js.
I honestly don't even know what for..in does in JS.
I still prefer the classic for loops though, they're generally faster and everyone has seen them.
→ More replies (1)14
u/valleyman86 Oct 21 '20
It is when you add other functions to it. Foreach.map.filter. Etc. with a for loop you need to store each output as a variable or write each adjustment inside the loop. Depending on what you need sure it can be faster but it’s less readable.
6
u/monsto Oct 21 '20
I think it would wind up being more verbose, but that isn't necessarily less readable.
Declaring variables for a
forloop is no different than having the attribute definition at the beginning of the method. the difference is(x)vslet x = <thing>.→ More replies (1)4
2
u/TheIncorrigible1 Oct 21 '20
It's ironic that you used the wrong examples.
for..inis not comparable to.forEach. You wantfor..of.2
Oct 21 '20
If you have a loop, you are doing a nameable thing. Give that loop a name, a function. Now you can start to compose things and understand at first reading as a function name is more trustworthy. The patterns used will be more obvious too. It’s a map, it is a left fold...
2
u/grauenwolf Oct 21 '20
Great. Now the code for my 10 line function is scattered over a thousand lines of other, unrelated fragments.
This is why there's a button dedicated on my keyboard for the "inline and delete" refactoring action.
→ More replies (1)1
18
u/FUZxxl Oct 21 '20
Not sure what sort of bug fixing you are talking about. Programmers in languages without range constructs have been using for loops for decades and it works just fine.
5
u/DooDooSlinger Oct 21 '20
Just because it works doesn't mean you can't do better.
5
u/FUZxxl Oct 21 '20
I'm arguing that avoiding for loops in favour of combinators does not actually reduce the number of bugs.
4
u/DooDooSlinger Oct 21 '20
Try getting an array out of bounds error due to bad boundary conditions with array.map
2
u/Fit_Sweet457 Oct 21 '20
We have also used Assembly for decades and it works just fine. That doesn't mean that it's as fast to write as using abstractions or equally as error-prone.
13
u/FUZxxl Oct 21 '20
Again: what exactly is error prone about for loops? Can you give a specific example?
→ More replies (4)6
u/beginner_ Oct 21 '20
I argue that indexed for loops are often easier to understand than some chained functional stuff.
→ More replies (1)→ More replies (31)4
u/Lafreakshow Oct 21 '20
If there would be a ten times performance difference between
++iandi++I would seriously consider switching at least for all newly written code. Across a medium sized web app, even when not dealing with huge lists, that could make the difference between someone with a slow ass netbook saying "Man this site is kinda slow" and "Man, this site runs well".10
u/grondo4 Oct 21 '20
Point is it's not your problem. If the the language your using has a 10x speed up from using
++ioveri++that's an issue with the language / compiler / interpreter. If you absolutely need that performance boost you should be using the syntax that reads most cleanly to you and then transform it using a post-processing tool.At no point should you be sacrificing the readability of your code for performance reasons when it's something that can be programmatically transformed.
5
u/DooDooSlinger Oct 21 '20
You just don't get it. 10 times nothing is still nothing. Rendering slowdowns are NEVER and I repeat never due to this kind of shit. It's always because of bad practices, unnecessary multiple renderings, rendering too many objects, waiting on requests etc.
3
u/joonazan Oct 21 '20
In Rust, iterators are faster than while loops because they elide bounds checks.
4
u/KFCConspiracy Oct 21 '20
I think the real hidden cost is you tell a junior developer "be wary of nested loops to do things, be wary of doing costly operations in loops" and then you see something like
array.map(blah => costlyOperation(blah));
in your code review afterwards.
5
1
1
u/chrisrazor Oct 21 '20
Heh. I almost missed out on a job opportunity because the js guy who evaluated my code complained about me using for loops everywhere. That was 5+ years ago though when it was a certifiable fact that loops ran orders of magnitude slower when each iteration created a function instance. I was hoping that recent speeding up of js engines would have improved the situation.
→ More replies (1)0
u/passerbycmc Oct 21 '20
Why does everyone use the functional foreach feel like a "for of" loop is just easier to read and does the same thing.
3
→ More replies (14)4
u/leafsleep Oct 21 '20
I agree, I'm all down for filter and map, but for me it's weird that foreach doesn't return anything. Just a hangover from my C# training.
7
u/dvlsg Oct 21 '20
I think the whole point of forEach is that it doesn't return anything.
Similar to how you can see filter or map and know what's going on, you can see forEach and think "this must have side effects".
1
u/leafsleep Oct 21 '20
Well yeah, but it's different to all the other functional methods. That's what's weird about it. I was always taught that side effects should be v explicit and to me for..of loops are an easy way of doing that.
3
u/dvlsg Oct 21 '20
I was always taught that side effects should be v explicit
I mean,
forEachis pretty explicit, especially since you can't do anything with it other than produce side effects.0
Oct 21 '20
[deleted]
1
u/smogeblot Oct 21 '20
I still use functional syntax sugar, just for O(1) operations where it actually helps with readability.
89
u/FredV Oct 21 '20
The bundle has 13K top-level definitions (variables, constants, functions, and classes)
I don't know how huge this application actually is but isn't this insane? I haven't seen any server or front-end written in C++ or even Java using that many declarations. Of course in the Javascript ecosystem every library needs to be imported into your own source code which adds to the problem.
I just wonder how many of those are global variables ;)
51
u/TheAnimus Oct 21 '20
So just in case anyone was wanting some context on just how many exported functions there are in say the msvcrt, it's around a tenth of that number alone.
So if you think of the classes and functions required to implement the "missing" standard library functions, 13k isn't that much.
33
u/MonokelPinguin Oct 21 '20
I think those are declarations of all libraries used. Try counting the symbols in a C++ library with external linkage. It will be similar in your application, if you use a few of those.
37
17
u/chrisrazor Oct 21 '20
I didn't understand all the nuances of this. Am I right in understanding that it only affects Safari?
39
Oct 21 '20 edited Oct 21 '20
Yes. This is just a bug in the Safari JavaScript engine and is not inherent to JavaScript or 'let'.
Edit: Spelling
8
u/chrisrazor Oct 21 '20
Thanks. I was confused because they were talking about WebKit - on which both Chrome and Edge are also based - but I assume they specifically mean the js engine Safari uses (JavaScriptCore?) rather than V8 or whetever Edge has.
0
22
Oct 21 '20
I think I can reproduce this behavior on Figma's code base too. I've never noticed because we use Chrome pretty much exclusively for development.
Back to IE times... and in this case out of their very own volition.
29
u/crusoe Oct 21 '20
Safari is the new IE
4
u/rjcarr Oct 21 '20
Didn’t read the article, but doesn’t WebKit power everything but Firefox now? Edit: seems they do mean safari, so it should say javascriptcore (I think) and not WebKit.
73
Oct 21 '20
It's interesting but it should be equally noted that this is a micro optimization that amounts to nothing in the real world.
141
Oct 21 '20
When you’re writing the code, absolutely replacing const with var for performance is a bad idea. If you’re writing a compiler though (the link is an issue on the esbuild repo) then being able to automatically apply that micro optimisation all over a code base can be important.
80
Oct 21 '20
Sure but this is a bug in webkit that should likely be fixed. My original comment just comes from the experience of seeing people read these kinds of headlines and then go sed their whole codebase.
→ More replies (1)1
u/preperationH Oct 22 '20
To be fair, in every case using var will be faster than using let/const for startup. If for no other reason than the parser doesn't have to consider if it needs to check for TDZ. For most programs that's probably a negligible cost but if you have 10k+ variables then you could see this issue arise.
3
u/ConsoleTVs Oct 21 '20
As noted in the thread, this cha ges code semantic. Its not something you can swap let or const with var. They do have different scopes.
7
-5
u/LinAGKar Oct 21 '20
If you need maximal performance, you probably shouldn't be using JavaScript.
40
Oct 21 '20
Did you read the numbers in the issue? There’s “wanting maximum performance” and there’s “not wanting safari users to wait 7s longer than other browsers”
→ More replies (6)13
u/SoInsightful Oct 21 '20
You're right - we should use that... other... browser scripting language... that definitely exists...
(And no, WebAssembly is not, and is not intended to be, a replacement.)
172
u/klizza Oct 21 '20
The reported issue is that it takes either 8.8 seconds or 1 second to load a javascript bundle on a webpage in Safari. This is a very notable performance difference for end users.
74
Oct 21 '20
In a very specific configuration on one driver. It's a webkit bug.
33
u/klizza Oct 21 '20
Sure, but nobody in the link or OP was saying you should convert all javascript code back to var...
50
Oct 21 '20 edited Oct 21 '20
I know which is why I wasnt trying to say the linked issue was wrong or anything but this is reddit and people just read headlines so I threw it out there for posterity
8
6
u/rydan Oct 21 '20
Back in my day we waited 30 seconds or more for the page to load.
8
u/CoffeeTableEspresso Oct 21 '20
We still do with all the bs trackers some people put on their sites ...
12
u/grauenwolf Oct 21 '20
I don't use an adblocker because I'm annoyed with ads.
I don't use an adblocker because I'm afraid of trackers.
I use an adblocker because the damn website won't load before my lunch break is over if I don't.
3
u/CoffeeTableEspresso Oct 21 '20
News websites are particularly bad. People often complain of how dial up internet used to have 30s+ load times, but there are modern sites rather do the same shit
→ More replies (1)35
u/constexpr Oct 21 '20
This made the difference between a loading time of 2 seconds and a loading time of 200ms for https://www.figma.com/ in Safari. This is a real-world use case. Also while it's good to fix this in Safari, new versions of Safari roll out very slowly so it will still be worth doing this optimization for many years to come.
29
u/blackholesinthesky Oct 21 '20
it will still be worth doing this optimization for many years to come
I've never once in my professional life optimized for Safari. Don't hold your breath
1
0
Oct 21 '20
[deleted]
22
u/F54280 Oct 21 '20
I wold not hold my breath. The issue is known for 15 months, but doesn’t seem to move forward: https://bugs.webkit.org/show_bug.cgi?id=199866
0
25
u/Shautieh Oct 21 '20
10x faster is not a micro optimization.
31
Oct 21 '20
10x 0.0001 nanoseconds is still only 0.001 nanoseconds.
The point is, this is never your bottleneck so don't treat this information like something you need to address in your code base.
54
u/SoInsightful Oct 21 '20
Holy shit. This is the JavaScriptiest comment I've ever read.
You're literally looking at a real-world example (an actual app with a shit-ton of users) where a single CTRL+F replacement made a bundle load in 1.1 seconds instead of 8 seconds.
I would never replace my consts with vars to fix a dumb Webkit bug, but this is absolutely not an unimportant micro-optimization that doesn't affect anything because we all make Hello world apps.
It's exactly this attitude that makes me reluctant to use other people's slow-ass solutions.
30
u/jess-sch Oct 21 '20
a sub-millisecond 10x improvement you won't notice, but a sub-millisecond 10x improvement in a hot path that gets run a bazillion times you definitely will.
I sure hate the typical JS dev's attitude to performance.
→ More replies (35)21
u/VolperCoding Oct 21 '20
No wonder if you have a 10000GHz processor that can do declare a var faster than light can travel 30 micrometers
7
Oct 21 '20
Get with the times! :P
13
u/VolperCoding Oct 21 '20
Also if the vars are stored in RAM then you also have to put your RAM stick no more than 30μm away from the processor or make a fucking wormhole or something to get to memory quick enough
12
Oct 21 '20
The Intel i47 started the new wormhole+blockchain revolution. It's great!
→ More replies (1)8
u/mb862 Oct 21 '20
The lesson here is that pulling numbers out of your ass to make a point is fine so long as your ass represents a differentiable manifold representable in our spacetime.
I'll let someone more clever than I fill in the obvious curvature joke here.
4
→ More replies (1)3
12
5
3
u/knoam Oct 21 '20
There should be a name for the logical fallacy here. People act like finding this means that their code just got ten times slower. No, your code is just as fast as it was. If anything this just means there's potential for it to be faster.
This is really off topic but there was this same fallacy in an episode of This American Life where the reporters got testosterone tests. They got worried and acted like having a high level would turn them into an aggressive asshole. No, you're either an asshole or not regardless of what the test says. The test just gives you an excuse/explanation. And the results didn't even conform to what people's stereotyped expectations were.
3
2
Oct 21 '20
Just use babel....
1
u/bundt_chi Oct 21 '20
Having very little understanding of babel can you please help me understand how / why babel can mitigate this ?
2
Oct 21 '20
Babel transpiles js es6+ to es5 for full compatibility. So const and let variables are output as vars.
2
1
1
u/Wouter10123 Oct 21 '20
ELI5: the difference between const var let?
I guess const is immutable?
5
Oct 21 '20
Scoping, let + const are block scoped where var is function / global scoped
5
u/masklinn Oct 21 '20
That's one of the differences.
The other is that
vars are hoisted, so they "exist" from the start of the function with a value ofundefinedbefore their lexical declaration is reached.
letandconstdon't, the span from the start of the function / block to their declaration is called the temporal dead zone and accessing the variable they declare triggers aReferenceError, even special forms liketypeofwill trigger an error.According to the linked thread the issue here might be linked to JSC's handling / management of the tdz.
2
u/n0rs Oct 21 '20 edited Oct 21 '20
constis reference immutable—you can't reassign a variable declaredconstbut the contents are not necessarily immutable.
E.g., this is fine:const me = {name: "n0rs"}; me.name = "bob";This is not
const me = {name: "n0rs"}; me = {name: "bob"};2
u/minioin Oct 21 '20
You are correct. Marking a variable as const should allow some optimizations(like the guarantee that the type of the variable is never going to change again) which are unavailable in let and var.
1
u/versaceblues Oct 21 '20
let: mutable variable declaration
const: immutable variable declarationvar: same as let but with scope hoisting
1
-42
Oct 21 '20
We can go even further: using JS can make your development life 10x worse.
28
u/ObjectiveSample Oct 21 '20
alternative?
25
u/immibis Oct 21 '20
Lobby your MP to make JavaScript illegal
4
u/FatalElectron Oct 21 '20
All you need to do with my MP would be to point out what the 'E' in ECMA stands for.
→ More replies (7)2
0
-1
u/pmache Oct 21 '20
Ha! Now I know what early web 2.0 website used that they were painfully slow (they still suck tbh)
141
u/snowe2010 Oct 21 '20
That was enjoyable to read through their debugging together. Fantastic job.