《2018年V8、JavaScript+的現在與未來.pdf》由會員分享,可在線閱讀,更多相關《2018年V8、JavaScript+的現在與未來.pdf(89頁珍藏版)》請在三個皮匠報告上搜索。
1、V8、JavaScript 的現在與未來History of JavaScriptV8 引擎針對 JavaScript 的性能優化TC39 的最新提案以及應用場景編寫高性能 JavaScript 代碼history of JavaScript1997LiveScript1996JavaScript1995EcmaScript2000ES32015ES6ES720162017ES8ES920182009ES5JScript2004FirefoxV82008IE62001IE72005Node.jsChromeEdge2006jQuerynpm2010Vue.js20142013ReactAngu
2、larI created JavaScript in 10 daysbug or feature?typeof null=object;/WTF?null instanceof Object=false;/WTF?null instanceof null;/TypeError:Right-hand side of instanceof is not an object WTF?圖片來源:wikipedia.orgSchrdingers NullES201xletconstclassspreadtrailing commasSetMapPromisearrow functionSymbolTyp
3、edArraysIterationGeneratorsExponentiation Operatortagged templateV8 Release Process每天每周每6周每6周V8 引擎針對 JavaScript 的性能優化V8 概覽快速的算術運算數組的高階函數內聯編譯逃逸分析IgnitionTurboFan(since Chrome 59)Optimization Killers生成器和 async 函數for-of 和數組解構try-catch 和 try-finally復合 let 或 const 賦值包含 _proto、get、set 的對象聲明debugger 或 with
4、 語句eval()TurboFan快速的算術運算const i=1;/SmallInteger(Smi)const d=1.1;/HeapNumber(Double)const o=;/JSObject(Heap)SMI vs Double代碼:a+bmov eax,amov ebx,bcall RuntimeAdd代碼:a+bmov eax,amov ebx,bcall RuntimeAddadd eax,ebxType feedback二元運算符可以收集函數的 typefeedback信息.function f(a,b)var c=a+a;return b+c;函數信息Feedbackve
5、ctor.StackCheck Ldar a0Add a0,2Star r0Ldar r0Add a1,3Return 2:unitialized3:unitializedType feedback二元運算符可以收集函數的 typefeedback信息.function f(a,b)var c=a+a;return b+c;f(1,2);函數信息Feedbackvector.StackCheck Ldar a0Add a0,2Star r0Ldar r0Add a1,3Return int+int-intint+int-intType feedback二元運算符可以收集函數的 typefeed
6、back信息.function f(a,b)var c=a+a;return b+c;f(1,2);f(1,0.1)函數信息Feedbackvector.StackCheck Ldar a0Add a0,1Star r0Ldar r0Add a1,1.1Return int+int-intnum+num-numType feedback二元運算符可以收集函數的 typefeedback信息.function f(a,b)var c=a+a;return b+c;f(1,2);f(1,0.1)/Deopt!函數信息Feedbackvector.StackCheck Ldar a0Add a0,1
7、Star r0Ldar r0Add a1,1.1Return int+int-intnum+num-numIgnitionTurboFanOptimizationDeoptimizationx is a Numberx is NOT a Number數組的高階函數const array=1,2,3;/elements kind:PACKED_SMI_ELEMENTSarray.push(4.56);/elements kind:PACKED_DOUBLE_ELEMENTSarray.push(x);/elements kind:PACKED_ELEMENTSarray.length;/5ind
8、exvalue01122334.564“x”array.length;/5array9=1;/array5 array8/elements kind:HOLEY_ELEMENTSindexvalue01122334.564“x”567891array8;/?8=0&8 b+x,0)=(0+1)+2)+3=6b 的初始值為 0對數組的元素進行累加function foo(A)return A.reduce(b,x)=b+x,0);function foo_inlined(A)const f=(b,x)=b+x;const len=A.length;if(typeof f!=function)th
9、row new TypeError();let b=0;for(let i=0;i b+x;if(typeof f!=function)throw new TypeError();let b=0;for(let i=0;i b+x;if(typeof f!=function)throw new TypeError();let b=0;for(let i=0;i b+x;if(typeof f!=function)throw new TypeError();let b=0;for(let i=0;i A.length;+i)if(i in A)b=b+Ai;return b;PACKED_SMI
10、_ELEMENTSfunction Array_reduce_inline(A)let b=0;for(let i=0;i A.length;+i)if(i in A)b=b+Ai;return b;PACKED_SMI_ELEMENTSfunction Array_reduce_inline(A)if(A not PACKED_SMI_ELEMENTS)Deopt;let b=0;for(let i=0;i A.length;+i)if(i in A)b=b+Ai;if(A not PACKED_SMI_ELEMENTS)Deopt;return b;PACKED_SMI_ELEMENTSf
11、unction Array_reduce_inline(A)if(A not PACKED_SMI_ELEMENTS)Deopt;let b=0;for(let i=0;i A.length;+i)if(i in A)b=b+Ai;if(A not PACKED_SMI_ELEMENTS)Deopt;return b;PACKED_SMI_ELEMENTSfunction Array_reduce_inline(A)if(A not PACKED_SMI_ELEMENTS)Deopt;let b=0;for(let i=0;i A.length;+i)if(i in A)b=b+Ai;if(A
12、 not PACKED_SMI_ELEMENTS)Deopt;return b;PACKED_SMI_ELEMENTSfunction Array_reduce_inline(A)if(A not PACKED_SMI_ELEMENTS)Deopt;let b=0;for(let i=0;i A.length;+i)b=b+Ai;return b;PACKED_SMI_ELEMENTSInliningfunction add(x,y)return x+y;function three()return add(1,2);function three_add_const_folded()retur
13、n 3;function three_add_inlined()var x=1;var y=2;var add_return_value=x+y;return add_return_value;function add(x,y)return x+y;function three()return add(1,2);leaq rcx,rip+0 x0movq rcx,rcx-0 x37testb rcx+0 xf,0 x1jnz CompileLazyDeoptimizedCodepush rbpmovq rbp,rsppush rsipush rdicmpq rsp,r13+0 xdb0jna
14、StackCheckmovq rax,rbp+0 x18test al,0 x1jnz Deoptimizemovq rbx,rbp+0 x10testb rbx,0 x1jnz Deoptimizemovq rdx,rbxshrq rdx,32movq rcx,raxshrq rcx,32addl rdx,rcxjo Deoptimizeshlq rdx,32movq rax,rdxmovq rsp,rbppop rbpret 0 x18leaq rcx,rip+0 x0movq rcx,rcx-0 x37testb rcx+0 xf,0 x1jnz CompileLazyDeoptimiz
15、edCodepush rbpmovq rbp,rsppush rsipush rdicmpq rsp,r13+0 xdb0jna StackCheckmovq rdi,movq rsi,rdi+0 x1fmovq rax,push raxmovq rax,0 x100000000push raxmovq rax,0 x200000000push raxmovq rdx,r13-0 x60movl rax,0 x2movq rcx,rdi+0 x2faddq rcx,0 x5fcall rcxmovq rsp,rbppop rbpret 0 x8function add(x,y)return x
16、+y;function three()return add(1,2);leaq rcx,rip+0 x0movq rcx,rcx-0 x37testb rcx+0 xf,0 x1jnz CompileLazyDeoptimizedCodepush rbpmovq rbp,rsppush rsipush rdicmpq rsp,r13+0 xdb0jna StackCheckmovq rax,rbp+0 x18test al,0 x1jnz Deoptimizemovq rbx,rbp+0 x10testb rbx,0 x1jnz Deoptimizemovq rdx,rbxshrq rdx,3
17、2movq rcx,raxshrq rcx,32addl rdx,rcxjo Deoptimizeshlq rdx,32movq rax,rdxmovq rsp,rbppop rbpret 0 x18leaq rcx,rip+0 x0movq rcx,rcx-0 x37testb rcx+0 xf,0 x1jnz CompileLazyDeoptimizedCodepush rbpmovq rbp,rsppush rsipush rdicmpq rsp,r13+0 xdb0jna StackCheckmovq rdi,movq rsi,rdi+0 x1fmovq rax,push raxmov
18、q rax,0 x100000000push raxmovq rax,0 x200000000push raxmovq rdx,r13-0 x60movl rax,0 x2movq rcx,rdi+0 x2faddq rcx,0 x5fcall rcxmovq rsp,rbppop rbpret 0 x8leaq rcx,rip+0 x0movq rcx,rcx-0 x37testb rcx+0 xf,0 x1jnz CompileLazyDeoptimizedCodepush rbpmovq rbp,rsppush rsipush rdicmpq rsp,r13+0 xdb0jna Stac
19、kCheckmovq rax,0 x300000000movq rsp,rbppop rbpret 0 x8escape analysisfunction foo(a)return abs(x:a,y:a);function abs(v)return Math.sqrt(v.x*v.x+v.y*v.y);return Math.sqrt(a*a+a*a);How?Step 1:內聯function foo(a)let v=x:a,y:a;return abs(v);function abs(v)return Math.sqrt(v.x*v.x+v.y*v.y);function foo(a)l
20、et v=x:a,y:a;return Math.sqrt(v.x*v.x+v.y*v.y);Step 2:替換屬性訪問操作function diagonal(a)let v=x:a,y:a;return Math.sqrt(v.x*v.x+v.y*v.y);function diagonal(a)let v=x:a,y:a;return Math.sqrt(a*a+a*a);Step 3:刪除未使用的變量function diagonal(a)let v=x:a,y:a;return Math.sqrt(v.x*v.x+v.y*v.y);function diagonal(a)return
21、Math.sqrt(a*a+a*a);TC39 的最新提案以及應用場景TC39 processBigIntPipeline operatorPattern MatchingTC39 process共包含 5 個階段使用 HTML 的超集進行格式化基于 GitHub pull requestsStagestrawmanStage 0Stage 1Stage 3Stage 2Stage 4proposalpolyfill 和 demodraftBabelcandidatefinishedStage2+準準備實現備實現寫寫設計文檔設計文檔原型原型設計設計BaselineStagedShipped公公
22、測測優化優化調試調試ProxyChrome 49 開始支持 ProxyChrome 62 改進了 Proxy 的性能Proxy 構造函數Proxy 獲取屬性值Proxy 判斷屬性值Proxy 設置屬性值Proxy 性能提升24%546%BigIntconst max=Number.MAX_SAFE_INTEGER;/9,007,199,254,740,991(=2*53-1)const max=Number.MAX_SAFE_INTEGER;/9,007,199,254,740,991(=2*53-1)max+1;/9,007,199,254,740,992(=2*53)const max=N
23、umber.MAX_SAFE_INTEGER;/9,007,199,254,740,991(=2*53-1)max+1;/9,007,199,254,740,992(=2*53)max+2;/9,007,199,254,740,992(=2*53)const max=Number.MAX_SAFE_INTEGER;/9,007,199,254,740,991(=2*53-1)max+1;/9,007,199,254,740,992(=2*53)max+2;/9,007,199,254,740,992(=2*53)max+3;/9,007,199,254,740,994(=2*53+2)cons
24、t max=Number.MAX_SAFE_INTEGER;/9,007,199,254,740,991(=2*53-1)max+1;/9,007,199,254,740,992(=2*53)max+2;/9,007,199,254,740,992(=2*53)max+3;/9,007,199,254,740,994(=2*53+2)BigInt(max)+2n;/9,007,199,254,740,993n(=2*53+1)1234567890123456789*123;/1518518504851852000001234567890123456789n*123n;/151851850485
25、185185047ntypeof 123;/numbertypeof 123n;/bigintPipeline operatorStage-1log(capitalize(double(hello)hello|double|capitalize|loglog(capitalize(double(hello)new User.Message(capitalize(doubledSay(value,)+!)value|(x=doubleSay(x,)|capitalize|(x=x+!)|(x=new User.Message(x)Optional ChainingStage 1/獲取用戶 nam
26、e 屬性/可能拋出異常const name=response.body.user.name;/獲取用戶 name 屬性/可能拋出異常const name=response.body.user.name;/對變量和屬性進行檢查const name=response&response.body/獲取用戶 name 屬性/可能拋出異常const name=response.body.user.name;/對變量和屬性進行檢查const name=response&response.body&response.body.user/獲取用戶 name 屬性/可能拋出異常const name=respon
27、se.body.user.name;/對變量和屬性進行檢查const name=response&response.body&response.body.user&response.body.user.name/獲取用戶 name 屬性/可能拋出異常const name=response.body.user.name;/對變量和屬性進行檢查const name=response&response.body&response.body.user&response.body.user.name|justjavac;With Optional Chainingconst name=response?
28、.body?.user?.name|justjavac;Pattern MatchingStage 1case(input)when 1-./matches if input is 1when foo-./matches if input is foowhen false-./matches if input is falsewhen null-./matches if input is nullwhen x:1-./matches if input can do ToObject and input.x is 1when 1,2-./matches if input can do GetIt
29、erator,has exactly 2 items,/and the items are 1,then 2.when x-./always matcheswhen/foo/-./SyntaxErrorwhen x if(x.match(/foo/)-./ok!Redux reducersfunctiontodoApp(state=initialState,action)case(action)when type:set-visibility-filter,filter:visFilter-return.state,visFilterwhen type:add-todo,text-return
30、.state,todos:.state.todos,textwhen type:toggle-todo,index-return.state,todos:state.todos.map(todo,idx)=idx=index?.todo,done:!todo.done:todo)when -/ignore unknown actions編寫高性能 JavaScript 代碼不要修改原型鏈使用 Object.keys()不要在遍歷時修改元素不要修改原型鏈不要修改原型鏈不要修改原型鏈不要修改原型鏈100 xObject.keys()Object.keys()1x不要在遍歷時修改元素A.filter(x,i)=x 50);/OKA.forEach(x,i)=if(x 50)Ai=undefined;);JavaScript函數式編程函數式編程都是垃圾