明けましておめでとうございます。本年もよろしくお願いいたします。
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 とか愉快なメッセージが出てるし、ログインサービスも死んで、お手上げ状態でした。おまけに、二度もリブートに失敗しましたよ。このルータ兼(中略)サーバってば、年に一度は死にかけてますねー、あはははははははは。
いやいや、落ち着け。
今は何とか持ちこたえていますが、可及的速やかにリプレースしないといけません。とりあえず、今度の週末にでもやるか… <さっさとやれよ