MOGOK最速レビュー

MOGOKクローズドβが始まったので、レビューをしてみんとてするなり。

MOGOK とは?

MOGOKは、Ruby on Railsアプリケーションの開発支援環境と実行環境を提供するサービスです。」端的に言えば「heroku みたいなの」です、IIJ がやってます。IIJ 自身による紹介は例えば「リソース管理とメッセージングの仕組みについての解説」など。

MOGOK 用アプリ

Rails の場合、いくつか heroku 向けアプリから修正すべき所があります。

config/environments/production.rb

チュートリアルの「Railsアプリケーションの作成」によると、以下のように書き足す必要があります。

  config.serve_static_assets = true
  config.logger = Logger.new(STDOUT)
  $stdout.sync = true
Gemfile

heroku からの書き換えという想定ですと、以下のような内容になります。

  • gem 'sqlite3' という行があったらコメントアウト
  • gem 'newrelic_rpm' など、heroku 用の gem もコメントアウト
  • gem 'therubyracer-heroku' は gem 'therubyracer' にする
  • gem 'pg' は Rails 2 ならば gem 'mysql' に、Rails 3 ならば gem 'mysql2' に変える必要があります。

本当にコメントアウトしてしまうと管理が煩雑になるので、わたしは以下のように hostname コマンドを実行してサーバーの名前を取得し、その内容によって分岐させました。
ローカルでは全て読み込むようにするのが正解な気がするんだけど、まぁそのうちそういう機能が bundler に入るでしょう。環境変数 BUNDLE_WITHOUT や Bundler.settings.without= を用いるとすっきり書くことができます。

if /\Amgk-/ =~ `hostname` # mogokのサーバ名は "mgk-" で始まる
  Bundler.settings.without = %w/development test heroku/
end

group :development do
  gem 'sqlite3'
  gem "therubyracer"
end

group :mogok do
  gem "therubyracer"
  gem 'mysql2'
end
group :heroku do
  gem 'therubyracer-heroku'
  gem 'pg'
  gem 'newrelic_rpm'
end

rake assets:precompile

Rails 3.1 にはまだ対応していないので、deploy 時に rake assets:precompile をサーバー側で自動的にやってくれたりはしません。また、手動でやっても後述のメモリサイズ制限で殺されます。よって、以下のように 2 コマンドに分けて手動実行する必要があります。

rake assets:precompile:all
rake assets:precompile:nondigest

deploy の仕方

以上を踏まえると、deploy のためのコマンドは以下のようになります。

git push mogok&&mogok deploy&&mogok rake assets:precompile:all&&mogok rake assets:precompile:nondigest

β版初期バージョンの制限

いくつかの文書化された制限と、まだ文書化されていない制限があります。IIJ MOGOKサービスβ版 ご利用の手引き」に制限が書かれています。大雑把には

  • 非同期ジョブの管理 (mogok worker) が未実装
  • 定期実行ジョブの管理 (mogok job) が未実装
  • サーバ上の環境変数の管理 (mogok env) が未実装
  • サーバ上でのRubyスクリプトの実行 (mogok run) が未実装
  • ssh 鍵のデータ長は 1024 バイトまで (ssh-dss 鍵が事実上登録できない)
  • 外部への通信ができない
  • プロセスのメモリサイズは 200MB まで (rake assets:precompile が通らない)

結論

動かそうと思っていた、RubyCI は HTTP で外に出れないと使えないので、出れるようになったら本気出す。

ServersMan@VPS Perfect Plan で NetBSD

先日から Ruby では DTI さんに VPS を無料で貸していただいてまして、以下のように chkbuild を走らせています。

で、この環境に NetBSD を入れると妙に固まるわけです。正確にはマシンが固まっているわけじゃなくて、通信が固まっている。これは何かというと、NIC ドライバの問題らしい。パッチ自体はすでに netbsd-5-0 向けにはあるので、current 用 を作って当てています。

で、どうも今の NetBSD current だといろいろ壊れてるみたいなんだよなぁ。(たぶん NetBSD 側の問題)

MS ゴシックの文字幅

こんな場末の日記をわざわざ見に来る方は UAX #11: East Asian Width なんかは当たり前に読み込んでいると思うんですが、読み込んだ人はきっと気づくと思うんです、このドキュメントはあてにならないことに。じゃあどうすればいいかってなるんですが、端的には融通の効かない奴に合わせるわけですな。それはアプリ側のこともフォント側のこともあるんですが、今回はフォント側の事を考えることにします。フォント側のことを考えるってことは、要するにフォントは不動と考えるってことで、そういうフォントって要するにMS ゴシックのことなので、これを測ることにするわけです。
さて、どうやって測るかというと、実際に描画して測るわけです。TextRenderer.MeasureTextとかでも行けそうに思えるんだけど、グリフがない場合に fallback しちゃうんでうまくいかない。

using System;
using System.Drawing;
using System.Windows.Forms;
using System.Windows;

class Program
{
	[STAThread]
	static void Main(string[] args)
	{
		Application.Run(new FormA());
	}
}

class FormA : Form
{
	protected override void OnPaint(PaintEventArgs e)
	{
		for (int c = 0; c <= 0x10FFFF; c++) {
			if (0xD800 <= c && c <= 0xDFFF) continue;
			measureChar(e, c);
		}
		//measureChar(e, 0x20bb7);
		//measureChar(e, 0x20b9f);
		//measureChar(e, 0x216b4);
		Application.Exit();
	}

	private void measureChar(PaintEventArgs e, int c) {
    Font stringFont = new Font("VL Gothic", 16.0F);
    RectangleF layoutRect = new RectangleF(0F, 0F, 300F, 300F);
		Pen pen = new Pen(Color.Red, 1);
    StringFormat stringFormat = new StringFormat();
    stringFormat.FormatFlags = StringFormatFlags.NoFontFallback;

		string str = Char.ConvertFromUtf32(c);
    CharacterRange[] ranges = {new CharacterRange(0, str.Length)};
    stringFormat.SetMeasurableCharacterRanges(ranges);


    Region[] stringRegions = e.Graphics.MeasureCharacterRanges(str, stringFont, layoutRect, stringFormat);
    RectangleF measureRect1 = stringRegions[0].GetBounds(e.Graphics);
		Console.WriteLine("{0,0:X6}: {1}", c, measureRect1.Width);

    //e.Graphics.DrawString(str, stringFont, Brushes.Black, 0, 0, stringFormat);
    //e.Graphics.DrawRectangle(pen, Rectangle.Round(measureRect1));
	}
}

で、これで測れたわけですがこのままだとまともに扱えないので、以下のようなスクリプトを使って区間にします。つまり、連続してる奴はまとめるわけです。

class CC
  def initialize(encoding=nil)
    @encoding = encoding
    @cc = []
  end

  def <<(v)
    case v
    when Fixnum
      _bsearch_add2(v, v)
    when Range
      _bsearch_add2(v.first, v.last)
    when CC
      v.to_a.each_slice(2) do |from, to|
        _bsearch_add2(from, to)
      end
    else
      raise TypeError, "invalid value to add a charclass"
    end
    self
  end

  def to_s
    return to_char(@cc.first) if @encoding && @cc.size == 2 && @cc.first == @cc.last
    buf = '['
    n = @encoding ? nil : 0
    @cc.each_slice(2) do |from, to|
      buf << ',' if n && 1 < n += 1
      buf << to_char(from)
      if @encoding.nil? ||  from != to
        buf << '-' if to - from > 1
        buf << to_char(to)
      end
    end
    buf << ']'
  end

  def inspect
    to_s.inspect[1..-1]
  end

  def empty?
    @cc.empty?
  end

  private
  def to_char(v)
    #Regexp.quote(@encoding ? v.chr(@encoding) : v.to_s)
    @encoding ? '\u%04x' % v : v.to_s
  end

  def _bsearch_add2(from, to)
    pos1 = _bsearch(from)
    pos2 = from == to ? pos1 : _bsearch(to)
    if pos1.odd?
      pos1 -= 1
      from = @cc[pos1]
    elsif pos1 > 0 && @cc[pos1-1] == from - 1
      pos1 -= 2
      from = @cc[pos1]
    end
    if pos2.odd?
      to = @cc[pos2]
    elsif to + 1 == @cc[pos2] || to == @cc[pos2]
      pos2 += 1
      to = @cc[pos2]
    else
      pos2 -= 1
    end
    @cc[pos1, pos2-pos1+1] = from, to
  end
end

cc = CC.new(Encoding::UTF_8)
IO.read('msgothic.txt').scan(/(\w+): (\d+)/) do |x, y|
  a << x.to_i(16) if y.to_i == 22
end
p cc

で、出来た全角文字にマッチする正規表現は以下の通りになります。うーん、なんか違う気がするのが混じってますね。やっぱり OpenType 直接読みに行かないとダメかなぁ。

/[\u0001-\u0008\u000b\u000c\u000e-\u001b\u007f-\u0083\u0086-\u009f\u00a7\u00a8
  \u00b0\u00b1\u00b4\u00b6\u00d7\u00f7\u0180-\u0191\u0194-\u01c1\u01c3-\u01f7
  \u0200-\u024f\u02a9-\u02c5\u02ca\u02cb\u02cd-\u02cf\u02d2-\u02d7\u02df-\u02e4
  \u02ea-\u02ff\u0305\u0307\u0309\u030a\u030d\u030e\u0310-\u0317\u031b
  \u0321-\u0323\u0326-\u0328\u032b\u032d\u032e\u0331-\u0333\u0335-\u0338
  \u033e-\u0360\u0362-\u0373\u0376-\u0379\u037b-\u037d\u037f-\u0383\u038b\u038d
  \u0391-\u03a9\u03b1-\u03c1\u03c3-\u03c9\u03cf-\u0401\u040d\u0410-\u0451\u045d
  \u0487-\u048f\u04c5\u04c6\u04c9\u04ca\u04cd-\u04cf\u04ec\u04ed\u04f6\u04f7
  \u04fa-\u070e\u0710-\u09f1\u09f4-\u0e3e\u0e40-\u17da\u17dc-\u180a\u1810-\u1e3d
  \u1e40-\u1e7f\u1e86-\u1ef1\u1ef4-\u1f6f\u1f74-\u1fff\u2001\u2010\u2011\u2015\u2016
  \u2018\u2019\u201c\u201d\u2020\u2021\u2025\u2026\u202f\u2030\u2032\u2033\u203b
  \u204a-\u2069\u2071-\u2073\u208f-\u209f\u20b2-\u20ff\u2103\u2116\u2121\u212b
  \u2139-\u2152\u2160-\u2193\u21d2\u21d4\u21eb-\u2200\u2202\u2203\u2207\u2208
  \u220b\u2211\u221a\u221d-\u2220\u2225\u2227-\u222c\u222e\u2234\u2235\u223d
  \u2252\u2260\u2261\u2266\u2267\u226a\u226b\u2282\u2283\u2286\u2287\u22a5\u22bf
  \u22f2-\u2301\u2303\u2304\u2307-\u230f\u2311-\u231f\u2322-\u2503\u250c\u250f
  \u2510\u2513\u2514\u2517\u2518\u251b-\u251d\u2520\u2523-\u2525\u2528\u252b\u252c
  \u252f\u2530\u2533\u2534\u2537\u2538\u253b\u253c\u253f\u2542\u254b\u2596-\u25a1
  \u25b2\u25b3\u25bc\u25bd\u25c6\u25c7\u25cb\u25ce\u25cf\u25ef-\u2638\u263d-\u265f
  \u2668\u266a\u266d\u266f-\u2933\u2936-\u2984\u2987-\u29f9\u29fc-\u2fff\u3001-\ud7ff
  \ue000-\ufb00\ufb03-\ufefe\uff00-\uff60\uffa0-\uffe7\uffef-\ufffe]/x

RubyKaigi2011

なかなか書き終わらないからとりあえず載せてしまおう。

Aaronの発表について

> 標準ライブラリなどで分野ごとに担当がはっきり決まっていることで

これは責任者(=バグったときに直せと言われる人)を明確にするって事と、ライブラリ全体のデザインをする人を確保するって意図・メリットがありますね。

> 担当者以外が触ることができず、担当者が居ないとその間全く直すことができなくなってしまうことを指摘しました。

運用としては、担当者が全くいないものは提案→(多くの場合沈黙による)合意の形成→コミットとかしてますね。いるのに反応がない場合は勝手にコミットするって事もありますな。

> Rubyの一部のライブラリが外部にupstreamのリポジトリを持っていることが挙げられました。
> RubyGemsなどは問題があってもRubyコアチームにお願いしてもダメで、外部のRubyGemsチームに頼まないといけないことを例示しました。

RibuGemsの問題もRubyRedmineでいいんですが。

> 標準ライブラリが一部がgem化されているものと,されていないものがあって不統一になってしまっている点も問題として挙げていました。

手段と目的がごちゃごちゃになっているような……。で、この話はなひさんが色々勧めるようだ

> Ruby開発はみんなが同じチームなのに,「境界」が存在してしまっており,Rubyの全てに対して触れない,貢献できないという点をAaronさんは指摘されていました。

デザインの決定者ってのがあるんですよねぇ。

> 「feel free to commit your patch...」

これはバグ修正限定、yuguiさんが「もうダメ」って宣言するまでっていう制限がありましてね、むしろ自由にコミットしていいよじゃなくて、バグをtrunkにコミットしたらruby_1_9_3ブランチにも自分でバックポートしておけという趣旨で……。

> Ruby本体をアップデートしても必要なgemだけをダウングレードして使い続けるといったこともできるようになる

rubygemsのバージョン指定requireとか使うのかしら。

> エンコーディングの仕様に対してASCII-8BITと他のエンコーディングの文字列を連結した場合には常に例外を発生させて欲しいと提案していました。

ASCII-8BIT の場合 7bit only そういう案自体は #3274 とか前から何度か出ているんですが、これって結構派手に互換性壊すので色々修正が必要だと思うところ、そこまで厳しくしてもうれしくないんじゃないかなぁと思ってるので、つらいんじゃないかなぁ。というわけで、rb_enc_check をいじるか、rb_str_plus をいじるなりしてエラーになるようにした環境で暮らしてみるといいんじゃないかと思いました。

Next version of Ruby 1.8 and 1.9

コスプレしたりしてました。2.0 の話が出ましたが、どうなるんですかねぇ。

そらさんの

その後そらさんの将来を心配する声を何度か聞いたんですが、なんというかそらさんはすでにレールから外れて久しい人なので、そういう人はどうするのが幸せなんだろうかと考えるとなかなか難しい問題だと思うんですよね。

プロファイラの話

仕事で使えると便利な気がするので是非公開して頂きたい。

軽量Ruby

みんな待望のRiteの話。Riteを使って文法色つけ・インデントするWindows向けエディタが欲しいなー。

H社の

いやぁ、変態でしたね。しかし、結論がRiteでおkになってしまうのが何とも言えない。

NariさんのGCの話

deqでがんばってみたという話だったけど、そんなに並列性の維持で頑張らなくていいんじゃないかなぁ。CAS使う部分がオーバーヘッドになるんだったらやらなければ速くなるんじゃないかと思いました。
……というような話をしたら散々既出なツッコミだったようなので、Rite GC を応援しておいた。
@nari3: 世代別GCねぇ。Ruby2.0で。」 がんばつてください

ささださんの

スピリチュアルな話にしたつもりだとか主張していらっしゃいますが、あんまりそうは聞こえない。

観察日記 2011-07-20

RubyKaigiの感想が書き終わらないので大昔のログでも。

cmd.exeさんとconhost.exeさん

うささんうささん、こんそーるほすとぷろせすってなに

ターミナルアプリケーションのことを指してるように聞こえる。
ruby.exeとかも変更が必要って意味?
いや
cmd.exeの代替物を作れと言ってるんじゃないかなあ
あぁ
作ってくれって意味で煽ってるのに
分離されてる、ってのが微妙だ。
何と何が分離されているんだろう
コンソールウィンドウのオーナープロセス、と言えばいいんですかねえ。
普通cmd.exeですよね。
cmd.exeをいじらないといけないだろうというのはまぁ予想しているので、
何が問題なのがわからないにょ
コンソールウィンドウはWindowsそのものが作成・管理してて、コンソールAPIと直結してるので
コンソールウィンドウの問題はコンソールAPIごとの置き換えが必要となる、ような
なるほど
Windows作り変えましょう。
じゃあ8でよろ
しかしまあ、普通のコンソールアプリケーションはコンソールAPIを叩かないと思うので
stdin,out,errを分捕った上でうまく振舞うttyを自作すればよい、とも言える。
その例がck。
なるほど
cmd.exeはもちろんコンソールAPIと直結してるのでそのまま使うのは諦めるとして
ck+適当なシェル... まあcygwinのを使うのが楽ですよね。
g>MinTTY
{ko1_ndk} google web bot: 「MinTTY」なら『Cygwin』をWindowsのUIのように操作出来る! : ライフ ... - http://www.lifehacker.jp/2009/03/minttycygwinwindows.html (and 1,010 hit)
これつかえばいいのかにゃ
MinTTYは使ったことないけど同じようなことになりますね。
エンコーディング対応は知らない。
ckはUTF-8はサポートしてたと思った。
* Comprehensive character encoding support, including UTF-8.
がんばってた
日本語入力はどうなってるんでしょうねえ。
すごーく頑張ってたら普通にインライン入力できるはずだけど
* Wide character display and Windows IME support. 次の行
http://code.google.com/p/mintty/
{_ocha_} (AutoCheck): mintty - Terminal window for Cygwin and MSYS - Google Project Hosting [AR]
まじか
前そこまでできたっけ
俺も実はちょっと作ってみたことあるんだけど
作るめんどくささと嬉しさと比較してやめちゃったような記憶がある。
なるほろ
(cmd.exeをそんな嫌いじゃないので)
{unak} Mintty is based on code from PuTTY 0.60 by Simon Tatham and team.
あ、なるほどねえ。
そういえばPuTTYよくできてるな
するとputty使いである俺には嬉しいかもしれない。
しかし
cygwinとmsysとどっちか要るのはWindowsわかってない。
うむ
うーん
やっぱ不具合があるな。リダイレクト周りで。
難しいんだよね。
ほう?
コンソールアプリじゃないけど標準入出力にアクセスする
という特殊なアプリを起動しようとしたとき
ブロックする。
ふむ
そんなアプリ世の中に何個もないと思うけどね。(自力でコンソールをアロケートするものは除くが)
http://d.hatena.ne.jp/gnarl/20100428/1272441051 ふぅん?
{_ocha_} (AutoCheck): はてな: Cygwin+mintty、Windowsの対話型コンソールアプリを正しく実行できない - <s>gnarl,</s>技術メモ”’<marquee><textarea>¥ [AR]
そうきたか
ckがこういう仕組みだったかな。
Windows使ってる人はたいへんですね
ほう
で、これをやると、コンソール絡みの元の問題が全部復活したりするので
はっはっは。
しょぼりん
ckじゃなくてckw?
ckwかな
忘れた
ckはcygwin

http://www.howtogeek.com/howto/4996/what-is-conhost.exe-and-why-is-it-running/
{_ocha_} (AutoCheck): What is conhost.exe and Why Is It Running? - How-To Geek [AR]
conhostねえ
何でこんな大騒ぎになるのかよく・・・
なるほど。
具体的に何してるんだこいつ
ttyそのものだな
ふーん
tty=conhost
sh=cmd.exe
ってこと?
かなあ。
知らなかった、へぇ
単純にそうは言い切れないけど。
conhostはttyよりもっと機能少なくて、その少ない分はcmd.exeにある。
なるほろ
で、conhost.exeごといじらないといけないから大変だおって事か
例えばコンソールの文字アトリビュートとか設定したりなんだりするのはconhost.exeじゃなくてcmd.exeさんのお仕事
なーるほろ
IME制御とかはconhostさんがやってる。
なんかフックとか打ち込んでたりもするな。
なかなか大事になってしまうことはなんとなくわかった
キーボードフックかなあ。APIフックかなあ。
とかまあそんな感じ。
なるほろり
ま、なんせ、コンソールウィンドウを持って、描画したり入力したりとかはconhost.exeさんのお仕事ですね。
実質それだけだと思うが。
で、コンソールAPIを介してcmd.exeと情報やり取りしてる感じ
まさにさっきと似たような方向になってきた
あー
コンソールアプリケーションが走ってる時はそのアプリとconhost.exeがやりとりしてるのかな
cmd.exeは完全Unicodeアプリケーション
cmd.exe経由?
ほう
conhost.exeが文字コード変換とか取り扱ってやがる。
へー
cmd.exeさんは悪くなかったのか
でと、直接のやりとりはないけど(アプリからconhost.exeの存在は見えない)、
さっき言ったように裏でカーネル経由でやりとりされますよー、という。
カーネル経由でサービスとして動いてるconhostさんに流れ込んでる感じですか
サービスでいいのか?
csrss.exeというサービスが仲介者
うーん
なるほろ
conhost.exeだけ作り変えれば理想の環境が得られる、ような
conhost.exeさんにも相当の機能を載せれば、zsh.exeさんとか大勝利ですか
たぶん
にゃるほろり
ますます中の人じゃないと手も足も出ないな
conhost.exeさん、非公開API叩きまくりだから、
ちょっと一筋縄ではないな。
cmd.exeさんはさほどでもないのだが。
cmd.exeさんはzsh改みたいなやつで置き換えたい
置き換えたいがconhostさんがなんとかならないとどうにもならんと
cmd.exeさんはコードページとかさっぱり知りませんなムード
だってぼくUnicodeしか使いませんよ的な
まぁ、それもありか
chcpとかの効果はconhost.exeに行ってて、Unicodeにすでになってるのがcmd.exeに行くと
そうそう
なーるほどねぇ
ぼくUnicodeでコンソール出力バッファに書いてコンソール入力バッファから貰うだけだもーん
サロゲートペアとかも悪いのはconhost.exeさんだったのか
というわけで思い出したのでwineをみれば
なんか役に立つかも。
あぁ、なるほど
さすがにWineのリポジトリはでかいな
conhostさんいないな
conhostさんがいる必要はないか
programs/winedbg/winedbg.c: /* FIXME: should CP_ACP be GetConsoleCP()? */
既視感のある問いだ
みんなそこで悩むんだな。
console系API呼び出しをどう処理してるかが参考になるんじゃないかなー、と。

おまけ

きんもー☆

観察日記 2011-07-15

Mac上でのベンチマーク結果速報

http://www.atdot.net/sp/readonly/nfbnnl_kosaki0
Mac上でのベンチマーク結果速報
これはえーと
一番下だけ見ればいいのか
はい
基本的には、若干悪化している、と。
稀に速くなってるのもあるな。
vm_thread_mutex3 はなんぞ
あと、vm3_clearmethodcache もなんぞ
cleanmethodcacheはささださんがメソッドキャッシュをごそっと変えた影響
vm_thread_mutex3は1000スレッドが1つのmutexを奪い合うベンチ
遅いっつってもじゅーぶん許せる範囲だと思いますです。
vm_thread_mutex3hは皆さんの努力の成果か。
ですす
ほとんどのベンチはシングルスレッドなので、そのへんだけが193の成果
...
短すぎて測定結果が無意味になってたベンチ全部ループ回数ふやしたった
これはヒドイ
{znz_v} biff: [ruby-changes:20308] kosaki:r32356 (trunk): * benchmark/bm_app_erb.rb: increase loop count. too short - http://mla.n-z.jp/?ruby-changes=20308

Linuxでの結果

app_answer はジョークベンチマークなので
消した方がいいかもしれません
スレッド2つの時に遅いのはlazy timer threadの影響があるかもしれないので、調べよう
app_answerは消したい。あれで性能負けると腹がたつけど、ベンチのソースコード読むと直し用がないという結論になって二重に腹がたつという
vm_thread_create_join が性能落ちてるのがあんまり身に覚えないんだけど、ささださん何か思いつきます?
Linuxでの結果もでたようだ
paste>
{ko1_ndk} http://www.atdot.net/sp/readonly/39pnnl_kosaki0
如実に悪化してるなぁ
困りますなぁ
うーん、thread_mutex2が遅いのは、lazy timer threadと gvl_yield が大変相性が悪いという結論になりつつある
観測事実としてはcontext switchがやたら増えているのと、ruby-192でCPU 99%使用がtrunkは150%
おおベンチマーク
なんか本当にすごい 1.9.3 遅いね
vm1_rescue* 0.111 -0.193
マイナス
この結果、もうちょっと見やすくならんもんかね
vm3_clearmethodcache 4.957 1.159
vm3_gc 2.176 5.464
それは whileloop1 の結果を引くという設計なので、値が小さくなりすぎると誤差で余裕にマイナスに突入する
この辺は興味深い
vm3_gcはnari3にみてってさっき@した
loop_whileloop がこんなに遅くなってるとか
column -tで
インデントもなんだけど、目で数値比較したくない
比率を自動計算ってできそうだよねえ
しかしこの速度低下は原因わからない限り blocker と呼びたいレベルだな
特にどれを問題にしています?
全体的にもっさりしてるの
目で数値比較した印象だから本当に全体的に遅くなっているのかはよくわからない
最初の方に遅くなってるのが多いだけ?
いや、全体的に遅い
原因を予想しよう
わたしもコミットするときは、自分の変更前後しか比較してなかったから気づいてなかった
1. GC
シングルスレッドでも遅いのはGVLやタイマースレッドは無罪っぽい
thread_mutex2のつづき。gvl_acquireからのrb_thread_wakeup_timer_thread() でタイマースレッドが起こされまくってるのは確定。timer_thread_functionはエライ数呼ばれてる。gvl_yieldがそれほど呼ばれてないのはmain threadが拾えないぐらいinterrupt_flag立てまくってるから。あかん、これはなおそう
速度劣化はこっちでも再現するっぽいなあ
まだぜんぜん途中だけど
vm_thread_mutex3 84.002 2.766
http://www.atdot.net/sp/readonly/kgtnnl
うちでの結果
やっぱり全般的に193が遅いな
strace したら write(4, "!", 1) とかでてるのはタイマースレッドかしら
シグナルうけたときと、GVL待ちスレッドが0から1に変化したときにwriteしてます
ですよねー
なにい再現しなくなった
ん? > 再現
全く何も変えていないけれど再現しなくなった
benchmark/bm_app_mandelbrot.rb を直接実行してみてるんだけど。
速度低下が? それともあたらしいバグ?
速度低下が。
そりゃ、不思議だ
benchmark/bm_app_mandelbrot.rb 以外では再現するやつもあるのかな
再 make benchmark 中
http://www.atdot.net/sp/readonly/5qunnl
そんなに顕著な差は見て取れなくなった、ような気もする
なんかx86_64のほうが差がでかい気がする
io_file_read は確実に遅くなっている気がする
あれじゃない。do_selectでrb_fdset_t対応されたなかったのを直したやつ。あれで毎回mallocするようになってしまったので・・・
最適化パッチつくるか
max = 200_000; len = 1000 を
max = 20_000; len = 10000 に変えると trunk の方がだいぶ速くなった
どういうことだろう
^^;;;;
maxを減らすと速いというのは、やっぱりreadそのものが遅いんだよな
lenはstring操作にからんでくる部分だから、だれかがstringを最適化した
io の前処理や後処理が遅くなって、読み込み部分が速くなった
blocking_region とか関係ないよね
ある
gvl_acquireがいままで、pthread_mutex_lockだったのが、mutex_lock, unlockの二手順になり、gvl_releaseも同じ
なので、gvl を取ったり離したりを繰り返すIO系ベンチはすこしは負けるのは予想できた
でも、readとwriteで落ち方が同じじゃないように見えるので
もうちょっと考える
write は別に影響なさ気ですね
いやいやいや、ちがう。おれはパッチ作ったときに直前のコミットと性能比較したんだった。ruby-dev:43465 の添付を見るとreadもwriteもちょっぴり落ちる程度の数値になってる

原因は rubygems

原因は rubygems のようです
$ time ./ruby --disable-gems benchmark/bm_io_file_read.rb
real 0m4.069s
$ time ./ruby benchmark/bm_io_file_read.rb
real 0m4.970s
rubygems が余計な (かどうかはしらんけど) Array をいっぱい作ってるようで
そのせいで GC が遅くなってる。
$ ./ruby --disable-gems -e 'GC.start; p ObjectSpace.count_objects[:T_ARRAY]'
18
$ ./ruby -e 'GC.start; p ObjectSpace.count_objects[:T_ARRAY]'
597
こういうときにオブジェクトの生成元知りたいな
知りたいっすねー
r27016
{unak_away} http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=27016
これのせいで attr ごとに配列ができるようになっちゃってる
これで 597 -> 527 になった
これを消したら
とりあえずこの ary は生でみえたらまずい予感がする
いろいろ変わってるけど vm_method.c の変更が重要
再測定してるけど、--disable-gemsつけたら192とtrunkはだいたい互角の性能っぽい
しかし、よく気づけましたね。そんけー
GC::Profiler さんのおかげ
1. GC と予言したとおりではあった
でも rubygems の人たちに配列やハッシュを保持すんなって言っても聞かないだろうな
ああ、1.9.2 のときは gem_prelude があったからか
preludeなくても性能に影響ないって言ったじゃん。あれ、いわなかったかも
Array が原因かはわからないけどオブジェクト数が倍増してるもんな
世代別 GC できてない以上、マイクロベンチマークにはクリティカルに影響しそうだ
マイクロベンチマーク以外に影響ないといいきれるような数字じゃないと思うんだが
1.9.2 でも rubygems 使ってる場合はこんなもんだった
ということになるんだと思う
ああ、どうせ本番ではgemつかうでしょ?って事
つまりぼくのような ProjectEuler する人とかが困るわけだ
こまるぞ!
声をあげるべきです
ProjectEuler 用のライブラリを gem にまとめようとしていたところで悲しい
gem を C で書き直すんだ
rubygems を C で書き直すんだ
戦う相手が Ryan になりそうだしなあ

そしてGC

GC 側でなんとかしろよ、というのが正しいとはぼくも思う
世代別 GC 導入しかないと思うが
そしてそれには全拡張ライブラリでの対応が必要
Ruby おわた
オワタ
拡張ライブラリがつらいよなぁ
やっぱり世代別 GC があれば解決できるんだ
世代別 GC 対応すれば並列マーキングも可能になるので
G1GCをぱくろう
Ruby の未来を考えると全拡張ライブラリを一旦捨てる選択肢もまじめに考えるべきなのかもしれない
互換性ぶっ壊すのはいいんだけど、
世代別と今みたいな拡張ライブラリって併存できるの?
メンテナンスされてない拡張ライブラリは切り捨てて良いと思いますよ
VALUE がインデックスなら、VALUE を特殊な使い方していなければ大丈夫なんじゃなかったっけ
あぁ、そうか
今みたいなって?
ポインタそのまま外に持ってける
世代別じゃなくてコピー/コンパクションだ
うーん
参照はできるかもしれんけど書き換えは多分ダメ
オブジェクトの mark 先が変わるような変更をした時に
具体的には RARRAY_PTR(ary)[idx] = elem; とか
変更したよーってことを GC に教えてあげるようにしないといけない
ああ、VALUE が途中で変わるかって心配か
いぇっさ
未対応の拡張ライブラリにオブジェクトを渡すと汚染されるフラグとか
未対応の拡張ライブラリに渡ったかどうか分かるのかな
未対応というか、まず対応してる拡張ライブラリはどう振る舞えばいいの
さっき言ったようにライトバリアを実装する
で、インデクスなら大丈夫ってはなしか
くらいで済まないかなあ。
汚染されたオブジェクトから参照されるオブジェクトも一気に汚染させることになる
あとグローバルに参照できるオブジェクトも
たぶんほとんど汚染
ポインタのママだと入れたVALUEの先が別の場所に行ったらダメに
VALUE をインデックスにしたら、全体的に遅くなると思うのだけど、どのくらい遅くなるのか気になる
インデックスにしなくてもいいと思うよ
移動させなければいい。性能向上の量は減るけど
でも RObject にポインタ 1 つか 2 つもたせないとダメだったかも
移動させる前提でどうしたらいいかって言う話だったので(わたしは)
移動させたいか
いや、わたしは関わりたくない
とかいってしまう
ぼくも関わりたくない
Ruby おわた
現実論で言えば移動しないのが妥当なのはまぁわかりきってて、
もとい nari さんのそうけんにかかっている
ぼくも移動させるもんだと思ってた
そうすると比較的夢のない泥臭い話になるので、ますます関わりたくない
がらっと変わるなら興味がないわけでもない、とかそういう感じ
slap で実験しよう
GC なんて元々泥臭いと思う
agree
遅いと文句は言われるが速いと褒められることは滅多に無い
関わる人の気がしれない (ぉ
作ったオブジェクトが例えばRARRY_PTR(hoge)[n]とかに入ったかどうかが分からないと、どうしても速くなるきがしない
だから hoge が変更されたことを知ったら
hoge を変更したことと GC に通知したら
preludeフェーズが終わったところで一度GCかけて、そこで生き残ったやつらはずっとmarkしっぱなしとかにするとか
GChoge の先をチェックしなおしてくれる
古い世代のオブジェクトから参照される新しい世代のオブジェクトは強制的に古い世代になったりする
ていうか、RubyのVALUEの先ってサイズ決まってるんだから、
コンパクションは必要ない (完
RVALUEといえ
いやいや
スロットが回収できるのとできないのの大きな違いはある
Ruby では heap というんだっけ
コンパクションするなら VALUE はインデックスになるね
何か手はないかねえ
たしかに
JNIだとどうしてんだっけ
でも、インデックスにするにしても、コンパクションのアルゴリズムは難しいだろうなぁ
コピー GC ならコピーするだけだから原理的には単純だよ
実際の実装がどのくらい難しいかはしらん
Javaのオブジェクトをそのまま見れるわけじゃない、まぁそうだな
コピーしてアドレスが変わったところ全部書き換えないと行けないんじゃない?
って前提読めてなかった
つめるだけ?いや、インデックス詰めないと行けないような
GC本読もう
インデクスとかどう実装するんだろう
hash みたいになるんかな
だとおもった
スーパー遅そうだな
僕のイメージでは、固定サイズスロット内のインデックスを持たせて、コンパクションするときは同じインデックスで空いている場所に移動する事を考えていた
それだとフラグメンテーション解決しなさそうだから
コピー GC する意味が減りそうだが
そう、フラグメンテーションの解決がとても難しそう
どのくらい減るかはしらない
実際に作って評価しまくるしかないね
いよいよやりたくない。
給料出るならやる
300 円払うから 3 日でたのむ
><
711のがたかい
時給1000円として、
3日で72時間か
1 時間でたのむ
この店で一番いいGCをたのむ
tweet いじってたらわけわからない @nari3 次第になった
複数またぐtweetはしたら負けだと思ってる
うん。負けた
http://www.fireproject.jp/feature/jni/class-object/reference.html
JVMはネイティブコードに渡した参照に関する情報をテーブルに保持する.これにより,JVMは「ネイティブコードでこの参照が使用されているからGCのときに注意しなければならない(削除や移動をしてはいけない)」ことがわかる」
めんどくせぇ
そういうことは可能なのだな
まあでも、コア部分だけでも十分
VALUE が変わりうるなんてのには耐えられないと思う
我々が。
でも変わるのってGCまたいだとこだけだから
どこだっけ
VALUE str=rb_str_new(); VALUE ary=rb_ary_new() /* ここでGC! */; rb_p(str) //=> SEGV
しねる
Java のコアはどうやって書かれてるんだ?
コアってJVM?らいぶらり?
JVM
C++っていってたような
上のような現象が発生するとしたらまともにプログラム書けなさそう
だから Java はほとんど Java でかいてる面もあるのかな
なのかなぁ
strはテーブル登録されてて動かせずにSEGVしないんじゃね?
いつテーブル登録解除されるんだろう
だとすると、ほぼ全てテーブル登録されてる気がする
外に抜けたら?
大変ですなあ
returnしたら解除されるが
RubyはOb(ry
return したら、とか C++ でできるだろうか
解除する関数を明示的に呼ぶんじゃなかろうか
そして解除漏れ
解除漏れしても死にはしないかな
事実上のメモリリークだよな
呼ぶ側が、テーブル作成、呼び出し、削除 をやっていると思われる。
外部ライブラリを呼ぶ部分はね
さっきの str はコア内部の話
内部でも同様にするのかな
vm_call_hogeあたりが
内部はどうするんだろなぁ?
ただ、スタックに乗ってるVALUEかどうかわかるきがするけど
まぁそうか
http://d.hatena.ne.jp/spider-man/20080309/p1
とりあえずString#equalsはJavaでかかれているようだ
http://blog.goo.ne.jp/muraokasemi/e/bdd3472b362941971ce13f6cd1eab3f7
ふむ
頭がふっと―してきた
Java は相当なところまで Java で書かれてるよね
安易に「C 化して高速化」なんて考えなくなるのでいい選択と言えるかもしれない
結論: やっぱり時代はJRuby
Java ってどうなるんだろう
一応ちゃんと投資するんじゃないですかねぇ、さすがに
まぁ、しかし、コピーGCやコンパクションは拡張ライブラリ以前に、
俺らが死ぬという知見を得た
結論: Ruby に未来はない
IronRubyがやってくれる・・・!
IronRubyJRuby 以上に終わってなかったっけ
一応開発続いてるよ
別に JRuby は終わってないが
少なくとも数日に1通ペースくらいでメールも流れているようだ

YARVの高速化

YARVバイトコードをもっとアグレッシブに最適化させたいなぁ
既に用意されている最適化オプションを動くようにメンテするとこから
なにが効いて何が効いてないんだろ
see vm_opts.h
末尾呼び出し最適化が0だ
まぁ、半分ジョークですしおすし
末尾 Proc#call も最適化したいですね
とりあえず、実行したいプログラムによって特化命令を変えて、
専用のYARVで動かすといいんじゃないですかね!
末尾最適化は set_trace_func とかあるからダメ
opt_helloからはじめよう
opt_eular_1から
それだ!
set_trace_funcがあるとなぜダメなのか
常にCとほぼ同速度でる
def foo; set_trace_func; end
としたときに foo の return を取れない
trace 呼び出しがはさまるから末尾にならない
あとバックトレースも読みにくくなるよ
Scheme のバックトレースはいつも読めない
まぁ、そこは、C で omit-frame-pointer するのと一緒ですし
そのときは-O0で
最適化部分にバグがあって泣く
それはよくあること
それなら Ruby 的にはデフォルト -O0 だろう
Rails なら容赦なく -O6 くらいで動かそうとして沢山バグレポート出してくれそうだ
そういえばlink time optimizationでぶっこわれてたな
-O6がどの辺りか分からないけど、動作保証しなければリリースには問題ないw
Rails って RubyVM::InstructionSequence.compile_option= とかいじってる?
さすがにそこは・・・どうだろう
さすがにやってないでしょうね
容赦ある
本当にやってないかしらんけど
そもそもいじって効果があるんかしらん
OPT_INSTRUCTIONS_UNIFICATION とかはやくなるようなうごかないような
Railsで作られるバイトコードで統計とって、
特か命令やoperands/insns unificationを整備すればだいぶ
Railsじゃなくてeularでやれと、そうですね

観察日記 2011-07-12

僕らの自称

僕らの自称はC Rubyなの?
CRuby じゃないっけ
純粋な疑問
JRuby とかと対比させるときは CRuby ということが多いかも
件のmatzはCRubyって言ってなかったっけ
CRubyはまあそうかなー的な
というかまあ、自称はRUBY_ENGINEに入ってるんですけど
混乱を避けられる名前ではないな。
ruby じゃなかったっけ >engine
です。
僕はよそに行くとMRIと言ってるんだけど。
まつもとさんも最近はMRIって言うようになったのかな
MRIYARVに対してMRIの場合とYARVを含んでMRIの場合とない?
そういえばそんなのも
ああ
たいていは文脈で判断可能だろうとは思う
狭義のMRI
CRubyとか言ってると、そのうちRiteを含むことになりそうなのがこう
RiteもMatzRubyImplementationなんじゃあるまいか
わはは
たしかにそうだな。
Rubyに対してrubyRHGが提唱元?
This method is not expected to work except "ruby".
くくっちゃえばなんか意味があるぽい。