Mono/ja
<videoflash>cGoM9p7q1jk</videoflash> |
高解像度版動画をダウンロード and Mono動作デモ動画いろいろ |
"Mono for Second Life"はスクリプトの動作速度、特に演算にかかわる部分について、を劇的に向上することができる新しいシミュレータです。リンデン・スクリプト言語(LSL)自体は何も変えませんでした。よって既存のスクリプト入りオブジェクトやアタッチメントは動作が速くなる可能性があるというだけで、以前と変わらず動作します。この改良のキーとなるのはオープン・ソースのMonoと呼ばれるスクリプト・エンジン技術です。
Monoはサーバー・バージョン1.24.3からメイングリッドに導入されました。
LSLスクリプトはどのように動作するか
すべてのLSLスクリプトは、あなたがいるリージョンそのものを稼動させているのと同じシミュレータ(リンデンラボのサーバープログラム)上で動作します。テレポートしたり、リージョン境界を越えたりすると、あたらしいリージョンのサーバーがあなたが稼動させているアタッチメントのすべてのスクリプト動作を引き継ぎます。ですがシミュレータはLSLを直接理解することはできません -- スクリプト言語は人間が読みやすいように設計された書式であって機械向けのものではありません。よってスクリプトを実行できるようにためには、その前にそれらを機械が読める形に変換する必要があります。このプロセスはコンパイルと呼ばれ、その結果機械が読める形になったスクリプトのことをバイト・コードと呼びます。LSLスクリプトはレジデントのプログラマーな方がそれを作成した時点でコンパイルされます。バイト・コードそのものはリンデンラボのアセットサーバに格納され、レジデンツから直接参照されることはありえません。代わりに、あなたがスクリプト入りのオブジェクトをRezすると、いまあなたがいるシミュレータはオブジェクトの中にあるスクリプトを控えて、アセット・データベースへ適切なバイト・コードを要求します。シミュレータのプログラムはいくつかの部分に分かれていますが、スクリプトのバイト・コードを実行する部分はスクリプト・エンジン、または仮想マシンと呼ばれています。
現在のセカンドライフではスクリプトはリージョンのあらゆる場所で使用されています。単純なオブジェクトを回転させるようなものから、複雑な乗り物や販売機、アタッチメントやあなたのボイス・コマンドに反応するようなものまで様々です。多くのリージョンにおいて、スクリプト・エンジンは数百ものスクリプトを一斉に稼動させようと忙しく働いています。リージョン内で稼動しているスクリプトの数の増加および複雑さ度合いの上昇によって、シミュレータに対する要求はどんどん高まっていきます。ある一定の点を越えると、スクリプト・エンジンのプロセス・タイムは他の(特に物理エンジン)シミュレータに影響し始め、結果としてサーバ側のラグを発生します。したがってスクリプトの動作をスピードアップすることができれば、そのサーバラグが起こり始める臨界点をもっと上に上げることができるわけです。
Monoの導入
Monoは(現在のものとは)別種のスクリプト・エンジンです。完全にオープンソースのもので、その高速性と汎用性は証明済です。今日に至るまで数年間においてリンデンラボはもともとのスクリプト・エンジン(LSL2 VMと呼ばれることもあります)の置き換えとしてMonoを検討してきていました。ですがスクリプト・エンジンを変更するには大きな課題があります。もっとも根本的な問題は(既存のものとMonoでは)バイト・コードが異なるという点でしょう。LSLのバイト・コードはMonoにとってチンプンカンプンのものであり、また逆もしかりです。Monoスクリプト・エンジンを使用し始める前に、私達はまずLSLスクリプトを扱うことができて、それらをMonoのバイト・コードに変換することができるコンパイラを開発する必要があります。これは非常にトリッキーです。つまりスクリプトが現在のスクリプト・エンジン上で動いているのと「まったく同じように」Mono上でも動作しているように振舞うようにしなくてはいけないわけです。これは非常に大変な仕事で、かつテストには多大な時間を要します。最終のコード作成がなされたのは2007年の第三四半期で、そしてその後 11月からリンデンラボのQA(品質保証)は新しいスクリプト・エンジンに対して一連のテストを自動および手作業で厳しく実施してきました。
今後の計画
テストに協力してくれた住人の方々とQAチームのがんばりによってメイングリッドへの導入ができました。Monoサーバーは1.24から稼動開始、メイングリッドにも8月29日から導入されました。
Monoは1.21以降のクライアントから対応しています。ビュワーの変更点としては、スクリプト編集画面へのMonoチェックボックス追加(これをチェックすることでMonoでコンパイルすることができます。)、ツールメニューへの「選択しているオブジェクトをMonoで再コンパイル」というメニューの追加。そして、統計メニューへ従来の「単位秒あたりのインストラクション数」ではなく「単位秒あたりのイベント数」表示の追加です。Monoスクリプトを作成するためには1.21以降のクライアントが必要です。ただし、Monoスクリプトを実行するだけであれば特別なクライアントは必要ないことに注意してください。これらはすべてサーバー側で自動的に行われる処理です。Mono対応ビュワーは、単にLSL2とMonoのどちらでコンパイルをするか選択するのに必要なだけです。
その他にビュワー側で注意しておく点として統計メニュー(ctrl-shft-1)の「Script pef」があるでしょう。1.20以前のビュワーを使用した場合、この欄の表示は意味をなさないものになってしまっています。1.21以降であればこの欄は「Script events」を表示しており、1秒当たりに処理されるイベントの数をあらわしています。
メイングリッドにMonoが導入されて数ヶ月が経過したら旧タイプのスクリプト・エンジン向けにコンパイルする機能をオフにできればと考えています。その時点では新規のもの、改めて編集したものはすべてMonoで稼動しているという状況です。ただし、旧スクリプト・エンジン自体を停止するわけではありません。つまり古いスクリプトは以前と変わらず動作し続けるけれど、編集をしたりするとMonoスクリプトになるということです。
Monoによる効果
旧スクリプト・エンジンMono仮想マシンを比較するベンチマークをいくつか実施しました。いくつかのテストの結果、Monoは LSL2に対して最大約220倍速いという結果を得ています。ベンチマークでは一般に性能評価用として使用するような数値計算スクリプトを使用しました。つまり普通のスクリプトでは、その効果はもっとバラついたものになるであろうということに注意してください。
Monoは典型的なLSLバイトコードよりも多くのメモリを消費します。そこで動的なメモリ管理を導入することで対応しています。LSL2では "Hello, Avatar"だけの単純なスクリプトでも一律に16Kを割り当てられていましたが、Monoでは必要な分だけのメモリが割り当てられます。一般的なリージョンにおけるテストでは、Monoがより多くのメモリを消費することと、よりよいメモリ管理の結果をざっくりと見てみると、全体としてのメモリ消費は良いものになるという結果を得ています。
極端な例ではLSL2に対して、Monoは最大4倍のメモリを消費する場合があります。そこで、後方互換性を保つためにメモリ制限は16Kから64Kに拡張しました。
Mono TIP: Monoではバイトコードの共有化が行われます。同じアセットIDである限り、同一のスクリプトのコピーが複数存在していたとしても、それらは1つ分のインスタンスしか消費しません。あなたの土地で同じスクリプトがいくつも使われているような状況を想像してみてください。それぞれのオブジェクトないのスクリプトが、それぞれコンパイル処理された場合、それらはその数分だけのメモリを消費します。が、まずひとつをコンパイルして、そのコンパイル済みのスクリプトを他のオブジェクトにコピーすればいくつのコピーがあったとしても1つのスクリプト(とデータ)分のメモリしか消費しないのです。
Mono How-to
サーバー1.24.3からメイングリッドでもMonoは完全対応となりました。すべてのリージョンでMonoでコンパイルしたスクリプトを稼動させることができます。Monoでコンパイルをする場合は1.21以降のクライアントが必要になりますが、コンパイル済みのMonoスクリプトを動作させるだけであれば以前の古いビュワーも使用可能です。
- Monoに対応したUI実装済みのビュワーをダウンロードします。
- 正規リリース1.21.6以降のビュワーをダウンロード・ページからダウンロードしてください。
- Monoに対応しているリージョンに行きます。
- 8月29日以降、すべてのリージョンはMono対応しています。
- 公式ブログ(英語): http://blog.secondlife.com/2008/08/20/mono-launch/
- リリースノート(英語): https://wiki.secondlife.com/wiki/Release_Notes/Second_Life_Server/1.24
- コメント用のフォーラムスレッド(英語): http://forums-archive.secondlife.com/348/38/277337/1.html#post2115465
- オブジェクトを作成/編集してMonoでコンパイルします。
- オブジェクトを作成して新しいスクリプトを追加します。
- コンテンツタブからスクリプトの編集を行います。
- スクリプト編集画面にMonoというチェックボックスがあるのでこれをチェックします。
- 保存ボタンを押してスクリプトをMonoで再コンパイルします。
- あとは他のスクリプトと同じように扱うことができます。以降は誰が所有しているか、どのバージョンのビュワーを使っているかにかかわらず自動的にMonoランタイムで稼動します。
- チェックボックスが見当たらないようであれば使用しているビュワーがMono対応していないのかもしれません。
- Monoのチェックボックスが灰色になって押せない場合、Monoが稼動しているリージョンにいない可能性があります。
- LSL2に戻したい場合はチェックボックスからチェックをはずしてください。
- 複数のスクリプト入りオブジェクトをまとめてMonoに変換するには
- スクリプト入りのオブジェクトをすべてrezします。
- 選択ツールを使って、まとめて選択します。
- ツールメニューから「再コンパイル / Mono」を選択します。
Monoに変換したら、それらがちゃんと動作するかどうかチェックをする必要があります。Mono自体はLSL2互換ですが、動作タイミングの差異などがありますので、その影響で挙動に変化が生じる可能性があります。Monoバージョンで製品をリリースする前にチェックをするようにしましょう。
- Mono関係の事項をJIRAに報告する。
- まず、Monoメタ・イシューを見て、他の人がその件ですでに報告をしていないかどうかチェックしてください。
- 何が問題箇所なのか?スクリプトの詳細まで調べていないとこのステップは実施できないでしょう。
- もしすでにその障害がJIRAに登録がされていて同じ事象のようである場合は、そこにあなたの発見した情報をコメントか添付で追記してください。
- 登録がまだされていない新しいものであれば、発見したバグごとにSVC(サーバ関連)のチケットを切ってください。チケットのサマリーに"Mono"という単語を入れておいてもらえるとフィルタリングしやすくなります。
- さらに、その問題をよりよく説明するために対象のスクリプトそのもの、もしくは(理想的には)二つのスクリプト・エンジン間での挙動の違いを示すことのできる小さなスクリプトを添付してください。
- あなたの登録したJIRA案件をMonoメタ・イシューにリンクしてください。
- まず、Monoメタ・イシューを見て、他の人がその件ですでに報告をしていないかどうかチェックしてください。
テスト
Mono実装過程ではテストを用いて逆行が生じないようにしています。最新版のレグレッション・テストは LSL Language Testを参照してください。これらは LSL仕様に沿うことを目的として提供されています。
ライブラリ・コールに関連するテストもあります。LSL Library Call Test 1 と LSL Library Call Test 2です。分割を利用することでメモリ上限の制限を回避することができます。
性能評価用のベンチマークもいくつか用意してあります。下記を参照してください:
- LSL Recursion Benchmark
- LSL Mandelbrot Benchmark
- LSL Partial Sums Benchmark
- LSL NSieve Benchmark
- LSL NSieve Bits Benchmark
FAQ
質問用のセクションです。
- Monoで明らかに速度が上がったというサンプルはありませんか?
- 以下のサンプルではMonoが明らかに速度向上していることがわかります。LSL_Recursion_Benchmark, LSL_Mandelbrot_Benchmark, LSL_Partial_Sums_Benchmark,LSL_NSieve_Benchmark, LSL_NSieve_Bits_Benchmark。
- 以前LSLスクリプトを購入したのですが、何故スクリプターの人がMono対応させるまで待ったほうがよいのでしょうか?自分でやってもよくありませんか?
- Monoによる速度向上の結果、複数のスクリプト間で通信を行っているような場合問題が起きることが考えられます。また、これはまれなケースですがMonoはLSLとは少し異なった動作をするようにしている場合もあります。したがってもともとのスクリプト製作者の方が変換と「テスト」をするのがより安全です。
- Monoコンパイルされたスクリプトは旧バージョンのビュワーでも動作しますか?
- はい。1.21以降のビュワーはMonoスクリプトを作成したい場合のみ必要になります。Monoはサーバー側で動作していますので、どのバージョンのビュワーを使用してもMonoスクリプトを使用することができます。
- Monoでコンパイルできるようになるまでどれくらいかかりますか?
- 1.21 release candidateのビュワーは 8月20日(水)にリリースされる予定です。
- スクリプトがMonoで動作しているかどうかを知る方法はありますか?
- いいえ。どのオブジェクトがスクリプトを含んでいて、どれがMonoで動いているかを判別するのはとても困難ですので、それを表示することは試みていません。
- OpenSimはMonoで動作していますが、二つの世界の間でLLによるMono実装共通化を促進するような考えはありますか?
- OpenSimの開発者の方々とMonoを基礎としたスクリプトの共通化について話し合いをすすめています。
- スクリプトで使用可能なメモリは変わりましたか?(現状のLSL2 VMでは16Kです)
- 同じLSLスクリプトのコードを扱った場合でもMonoのバイトコードと 旧タイプ(LSL2)のバイトコードは異なったサイズになります。今回私達は、すべての既存スクリプトとの互換性を保つため Monoでの上限を 64Kに拡張しました。これはMonoの場合に限ってのみできる対応です。Monoは動的にメモリ割当を行いますが、LSL2ではどんなスクリプトでも必ず16Kを占有してしまいます。Monoではスクリプトは必要な分だけのメモリを割り当てるようになっています。
- 64K?それって効率的じゃないスクリプトを助長することにならない?
- この変更によってより効率的なスクリプト作成が行われるようになることを望んでいます。現状ではプログラマーの方々は16Kの壁を越えるために複数のスクリプトを使っており、そのためにスクリプト間のデータ通信に多くのサイクルを費やしています。単体のスクリプトであればこれが必要なくなります。
- Monoを使うにあたってよりメモリ効率のよい手法はありますか?
- もちろんです。Monoはバイトコード共通化をすることができます。例えば XYTextや Puppeteerのように同じスクリプトが複数のインスタンスを使用しているようなものがリージョン内にあると考えてください。それらのインスタンスが同一のアセットIDである限り、バイトコードは1度だけしかメモリ確保されずにすべてのスクリプト間において共有化されます。この効果を確実に得られるように、スクリプトが完成したら、あとは単純にそれをコピーする(もしくはスクリプトが入っているオブジェクトをコピーする)ようにしてください。購入したスクリプトが多くのメモリを消費していたら、作成者の方にMonoバージョンについて聞いてみて、そのスクリプトをオブジェクトにコピーするようにしてみてください。ここで重要なのはアセットIDが同一になるようにコピーをするということです。もしそれぞれのインスタンスを個々に再コンパイルしてしまった場合、それらは異なったアセットIDとなるのでエンジンはバイトコード共通化を行うことができません。
- Monoを使用するためには自分のオブジェクトをすべて手作業で変換をしなくてはいけないですか?自動でやってくれるツールはありませんか?
- そうです。手作業でMonoへのコンパイルを実行しないといけません。なお Toolsメニューを使用して、選択しているスクリプトをすべてMonoでコンパイルしなおすということもできます。
- 自分のスクリプトを旧スクリプト・エンジンでずっと使い続けることはできますか?
- 旧スクリプト・エンジンを廃止する予定はいまのところありません。これについてはメイン・グリッドにMonoが導入されてしばらくしてから再検討することになるでしょう。現段階では、すべてのスクリプトを移行してもらうよりも旧スクリプト・エンジンも対応し続けておくほうがよいと判断しています。
- Monoは他のいくつかの言語もサポートしていると思いますが、LSL以外の言語でもスクリプトを書くことはできますか?
- 将来的には。まずは、旧スクリプト・エンジンで LSLスクリプトを使った場合と同じになるように Monoの互換性を完璧にすることが私達の目標です。
- 今回、LSLに本当の開発言語のような機能は追加されますか?(例:配列、参照/ポインタ、インクルード/インポート)
- いいえ。LSL言語自体は今回の更新では変更されません。
- 旧スクリプト・エンジンではスクリプトはビュワー側でコンパイルされてからアップロードしていましたが、Monoでは変更されますか?
- はい。Monoでのコンパイルはシミュレータホスト側で行われて それを配布する方式になります。
- 上の質問に関連しますが、私は正規のスクリプト・テキストの形ではなく、「ちょっとしたトリック」を使ってLSL2コンパイル済みのバイトコードをアップロードしています。Monoに変更された場合、アップロード済みのスクリプトはどうなりますか?Monoスクリプトでも「ちょっとしたトリック」を使用し続けることはできますか?
- Monoコンパイラはスクリプト・テキストのみを取り扱います。Monoエンジンは私達の Monoコンパイラでコンパイルしたバイトコードのみを実行するようになっています。Monoバイトコードをアップロードして実行することはできません。
- LSL コード がすでに失われている バイト・コード のスクリプトはどうすればよいか?例えばスクリプト自体は稼動しているが、編集をしようとすると "データベースにスクリプトがありません。" となるようなもの。バイトコードを変換する方法はありますか?もしくはそういったスクリプトは永遠に旧スクリプト・エンジンでしか使えないのでしょうか?
- 現時点ではLSLスクリプトからのバイトコード変換の予定はありません。ソースからのコンパイルのみを認めています。レジデンツからの要求が多いようであれば対応を検討するかもしれません。
- LSL2とMonoコンパイラおよび実行環境の違いはなんですか?
- Monoを旧エンジンと完全互換にしようとはしていません。少なくとも LSL2で容認されていたトリックやハックは再現しようとはしません。以下に現在判明している挙動の違いを記載します。わかり次第このリストは追記される予定です。
- ユニコードのサポート。Strife Onizukaさんからの情報「LSO LSLでは RFC 2279 (20億の文字種を扱うことができます)に準拠することでユニコード全体がサポートされていました。Monoは RFC 3629 という RFC 2279 の後継となる規格をサポートしており、これはユニコードの初めの 1,114,112文字コードをカバーしています。このことは直接的には llBase64ToString, llUnescapeURLといった関数に影響します。LSOスクリプトから Monoスクリプトへ投げられた文字列のうち、この制限域を越えるものは(定性的な動作として)化けてしまいます。」-- SVC-1960
- Monoが導入された後、グリッドに存在するすべてのスクリプトをMonoでコンパイルしなおさないのは何故ですか?
- 一種類のコンパイラとランタイムだけをサポートするほうがより良いということはわかりますが、事前の検討によりこれは現実的ではないと判断しました。以下に私たちがそう判断した困難な点のリストを示します:
- 現在稼動しているすべてのスクリプトのテキスト(LSLコード)が保管されているわけではありません。そのような"バイトコードしかない"スクリプトは動作できなくなってしまいます。
- 自動再コンパイルをかける場合、それはつまりスクリプトをリセットすることになります。リセットすることなく継続して動作し続けることを想定して作られている多くのスクリプトがあります。
- Monoスクリプトは以前と比較して異なるタイミングで設計する必要があります(多くの場合 Monoのほうが速くなります)。このことで挙動の差が生じてスクリプトがわずかに破綻する可能性があります。
- いくつかのスクリプトはLSL2の非公開の機能を利用して性能向上を図っています。Monoではこのような「機能」について完全互換は目指さず、正規の想定される動作をするように勤めています。
- 以上のような理由により、スクリプトが再コンパイルされた場合、その後に品質管理の工程が必要となります。コーディングやLSLスクリプトの販売をしてる住人の方はテストの実施と、そしておそらく各スクリプトをMonoの挙動に対応させる必要があるでしょう。もし自動再コンパイルとなった場合、このような品質管理が行われる保証がありません。手動コンパイルが必要とすることで、スクリプターの方はテストや変更をしたうえでMono対応バージョンをアップグレードとして販売することができるでしょう。
- すべてのスクリプトを再コンパイルするということは権限システムからすれば高圧的とも取れるでしょう。「変更不可」で販売しているスクリプトを自動再コンパイルするということはこのポリシーに違反することになります。これをかまわないというスクリプターの方もいれば、おそらくそうして欲しくないと望む方もいるはずです。
- Monoはまだプレビュー・グリッドで使用することができますか?
- はい。Mono/Beta FAQを参照してください。