Sep 22, 2008

VMware Fusion 2.0のミラーフォルダの設定

VMware Fusion 2.0がリリースされたので早速アップデートした。1.1でいろいろダメだった部分(主にインタフェース部分)が改善されている。VMの性能としてはあまり変わらない印象(サスペンド・リジュームが速くなったくらいじゃないか?)だが、きっと誰かが詳細なベンチマーク結果を示してくれているだろう。2.0での本当の意味での重大な改善はマルチディスプレイ対応くらいしかないんじゃないか。

さて、本題。

VMware Fusionでは、ホスト(Mac)側の/Users/XXX/Documentsなどを共有フォルダとしてVMにexportできる。exportした共有フォルダは、ゲストVM(私の場合はWindows XP Professional)側からは\\.host\SharedFolders\DocumentsなどといったUNCで参照できる。さらに2.0からサポートされたミラーフォルダ機能では、exportした共有フォルダを自動的にWindowsのマイドキュメントやデスクトップなどにマッピングしてくれる。2.0で改善されたユニティモードと組み合わせると、あたかもWindowsアプリケーションをMac上でシームレスに利用しているかのような感覚を得られるのが「売り」である。

共有フォルダ・ミラーフォルダの設定は、もちろんGUIから行うことができるのだが、詳細な設定変更をしようとするとvmxファイルを直接編集する必要がある。とても分かりにくい上、VMwareの公式なドキュメントやWeb上のリソースでは今のところほとんど言及されていない。このエントリーでは設定オプションの大まかな意味をidentifyしようと思う。

共有フォルダ全体の一般的な設定

共有機能の有効・無効を制御したりする部分。

isolation.tools.hgfs.disable
共有フォルダ機能のオン・オフを制御する。FALSEに設定するとオン、TRUEに設定するとオフ。
hgfs.mapRootShare
共有フォルダのルート、つまりUNCで表すと\\.host\SharedFolders、をネットワークドライブ(Z:)としてマウントするか否かを制御する。TRUEにするとネットワークドライブが作られる。ドライブレターを変更できるかどうかは今のところ不明。
hgfs.linkRootShare
共有フォルダのルート(\\.host\SharedFolders)へのショートカットをデスクトップに作るか否かを制御する。TRUEにすると「VMware共有フォルダ」という名前のショートカットが作られる。ショートカット名を変更できるかどうかは今のところ不明。

設定例は以下のとおり。

isolation.tools.hgfs.disable = "FALSE"
hgfs.mapRootShare = "TRUE"
hgfs.linkRootShare = "TRUE"

各共有フォルダの詳細な設定

各共有フォルダのホスト側のパスや、共有フォルダの共有名などの詳細を設定している部分。共有フォルダの数だけ同じような設定を行う。

sharedFolder.maxNum
共有フォルダの最大数を指定する。例えば最大数として"2"を指定すると、VMwareは後続のsharedFolder0, sharedFolder1の設定を読み込んで共有フォルダを作成する。
sharedFolderN.present
共有フォルダが存在するか否かを指定する。FALSEにすると共有フォルダが利用できなくなる。
sharedFolderN.enabled
共有フォルダが使用可能か否かを指定する。FALSEにすると共有フォルダが利用できなくなる。
sharedFolderN.readAccess
共有フォルダの読み込みアクセスの可否を指定する。
sharedFolderN.writeAccess
共有フォルダの書き込みアクセスの可否を指定する。
sharedFolderN.hostPath
共有フォルダのホスト側のパスを指定する。例: /Users/XXXX/Desktop。
sharedFolderN.guestName
共有フォルダの共有名を指定する。例えば、"Development"を指定すると、この共有フォルダは、「\\.host\SharedFolders\Development」というUNCでアクセスできるようになる。
sharedFolderN.expiration
共有フォルダの接続がexpireするまでの期間(?)を指定する。"never"(expireしない)以外の値を設定できるかどうかは不明。
sharedFolderN.shareTags
共有フォルダをミラーフォルダとしてマッピングするためのヒント情報を指定する。"auto,desktop"(デスクトップ)、"auto,documents"(マイドキュメント)、"auto,music"(マイミュージック)、"auto,pictures"(マイピクチャ)という値が採れることが分かっている。これ以外の値を設定できるかどうかは不明。

設定例は以下のとおり。

sharedFolder.maxNum = "4"

sharedFolder0.present = "TRUE"
sharedFolder0.enabled = "TRUE"
sharedFolder0.readAccess = "TRUE"
sharedFolder0.writeAccess = "TRUE"
sharedFolder0.hostPath = "/Users/XXXX/Desktop"
sharedFolder0.guestName = "この デスクトップ"
sharedFolder0.expiration = "never"
sharedFolder0.shareTags = "auto,desktop"

sharedFolder1.present = "TRUE"
sharedFolder1.enabled = "TRUE"
sharedFolder1.readAccess = "TRUE"
sharedFolder1.writeAccess = "TRUE"
sharedFolder1.hostPath = "/Users/XXXX/Documents"
sharedFolder1.guestName = "この ドキュメント"
sharedFolder1.expiration = "never"
sharedFolder1.shareTags = "auto,documents"

sharedFolder2.present = "TRUE"
sharedFolder2.enabled = "TRUE"
sharedFolder2.readAccess = "TRUE"
sharedFolder2.writeAccess = "TRUE"
sharedFolder2.hostPath = "/Users/XXXX/Music"
sharedFolder2.guestName = "この 音楽"
sharedFolder2.expiration = "never"
sharedFolder2.shareTags = "auto,music"

sharedFolder3.present = "TRUE"
sharedFolder3.enabled = "TRUE"
sharedFolder3.readAccess = "TRUE"
sharedFolder3.writeAccess = "TRUE"
sharedFolder3.hostPath = "/Users/XXXX/Pictures"
sharedFolder3.guestName = "この 画像"
sharedFolder3.expiration = "never"
sharedFolder3.shareTags = "auto,pictures"

ミラーフォルダの設定

マイドキュメントやデスクトップなどにマッピングする共有フォルダを指定する。

hgfs.redirectShellFolder.maxNum
ミラーフォルダの最大数を指定する。例えば最大数として"2"を指定すると、VMware Fusionは後続のhgfs.redirectShellFolder0, hgfs.redirectShellFolder1の設定を読み込んでミラーフォルダを作成する。この値はsharedFolder.maxNumと同じか小さい値になるはずである。
hgfs.redirectShellFolderN.name
指定された名前のミラーフォルダの設定を行う。例えば"desktop"を指定すると、sharedFolderN.shareTagsに"desktop"が含まれている共有フォルダをデスクトップにミラーリングする。上の設定例ではsharedFolder0が"desktop"に対応しているので、「\\.host\SharedFolders\この デスクトップ」をデスクトップにミラーリングする。"desktop", "documents", "music", "pictures"以外の値が採れるかどうかについては今のところ不明。
hgfs.redirectShellFolderN.enabled
ミラーリングの可否を指定する。

設定例は以下のとおり。

hgfs.redirectShellFolder.maxNum = "4"

hgfs.redirectShellFolder0.name = "desktop"
hgfs.redirectShellFolder0.enabled = "TRUE"

hgfs.redirectShellFolder1.name = "documents"
hgfs.redirectShellFolder1.enabled = "TRUE"

hgfs.redirectShellFolder2.name = "music"
hgfs.redirectShellFolder2.enabled = "TRUE"

hgfs.redirectShellFolder3.name = "pictures"
hgfs.redirectShellFolder3.enabled = "TRUE"

Sep 16, 2008

PayPalでのご寄付に大変感謝しております _o_

ogawa - Google Code では、自作のフリーソフトウェアの開発サポートという名目で、ごく控えめなスタンスで寄付のお願いをしてきました。私のそういう消極的なスタンスにも関わらず、これまでご寄付いただいた皆様には大変感謝しております。非常に励みになっております。

もし自分も寄付してもいいとお考えでしたら、下の「Make a Donation」のリンクから寄付していただけると幸いです。

2007年以降私が受け取ったご寄付は、ほぼ全額(PayPalに入金された相当額分)をWFP 国連世界食糧計画に募金しています。

Sep 11, 2008

Chromeのevalは遅い? (cont)

Ogawa::Buzz: Chrome のevalは遅い?の追記というか解答編。

test3は以下のように書けば一行で済む:

eval('(function(){' + code + '})()');

というのはさておき。

test2がJITコンパイルのオーバーヘッドで遅いというのには無理がある。

まず、test2が遅くなるのはV8に限った話ではない。IE7でもFirefox3でも遅くなるが、V8の基本性能が高いためにChromeの速度低下が著しいように見えるだけである。もっと手っ取り早く確認したければ、test2のループカウントを増加させながらプロットしてみればいい。カウントの値のほぼ定数倍の実行時間がかかる(=JITコンパイル時間が無視できる)ことが分かるはずだ。

そうではなく、単純にプロパティアクセスが速い場合と遅い場合があるためと考えるのが自然である。つまり、

  • test1では、コアループで使用するプロパティ(i, result)は、test1というfunction(オブジェクト)の固定オフセットに格納されるので、高速にアクセスできる。
  • test3では、コアループで使用するプロパティは、calcEvalというfunctionの固定オフセットに格納されるので、高速にアクセスできる。
  • test2では、コアループで使用するプロパティは、test2のコンパイル時にはアロケートされない(字面上アロケートされるかどうか判別できないから)。したがって、実行時にeval内で動的にアロケートするコストがかかる上、functionの固定オフセットでアクセスすることはできないので高速なアクセスも望めない。

さてここで、test2を若干修正して、eval時ではなく、このfunctionのコンパイル時にresult, iをアロケートし、そのプロパティを使ってeval内の計算を行うようにしてみる。

function test2_prealloc() {
    var code = [
        'result = 0;',
        'for(i = 0; i < 1000000; i++){',
            'result += i;',
        '}'
    ].join('\n');
    var date = new Date();
    var result = 0;
    var i = 0;
    eval(code);
    print((new Date() - date).toString());
}

test2が約1200msecかかっていたのに対して、test2_preallocは約600msecで済む。高速化されたのは、メジャーな要因としてはevalでのアロケートのコストの削減、マイナーな要因としてはプロパティアクセスのオーバーヘッドの一部の削減、による効果と推定できる。こんなに速くなるのはアロケータの実装も寄与している可能性がある。記憶域をハッシュテーブルで実現しているような処理系ではここまでの高速化は望めないのが一般的だろう。

しかし、まだ20msecには程遠い。なぜかと言えば、どうやらevalによって作られたコンテキストからダイレクトにtest2_preallocの固定オフセットを使って高速にプロパティにアクセスする方法がないから、のようだ。想定できる状況としては2つあり、その一方または両方の問題があると思われる。

まず、test2_preallocのevalで使用するプロパティが、eval内新規にアロケートすべきプロパティか、test2_preallocでアロケート済みのプロパティか(あるいは他のところでアロケート済みのプロパティか)を判別する必要がある。そのため、スコープの内側から順にresult, iがアロケート済みかどうかルックアップして、なければアロケート、あればそれを使うという処理が必要になる。これは固定オフセットを使ってアクセスするのに比べて低速になる。ただし、この判定はevalが呼ばれるたびに一度だけ行えば済むはず。もしプロパティアクセスごとに検査しているようならそれは実装が悪い。ああ、Thread-Safeにする目的があるのなら実装が悪いとは言い切れないね。いつかはJavaScriptのスレッドモデルがまともに拡張される可能性がまったくないわけではない。

もうひとつは、evalが作るコンテキスト(活性レコードと言ってもいい)から外側のコンテキストに高速にアクセスする方法が提供されていない可能性を疑ってもいいかもしれない。両者のスコープは通常の静的スコープに従うのだから(そうだよね?)、呼び出し元のコンテキストに静的リンクを辿るなりディスプレイを参照するなりして比較的小さいオーバーヘッドでアクセスできるはず。もしそうじゃないならそれは実装が悪いと思うが、私が見落としている問題があるかもしれない。

以上。evalは慎重にね。

Sep 10, 2008

Chromeのevalは遅い?

Google ChromeのJavaScript、evalしたらすごい遅かった - むぅもぉ.jp

本当に?

V8 shellを使って以下のコードを実行したら、test1が20msec、test2が1168msecかかった。Athlon 64 X2 5000+上のVM上で実行したものなので数値はあまり信用できないが、test2の方が明らかに遅い。

function test1() {
    var date = new Date();
    var result = 0;
    for(var i = 0; i < 1000000; i++){
        result += i;
    }
    print((new Date() - date).toString());
}
function test2() {
    var code = [
        'var result = 0;',
        'for(var i = 0; i < 1000000; i++){',
            'result += i;',
        '}'
    ].join('\n');
    var date = new Date();
    eval(code);
    print((new Date() - date).toString());
}
test1();
test2();

でもこれはChromeのevalが遅いからそうなるのか?

そうではない。test2をちょっとだけ書き換えたtest3を用意してみた。

function test3() {
    var code = [
        'var result = 0;',
        'for(var i = 0; i < 1000000; i++){',
            'result += i;',
        '}'
    ].join('\n');
    var date = new Date();
    eval('function calcEval(){' + code + '}');
    calcEval();
    print((new Date() - date).toString());
}
test3();

と、やっぱり20msecで済み、test1と遜色ない結果になる。場合によってはtest3の方がtest1より速くなることもある。

ブラウザで確認する場合は以下のページからどうぞ。test1, test2は元記事のもので、test3が新しく追加したもの。私の環境だとtest1, test3が20msec、test2が約1900msecかかる。

JavaScriptテスト

追記: Ogawa::Buzz: Chromeのevalは遅い? (cont)

Sep 9, 2008

Re: Google Chromeは速くないって

Google Chromeは速くないって - umitanuki日記

ベンチマークを行うなら測定環境を書いてほしいな。それはさておき。

同じレンダリングエンジンを使っているにも関わらず、SafariよりChromeの方が3.6倍ほど遅いとすると、それはV8からレンダリングエンジンを操作するコストが、SafariのJavaScriptエンジンからレンダリングエンジンを操作するコストより、かなり大きいということを示唆しているのではないか。つまり、Templates (Embedder's Guide - Google V8 JavaScript Engine - Google Code)の呼び出しオーバーヘッドが現状無視できない程度に大きい、と。

もしそうなのだとすると、Templatesには最適化の余地があるのだろうし、十分な最適化がなされればChromeのDOM操作もSafariと遜色ないものになると考えるのが自然だ。いつまでもSafariより遅いままのChromeと思うなよということ。

また、Chromeには別の最適化の余地があることも忘れてはならない。すなわち、ネイティブメソッド呼び出しのコストを支払うくらいならV8で実行するコストを支払った方がよい場合もあるということだ。

ここで話題にしているDOM操作に関して言えば、ネイティブメソッド呼び出しのオーバーヘッドの削減に限界があるのは仕方がないとして、DOM操作のコア部分をV8内にオフロードすることでさらなる最適化を目論むという方針を採り得るのではないか。例えば、現在のDOMステートをV8のスペース内に保持しておき、定期的にレンダリングエンジンにバッチ的にwrite backするというアーキテクチャを採れたとする(あるいはLazyなDOM操作を実現するJavaScriptライブラリを実装してそれを使うのでもいいかも)。

もしそれが可能なら、大半のDOM操作はV8ヒープ上の操作で済み、しかもそれはV8エンジンによって圧倒的に高速化される…少なくとも見込みがある。JavaScriptエンジンが低速だった時点ではこういう手法は「逆最適化」でしかなかったが、V8やTraceMonkeyであれば事情が違ってくるのではないか。

と、まあそんなことを考えた。卒論ネタなどにどうぞ。

Sep 8, 2008

Cybozu2iCal 0.32公開

度々で申し訳ないデスが、cybozu2icalを0.32にアップデートしました。

Cybozu2ICal - ogawa - サイボウズオフィス6のカレンダーをiCalendar形式に変換するスクリプト。 - Google Code

主な変更点は、

  • 終日イベントが正しく終日イベントとして認識されないバグがあったので修正しました。
  • UIDが一定になるように修正しました。

後者について補足します。

元々各イベントのUIDは、サイボウズが出力する「イベントのID」、「イベントのタイムスタンプ」と、「ホスト名」から生成するようにしていました。が、サイボウズの出力するタイムスタンプは作成時刻ではなくAPIのリクエスト時刻になるという問題があり、このままだとiCalendarファイルを生成する度に異なるUIDを持つイベントを生成することになってしまいます(ちなみにiCalendarファイルのDTSTAMPとCREATEDが生成ごとに異なるのも同じ理由です)。このため、一部のUIDを真面目にハンドリングするiCalendarアプリで問題が起きる可能性がありました。

この問題に関して、私はサイボウズのつまらないバグの一つと解釈していてバージョンアップでいずれ対策されるだろうと思っていました。だから放置してきたのですが、今回サイボウズオフィス7でも対策されていないことに気がついたので、cybozu2ical側で対応することにしました。つまり、「イベントのID」と「ホスト名」のみからUIDを生成するようにしました。

Sep 2, 2008

ワイルドカードCNAMEはもう全部 ghs.google.com.に向ければいいと思う

Google Appsの各アプリのエントリーポイントURLが独自ドメインにマップできるのはいいとして、Google Appsの一つであるGoogle Sitesの各サイトのエントリーポイントURLも独自ドメインにマップできる。これくらいいたるところでマッピングを追加できるとなると、サービスが追加されるたびにghs.google.com.に向けたCNAMEレコードを作ってDNSの伝搬を待って...、という作業はたいがい面倒くさくなってくる。

なのでCNAMEにワイルドカードレコードを追加してghs.google.com.に向けてみた。これが思いがけず快適だった。

私が使っているSlicehostのDNSだとこんな感じに設定するだけで済む。国内の個人ユーザが多いValue Domainでもほぼ同じ設定が可能なはず。

こうしておくと、Google Mailのエントリーポイントをmail.as-is.netにマップする設定をするだけで(つまりDNSへの変更なしで)このホスト名でGoogle Mailにアクセスできるようになる。また、新しいGoogle Sitesのサイトを追加する場合にも適当なas-is.net以下のFQDNにマップする設定をするだけで済む。

ちなみにマッピングしていないURL(http://404-not-found.as-is.net/)にアクセスすると、ちゃんと404 Server Not Foundを返してくれるようになっている。至れり尽くせり。

About Me

My Photo

つくばで働く研究者

Total Pageviews

Amazon

Copyright 2012 Ogawa::Buzz | Powered by Blogger
Design by Web2feel | Blogger Template by NewBloggerThemes.com