The Rusty Web: Targeting the Web with Rust
davidmcneil.github.io
davidmcneil.github.io
https://github.com/kripken/emscripten-fastcomp/issues/171
to track this issue in Emscripten.In JS, the assumption is that code may be written by humans, so engines are expected to optimize things like Math.pow calls with small integer exponents implicitly, which is likely why this code is faster in JS. And in the asm.js case, the page mentions that it's using "almost asm", which is not actually asm.js, so it's using the JS optimizations.
This is one of the characteristic differences between JS and WebAssembly: in WebAssembly, the compiler producing the code has a much bigger optimization role to play.
[1] https://medium.com/gopherjs/surprises-in-gopherjs-performanc...
It's used for multiplying integers in SunSpider: https://github.com/adobe/chromium/blob/master/chrome/test/da...
From https://news.ycombinator.com/item?id=7837433 :
"(For example, did you know that every major JS engine now has a daylight savings offset cache, something which is entirely useless for any real code, but substantially speeds up the date benchmarks in SunSpider? Bleh.)"
From https://blog.mozilla.org/javascript/2013/08/01/staring-at-th... :
"All Javascript engines, including SpiderMonkey, use optimizations like transcendental math caches (a cache for operations such as sine, cosine, tangent, etc.) to improve their SunSpider scores."
As opposed to some other benchmark, that gets some other micro-optimizations? I'm not sure that's productive. That said...
> "(For example, did you know that every major JS engine now has a daylight savings offset cache, something which is entirely useless for any real code, but substantially speeds up the date benchmarks in SunSpider? Bleh.)"
I'm not sure this is without benefit for me. I store time stamps in UTC in the DB, and pass them along in that form to the client, which then converts to local time. I imagine this might benefit the sometimes hundreds of conversions the client does in my case?
Edit: Maybe what we need a something like the Fortune 500, but for webpages. Take the top 50 web properties(by whatever metric), and allow them to submit benchmark webpages that approximate a real world situation. Facebook would have one that loads a canned sample Facebook account, Google might have one to approximate search results, one to approximate docs, and one to approximate gmail, etc. Only allow new submissions once a month or quarter, but index them so we can see performance over time, performance against older technology, and how technologies change over time.
Yes, because SunSpider in particularly is notoriously, egregiously bad. Google's Octane benchmark suite ( https://developers.google.com/octane/benchmark ) at least attempts to approximate real-world usage by benchmarking actual applications (like PDF.js), as well as scraping regexes from popular sites and using those as part of a regex performance suite. (And even still there are some arguably dubious entries in Octane.)
Anybody who uses a pow call to square a number must believe compilers are magic. Worse yet, some compilers might actually optimize for that case, reinforcing that belief.
Compilers should be dumb, fast and predictable instead. That way, everyone gets what they deserve.
Also, your comment that "everyone gets what they deserve" suggests that those who write high-level code (e.g. using pow() to square a number) "deserve" to have slow code. That's a strange moral outlook.
So, it's a trade-off. I would also prefer less special cases optimized for naive use, but only if it's accompanied by documentation that says "prefer X instead of pow(x, 2), prefer Y instead of pow(-1, k), etc." It shouldn't be guesswork as to what's best to do for common cases.
You, too, believe in the magic compiler that doesn't exist. You don't get good code from a high-level specification. You really have to understand what the compiler actually can do for you and write your code accordingly, either way - except the predictable case is more straightforward (though maybe not as pleasing).
As a simple example, take SROA: without that optimization, you can't make a "Point { float x, y, z; }" struct and have that be as efficient as "float x, y, z;", because x, y, and z can live in registers in the latter, while in the former they remain as memory instead of being promoted to SSA values. But being able to use a Point structure like that is extremely helpful, because then I can define useful methods on it and so forth. I shouldn't have to choose between good engineering practice and performance, and thanks to SROA, I don't have to.
If you really care about performance to the point of register occupancy, you need to look at the context. The "abstraction" of having a Point type with methods is almost certainly far from optimal, because it doesn't fit SIMD well. It's then also not "good engineering practice" to use it.
"Expands to the exact same code everywhere on every imaginable compiler, even toy compilers nobody uses" is not part of the definition of "abstraction".
> If you really care about performance to the point of register occupancy, you need to look at the context. The "abstraction" of having a Point type with methods is almost certainly far from optimal, because it doesn't fit SIMD well.
What do you think http://www.agner.org/optimize/#vectorclass is then?
> It's then also not "good engineering practice" to use it.
Yes, it is! It makes your code more readable, and if you're compiling on any production-quality C compiler anywhere your Point class will have the same performance as the raw version. Lower maintenance cost, fewer bugs, same performance.
MSVC compiler doesn't do SROA, as far as I know.
> What do you think http://www.agner.org/optimize/#vectorclass is then?
Have you actually looked at that thing? It's not a Point struct, I can tell you that. There's nothing abstract about it.
If you want to take advantage of SIMD fully, you need to lay out your data in a very specific way. A Point {x,y,z} struct doesn't naturally fit a SIMD register.
Now, if you're willing to make a lot of assumptions on your compiler, you can do something like this: http://www.codersnotes.com/notes/maths-lib-2016/
Still, you need to put in the work and the research. No magic.
> Yes, it is! It makes your code more readable, and if you're compiling on any production-quality C compiler anywhere your Point class will have the same performance as the raw version. Lower maintenance cost, fewer bugs, same performance.
If performance really matters then your abstract solution is almost certainly suboptimal and it's not good engineering practice to use it for the sake of readability.
Yes, it has since at least 2010 (and probably earlier). See "scalar replacement": https://blogs.msdn.microsoft.com/vcblog/2009/11/02/visual-c-...
> Have you actually looked at that thing? It's not a Point struct, I can tell you that. There's nothing abstract about it.
The Vec classes can be used as Point structs.
> If you want to take advantage of SIMD fully, you need to lay out your data in a very specific way. A Point {x,y,z} struct doesn't naturally fit a SIMD register.
So pad it out to 4 fields, using homogeneous coordinates.
> Now, if you're willing to make a lot of assumptions on your compiler, you can do something like this: http://www.codersnotes.com/notes/maths-lib-2016/
That's not making a lot of assumptions about your compiler. The x87 floating point stack, for example, has been obsolete for a long time.
> If performance really matters then your abstract solution is almost certainly suboptimal and it's not good engineering practice to use it for the sake of readability.
I disagree. Let's look at actual examples. "Almost certainly" suboptimal abstractions are not what we've seen in Rust, for example, which leans on abstractions heavily.
See my reply to whitequark_, this seems to be loop-specific.
> The Vec classes can be used as Point structs.
Oh, sure. Which one though? How do I abstract this, again?
> So pad it out to 4 fields, using homogeneous coordinates.
In other words, "do something else than what I originally did" and "potentially leave 25% throughput on the table".
I think you're trying to pull a fast one on me.
> That's not making a lot of assumptions about your compiler. The x87 floating point stack, for example, has been obsolete for a long time.
Did you even read beyond the first paragraphs? There's five compiler-specific flags you'll have to get right for any of this to work.
Again, there's no free lunch...
> I disagree. Let's look at actual examples. "Almost certainly" suboptimal abstractions are not what we've seen in Rust, for example, which leans on abstractions heavily.
Could you just scroll up for a moment? We are talking about this because someone wrote the "abstract" version of squaring a number and some optimization didn't kick in, resulting in significantly degraded performance. And that's a trivial example! In a real codebase, you'll have to carefully audit compiler output to see if it does the right thing, potentially requiring you to rewrite code. For Rust, you also have the blessing that there is only one compiler...
In the future, consider verifying your extraordinary claims. Of course it does, and it took me about two minutes to demonstrate that: https://godbolt.org/g/9kT1NP
You haven't actually verified SROA. The scalar replacement didn't kick in for the non-inlined method, so this could be a result of loop-specific optimizations. The code is also far from optimal, but that's besides your point of course.
Also note that you're testing an RC of the latest version. There's a feature request for SROA from 2013, so it may be implemented by now: https://connect.microsoft.com/VisualStudio/feedback/details/...
With dumb compilers we are putting the need to understand every machine on every developer. Isolating what knowledge is required in different locations is exactly why we have abstractions. The compiler is just one more abstraction to help this kind of specialization and basic division of labor.
The abstraction is fundamentally leaky. As someone who worked on a compiler for years, cost models are important, and benchmarks and perceptions are very important -- but they are often non-intuitive and not totally "free", as TINSTAAFL says.
That said, optimizing something like a self-pow call to a square is probably not overreaching as an optimization or whatever. But there is certainly something to be said about over doing it and before you know it, you've kicked the can down to <person in the hallway who's really good at optimizing on platform X> because they had to do it anyway because only they know why the JVM or whatever behaves that way on a Friday with 17 inner class methods or something and you're really sure it can be faster but you've got a deadline in like a week and holy shit you have 3 other things to do.
As an aside, I think if any compiler gets the "most sane cost model award", it would probably be Chez Scheme, since it is both unbelievably fast, and based entirely around a practical metric: basically no optimization is added if it cannot speed up the compiler itself. Performance should be predictable both in terms of runtime and compile time. Since the compiler is a rather general purpose application -- if the optimization isn't worth it there, it's probably too overly specific, and likely isn't carrying its own weight. After 30 years of following this rule -- Chez is very, very fast.
If you presume this, we would still need that knowledge for simple compilers too and the hardware.
Regardless, I disagree with this. Even though the abstractions are leaky, not everything is leaked. For example: Algorithms that have tight loops to do things that fit in cache will do better than those that loop over massive sets. This only leaks the cache size and little else.
You claim to develop compilers, so maybe I am out of my depth. When I read blog posts or watch videos, like those from the latest cppcon. They all boil down to the simple advice "write idiomatic code and don't try to be more clever than the problem requires". Then when that performance isn't good enough profile and optimize. This is working well for me in 3d games. When I see fit to look at my assembly all of it makes good direct sense, and when it doesn't it is extremely fast.
So looking at the previous example leaking the cache size; A slightly smart compiler might insert extra instructions to tell some CPUs how to prefetch whatever is next. A very smart compiler will detect data dependency and rework the loop to operate on a data set that fits in cache (maybe even querying the size of the cache). The alternative is for the dev to know the cache szie at the time the algorithm is written and take it into account there. This is a simple example but shows the problem, why should the dev care about the cache size, when it can be automatically accounted for?
Are there some more nuanced examples where the simple pattern of write idiomatically then profile fails?
I happen to have of those videos[1] running in the background right now about abstractions that cost nothing. I will start it over and pay more attention with your added details in mind. I will also look into Chez Scheme this is the first I have ever heard of it.
[1] CppCon 2016: Serge Guelton “C++ Costless Abstractions: the compiler view" - https://www.youtube.com/watch?v=q0N9Tvf7Bz0&index=108&list=P...
However, for a compiler writer, it isn't sufficient. They're in the business of being the bottleneck! As such, they quickly enter a space where they have to set down their own principles for what idiomatic code looks like and how much they allow abstractions to leak upwards, negotiating those principles against the ecosystem of real-world code.
A consequence of this is that a compiler that only has to operate on a single codebase has it easy, because all its optimizations can be customized to the problem domain and target devices, while more generalized compilers have a dynamic optimization problem, where some features help some of the time, and not others. And their clients are all going to be programmers who get themselves into big trouble and then want the compiler to solve the problem.
Regarding the second statement: These "smart" optimizations happen before architecture specialization, so that's wrong too. But even if it was true, you now shift the burden to understanding every compiler in order to get the optimization you need.
If people expect that pow(x,2) transforms to x * x, then every compiler would have to implement that. This is a trivial example, but you in reality you always have to structure your code appropriately for some optimization to kick in, what if one of your target compilers needs a different structure?
Do you get your copy of Hacker's Delight off the bookshelf to look up the magic number instead of writing "x / 3"?
Everyone relies on optimizations to some extent. It's simply infeasible to do otherwise.
Clearly that is not what you mean and is not a good thing. Perhaps optimizing compilers put you outside of your comfort zone because you think they force you to learn and keep up to date.
You can do that or you can stick to writing idiomatic code that uses the std library for a given compiler. Doing just this tends to produce extremely good results. I often outdo others near just with this when they are dropping to assembly or doing silly workarounds because they know something is slow. Profiling and timing are required to pick up the rest of the performance, and presuming otherwise is silly. No special knowledge of the machine or compiler is required, just a knowledge of when and how to optimize and when and how to write idiomatically.
This is what gave us C, while the rest of the mainframe world was busy using Algol, PL/I, Fortran and Lisp dialects. Where many of the compilers already were capable of doing bounds checking elision.
I'm guessing he thought using a temporary variable would look less pretty, and had no idea of the relative costs of imul and ipow.
> Compilers should be dumb, fast and predictable instead.
I don't care too much about dumb or fast, but they definitely need to be predictable. Even with something as low-level as C++ or Fortran, you often have to profile and disassemble to see if the compiler is doing the optimizations you want (e.g. unrolling loops, inlining functions, propagating constants, using SSE), or if you have to hold its hand. Trying to predict whether something as high-level as GHC will do what you want, or to figure out how to make it do so, is an absolute nightmare.
GHC also happens to be one of the slowest compilers you could possibly use. It all goes together.
One cannot realistic expect that any compiler for a given language behaves the same way.
This doesn't matter when any correct program is "good enough," but it matters a whole lot when failure to perform specific optimizations makes a program unacceptably slow.
That's a good way to get pummeled in benchmarks. Benchmark scores matter a lot to perception: just look at any HN thread about programming language or browser performance, or any review of browsers in the tech press.
We may not like it, but the benchmark-dominated world is the world we live in.
On Chrome 56 with default flags, the tab immediately crashes upon page load. I've tried enabling the "Experimental WebAssembly" flag, which prevents the crash but the demo fails to load with:
WebAssembly instantiation failed: TypeError: WebAssembly.instantiate is not a function
And this is a computation benchmark, it's not even hitting sand-boxed API overheads.
But regardless, my ultimate point is mostly "hey this stuff is brand new so some stuff not being great is to be expected." The exact details aren't very important.
Further, and I don't even know if this question is a meaningful one, but are there any curated lists of libraries known to work with wasm, or do you just compile something and hope for the best? I'm curious if there are any gaming-oriented sound libraries known to work well, and with bindings to Rust? I'm a blind developer with a casual interest in building audio games, a niche gaming genre that's basically what it (har har) sounds like. Unfortunately, much of what is available is Windows-only, and I'm a Linux user. But increasingly over the past few years, the web has struck me as a great platform for building these sorts of games. You don't need a powerful CPU for one thing, and the browser's built-in TTS APIs abstract away one of the biggest platform hurdles. There really isn't a good cross-platform hook into text-to-speech systems, and often you need speech presented in ways that clash with how screen readers work.
Anyhow, I've been wanting to experiment with multi-player gaming, and Rust's new wasm support along with Firefox 52's inclusion seems like a nice bit of synchronicity. If only I could find a good audio library known to work, particularly something with spatialization.
And yes, I do know about the Web Audio API, but was disappointed to learn that its panner nodes don't support more than 2 speakers. That said, I don't know if there are any wasm-compatible libraries that'd work with Rust and support 5.1. I'm also looking for a fun project to use Rust with, and an audio game that uses the strengths of both the web and Rust might be just the thing.
Pardon the diversion, but I'm stupidly excited about using the browser as a cross-platform runtime via a language more sane than JavaScript. :)
http://floooh.github.io/2016/04/09/oryol-3rd-party-code.html
All the C libraries in there should be trivial to integrate with Rust, the C++ libs might be a bit more complicated though.
For audio, I can recommend SoLoud, it's multiplatform and also works well in asm.js/wasm (and doesn't add much size):
I'm not aware of any specifically, but I do know at least one Rustacean who has been playing with this tweeted something like "I'm surprised but these 80 crates i've been using for advent of code work out of the box with wasm". So we'll see!
It's a bit spare, and certainly not comprehensive. I've personally gotten ICU and jsoncpp working with minimal effort. Basically if the library has good cross platform support it should work.
The opposite is also true - you have a html5.h header file you can reference to do DOM/browser manipulations from your native code.
It's pretty fascinating.
Does anyone have benchmarks that tell a different story?
http://floooh.github.io/virtualkc/
It's implemented in a C-with-classes style C++ though, not Rust.
When you press the 'UI' button, there's a little millisecond timer in the top-right corner which tells you how much time is spent in the 'emulator frame', which is pure asm.js/wasm code which doesn't call out into JS APIs.
You can switch between the asm.js and wasm version through the hamburger-menu-icon at the top-left corner.
I'm seeing the "1.2..1.5x slower than native" performance there.
Some of my other demos are also fairly CPU heavy, for instance the two Bullet-Physics demos here:
http://floooh.github.io/oryol-samples/
These demos have asm.js, wasm and pnacl versions and also have fairly detailed timing information which makes it possible to compare performance to the natively compiled versions.
I do currently see some mysterious performance differences between Mac and Windows though, not sure what's up with that (e.g. my mid-2014 MBP with a 2.8 GHz i5 is giving better performance than the 3.5 GHz i7-4770K in my work PC).
It's worth checking the single thread performance of both your CPU models (see www.cpubenchmark.net), sometimes the higher end models actually have slower single thread performance.
Best thing since sliced bread if I may say so :)
This seems an overly complex approach. Just because you can do it doesn't mean you should. Most of the advantages of Rust don't apply when you're targeting the Javascript engine of a browser.
Modern Javascript, as a language, isn't that bad. Use the right tool for the job.
Also, modern Javascript has been the only available tool in browsers, but that doesn't mean it's a good one. asm.js and WebAssembly are making it easier to introduce new, and in many cases, better tools.
Knowing nothing of rust development or this particular tool, could a potential benefit be that the outgoing javascript is structured ideologically similar to the rust code that went in? I'm not saying that this would be a primary reason to make this switch but surely this approach isn't without benefit or reason?
Almost every programming languages is better than javascript. The roots of javascript are for tiny special effects and not for huge well running applications. Typescript and all other frameworks for javascript are just workarounds for a buggy language.
In my opinion the final step is to replace completely javascript with something else!
It's also easy to be "one of the worst" when there are only a handful of languages that see widespread use. You only need to be in the bottom 5 of 15 or so languages, but my point is that that may not imply that it's a bad language.
A Software engineer uses always the best tool and not the worst.
There is no way to "fix" Javascript without breaking compatibility. It will always suffer from its poor initial design decisions, or it will stop actually being Javascript.
I am not javascript expert, but it seems that the the choices in the newer versions of Javascript are similar to the new changes in C++. No language can make it impossible to prevent bad decisions, but the newer versions of these languages can make good decisions easier.
Rewriting a codebase that had:
#define static_assert(x) ...
Was "fun" (tm) (C++11 adds a 2-argument keyword, C++17 adds a 1-argument overload that finally undoes the need for the rewrite.)I'll also note we have vastly different standards as to what it would take to "fix" C++. atoi("9999999999") can still launch nethack (undefined behavior!), and C++11's response is to add a new overload, atoll. C++17 still doesn't have modules (TRs aside), still has a grammar that's so obscene to try and parse that compilers still disagree on some of the finer points, and still thinks "undefined behavior" is a hip new metal band to name drop for cred, rather than a last resort.
This is not to say we shouldn't try to improve the language anyways, but compatibility was and will continue to be broken (hopefully in small ways that generate compile errors), and C++ will continue to suffer from it's initial design, and it will continue to do so for as long as it remains C++.
atoi causing undefined is not a real complaint because it has always caused undefined behavior. You can't blame changing that on the standard or the new version of C++ because it was already allowed to change with every execution of the program. Trying to fix non-determinism is a good thing because well formed code should already be avoiding these undefined behaviors.
Why do and others try to complain when you use undefined behavior and are surprised when it changes in undefined ways? You specifically asked to not be able to know the answer.
Merge conflicts are the gift that just keeps on giving. Every refactor on another branch touching the same code is now a conflict. Any branch doing a search and replace slightly differently (say, whitespacing) is now a conflict. Have you ever had to resolve so many of these conflicts that you started accidentally misresolving even the trivial ones? I have. The nontrivial ones can become much harder to code review (e.g. two branches refactored code in the same file, possibly already causing a merge conflict, now complicated by 'spurious' conflicts unrelated to that refactoring.)
Guess how I found out that P4Diff's UI was buggy and could corrupt your local changes? ...a similarly 'trivial' search and replace for logging functions. The static_assert one actually wasn't really that bad ;). Still not 'trivial' though.
> [...] atoi [...] You can't blame changing that on the standard
That wasn't my intent. My intent was to point out broken behavior that the standard decided to double down (by adding atoll) on instead of fixing (by, say, deprecating atoi, like your compiler or programming standard should.) atoi causing UB is still a real complaint - just not a broken compatibility complaint.
> Why do [you] and others try to complain when you use undefined behavior and are surprised when it changes in undefined ways? You specifically asked to not be able to know the answer.
I don't?
You're perhaps thinking of unspecified behavior. Undefined behavior is a damn sight worse than "asking not to know the answer": it's accidentally telling the compiler to generate a broken program that could do anything, for nobody does this intentionally.
On the subject of things I do ask: I spend a lot of time on enabling more warnings as errors, using more static analysis tools, new compilers, etc. to try and find every instance of accidental undefined behavior so we can fix it. I'm specifically asking to know about all instances of undefined behavior so we can fix them to not invoke undefined behavior. If I could get a comprehensive answer to this, I'd give C++ a lot less shit.
But I cannot get a comprehensive answer to this. There will always be something to slip through the cracks. And other programming languages, taunting me with their lack of undefined behavior. Hell, I'd even settle for a comprehensive answer to "where's all the undefined behavior in my code", and settle for my existing debugging loop when dealing with undefined behavior in third party and system libraries. But I can't even have that on C++ codebases.
Why don't you complain about this?
I deeply sympathize you on this.
I see now what you meant on atoi, I suppose I agree. I prefer boost::lexical_cast or rolling my own when performance matters and type safety is in question.
I was too harsh in my earlier comment and I see I wrote at least some it in anger and misunderstanding. The fact it is accidental is bad, more compiler warnings should be able to be enabled by default in my opinion that catch this kind of non-sense. I agree it shouldn't be possible to be accidental.
I suppose I have had this argument with too many people who see C and C++ as slightly more portable assemblers and grow to rely on specific results of undefined behavior. These people try to defend their right to rely on old and specific undefined behavior. I mistakenly lumped you in with these people incorrectly, please forgive me.
Another big one for me is "this", which has significantly different semantics than nearly any other OO language out there. I personally find it confusing, and it requires you in many cases to understand the invocation point of a function. I can not reason about all the data related to the scope of the function, in the function, without first taking into consideration all the callers of the function.
To be fair though, JS is not the only language that features these flaws. The biggest problem with it is that I'm not really given a choice to use other languages. Yes, there are transpilers, but even with those I almost always need to use JS at some point for integration with other code.
It's one of the fastest dynamic languages in existence, considerably faster than e.g. Ruby and Python
> - Extremely weak type system
Compared to what? It's a dynamic language.
> - No generic language - Too many abstractions - Double behavior of types - Bad scaling -
Vague, what does these even mean? Compared to what?
> Extremely bad OOP Implementation (Just 1% of OOP)
Again vague, what is it lacking? Perhaps it just implements the bits people actually use?
> the Debugging approach doesn't make any sense
No idea what this means. Chrome devtools debugger is excellent.
> The Community (1000+ Frameworks with almost the same features for what existing standards?????)
It's a huge community, there're bound to be lots of camps and lots of people trying to crack the same nut different ways. What's wrong with competition? I personally think it's a fantastic community, and find others lacking by comparison.
I think this is kind of a question of what it means for a language to be fast. The big browser companies have poured a mind-blowing amount of resources into making their JavaScript engines fast. This has made these JavaScript engines faster than other implementations of slow languages that have not had similar resources devoted to performance. But this does not mean "JavaScript is fast" in the sense that the design of JavaScript readily enables good performance, and it doesn't make JavaScript fast relative to actually fast languages.
> Compared to what? It's a dynamic language.
JavaScript's type system is extraordinarily weak even compared to most popular dynamic languages. For example:
$ python -c "print(1 + '1')"
Traceback (most recent call last):
File "<string>", line 1, in <module>
TypeError: unsupported operand type(s) for +: 'int' and 'str'
$ ruby -e "puts(1 + '1')"
-e:1:in `+': String can't be coerced into Fixnum (TypeError)
from -e:1:in `<main>'
$ node -e "console.log(1 + '1')"
11It's significantly faster than most other dynamic languages. It's fast as a compilation target to the extent we can run Unreal Engine in the browser. So I consider the original comment I replied to that simply stated 'Bad performance' incorrect or at least lazy/contextless criticism. If you want to reframe, fine, but I'm not going there :)
Accidental string coercion is a valid point. Also hasn't bitten me in ~10 years of building large JS apps. And JS has many advantages over e.g. Python these days that to me vastly overshadow that downside (better support for FP for one).
(And if you really want that type safety you can use TypeScript, just another great thing to come out of the JS community, you know the one that GPP criticised for daring to provide choice).
The entire point of my comment is that the statement "JavaScript is faster than other dynamic languages" is lazy/contextless praise.
V8 is fast. Rhino is slow. JScript 5 is really slow. They are all JavaScript. V8 is fast because people really wanted it to be fast and did some impressive cutting-edge work to make it happen, not because the language lends itself well to speed. It is a credit to the skill of the people working on the JavaScript engines that JavaScript programmers nowadays can enjoy decent speed, and AFAIK it's not particularly attributable to any specific features of the language.
Whatever flaws JS clearly has, speed is not one of them. All the widely used implementations of the language are fast compared to similar languages.
I'm unsure why you think it matters that this speed came about due to hundreds of thousands of hours of work spent on optimizing various compiles and interpreters. I never see anyone saying "Boy SQL sure is fast, but only because so many intelligent people spent their careers making it fast, so it doesn't count."
Remember, this little argument started because someone described JavaScript as slow. That claim is incredibly disingenuous. No, JavaScript's speed isn't directly linked to the language spec but...who cares?
Why created the c community a paper for to create a "c" version? (https://en.wikipedia.org/wiki/C_POSIX_library)
One reason was to establish a good standard for all people that you can run your code everywhere without effort.
Our history showed many times is better to create a standard instead of many non-standards because that creates unnecessary complexity on our world. Look at the pipeline concept of unix. More and more companies steal this concept to build real time web applications without having so much state (that is concept is pretty old). Our ancestors created all of the wonderful things like tree, pipes, functional and etc. We are just sometimes too stupid to reuse it.
> Compared to what? It's a dynamic language.
But it's worse than just being a dynamic language. The biggest problem is the implicit type conversions. If it would at least throw runtime errors when there is a type mismatch, instead of silently converting to another type, it would help a lot.
I also don't think it's the lack of language features that makes it bad. This is something that is getting addressed.
What really does cause problems is the basic types, the type "system" and the way numbers are treated/represented.
For instance:
- javascript has just one datatype for numbers, HOW CAN YOU WIRTE A NUMBERS APP WHITH PURE JAVASCRIPT SHIT, WTF?. - Debugging is a hell - No generic language - Slow as hell - Double meaning of many this like undefiend - etc - etc
All what you describe above is syntax sugar.
I have learning 6 programming languages (c, go, javascript, python, java and php)