Hatena::ブログ(Diary)

hogeなlog

プロフィール

hogelog

hogelog

小室 直(こむろ すなお)。電気通信大学2003年入学。2010年修士卒業。プログラミングとかしてます。

カレンダー
1984 | 01 |
2006 | 07 | 08 | 09 | 10 | 11 | 12 |
2007 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2008 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2009 | 01 | 02 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 |
2010 | 01 | 06 | 08 | 09 | 10 | 11 | 12 |
2011 | 01 | 02 | 03 | 05 | 08 | 09 | 10 | 12 |
2012 | 01 | 04 | 06 |

June 28(Sun), 2009

[][] Firefox 出張ワークショップ 〜基礎から学べる拡張機能開発〜参加しました。

結果こんなにも立派な拡張機能を実装することができました!

f:id:hogelog:20090628214522p:image

ボタンがロボットに見えて困ってしまう拡張機能です。

http://konbu.s13.xrea.com/lib/firefox/robotbutton.xpi


あと拡張機能のinstall.rdfにはfirefoxのGUID書かんといけないのですけどそんなもの憶えられるわけがないのでGUIDなど含むアプリケーション情報を吐くvimperator pluginを書いた。

http://coderepos.org/share/browser/lang/javascript/vimperator-plugins/trunk/appinfo.js


これでFirefox拡張も楽勝だ、やった!

追記

既にぜんぶろぼっとという拡張機能があるらしい。まあ練習で作ったものだからいいんだけど。

June 23(Tue), 2009

[] ダイレクトスレッデッドコード復習。

ひどく単純なVM

#include <stdio.h>

#define STACK_SIZE 30000

enum Instruction {
  I_PUSH, I_POP, I_DUP,
  I_ADD, I_SUB,
  I_JUMP, I_IF,
  I_NOT, I_EQ,
  I_RETURN
};
typedef enum Instruction Instruction;
struct Code {
  Instruction inst;
  int value;
};
typedef struct Code Code;

int exec(Code *program) {
  int stack[STACK_SIZE];
  int stack_top = 0;
  int pc;

  for(pc=0;;++pc) {
    Code code = program[pc];
    switch(code.inst) {
      case I_PUSH:
        stack[stack_top++] = code.value;
        break;
      case I_POP:
        --stack_top;
        break;
      case I_DUP:
        stack[stack_top] = stack[stack_top-1];
        ++stack_top;
        break;
      case I_ADD:
        stack[stack_top-2] += stack[stack_top-1];
        --stack_top;
        break;
      case I_SUB:
        stack[stack_top-2] -= stack[stack_top-1];
        --stack_top;
        break;
      case I_JUMP:
        pc = code.value-1;
        break;
      case I_IF:
        if(stack[stack_top-1]) {
          pc = code.value-1;
        }
        --stack_top;
        break;
      case I_NOT:
        stack[stack_top-1] = !stack[stack_top-1];
        break;
      case I_EQ:
        stack[stack_top-2] = stack[stack_top-1]==stack[stack_top-2];
        --stack_top;
        break;
      case I_RETURN:
        return stack[--stack_top];
    }
  }
}
int main(int argc, char **argv) {
  Code program[] = {
    {I_PUSH, 0},
    {I_PUSH, 1},
    {I_ADD, 0},
    {I_DUP, 0},
    {I_PUSH, 20000000},
    {I_EQ, 0},
    {I_NOT, 0},
    {I_IF, 1},
    {I_RETURN, 0}
  };
  int result = exec(program);
  printf("%d\n", result);
  return 0;
}

ひどく単純なVMをダイレクトスレッデッドコード

#include <stdio.h>

#define STACK_SIZE 30000

enum Operation {
  I_PUSH, I_POP, I_DUP,
  I_ADD, I_SUB,
  I_JUMP, I_IF,
  I_NOT, I_EQ,
  I_RETURN
};
union Instruction {
  enum Operation op;
  void *addr;
};
typedef union Instruction Instruction;
struct Code {
  Instruction inst;
  int value;
};
typedef struct Code Code;

int exec(Code *program, size_t len) {
  const static void *j_table[] = {
    &&I_PUSH, &&I_POP, &&I_DUP,
    &&I_ADD, &&I_SUB,
    &&I_JUMP, &&I_IF,
    &&I_NOT, &&I_EQ,
    &&I_RETURN
  };
  int stack[STACK_SIZE];
  int stack_top = 0;
  int pc;

  for(pc=0;pc<len;++pc) {
    program[pc].inst.addr = (void*)j_table[program[pc].inst.op];
  }

  goto *program[pc=0].inst.addr;

I_PUSH:
  stack[stack_top++] = program[pc].value;
  goto *program[++pc].inst.addr;
I_POP:
  --stack_top;
I_DUP:
  stack[stack_top] = stack[stack_top-1];
  ++stack_top;
  goto *program[++pc].inst.addr;
I_ADD:
  stack[stack_top-2] += stack[stack_top-1];
  --stack_top;
  goto *program[++pc].inst.addr;
I_SUB:
  stack[stack_top-2] -= stack[stack_top-1];
  --stack_top;
  goto *program[++pc].inst.addr;
I_JUMP:
  pc = program[pc].value-1;
  goto *program[++pc].inst.addr;
I_IF:
  if(stack[stack_top-1]) {
    pc = program[pc].value-1;
  }
  --stack_top;
  goto *program[++pc].inst.addr;
I_NOT:
  stack[stack_top-1] = !stack[stack_top-1];
  goto *program[++pc].inst.addr;
I_EQ:
  stack[stack_top-2] = stack[stack_top-1]==stack[stack_top-2];
  --stack_top;
  goto *program[++pc].inst.addr;
I_RETURN:
  return stack[--stack_top];
}
int main(int argc, char **argv) {
  Code program[] = {
    {{I_PUSH}, 0},
    {{I_PUSH}, 1},
    {{I_ADD}, 0},
    {{I_DUP}, 0},
    {{I_PUSH}, 20000000},
    {{I_EQ}, 0},
    {{I_NOT}, 0},
    {{I_IF}, 1},
    {{I_RETURN}, 0}
  };
  int result = exec(program, sizeof(program)/sizeof(Code));
  printf("%d\n", result);
  return 0;
}

やってることはRubyist Magazine - YARV Maniacs 【第 3 回】 命令ディスパッチの高速化そのまんま。

計測

AMD Athlon(tm)64 X2 Dual Core Processor 4600+ x86_64 Linux環境

% gcc -O2 vm.c -o vm
% time ./vm
20000000
1.540 user 0.000 system 1.541 total
% gcc -O2 vm_dthreadead.c -o vm_dthreadead
% time ./vm_dthreadead
20000000
0.760 user 0.000 system 0.760 total

まあここで実行した

  Code program[] = {
    {{I_PUSH}, 0},
    {{I_PUSH}, 1},
    {{I_ADD}, 0},
    {{I_DUP}, 0},
    {{I_PUSH}, 20000000},
    {{I_EQ}, 0},
    {{I_NOT}, 0},
    {{I_IF}, 1},
    {{I_RETURN}, 0}
  };

というVM命令列はそれ自体の処理が非常に軽いため、元々実行時間のうち命令ディスパッチが占める割合が大きかったからこのくらい速くなる、と。あと「ダイレクトスレッデッドコードとかやるならもうJITやればいいじゃんJIT」というのが世の流れかもしれない。

昔やったあたりのことを再確認してるだけ。 http://d.hatena.ne.jp/hogelog/20080706/p2

[] (本題)Luaのダイレクトスレッデッドコード

非常にいいかげんに実装。たいていのプログラムはセグフォで落ちる。非常に恣意的なテストプログラムを走らせる。

local i = 1
local j = 1
while i<100000000 do
  i = i + 1
  j = j + i
end
print(j)
% time (repeat 10 ./lua test.lua >/dev/null)
1:08.98 user 0.052 system 1:09.07 total
% time (repeat 10 ./lua-dthreadead test.lua >/dev/null)
1:06.77 user 0.052 system 1:06.86 total

すばらしく微々たる違い。3%強の高速化に成功したぞ!

% time (repeat 10 luajit test.lua >/dev/null)
6.044 user 0.032 system 6.108 total

やっこさん桁が違う……!

JITってすごいなーというお話です。

[] Beep音を消そう

Beep音はデバイスマネージャで「非表示のデバイスを表示」にチェックを入れて「プラグアンドプレイではないドライバ」にある「Beep」を無効にすることで鳴らなくなります。

f:id:hogelog:20090623124732p:image

トラックバック - http://d.hatena.ne.jp/hogelog/20090623

June 20(Sat), 2009

[]bashrc設定切り分け

HOMEをNFS共有してるのでこんな感じにFreeBSD環境、Linux 64bit環境、Linux 32bit環境と切り分けてる。

if [ `uname` = "FreeBSD" ]; then
  source $HOME/.shell.d/bashrc.bsd
elif [ `uname` = "Linux" ]; then
  source $HOME/.shell.d/bashrc.linux
  if [ `uname -m` = "x86_64" ]; then
    source $HOME/.shell.d/bashrc.linux64
  elif [ `uname -m` = "i686" ]; then
    source $HOME/.shell.d/bashrc.linux32
  fi
else
  echo "Unknown Machine"
fi
トラックバック - http://d.hatena.ne.jp/hogelog/20090620

June 15(Mon), 2009

[][] 未踏ユースに応募とかしてました。

書類選考は通って、2009/06/13の土曜にオーディションでプレゼンをしました。なかなか面白いイベントでした。24歳とかそのあたり以下の人とかは面白いのでどんどん応募すると良いんじゃないでしょうか。

資料とかはたぶんそのうちどっかにアップロードします。開発は適当にgithubとかで公開しながら進めます。

トラックバック - http://d.hatena.ne.jp/hogelog/20090615

June 05(Fri), 2009

[][] 「ふろぉー しいてる ひちとたの はげつんを けっりんぶじ します。」なbotを書きました。

http://twitter.com/cmriadbge_bot

ケンブリッジ大学がどうたらこうたら - hogeなlog

に書いたケンブリッジなんたらをtwitterの発言に適用してるだけです。

  • 13分おきくらいにフォローしてる人の発言を適当にケリブッンジ化して発言します。
  • 話しかけるとだいたい1分以内にその発言をケリンッブジ化して返信します。
  • フォローすると自動フォロー返しをしますspamが感染するのでやめました。
  • リムーブすると自動リムーブ返しします。

使ってるのはruby1.9にkakasi、mecab、twitter、pitあたりのライブラリを使って適当に。

1度動かすと1時間弱ほど走り続けるプログラムをcronで1時間おきに起動。

mecab-rubyがなんか妙で分かち書きに失敗することがあって、そういう時はkakasi使ったりしてる確か。


botはネタバレするとつまらなくなる的な意味でソース公開されてないのも多いんじゃないかという気がするけど、このbotはあんまそういうのないだろということでgithubで公開。

http://github.com/hogelog/cmriadbge_bot/tree/master

[][] なんかアレな CentOS 4.7 (x86_64) に RPMForge を入れて多少アレにする

「# yum list」の出力を見て愕然とせざるをえないので RPMForgeなど導入する。ただし RPMForge のパッケージは yum で陽に指定したときのみ使うことにする。

# wget http://dag.wieers.com/rpm/packages/rpmforge-release/rpmforge-release-0.3.6-1.el4.rf.x86_64.rpm
# rpm -Uhv rpmforge-release-0.3.6-1.el4.rf.x86_64.rpm
# vim /etc/yum.repos.d/rpmforge.repo
...
enabled = 0
...  
#
# wget http://dag.wieers.com/packages/RPM-GPG-KEY.dag.txt
# rpm --import RPM-GPG-KEY.dag.txt

ほんで

# yum --enable=rpmforge install hogehoge

とかする。


参考

トラックバック - http://d.hatena.ne.jp/hogelog/20090605
最近のコメント
Connection: close