Opera Turboが高速な理由 - Delayed Script Execution

昨日出た Opera Turbo 有効版のお試し Opera

言ってみれば単なる圧縮プロキシ設定を追加しただけの Opera。(ホスト側から見た IP アドレスも変わるOpera は Great Fire Wall 越えを狙っているのだろうか?)

まあ、使ってみたらたぶんけっこう速いと思うんじゃないかな。


でも速いと感じるのは、実はプロキシの効果ではなくて、opera:config#Delayed Script Execution がオンになってるから。

(プロキシの効果は、携帯の回線でネットしている人とかでないとわからないと思う。デスクトップで使っても画像が汚なくて見るに耐えないよ。)

ここにもちらっと書いてある。


この機能自体は前からあるもので、詳しい解説とテストページはこっちを参照してもらうことにする。

簡単に言うと、ページの描写が終わるまでスクリプトを実行しない機能のこと。

元々は Opera Mobile のための機能らしく、「デスクトップで使うと不具合もあるだろうから何が起きても保証しないよ」とどこかで読んだ記憶がある。

スクリプト要素というのは HTML の中でも特殊な要素で、あるスクリプトが DOM を書き換えることができるため、普通はスクリプトの実行中はページ内要素のダウンロードをしないし、スクリプト部分を飛ばして HTML の描写をすることもない。

Delayed Script Execution を使うと、DOM の構築が終わってページ描写も終わってからスクリプトを実行するため、見た目のページ描写はかなり速くなる。

特に document.write を多用するサイトや、document.write によって別の script 要素を挿入するサイト (こんな変テコなことをするのは広告を表示する場合だけと言ってもいい) なんかで効果がある。

(ちなみに、次のバージョンの FirefoxSafari は Speculative Loading という、スクリプト実行中にも他の要素をダウンロードしておく機能を付けるらしい。Delayed Script Execution とはよく似た性質のものだけど、Delayed Script Execution のほうが変態頭がぶっ飛んでいるように思う。上のテストページがどうなるのかちょっと楽しみ。)

こんなのあった。斜め読み - クライアント・サイド・スクリプティング with Web Standards 上の記事の要約など。Chrome も IE8 も Speculative Loading を実装するんだね。


スクリプトの実行タイミングをずらすなんて、けっこうな変更をウェブページに加えているわけで、不具合は当然出るだろうと思っていたのだけど、どっかの Opera 社員のブログのコメントによると、けっこう不具合は少ないらしい。

ただ、どうやら DOMContentLoaded イベントが出ていないようなので、UserJS は動かなくなるものも多いと思う(oAutoPagerize とか)。

Delayed Script Execution 有効の場合と無効の場合でスクリプトを書き分けないといけないなんてことは無いようにしてほしいのだけど…


何はともあれ、「Opera Turbo? 何それ食えんの? ダウンロードすんのかよウゼー」ってな人は Opera Turbo を入れるまでもなく、opera:config#Delayed Script Execution をポチっと有効にしてみればどんなものか分かるはず。

例えばこのはてなダイアリーみたいに、意味もないスクリプトをページの頭のほうで大量にロードしているサイトで効果があるよ。

Delayed Script Executionが有効でもoAutoPagerize(など)を動かしてみる。

まず、以下の UserJS を入れる。

  • 0DOMContentLoaded.js
// ==UserScript==
// @include http://*
// ==/UserScript==

(function(){

function fireEvent(){
  var ev = document.createEvent('Event');
  ev.initEvent('DOMContentLoaded', true, true);
  document.dispatchEvent(ev);
}

window.addEventListener('load',fireEvent,false)

opera.addEventListener('BeforeEvent.DOMContentLoaded',function(){
  window.removeEventListener('load',fireEvent,false);
},false)

})()

load イベントの中で DOMContentLoaded カスタムイベントをキックしている。

BeforeEvent.load にしようと思ったのだけど、そのタイミングではまだ document.body が null らしい。


で、普通のスクリプトならこれだけで大丈夫なのだけど、oAutoPagerize の場合はちょっとややこしいことになっているので、oAutoPagerize.js の中で以下のような部分 (だいたい156行目) を見つけて

window.opera.addEventListener( 'BeforeEventListener', function (e) {
	if (e.event.type != 'DOMContentLoaded') e.preventDefault();
}, false );

コメントアウト

//window.opera.addEventListener( 'BeforeEventListener', function (e) {
//	if (e.event.type != 'DOMContentLoaded') e.preventDefault();
//}, false );

あんまりいい方法とは言えないけど、一応動くようになる。(このままだと Delayed Script Execution を切ったときに挙動が変わってきちゃうなあ…)

もしかしたらページによっては DOMContentLoaded が出てる気がする。そしてページによっては上の方法でも oAutoPagerize が動いてない気がする。このはてなダイアリーでは上ので動くようになるけど、例えばここでは失敗する。