标签:
原文:https://developers.google.com/v8/?hl=zh-CN
Understand how V8 optimzes Javascript;
Write code mindfully;
Learn you tools and how they can help you;
Hidden Classes Make JavaScript Faster.
(注:Hidden Class 可以理解为VM内部实现对描述抽象类的描述,共享隐藏类才能让VM更高效)
Limit Compile-time type information
It‘s expensive to reason about JavaScript types at compile time...
Initialize all object members in constructor functions;
Always Initialize members in the same order;
(If you add members in different orders, you create a different tree of hidden classes.
And at the end, you‘ll have objects with two different hidden classes that can‘t use the same optimized code)
We use a technique called tagging. So inside of V8 we pass around values of 32-bit numbers and objects.
But we want to be able to use the same 32 bits to represent both. And that way we can have one code path that can handle, in many cases, the objects and integers. So what we do is we use the bottom bit.
And each of the values have s special meaning. If the bit is se, it‘s an object pointer. If it‘s clear, it‘s what we call small integer or smi. And that‘s a 31-bit signed integer. Now if you have a numeric value that you‘re passing around, assigning to a member that is bigger -it‘s a numeric value that‘s bigger than 31 signed bits - then it doesn‘t fit in one of these smis. And we have to create what‘s called a box for it. We box the number. We turn it into a double and we create a new object to put that number inside of it. And what follows from that is the next speed trap to avoid, which is make sure, whenever possible, you use 31-bit signed numbers for performance critical calculations.
Prefer numberic values that can be represented as 31-bit signed integers.
Use contiguous keys starting at 0 for Arrays. (
Don‘t pre-allocate large Arrays(e.g. > 64K elements) to their maxium size, instead grow as you go.
Don‘t delete elements in arrays, especially numberic arrays.
Double Array Unboxing
Initialize using array literals for small fixed-sized arrays
Preallocate small arrays to correct size before using them
Don‘t store non-numeric values(objects) in numeric arrays
V8 has tow compilers
"Full" compiler Starts Executing Code ASAP
Inline Caches(ICs) handle Types Efficiently
Monomorphic Better Than Polymophic
function add(x,y) { return x + y; } add(1,2); //+ in add is monomorphic add("a", "b") //+ in add becomes polymorphic
Prefer monomorphic over polymorphic whenever is possible.
Type Feedback Makes Code Faster
Logging What Gets Optimized
d8 --trace-opt prime.js
logs names of optimized functions to stdout
Not Everything Can Be Optimized
Some features prevent the optimizing compiler from running(a "bail-out")
Avoid the speed trap
Optimizing compiler "bail-out" on functions with try{} catch{} blocks.
Maximizing Performance With Exceptions
function perf_sensitive() { //Do performance-sensitive work here } try{ perf_sensitive() } catch(e) { //handle exceptions here }
How to Find Bailouts
d8 --trace-bailout prime.js
logs optimizing compiler bailouts
Invalid assumptions lead to deoptimization[37:55]
Deoptimization...
Passing V8 Options to Chrome
"/Applicaitons/Google Chrome.app/Contents/MacOS/Google Chrome" \--js-flags="--trace-opt --trace-deopt --trace-bailout"
Avoid the speed trap
Avoid hidden class changes in functions after they are optimized
"Identify and Understand" for V8
Prime Generator -- Profile It
%out/ia32.release/d8 prime.js --prof
287107
using teh built-in sampling profiler
What to expect from the primes Code
function Primes() { ... this.addPrime = function(i) { this.primes[this.prime_count++] = i; } this.isPrimeDivisible = function(candidate) { for(var i = 1; i <= this.prime_count; ++i) { if(candidate % this.primes[i]) == 0) { return true; } } return false; } }; function main() { p = new Primes(); var c = 1; while (p.getPrimeCount() < 25000) { if(!p.isPrimeDivisible(c)) { p.addPrime(c); } c++; } print(p.getPrime(p.getPrimeCount()-1)); }
Prediction: Most Time Spent in main
(输出省略 @42:50)
Can you spot the bug?
this.isPrimeDivisible = function(candidate) { for(var i = 1 ; i <= this.prime_count; ++i) { if (candidate % this.primes[i] == 0) return true; } return false; }
(Hint: primes is an array of length prime_count)
% out/ia32.release/d8 primes-2.js --prof
287107
(省略)
JavaScript is 60% faster than C++
C++
% g++ primes.cc -o primes % time ./primes 287107 real 0m2.955s user 0m2.952s sys 0m.001s
JavaScript
% time d8 primes-2.js 287107 real 0m1.829s user 0m1.827s sys 0m0.010s
JavaScript is 17% slower than optimized C++
Optimize Your Algorithm
this.isPrimeDivisible = function(candidate) { for(var i = 1 ; i < this.prime_count; ++i) { var current_prime = this.primes[i]; if(current_prime*current_prime > candidate){ return false; } if (candidate % this.primes[i] == 0) return true; } return false; }
Final Results
(输出省略)
That‘s more than a 350x Speed-up!
Keep Your Eyes on the Road
JavaScript 性能优化 --By Google V8 Team Manager
标签:
原文地址:http://www.cnblogs.com/Tue/p/5505618.html