kikobeats / js-mythbusters Goto Github PK
View Code? Open in Web Editor NEW:ghost: STHAP js, where is my perf?
Home Page: https://mythbusters.js.org
License: MIT License
:ghost: STHAP js, where is my perf?
Home Page: https://mythbusters.js.org
License: MIT License
Maybe one of that: http://www.flaticon.com/search?word=Ghost
https://mythbusters.js.org/#/v8-tips/freeing-memory
using
var foo = { bar: 'hello world' } foo.bar = undefined // Efficient way (good)
can lead to memory leaks because foo keeps the string key "bar" stored potentially forever. Can happen when objects are used as maps.
This is a popular internet topic.
About:
const newArray = arr.slice(0)
const anotherArray = [...arr]
const newObj = Object.assign({}, obj)
const anotherObj = {...obj}
also known as shallow clone:
> third = {hello: 'world'}
> obj = {foo: 'bar', third}
{ foo: 'bar', third: { hello: 'world' } }
> shallow = Object.assign({}, obj)
{ foo: 'bar', third: { hello: 'world' } }
> shallow
{ foo: 'bar', third: { hello: 'world' } }
> third
{ hello: 'world' }
> third.hello = 'test'
'test'
> shallow
{ foo: 'bar', third: { hello: 'test' } }
const deepClone = obj => {
let clone = Object.assign({}, obj);
Object.keys(clone).forEach(
key => (clone[key] = typeof obj[key] === 'object' ? deepClone(obj[key]) : obj[key])
);
return clone;
};
JSON.parse(JSON.stringify(value))
is not enough.
- Will throw error in circular objects.
- The JSON.stringify conversion has to be lossless. Therefore, methods are not allowed as members of type function are ignored by the JSON stringifier. The undefined value is not allowed either. Object keys with undefined value are omitted, while undefined values in arrays are substituted by null.
- Members of the Date object become ISO-8601 strings, not representing the timezone of the client. The value new Date(2011,0,1) becomes "2010-12-31T23:00:00.000Z" after executing the above deep copy method in case you live in Central Europe.
parse/stringify is a CPU intensive task, so no I/O is here and not supported from low level Node.js API.
The only "async" way possible is in deepClone wrap each deepClone call into a process.nextTick, simulating deferrer it.
Inspiration:
Description
Would be great to talk about how .toString() is used, it's recently been updated in the latest V8 release.
Function.prototype.toString() now returns exact slices of source code text, including whitespace and comments
https://v8project.blogspot.com.es/2018/03/v8-release-66.html
When it comes to Javascript data, thereβs pretty much four ways to access it: literal values, variables, object properties, and array items. When thinking about optimization, literal values and variables perform about the same, and are significantly faster than object properties and array items.
So whenever you reference an object property or array item multiple times, you can get a performance boost by defining a variable. (This applies to both reading and writing data.)
While this rule holds mostly true, Firefox has done some interesting things to optimize array indexes, and actually performs better with array items than with variables. But the performance drawbacks of array items in other browsers mean that you should still avoid array lookups, unless you are really only targeting Firefox performance.
Add a tip related with the difference between parameter vs argument.
Javascript is always pass by value, but when a variable refers to an object (including arrays), the "value" is a reference to the object.
Changing the value of a variable never changes the underlying primitive or object, it just points the variable to a new primitive or object.
However, changing a property of an object referenced by a variable does change the underlying object.
reasons to name functions:
Source: http://elijahmanor.com/talks/js-smells/#/11/3
Related: https://www.youtube.com/watch?v=_0W_822Dijg
https://github.com/Kikobeats/js-mythbusters/blame/master/docs/v8-tips/inline-initialization.md#L44
var array = []
for (var i = 0; i < 10; i++) array[i] |= 0 // Oh no!
var array = []
array[0] = 0
for (var i = 0; i < 10; i++) array[0] |= i
The first one creates an array with 10 elements. The second one creates an array with a single element.
Maybe it's something like this:
var array = new Array(10)
for (var i = 0; i < 10; i++) array[i] = 0
The unicode flag was recently added:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/unicode
It should be used by default!
/^.$/.test('a') //β
/^.$/.test('πΆ') //β
/^.$/u.test('πΆ') //β
By default, . matches any character except for line terminators:
/foo.bar/u.test('foo\nbar');
// β false
(It doesnβt match astral Unicode symbols either, but we fixed that by enabling the u flag.)
ES2018 introduces dotAll mode, enabled through the s flag. In dotAll mode, . matches line terminators as well.
/foo.bar/su.test('foo\nbar');
// β true
__
both flags can be used as the new standard
Reference:
arr = []
arr.length = 0
while(arr.length) arr.pop()
Hey, very nice initiative and website π
The items.length
part in Variable access is not always true and even probably wrong for your example. Most modern VMs apply loop-invariant code motion. Array#length
is no exception, there is a very detailed article that explains what happens here: http://mrale.ph/blog/2014/12/24/array-length-caching.html.
I'd suggest refactoring this part and mentioning that accessing Array#length
IS OK (myth busted) if the loop body does not mutate the array or is simple enough.
For http://mythbusters.js.org/workflow/boolean-conditions.html
Using https://jsfiddle.net/tj2o7oza/3/
And tested on both firefox and chrome with multiple runs
seems to suggest that the "not a myth" is a myth
More indepth discussion in this comment https://news.ycombinator.com/item?id=12393642
Related: http://www.w3schools.com/js/js_performance.asp
I'm sure that @rstacruz know more tips in this are than me π .
Hey me again,
I would suggest a short paragraph to make the user aware of eager optimizations and the fact it is often an enemy.
Measure it, don't guess it
docs/v8-tips/inline-initialization.md
var array = []
for (var i = 0; i < 10; i++) array[0] |= i // Oh no!
Should not there be array[i] |= 0
instead of repeated modifying of one first element? The same for next "correct" example.
Another interesting benchmark is String.prototype.indexOf vs RegExp.prototype.test, I personally expected the latter to be faster, thatβs what happens in Firefox, but in Chrome, itβs not. RegExp.prototype.test is 32% faster on Firefox, while String.prototype.indexOf is 33% faster on Chrome. In times like this, go with the one you like most, i think.
https://jsperf.com/exec-vs-match-vs-test-vs-search/5
https://jsperf.com/search-vs-indexof11/4
https://jsperf.com/regexp-indexof-perf
https://jsperf.com/regexp-test-search-vs-indexof/12
Improved code caching
V8 uses code caching to cache the generated code for frequently-used scripts. Starting with Chrome 66, we are caching more code by generating the cache after top-level execution. This leads to a 20-40% reduction in parse and compilation time during the initial load.
Please note that:
https://v8project.blogspot.com.es/2018/04/improved-code-caching.html
Without context or explanation of the fundamentals, these "mythbusting" statements are of low value. See #25
You need to take in account
A very blatant example is in https://mythbusters.js.org/#/v8-tips/freeing-memory
Consider a scenario were your object is not used as a class-type element with an explicit structure, but rather like a dictionary were keys are added and removed dynamically. Setting keys to null will release the reference to the element, but the dictionary will still hold a pointer for that key, slowing down lookups significantly.
With a clear example, you could illustrate the impact of both approaches.
An example for hardware profile would be the over usage of V8 C++ - side methods, which perform exponentially better on bigger hardware. You can witness this in libraries that implement protocols in pure-js versus their C++ bindings version.
A lot of bundled JS methods also take advantage of this, like JSON.stringify/ JSON.parse.
You can try benchmarking https://github.com/compactr/compactr.js on different machines to see just how big of a difference it makes.
For Node version, Buffers got a speed boost recently in Node 8. Prior to that, it was much faster to use arrays/ UINT8Arrays. In the browser, Buffers are polyfilled as UINT8Arrays anyways.
When a variable is referenced, Javascript hunts it down by looping through the different members of the scope chain. This scope chain is the set of variables available within the current scope, and across all major browsers it has at least two items: a set of local variables and a set of global variables.
Simply put, the deeper the engine has to dig into this scope chain, the longer the operation will take. It first goes through the local variables starting with this, the function arguments, then any locally defined variables, and afterwards iterates through any global variables.
According to the author, JSPerf is used incorrectly, 70% of the time.
http://www.slideshare.net/mathiasbynens/using-jsperf-correctly
βββββββββββββββββββββββββ
ββ>β timers β
β ββββββββββββ¬βββββββββββββ
β ββββββββββββ΄βββββββββββββ
β β I/O callbacks β
β ββββββββββββ¬βββββββββββββ
β ββββββββββββ΄βββββββββββββ
β β idle, prepare β
β ββββββββββββ¬βββββββββββββ βββββββββββββββββ
β ββββββββββββ΄βββββββββββββ β incoming: β
β β poll β<ββββββ€ connections, β
β ββββββββββββ¬βββββββββββββ β data, etc. β
β ββββββββββββ΄βββββββββββββ βββββββββββββββββ
β β check β
β ββββββββββββ¬βββββββββββββ
β ββββββββββββ΄βββββββββββββ
ββββ€ close callbacks β
βββββββββββββββββββββββββ
Use setImmediate if you want to queue the function behind whatever I/O event callbacks that are already in the event queue.
Use process.nextTick to effectively queue the function at the head of the event queue so that it executes immediately after the current function completes. It's slightly faster than setTimeout:
'use strict'
var bench = require('fastbench')
var run = bench([
function benchSetImmediate (done) {
setImmediate(done)
},
function benchNextTick (done) {
process.nextTick(done)
}
], 1024 * 1024)
// run them two times
run(run)
Considerations on browser side
setTimeout(fn, 0)
.Context
Node is single threaded. That is a very simple explanation of how it works. There is a thread pool to manage file handles. Two event loops, the main one and the worker pool. The main loop is divided in several important phases so it would be great to explain them in a simple way and how threading is managed in node/v8.
References
https://stackoverflow.com/questions/18895305/will-function-prototype-bind-always-be-slow
You can see that var self = this pattern is still about 60% faster. But it requires the function definition to be inlined where as you can bind from anywhere and therefore have better maintainability.
You have the following example in parsing of numbers:
const toNumber = num => ~~num
console.log(toNumber('10.9'))
// => 10.9
But according to your table, the output should be 10
Therefore, this should be:
const toNumber = num => ~~num
console.log(toNumber('10.9'))
// => 10
https://github.com/nolanlawson/optimize-js
This has become very popular recently. Would be great to clarify why this 'optimization' works.
I like the idea, but two pieces of feedback:
The colour scheme is dark and is okay, in general. However code samples look terrible, particularly comments on them which end up being a dark text on dark background situation.
The main point: None of these appear to be actual mythbusting, at least that I've seen so far. No benchmarks or other repeatable bits of code. Just "Hey this is better!", which amounts to little more than myths in and of itself. Mythbusters was all about taking myths, creating an experiment and figuring out if it was true or not. e.g. http://mythbusters.js.org/workflow/math.html at the very least there should be some simple microbenchmarks there.
Reading about Proxies at
https://hacks.mozilla.org/2015/07/es6-in-depth-proxies-and-reflect/
I found a very nice WeakMaps usage example:
Proxies β₯ WeakMaps. In our readOnlyView example, we create a new proxy every time an object is accessed. It could save a lot of memory to cache every proxy we create in a WeakMap, so that however many times an object is passed to readOnlyView, only a single proxy is created for it.
throw new Error("can't modify read-only view");
}
var handler = {
// Override all five mutating methods.
set: NOPE,
defineProperty: NOPE,
deleteProperty: NOPE,
preventExtensions: NOPE,
setPrototypeOf: NOPE
};
function readOnlyView(target) {
return new Proxy(target, handler);
}
This is one of the motivating use cases for WeakMap.
Because WeakMaps
is confused with Maps
, could be interesting add a section about when to use WeakMaps
I didn't remember the article, but I started understanding why wasm when I understood browsers spend a lot of time in parsing step.
Need to investigate a bit.
Related:
Because every section of the web is linked with a GitHub file, could be awesomeness link each section with a "Edit File" button for make easy contributions.
Related: docsifyjs/docsify#162
I didn't remember the article, but I started understanding why wasm when I understood browsers spend a lot of time in parsing step.
Need to investigate a bit.
non-exhaustive list:
for
loop.π¨ You need to enable Continuous Integration on all branches of this repository. π¨
To enable Greenkeeper, you need to make sure that a commit status is reported on all branches. This is required by Greenkeeper because we are using your CI build statuses to figure out when to notify you about breaking changes.
Since we did not receive a CI status on the greenkeeper/initial
branch, we assume that you still need to configure it.
If you have already set up a CI for this repository, you might need to check your configuration. Make sure it will run on all new branches. If you donβt want it to run on every branch, you can whitelist branches starting with greenkeeper/
.
We recommend using Travis CI, but Greenkeeper will work with every other CI service as well.
Once you have installed CI on this repository, youβll need to re-trigger Greenkeeperβs initial Pull Request. To do this, please delete the greenkeeper/initial
branch in this repository, and then remove and re-add this repository to the Greenkeeper integrationβs white list on Github. You'll find this list on your repo or organiszationβs settings page, under Installed GitHub Apps.
The URL provided for lodash _.bind
benchmark test returns 404.
It's used in https://mythbusters.js.org/#/function/bind and the URL is https://jsperf.com/bind-vs-jquery-proxy/104
Also, bind works better in the last v8 implementations:
I really do love jsPerf (even wrote a tutorial for jsPerf for a Meetup). But it needs Java... which is kinda something I try to avoid.
Thanks for your resource; I'll have to add in my finds later.
Have you thought about a PDF version?
The PDF will be all the .md in in the same order that are in the website.
Please I need that https://codepen.io/loktar00/pen/FmkAd
A declarative, efficient, and flexible JavaScript library for building user interfaces.
π Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. πππ
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google β€οΈ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.