こしごぇ(B)

旧:http://d.hatena.ne.jp/koshigoeb/

「プログラマのための文字コード技術入門」で勉強中(2)

プログラマのための文字コード技術入門 (WEB+DB PRESS plus) (WEB+DB PRESS plusシリーズ)

プログラマのための文字コード技術入門 (WEB+DB PRESS plus) (WEB+DB PRESS plusシリーズ)

  • ASCII
  • ISO/IEC 646 国際基準版
  • JIS X 0201
    • 0x5C, 0x7E
  • JIS X 0208
    • 0x21 - 0x7E
    • 区点番号(区番号、点番号)
    • 長音1-28
    • 第一水準、第二水準
    • 83JIS, 字体の変更、符号位置の入れ替え
    • 97JIS, 包摂規準
    • 符号化方式: Shift_JIS, ISO-2022-JP, 国際基準版・漢字用8ビット符号
    • 外字・機種依存文字、環境依存文字
  • JIS X 2012
  • JIS X 2013
    • 第三水準、第四水準
    • JIS2000, JIS2004
    • JIS X 0208を包含するスーパーセット
    • 漢字集合1面、漢字集合2面
    • 符号化方式: Shift_JIS-2004, ISO-2022-JP-2004, EUC-JIS-2004, 国際基準版・漢字用8ビット符号
  • ISO/IEC 8859
    • Latin-1, ISO/IEC 8859-1
    • ノーブレークスペース(NBSP), ソフトハイフン(SHY)
    • Latin-2, ISO/IEC 8859-2
  • Unicode, ISO/IEC 10646(UCS)
    • JIS X 0221
    • UCS-4, UCS-2, BMP(Basic Multilingual Plane)
    • 結合文字、基底文字
    • 一意な文字名
    • 往復変換
    • 漢字統合, CJK漢字統合, 原規格分離規則, 互換漢字

「プログラマのための文字コード技術入門」で勉強中(1)

いわゆる「文字コード」について余りにも無知なので、今更ではあるけれどちゃんと勉強しておこうと思い「プログラマのための文字コード技術入門」で入門してみた。

プログラマのための文字コード技術入門 (WEB+DB PRESS plus) (WEB+DB PRESS plusシリーズ)

プログラマのための文字コード技術入門 (WEB+DB PRESS plus) (WEB+DB PRESS plusシリーズ)

JavaScriptにも対応したボットをRubyで書く

CapybaraとPoltergeistとPhantomJSを使えば、割と簡単にできそうな感じがする。

簡単なJavaScriptを実行した結果のHTMLに対して操作できるという所までは確認してますが、これが非同期処理などの複雑なJavaScriptに対してどこまでやりきれるかは未確認です。
また、Rubyで書けるのは良いのですが、実際の処理をPhantomJSが実行するため、Mechanizeを使った場合のようにWebMockなどを使ってテストを簡単に書けるわけではなさそうな所も不安です。

一方、Ghost DriverというPhantomJSをWebDriver APIに対応させるプロジェクトもありますが、PhantomJSのブランチを使う必要があるとかなんだとかで手を出していません。PhantomJSに取り込まれるという噂もあったりなかったり。

電話番号を電気通信番号指定状況に従って分割してみる

総務省のサイトにある「電気通信番号指定状況」のページを参考に。

既に誰かが書いている気がしますが、いまいちよく分からずに息抜きがてら自分で書いてみたのが以下。

上記を書く前に書いたのが以下。

重い腰を上げてテストにかかる時間の短縮を試みる

とあるプロジェクトの通しテストについて、MRIとREEで設定を変えて時間を計ってみた。
その後、parallel_tests を試してみた。

.rbenv-vars

RUBY_HEAP_MIN_SLOTS=1000000
RUBY_HEAP_SLOTS_INCREMENT=1000000
RUBY_HEAP_SLOTS_GROWTH_FACTOR=1
RUBY_GC_MALLOC_LIMIT=600000000
RUBY_HEAP_FREE_MIN=2000000

ruby-1.8.7-p174

速度 0.97 倍。

  • before: 798.858277
  • after: 819.793473

ree-1.8.7-2009.09

速度 1.15 倍。

  • before: 739.677229
  • after: 642.832992

対MRIでみると、前1.08倍、後1.28倍。

parallel_tests

  • 並列2: 397.472827
  • 並列4: 343.886055

MRIデフォルトから比べると、並列2で2.00倍, 並列4で2.32倍(ivy i7 2GHz 2コア)。

ただし、並列実行を想定しないテストがあっていくつか失敗してる。

New Relic がどうやってメトリクスを集めているのか気になったのでちょっと調べてみた

Passenger の場合について簡単に調査。

PhusionPassenger.on_event(:starting_worker_process) で、NewRelic::Agent.after_fork を実行している。
NewRelic::Agent.after_fork は、Thread.new してワーカースレッドを作っている。

という事で、Passenger のワーカーインスタンスが作った Thread に NewRelic サーバへのリクエストを任せているという理解で良い気がする。

以下メモ。

newrelic_rpm-3.4.1/lib/new_relic/agent/agent.rb

  • NewRelic::Agent::Agent#start
    • -> NewRelic::Agent::Agent#check_config_and_start_agent
      • -> NewRelic::Agent::Agent#start_worker_thread
        • -> Thread.new
          • -> NewRelic::Agent::Agent#deferred_work!
  • -> NewRelic::Agent::Agent#after_fork
    • -> NewRelic::Agent::Agent#start_worker_thread
      • -> Thread.new
        • -> NewRelic::Agent::Agent#deferred_work!

newrelic_rpm-3.4.1/lib/new_relic/agent/instrumentation/passenger_instrumentation.rb

DependencyDetection.defer do
  @name = :passenger
  
  depends_on do
    defined?(PhusionPassenger)
  end

  executes do
    NewRelic::Agent.logger.debug "Installing Passenger event hooks."

    PhusionPassenger.on_event(:stopping_worker_process) do
      NewRelic::Agent.logger.debug "Passenger stopping this process, shutdown the agent."
      NewRelic::Agent.instance.shutdown
    end

    PhusionPassenger.on_event(:starting_worker_process) do |forked|
      # We want to reset the stats from the stats engine in case any carried
      # over into the spawned process.  Don't clear them in case any were
      # cached.  We do this even in conservative spawning.
      NewRelic::Agent.after_fork(:force_reconnect => true)
    end
  end
end

newrelic_rpm-3.4.1/vendor/gems/dependency_detection-0.0.1.build/lib/dependency_detection.rb

module DependencyDetection

  module_function
  @@items = []
  def defer(&block)
    item = Dependent.new
    item.instance_eval(&block)
    @@items << item
  end

  def detect!
    @@items.each do |item|
      if item.dependencies_satisfied?
        item.execute
      end
    end
  end
...

newrelic_rpm-3.4.1/lib/new_relic/control/frameworks/rails.rb

  • NewRelic::Control::Frameworks::Rails#init_config
    • -> rails_config.after_initialize
      • -> DependencyDetection.detect!

newrelic_rpm-3.4.1/lib/new_relic/control/instrumentation.rb

  • NewRelic::Agent#add_instrumentation
    • -> NewRelic::Control::Instrumentation#add_instrumentation
      • -> NewRelic::Control::Instrumentation#load_instrumentation_files
  • NewRelic::Control#init_plugin
    • -> install_instrumentation
    • -> NewRelic::Control::Instrumentation#install_instrumentation
      • -> NewRelic::Control::Instrumentation#_install_instrumentation
        • -> NewRelic::Control::Instrumentation#load_instrumentation_files

Homebrew の patches で圧縮ファイルを指定する場合

patch の流れはざっくりと以下の様な感じ。

  • curl で %03d-homebrew.diff という名前で保存する
  • 圧縮されているか判別して適切な拡張子を付け足す(mv する)
  • 圧縮されている場合は展開する
  • %03d-homebrew.diff という名前のファイルを patch する

圧縮ファイルを展開する際にファイル名を指定しないため、圧縮ファイルの名前に書き換わる場合がある。

上記のパッチを使おうとすると、gunzip で展開されたファイルの名前がオリジナルの libiconv-1.13-ja-1.patch になってしまう。

というところまで分かった。

追記

-n でオリジナルの名前を使わない様にしたらよいのかな?