たまに18歳未満の人や心臓の弱い人にはお勧めできない情報が含まれることもあるかもしれない、甘くなくて酸っぱくてしょっぱいチラシの裏。RSSによる簡単な更新情報を利用したりすると、ハッピーになるかも知れませんしそうでないかも知れません。
の動向はもえじら組ブログで。
宣伝。日経LinuxにてLinuxの基礎?を紹介する漫画「シス管系女子」を連載させていただいています。
以下の特設サイトにて、単行本まんがでわかるLinux シス管系女子の試し読みが可能!
ページ全体を選択したりしてるとコンテキストメニューの展開が遅くなる件について、処理を色々スキップするようにして、だいぶ速くなった。
やってることというのは、メニューを表示する時に毎回選択範囲の中のURIを全部検出するんじゃなく、選択範囲の中で最初のURIっぽい文字列と最後のURIっぽい文字列だけ検出するようにするという変更。ツールチップで全部のURIを表示する機能はなくさざるを得ない、あるいはプログレッシブ表示みたいな感じになると思う。
で、テスト用に使ってるページでは、最初のURIの検出に約300ミリ秒、最後のURIの検出に500ミリ秒程かかってる。合わせて大体1秒近いので、まだ結構重たい。Venkmanでプロファイルを取って見てみた感じでは、1つ1つの処理は20ミリ秒とかそのくらいなんだけど、それが何十と重なってトータルでこの重さになってる。
「URIっぽいんじゃね?」と思われるものの実はURIではない、という文字列(例えばHH:MM:SS形式で示された時刻やid:XXXXなど)の数が多いとこうなってしまう。URIっぽい文字列の検出条件を厳しくすれば回避できる(例えばXXX://で始まってない物を除外するようにすれば先の例はすべてスキップできる)けど、それはちょっとやりたくない……
先週頭に自転車の後輪がパンクしてしまって、先週はずっと自転車通勤だった。まあ雨が降ってたから、パンクしてなくても電車通勤になってたのかもしれんけど。しかし自転車がないと買い物に行くのも億劫になってしまって……
そういうわけで日曜にやっとパンク修理に行ってきた。最初に行こうと思ってた店が日曜定休でがっくりきて、ちょっと遠いけど大きい店まで歩いて持って行って、そこで依頼したら3時間くらいかかるって言われたので、自転車預けて区役所の展望台とかで時間潰してた。
タイヤ交換と工賃で5000円ちょっと。自分でやれば半額で済んだみたいだけど……その気力もないし、少しは地域経済に貢献できたと思って、そこはこだわらないでおこう。
携帯が新しくなり、PCも新しくなり、自転車も(後輪だけ)新しくなって、最近色々新しくなってる気がする。
救出したデータのうちiTunesのライブラリを新マシンの C:\Users\<username>\Music\iTunes に移動してiTunesを起動したところ、一部の(数としては大量の)曲について、ファイルが見つからないと言われてしまった。
iTunes導入後(=iPod導入後)にCDを買った物とかはiTunesでリッピングしてそのままライブラリ行きだったので、それらについてはちゃんと認識されてるっぽい。駄目だったのは、それ以前にリッピングしてMP3化して別の場所に置いてあった物をインポートしたやつ。旧マシンではこれらはDドライブのフォルダの中に入れてたんだけど、救出した後は C:\Users\Public 以下に置くようにしたため、リンク切れ状態になってしまった。
iTunesのライブラリをエクスプローラで開くとiTunes Music Library.xmlというファイルがあって、これをメモ帳で開くとそれっぽい情報が色々書かれているので、一括置換でlocalhost/D:/となってるところをlocalhost/C:/Users/Public/に置き換えて上書き保存してみた。しかしiTunesを起動して再生を試みてもやはりファイルが見つからないと言われる。iTunes終了後にもう一度iTunes Musc Library.xmlを開いてみたら、さっき置換したはずの所が全部元に戻ってしまっていた。どうも、ほんとの情報はiTunes Library.itlあたりにバイナリとして保存されてて、iTunes Music Library.xmlの方をいくらいじっても無駄みたいだ。
「iTunes 場所 変更 xml」で検索してみたら、63Blog: フォルダ名変更の時のiTunes再構築方法 というエントリが引っかかった。
という風にするといいらしい。実際、試してみたらうまくいった。プレイリストに入ってないけど管理下にはあった曲、というやつもちゃんと認識されたっぽい。iTunes Storeで買った曲が入る「購入したもの」も復元された。
リンク作成シェル拡張で作ったシンボリックリンク(うちの場合はフォルダのリンクなので、正確にはジャンクション?)があると、ファイルのコピーが途中で止まってしまう……
かつてWindows 2000でCドライブとDドライブだった物が、今FドライブとGドライブとして認識されてるんだけど、この状態でフォルダのリンクを含むフォルダ群をVista上で普通にコピーしようとすると、リンク切れ状態のリンクを処理しようとして詰まってそこで後のファイルのコピーも全部キャンセルされてしまう。仕方がないので、先にFとGからリンクの残骸を探して削除して回ってからコピーをやり直してみてるけど、見落とした物があるとまたそこでやり直しなのでうんざりだ。
関係ないけど、Vistaのファイル移動やコピー時の上書き確認関係のダイアログは、なかなかよくできてるっていうか丁寧だなと思う。「どういう操作を選ぶか」じゃなくて「結果的にどうしたいのか」を提示してる、というかなんというか。
これでやっと復旧?にとりかかれる。
買ったのはDellのStudioとかいうモデルで、XPは選択できなかったのでVista Home Premiumになった。メモリ4GB、HDD500GBとかこの辺はプリセットの構成のままで、グラフィックボードをデュアルディスプレイ構成で使えるようにnVIDIA GeForce 9800 GTにして、あとブルーレイコンボドライブも付けた。ディスプレイ無しで11万ちょっと。
最近のマシンはPS/2なんて付いてないんですね……なにげに気に入ってたTK-P09FPBKが使えなくてしょんぼり。でもググってみたらUSB→PS/2というマウスとかによく付いてきてた奴だけじゃなくて、その逆のPS/2→USBというのもあるのか。これ使えばいけるかな?
せっかくブルーレイが付いたんだからって事で、前に買うだけ買って再生環境が無くて死蔵してたマクロスFの1巻を再生してみようとしたんだけど、HDCPがどうとか言われて再生できない……ディスプレイがHDCPという仕様に対応してないとHD画質のコンテンツは見れませんよっていう話らしい。今の構成は、新しく買ったPCにDVI-I端子経由でEizo FlexScan S170とViewSonic ViewPanel VE150を繋いでるんだけど、どっちも古くてそんな仕様には対応してないから、ブルーレイは禁止!ということらしい。なんじゃそらー。ディスプレイ買い換えるつもり無かったのにそんなこと言われても困るよ。
さらにもう少し調べてみたら、HDCPはコピーガード(コピーの時に働く機能)じゃなくてアクセスコントロール(ただ再生するだけの時にも働く機能)だから回避しても法的には問題がないという話もあるようだ。
さらにもうちょっと調べてみたらAnyDVD HDというシェアウェア(21日間の試用期限あり)を使うと、ソフトウェア的にHDCPを回避できるようになるとか。で実際試してみたら、確かに再生できた。ただ、AnyDVD HDの問題なのかPowerDVD 8.1の問題なのか、普通にディスクを入れてすぐに再生が始まるパートは再生できるんだけど、ディスクメニューから映像特典を見ようとすると止まってしまう。結局全然駄目ってことなのか……
遊んでないでシステム復旧に取りかかれって話ですよね。はい。
旧マシンはオンボードのSATAが無かったので手も足も出なかったけど、新マシンはSATA標準搭載(というかそれしか付いてない)なので、ここにRAID1のうち片方のディスクだけ繋いでみた。Windows Vistaの起動前に何かメッセージが出て、CHKDSKによるエラーチェックが始まって……うわあ、何かすごい量のメッセージが出まくってるよ。こりゃもう駄目かもわからんね。
エラーチェックが終わったので、とりあえずディスクの中身を新マシンの方に吸い出しておくことにする。
逆に考えるんだ。自動テストのおかげでリグレッションがこのレベルにおさまってると考えるんだ。
いや実際これがなかったらほんとに日に5回6回はアップデートすることになってたかもしれんですよ。いつかの頃みたいに。
コンテキストメニューやダブルクリックがめちゃめちゃ重くなることがあったのは、呆れる位しょうもないミスのせい。「クリック位置の前後のテキストからURIっぽい文字列を探す」時に、部分選択されたURIの全体を取得するために、一定の文字数に達するまで前後にRangeを広げるようになってるんだけど、この時にループを回す方向を逆にしてしまってて、一番近いノードじゃなくて一番遠いノードから数えてた。そりゃ遅くもなるって。ログによると18日の変更によるリグレッションだった。
改善されたとはいっても原理的に若干のもたつきは避けられない(特にページ全選択した状態でメニュー開いたりしたらやっぱり死ぬ程時間かかる)んだけど、まあ、ページの中をうっかりクリックする度に数秒間固まるのに比べればまだマシってことで……
Venkmanのプロファイラの使い方がやっと分かったんで、パフォーマンスの改善にも取り組みたいところです。
Shredderに取り込まれたパッチだけど、2つとも、「Thunderbird 2.0.0.xには入れらんないよ」と蹴られてしまった。「そんなに重要じゃないから」だそうです。ちょっと待ってよ、日本語環境じゃどっちもめっさ重要やん。そしてThunderbirdはレガシーなメールソフトが必要とされ続けてる日本でこそシェアの伸びが期待できるわけじゃないすか。それなのに。
Firefoxでは中野さんの頑張りのおかげかマーケティングの都合なのか2.0.0.x系のセキュリティアップデートでも日本語環境特有の問題の修正を入れてもらえてたそうだけど、人もいないしMozilla内部じゃ注目度も低いThunderbirdでは絶望的ですかね……
「本当に言いたかった事は、こういう事なんだ」という言い方はあんまりしたくないなと思った。最初の発言できちんと意図を表現できてなかったってことを自ら暴露する訳だし、それに加えて、「ほうほう、本当に言いたかったのがそういう事なんだったら、こういう意図は全く無かったんだね? じゃあここはどういうことなんだい?」と嫌味なツッコミを受けるリスクが増すからだ。
なので、これからは「いくつも意図はあるけど、その一つはこういうことだ」という言い方にとどめるようにしたい。したいと思うけど、できるかどうかは分からない。
中野さんが、JavaScriptにはsleep(一定時間待ってから次の処理に進むという命令文)が無いせいでテストを書くのに難儀したという話を書かれているけれども。まさにこれをどうにかしたくて、UxUは進化してきたようなものと言える。
知ってる人は知ってるだろうけど、Firefox/Thunderbirdアドオン向けの自動テスト実行ツール・UxUでは、テストを書く上でsleepに相当する機能を利用できる。これは、JavaScript 1.7でジェネレータ・イテレータ機能を実現するために追加されたyield式のトリッキーな使い方だ。
これを実現しているのは、lib/utils.jsのdoIteration()
と、test/test_case.jsのrun()
ということになる。ここから要点だけを取り出すと、以下のような事をしている。
まず、スクリプトの書き手は、「sleepを使いたい処理」を関数として定義する。この時、sleep
の代わりにyield
を使う。
var task = function() {
doSomething1();
yield 1000;
doSomething2();
yield 1000;
doSomething3();
}
次に、スクリプトの書き手は、この関数を後述するdoIteration()
に渡す。すると、doIteration()
がよしなに計らって、「doSomething1()
を実行した後、1000ミリ秒待って、doSomething2()
を実行し、また1000ミリ秒待って、doSomething3()
を実行する」という風な形で先程の関数の内容を実行する。
この時のdoIteration()
の内容は、以下のような感じ。
function doIteration(aTask) {
if (typeof aTask == 'function') {
// 渡されたのが関数だったら、まず、評価した返り値を得る。
aTask = aTask();
}
if (!aTask ||
!('next' in aObject) ||
!('send' in aObject) ||
!('throw' in aObject) ||
!('close' in aObject) ||
aObject != '[object Generator]') {
// 渡されたオブジェクトまたは関数の返り値が
// ジェネレータ・イテレータではない場合、何もしない。
return;
}
// ここからがミソ!
// 全部の処理が終わったかどうか、を示すオブジェクトを定義
var finishFlag = { value : false, error : null };
var last = 0; // スリープ開始時点の時刻を保持する変数
var sleep = 0; // スリープの長さ(秒数)を保持する変数
var timer = window.setInterval(function() {
if (
// スリープの長さがちゃんと指定されていて
sleep > 0 &&
// スリープ開始時点からの経過時間がスリープとして
// 指定された時間未満であれば
(Date.now() - last) < sleep
) {
// ここで処理を終えて、100ミリ秒後まで待つ。
return;
}
// スリープとして指定された時間が経過したので、処理を進める。
try {
// 次にyieldが登場するまでの間の処理を実行。
sleep = aTask.next();
// next()の返り値はyield式に渡された値。
last = Date.now(); // スリープ開始時刻を保持して
return; // 処理を一旦終えて100ミリ秒後を待つ。
}
catch(e if e instanceof StopIteration) {
// 最後のyield式の後の内容が実行されて、定義された関数の内容が
// 最後まですべて実行されると、StopIteration例外が発生する。
// よって、処理完了とみなす。
finishFlag.value = true;
}
catch(e) {
// それ以外の未知の例外が発生した時は、処理中断とする。
finishFlag.error = e;
}
// 100ミリ秒ごとの繰り返し処理を停止。
window.clearInterval(timer);
}, 100);
return finishFlag;
}
UxUの内部でやってる事は基本的にはこういう事。ただ、実際にはもうちょっと使い勝手をよくするために細かい処理が加わってる。
doIteration()
が中で何をやってるのかを知らなければ、パッと見は、sleepという命令文の名前がyieldに変わっただけのようにすら見えるんじゃないだろうか。そこが、このやり方の狙いだ。スクリプトの書き手はタイムアウトだのコールバックだのといった難しい事を何も考えなくても良くて、単に「sleep文に相当する機能が加わったJavaScript」として好きなように処理を書く事ができる。テストを書くための工数が大幅に削減される(かもしれない)ので、テストを書くのが苦にならず、ばりばりテストを書けるようになる(はず)。その結果、充実したテストのおかげでより安心して開発に専念できるようになる(はず)。という理屈です。
ちなみに、勘のいい人は気付くだろうけど、setInterval()
に渡している関数の冒頭に以下の内容を挿入すれば、doIteration()
をいくらでも入れ子にできるようになる。
if (
typeof sleep == 'object' &&
(!sleep.value || !sleep.error)
) {
return;
}
var task = function() {
doSomething1();
yield 1000;
yield doIteration(function() {
doSomething2();
yield 500;
doSomething3();
yield doIteration(function() {
doSomething4();
yield 100;
doSomething5();
});
});
doSomething6();
};
doIteration(task);
さらに、こんなこともできる。
var task = function() {
doSomething1();
yield doIteration(function() {
var flag = { value : false; }
frame.addEventListener('load', function() {
frame.removeEventListener('load', arguments.callee, false);
flag.value = true;
}, true);
frame.contentDocument
.defaultView
.location.href = 'http://www.example.com/';
yield flag;
// フレームの読み込みが終わったらここに進む
doSomething2();
});
doSomething3();
};
doIteration(task);
この辺をもっと簡単に書けるようにヘルパーメソッドを色々と整備したのがUxUのテスト実行環境、と思ってもらえれば大体それで正解です。
25日追記。他にも色々やり方があるようです。(どっちもMozilla限定だけど)
昨年末くらいからずっと調子悪かったんだけど、とうとう本格的に逝ってしまったみたい。RAID1の起動ドライブから起動できなくなった。Windows 2000 Professionalの起動中にINACCESSIBLE_BOOT_DEVICEというエラーメッセージのブルースクリーンになる。CD-ROMから起動して修復する方法というのを試してみようとしたけど、どうもCDから起動した状態だと(Windows 2000 ProfessionalのCD-ROMにドライバが無いせいで)RAID1の構成のドライブが繋がってるRAIDカード兼SATAコントローラを認識できないみたいで、もう完全にお手上げです。
幸いというかなんというか、こうなる直前の時点でDellで新しいマシンを注文していた(この注文の最中にも3回程フリーズした)ので、それが届いてからならデータの救出とかそういう作業もできそう。
ただ、目下の問題は、コミックマーケット76の申し込み〆切が24日なのに、サークルカットができていないという点で。どう考えてもそれまでには新マシンは届かないだろうから、とりあえず前回(C75)のサークルカットを申し込み履歴からダウンロードしてきてC76用にアップロードした。ほんとは良くない事だって分かってるんだけど、今回ばかりはどうか大目に見て欲しい……