明けましておめでとうございます。本年もよろしくお願いいたします。
C++のソースコードとPerlのソースコードを同一ファイルに混在させる方法。C++としても、Perlとしても有効です。
//; << 'END_CPP_AND_START_PERL'; // C++ code int main() { return 1; } /* END_CPP_AND_START_PERL # Perl code sub main() { return 1; } main(); # */
久しぶりに更新したような気がします。別に遊んでたわけではなくて、単にサボっていただけです(ダメだろ)。
曲線描画系(開/閉三次スプライン、開/閉チャイキン補間、ラグランジュ補間、N次ベジエなど)、システム系その他諸々の実装が終わり、プラグインから使えるようにしてみました。version 0.5として公開しようと思いましたが、今手を付けているものを含めて、version0.6として公開する予定です。0.5はお蔵入りでしょうね。まあ、SVNリポジトリから引き出してくればいつでも公開できますが。
今開発しているのは、吉里吉里からRDBMSを扱えるようになるプラグインです。RDBMSの実装は、コンパクトな組み込みRDBMSとしてお馴染みのSQLiteです。インターフェースはSQLitePlusを使用します。
// SQL即時実行 Plugins.link("util_sqlite.dll"); var db = new SQLite3(); db.open('test.db'); db.executeQuery("create table foo ( a number, b varchar );"); db.close();
// プリコンパイルステートメント Plugins.link("util_sqlite.dll"); var db = new SQLite3(); db.open('test.db'); var statement = db.createStatement("insert into foo values (?, ?);"); statement.setParam(1, 5); // 1つ目のカラム (a) statement.setParam(2, 'Hello TJS.'); // 2つ目のカラム (b) statement.execute(); db.close();
だいたいこんな感じで使えます。使い道があるのかどうかよくわかりませんが、趣味でやってるのでまあいいかな、と。
メモリ大食らいの肥満火狐。
やっぱりMozilla、定期的に再起動しないと、際限なく消費していくようです。
いまさらですが、エキスパートモードをクリアしました。エキスパートは難しくてずっと敬遠していたのですが、今日ちょこちょことやってみたら、比較的すんなりクリアできました。さすがに越前東尋坊と陸奥仏ヶ浦は苦労しましたが。
カーソルを実装しました。こんな感じで使えます。
// カーソルを使ったフェッチ Plugins.link("util_sqlite.dll"); var db = new SQLite3(); db.open('test.db'); var statement = db.createStatement("select * from foo;"); var cursor = statement.openCursor(); while (cursor.next()) { var a = cursor.value(0); var b = cursor.value(1); } cursor.close(); db.close();
こういうロボットはですね、球形ではなくて、メイド服を着た素敵なメ(以下略)
Subversionで管理しているのでメモする必要がない気もしないでもないが、メモ。
--- SqliteConnection.h (revision 14) +++ SqliteConnection.h (working copy) @@ -146,7 +146,7 @@ */ static SqliteString version() { - return SqliteString::fromANSI(sqlite3_version); + return SqliteString::fromANSI(sqlite3_libversion()); }
SQLiteのベンチマーク。トランザクション中に一万件INSERTして、プリコンパイルステートメントの実力を測ってみました。
実験項目 | 所要時間 [ms] | 備考 |
---|---|---|
1. executeQuery() | 500 | 毎回ステートメントを作成 |
2. prepared statement | 187 | 初回のみsetParam() |
3. prepared statement | 266 | 毎回setParam() |
この(?)業界では常識として、同じSQLを何度も流す場合にはプリコンパイルステートメントを使う、というのがあります。吉里吉里+SQLiteでも、確かにプリコンパイルステートメントを使用したほうが速いのですが、思ったほどの差は出ませんでした。まあ、一万件程度ならどっちでもいいか。
以下、ソースコード。
create table bench_table ( col1 int, col2 real, col3 text);
Plugins.link("util_sqlite.dll"); var path = "c:/foo/bar"; var bench_loop = 10000; bench(bench1); bench(bench2); bench(bench3); // ベンチマーク function bench(bf) { var db = new SQLite3(); db.open(path + "/bench.db"); db.beginTrans(); var start = System.getTickCount(); bf(db); var end = System.getTickCount(); System.inform(end-start); db.rollback(); db.close(); } // 毎回createStatement function bench1(db) { with (db) { var query = "insert into bench_table values (789, 3.1416, 'Hello SQLite.');"; var cnt = bench_loop; while (cnt--) { .executeQuery(query); } } } // 一回だけsetParam function bench2(db) { var query = "insert into bench_table values (?, ?, ?);"; var st = db.createStatement(query); with (st) { var cnt = bench_loop; .setParam(1, 789); .setParam(2, 3.1416); .setParam(3, 'Hello SQLite.'); while (cnt--) { .execute(); .reset(); } } st.close(); } // 毎回setParam function bench3(db) { var query = "insert into bench_table values (?, ?, ?);"; var st = db.createStatement(query); with (st) { var cnt = bench_loop; while (cnt--) { .setParam(1, 789); .setParam(2, 3.1416); .setParam(3, 'Hello SQLite.'); .execute(); .reset(); } } st.close(); }
ちなみに、トランザクションを開設しないでやったら、無茶苦茶遅かったです。ジャーナルファイルへのディスクI/Oが発生しまくって、遅々として処理が進みませんでした。
ねぇ、もういっそのことシステム業界自体を真っ二つに分裂させない?マターリ派とデスマーチ派で。
いいですね。私はマターリ派です。
…はあ?何の冗談ですか?エイプリルフールにはまだ早いんじゃ?
私も時々Lynxを使いますが、私もタイーホされちゃいますか?くわばらくわばら。
ちょっとした設定画面を作るのにもってこいですね。手軽に書けて、実行バイナリも10KB程度に収まります。
ちょいと改造して、設定内容をTJS2の辞書配列形式で吐き出すようにしてみました。出力ファイルを Scripts.evalStorage() なり何なりでエバってやれば、設定を即ロードできる、と。引用符のエスケープはできませんが、必要になったら考える、ということで逃げ。
我が家のルータ兼DNSサーバ兼NTPサーバ兼Webサーバ兼まどかちゃん兼…サーバが、危篤状態です。HDDが快音、いや怪音を立てています。素敵です。セクシーです。断末魔の叫び?ていうか、今日一度落ちました。syslogにはfailed to exec /sbin/modprobe とかexecv /usr/sbin/tcpd: Exec format error とか愉快なメッセージが出てるし、ログインサービスも死んで、お手上げ状態でした。おまけに、二度もリブートに失敗しましたよ。このルータ兼(中略)サーバってば、年に一度は死にかけてますねー、あはははははははは。
いやいや、落ち着け。
今は何とか持ちこたえていますが、可及的速やかにリプレースしないといけません。とりあえず、今度の週末にでもやるか… <さっさとやれよ