2012年1月8日 星期日

改善 array 的記憶體使用方式

原文網址:https://plus.google.com/u/0/110412141990454266397/posts/U7wMJv2cNnj

本週 GWT 改良進度:加強 array 的記憶體使用方式。

GWT 會給予每個 type 一個稱為 queryId 的數字,透過檢查這個數字來模擬出 Java 的 runtime type check。舉例來說,這段程式碼「foo instanceof IFoo」會去取得 IFoo 的 queryID,假設是 42。

接著,在設定 object 的 prototype 時,會加上 map,例如:
Foo.prototype.castableTypeMap = { 42: 1 };
如此一來,像「foo instanceof IFoo」會轉換成「!!foo.castableTypeMap[42]」,在這個例子會回傳 true。

一切都運作完好...... 除了 array。GWT 中模擬 array 的方式,並不是透過修改 Array.prototype,而是在 native 的 JS Array object 當中加入 field,所以「x=new Foo[10]」最終會變成像這樣:
x=makeArray({42:1});
發現問題了嗎?每一次 allocation 會使用一個新的 array literal,即使它們共用相同(且 immutable)的 literal。這會浪費 JS VM 的記憶體。

這星期我增加的最佳化部份,做了兩件事:
  1. 所有傳給 array constructor 的 cast-map literal 會被儲存並保留在全域變數中。
  2. 所有 cast-map literal 如果出現兩次以上,就會被儲存並保留在全域變數中。
因此,如果 FooFoo2implements IFoo,它們都會有相同的 literal,所以現在 compiler 會產出:
var x = { 42: 1 };
Foo.prototype.castableTypeMap = x;
Foo2.prototype.castableTypeMap = x;
視 application 規模,程式碼的量會減少 0.5~2.5%。

沒有留言:

張貼留言