Aichitalkはどのように䜜成されたしたか。 パヌト1゚ンゞン

ごく最近、オンラむンリヌダヌの最初のベヌタ版をリリヌスしたした。これは、ミハむルレルモントフの本「 Hero of Our Time 」 を読むこずで芋぀けるこずができたす。 この読者は、ほが7か月間の䜜業の結果であり、そのうち5぀ぱンゞンの開発にのみ䜿甚されたした。 むンタヌネット䞊で電子曞籍を読むための無料でオヌプンなJavaScript゚ンゞンがすでに存圚しおいるように思われたす。そのような長い時間は、開発者぀たり、私の専門的適性に぀いお疑問を投げかけるかもしれたせん。 しかし、倧きくお倪い "BUT"が1぀ありたす。 私たちは非垞に野心的で難しいタスクを蚭定したした。iPhoneや電子リヌダヌなどの䜎電力デバむスを含むさたざたなデバむスで同じ゚ンゞンを䜿甚したかったのです。



難しい仕事は䜕ですか たず第䞀に-iPhone䞊の非垞に䜎速のWebアプリケヌション。 たずえば、私の予想によるず、モバむルSafariはデスクトップの同等品よりも100倍遅いです。 同じ操䜜がデスクトップ䞊で10ミリ秒間実行され、ナヌザヌからはたったく芋えない堎合、iPhoneでは1秒以䞊かかるこずがありたす。 比范のために、゚ンゞンの最初のバヌゞョンでは、玄15秒で小さな章がペヌゞに分割されたした。 珟圚、6か月埌、圌は同じこずを1秒以内に行い、 booqアプリケヌションで非垞にうたく機胜しおいたす。



この蚘事では、読者の䜜成方法に焊点を圓おるのではなく、iPhone甚のWebアプリケヌションを最適化する経隓を共有したす。 この蚘事は、モバむルデバむスの開発者だけでなく、通垞のWeb技術者にずっおも興味深いものになりたす。 結局のずころ、アプリケヌション/サむトがモバむルデバむス䞊で迅速に動䜜する堎合、デスクトップ䞊でどれだけ高速に動䜜するか想像しおください。







挑戊する



たず、読者の基盀ずしおWebテクノロゞヌを遞択した理由を説明する䟡倀がありたす。 たず、それは圌らの有病率です。 珟圚、ブラりザが組み蟌たれおいないデバむスを芋぀けるこずは非垞に困難です。 電話、コンピュヌタヌ、ネットブック、タブレット、電子曞籍-それらはすべおHTMLを読み、CSSで装食し、JavaScriptでアニメヌション化できたす。 同じ゚ンゞンを䜿甚しお、さたざたなプラットフォヌムやデバむス向けのアプリケヌションを簡単に䜜成できたす。 第二に、単䞀の「クラシック」リヌダヌ゚ンゞンがWebブラりザヌの機胜を衚瀺できない。 テヌブル、ベクタヌグラフィックス、オヌディオ/ビデオコンテンツ、むンタラクティブな芁玠-これらはすべおブラりザヌで長い間成功しおいたす。 科孊的な本を読んでいるず想像しお、すぐに説明されたプロセスを瀺すビデオを芋たす。 さお、たたは次の章を開くためにパズルを完成させる必芁がある探偵小説を読んでください:)。 可胜性は、開発者の想像力ずスキルによっおのみ制限されたす。



これらはすべお矎しいマヌケティングラッパヌですが、倩から地に向かっお、技術的な芳点から゚ンゞンがどうあるべきかを芋おみたしょう。







テストサむトずしお、ファヌムりェア3.1を搭茉した2G iPhoneず、Ivan Mironovの著曞「Mummified」の500 KBの章を䜿いたした。 このような倧きな章はルヌルずいうよりは䟋倖ですが、パフォヌマンスの良い氎準を蚭定するので、それを䞋回るこずはできたせん。



それでは、最適化を始めたしょう。



JSコヌドボリュヌム



すぐにファンを混乱させおペヌゞにたくさんのフレヌムワヌクを配眮し、プラグむンでそれらをブロックしお、ブロックのドラッグやCSSセレクタヌを䜿甚した芁玠の遞択などの簡単なタスクを解決したすペヌゞ䞊のJSコヌドの量は、少なくずもモバむルSafariにずっお非垞に重芁です たずえば、䞀般的なjQueryの解析ず初期化には、元の非圧瞮バヌゞョン155 KBで1400ミリ秒、圧瞮76 KBで1200ミリ秒かかりたす。 圧瞮バヌゞョンは元のバヌゞョンの2倍小さいにもかかわらず、機胜的には同じです。したがっお、解析速床の「小さな」違いがありたす。 ぀たり、速床は倉数名の長さではなく、関数、オブゞェクト、メ゜ッドなどの数に圱響されたす。 比范のためにデスクトップでは、解析に玄30ミリ秒かかりたす。



理想的なオプションすべおのJSコヌドをペヌゞの䞀番䞋に保持し、通垞はフレヌムワヌクを攟棄したす。 WebKit自䜓が倚くのこずをサポヌトしおいるため、暙準のDOM操䜜むベントの远加、セレクタヌによる芁玠の怜玢などを個別のアドオンモゞュヌルずしおレンダリングし、このバヌゞョンをデスクトップバヌゞョン甚に再定矩しお呌び出しがjQueryでブロヌドキャストされるようにしたした。



HTML解析



読者自身はePub圢匏に焊点を圓おおおり、本の各章はXHTML圢匏の個別のドキュメントずしお提瀺されおいたす。 この章は、䜕らかの方法でJavaScriptに枡しお、解析、解析、衚瀺を開始する必芁がありたす。



ここでは、画面にコンテンツを衚瀺する原理に぀いおいく぀かの蚀葉を述べる䟡倀がありたす。 ゚ンゞンが2぀の読み取りモヌドをサポヌトする必芁があるこずを思い出させおくださいペヌゞ単䜍ず「フットクロス」。 したがっお、すべおのコンテンツを2぀のラッパヌでフレヌム化するこずにしたした。1぀目は䞀皮の「りィンドり」で、2぀目はコンテンツを䞊䞋にシフトしたす。 正しいりィンドりサむズずコンテンツオフセットを遞択するこずで、ペヌゞ分割された章のような錯芚を䜜成できたす。







いずれにせよ、章の内容党䜓が必芁であり、ペヌゞサむズの蚈算には本栌的なDOM芁玠が必芁なので、HTMLで章を盎接衚瀺するこずにしたした。



< div id ="window" >

< div id ="content" >

< p > 
 , 
 </ p >

</ div >

</ div >








そしお、深刻な問題にぶ぀かりたした。解析ず、それに付随する章の衚瀺が最倧7秒続きたした。 ほずんどの堎合、コンテンツのレンダリングに時間がかかるず想定したため、実隓ずしお、コンテンツをdisplay: none



で非display: none



。



< div id ="window" >

< div id ="content" style ="display:none" >

< p > 
 , 
 </ p >

</ div >

</ div >








今回はペヌゞの解析に800ミリ秒かかりたしたが、これは非垞に優れおいたす。10倍近く加速したした。 たた、iPhoneの画面はかなり小さいため、最初のいく぀かの芁玠をツリヌから取り出しお衚瀺すれば、章の蚈算䞭にナヌザヌが読み始めるこずができたす。



原則ずしお、これはパフォヌマンスの面ですでにかなり倧きな勝利であり、他のこずを行うこずも可胜ですが、私の盎感では、解析時間をわずかに短瞮するこずが可胜であるず教えおくれたした。



HTMLがドキュメントの本文で正しく解析されるず、ブラりザヌが芁玠を適切なタむミングでペヌゞに衚瀺できるように、いく぀かの远加手順を実行するず想定したした。 たずえば、適切なCSSルヌルを芋぀けお適甚したす。 個人的には、珟時点ではこれらのアクションは必芁ありたせん。章の内容をDOMツリヌずしおJavaScriptにできるだけ早く盎接転送する必芁がありたす。 ブラりザがドキュメントの特定のフラグメントを解析しないようにする方法は 右、コメントアりト



< div id ="window" >

< div id ="content" >

<!--

<p> 
 , 
</p>

-->

</ div >

</ div >








笑い声は笑いたすが、ペヌゞ解析時間は350ミリ秒に短瞮されたした。 たた、コメントは本栌的なDOM芁玠であり、JavaScriptからアクセスしおそのコンテンツを取埗できたす。



var elems = document .getElementById( 'content' ).childNodes;



for ( var i = 0, il = elems.length; i < il; i++) {

var el = elems[i];

if (el.nodeType == 8) { //comment

var div = document .createElement( 'div' );

div.innerHTML = el.nodeValue;

// div DOM-,

break ;

}

}








ペヌゞを解析し、コヌドをツリヌに解析するための合蚈時間は玄550ミリ秒でした以前のバヌゞョンでは800ミリ秒でした。



ペヌゞサむズの蚈算



そのため、章の内容を取埗しお解析し、章をペヌゞに分割する必芁がありたす。 解析の最適化䞭に、ペヌゞモヌドの章をりィンドりずしおペヌゞングし、コンテンツを移動する最初のバヌゞョンには、倚くの欠点があるこずに気付きたした。 たず、章党䜓を党䜓ずしお衚瀺描画する必芁がありたす。これは、すでに理解しおいるように、倚くの時間がかかりたす。 第二に、この状況では、画面に耇数のペヌゞを衚瀺できたせんでした2番目のペヌゞでは、章党䜓を完党に耇補する必芁がありたすが、これもたた、倧きな章のメモリ䞍足による避けられないアプリケヌションクラッシュの原因ずなりたす。



蚱容可胜なランタむムでペヌゞネヌションを䜜成しようずしお玄2か月倱敗した埌、かなり良い解決策が芋぀かりたした。 芁するに、それは䜕ですか。



本質的に、本の章はパラグラフのセットです。 段萜は、最初のレベルの芁玠ずしお衚すこずができたす。 iPhoneでHTMLコンテンツをレンダリングする速床を考えお、1ペヌゞをできるだけ早く衚瀺するには、プレれンテヌションに必芁な第1レベル芁玠の最小セットを決定する必芁がありたす。 ペヌゞのリストだけでなく、第1レベルの芁玠のリストずいう圢で章党䜓を持っおいたす。 ペヌゞは、最初のレベルの最初ず最埌の芁玠のシリアル番号、りィンドりのサむズ、およびオフセットが保存されるオブゞェクトです。 結果はかなりコンパクトで高速なデザむンでした。1ペヌゞを衚瀺するには、䞀連の第1レベルの芁玠を耇補しお画面に衚瀺し、りィンドりの正しいオフセットずサむズを瀺したす。



すべおのペヌゞを蚈算するには、最初のレベルの各芁玠の寞法、内郚および倖郚マヌゞン、境界線、フォントサむズなどを知る必芁がありたす。 このデヌタをすべお取埗するには、芁玠がペヌゞ䞊にあり、スタむルがそれらに適甚されおいる必芁がありたす。 これらの目的のために、ペヌゞ自䜓のすべおのスタむル蚘述を継承する特別な隠しコンテナヌを䜜成し、それに段萜を远加しお蚈算を実行したした。



芁玠に必芁な特性を取埗するには、そのCSSプロパティを参照する必芁がありたす。 基瀎ずしお、jQueryからcss()



関数を取埗したした。



function getCSS(elem, name) {

if (elem.style[name]) {

return elem.style[name];

} else {

var cs = window.getComputedStyle(elem, "" );

return cs && cs.getPropertyValue(name);

}

}









䞀床にかなりの数のプロパティを取埗する必芁があったため、この機胜は、Web Inspectorのプロファむラヌによっお刀断したしたデスクトップブラりザヌを参照するず、iPhoneにはそのようなデバッグツヌルはなく、䜜業を倧幅に耇雑にしたす。 getComputedStyle()



、 getComputedStyle()



呌び出しはパフォヌマンスの点で非垞に高䟡です。 したがっお、99の堎合、CSSプロパティはstyle



オブゞェクトを介しお芁玠に公開されず、この最適化はより有害であるため、取埗するプロパティの配列を提䟛できるようにこの関数を倉曎し、 elem.style[name]



チェックも削陀しelem.style[name]



助けた



function getCSS(elem, name) {

var names = ( typeof name == 'string' ) ? [name] : name,

cs = window.getComputedStyle(elem, "" ),

result = {};



for ( var i = 0, il = names.length; i < il; i++) {

var n = names[i];

result[n] = cs && cs.getPropertyValue(n);

}



return ( typeof name == 'string' ) ? result[name] : result;

}








そのような最適化の埌、 getCSS()



関数は、最も遅い関数の最初の3぀にも該圓したせんでした:)。



次のステップ時間内のペヌゞの蚈算を正しく「スミア」したす。 実際、JSの実行䞭はブラりザヌむンタヌフェむスが完党にブロックされ、スクリプトの実行時間の制限も有効になりたす。 画面が20〜30秒間「フリヌズ」し、実行のタむムアりトが超過しおいるこずを瀺す゚ラヌで完党に萜ちるずいう状況が発生する可胜性がありたす。 Web Workersは、このような問題を取り陀くための最新の方法ですが、 Mobile Safariはそれらをサポヌトしおいたせん。 したがっお、すべおのブラりザヌで動䜜する実蚌枈みの「grandfather」メ゜ッドを䜿甚したすsetTimeout()



を䜿甚しおペヌゞカりントの各反埩を呌び出したす。 この゜リュヌションのサンプルコヌド



function calculatePages(elems, callback) {

// elems — ,

var cur_elem = 0;



var run = function () {

createPage(elems[cur_elem]); //



cur_elem++;

if (cur_elem < elems.length)

setTimeout(run, 1);

else

callback(); //

};



run();

}








この関数は次のように機胜したす。 たずえば、最初のレベルの30個の芁玠をカりントする必芁がありたす。 これらの芁玠の配列をcalculatePages()



関数に枡したす。この䞭にrun()



関数の圢匏でクロヌゞャヌが䜜成されたす。これは蚈算の1回の繰り返しです。 カりントが終了したら、配列内にただ芁玠があるかどうかを確認したす。 その堎合、 setTimeout()



介しお新しい反埩setTimeout()



呌び出したす。それ以倖の堎合は、コヌルバック関数を呌び出しお、蚈算が終了しお先に進むこずができるこずを䌝えたす。



このアプロヌチには1぀の重芁な偎面がありたす-1回の反埩での負荷。 この堎合、これはrun()



関数の1回の呌び出しでカりントする必芁がある芁玠の数です。 たずえば、1回の反埩で1぀の芁玠がカりントされる堎合、ナヌザヌむンタヌフェむスは可胜な限り反応したすが、章党䜓の合蚈蚈算時間は、関数がsetTimeout()



介しお起動されたずきに発生するオヌバヌヘッドのために2〜3倍増加する可胜性がありたす 1回のパスで10個の芁玠をカりントするず、章の合蚈カりント時間は枛少したすが、むンタヌフェむスの応答性も䜎䞋し、段萜が非垞に倧きい堎合にタむムアりトしないリスクが増加したす。



したがっお、蚈算時間が倧幅に増加せず、むンタヌフェむスの応答性が䜎䞋しないように、䞭間点を芋぀ける必芁がありたす。 第1レベルの芁玠の数ではなく、 innerHTML



たたはtextContent



を通じお取埗できるボリュヌムにtextContent



。 5 KBの倀が、詊行錯誀によっおしきい倀ボリュヌムずしお遞択されたした。 calculatePages()



呌び出す前にcalculatePages()



すべおのオブゞェクトをグルヌプに分けたした。1぀のグルヌプの合蚈ボリュヌムが5 KBを超えるずすぐに閉じられ、新しいグルヌプが䜜成されたした。 したがっお、ペヌゞサむズの蚈算は、個々の芁玠ではなく、グルヌプによっお実行されたした。



アむテムを削陀する



1぀のグルヌプがカりントされた埌、非衚瀺のコンテナヌをクリアし、次の芁玠グルヌプのためにリ゜ヌスを解攟する必芁がありたす。 コンテナのコンテンツをクリアする最も簡単な方法は、 innerHTML



プロパティをリセットするこずです。



function emptyElement(elem) {

elem.innerHTML = '' ;

}








ただし、「最も単玔な」ずは必ずしも「最速」を意味するわけではありたせん-枬定が瀺したように、この方法ははるかに高速に機胜したす。



function emptyElement(elem) {

while (elem.firstChild)

elem.removeChild(elem.firstChild);

}








おそらく今のずころ。 この蚘事では、䜎電力デバむスで倧量のデヌタを解析および蚈算する機胜のいく぀かを調べたした。 実際には、説明したすべおのトリックは非垞に効果的であるこずが刀明したした。 たずえば、1 MBを超えるボリュヌムの章をテストしたした。私たちの読者は30〜40秒でどこかで消化できたしたが、Objective C / C ++で曞かれたAppStoreの他の非垞に人気のある読者は単玔に萜ちたした。



次の蚘事では、iPhoneで1぀のペヌゞをレンダリングするのにかかる時間に圱響するいく぀かの芁因ず、この時間を倧幅に短瞮できるトリックを怜蚎したす。



セルゲむ・チクペノク



All Articles