今年行った場所。
日本以外は7カ国。そのほか、福岡に何度か。 そういえば、一度も松江に行っていない。 日本のいろんな都市に行ってみたいなぁ。
来年は、もうこんなには行けなさそう。 落ち着いて開発しよう。
Ruby 2.3.0 リリースできて何よりでした。
来年もよろしくお願いします。
RubyKaigi 2015 です、でした。
発表した内容について。
Koichi Sasada: Compiling Ruby scripts, RubyKaigi 2015, Tokyo, Japan (2015.12). 2015_RubyKaigi2015.pdf (1136KB), http://rubykaigi.org/2015/presentations/ko1
Ruby プログラムを、一度バイナリに落として、という感じです。 速度を強調したスライドになっていますが、ちょっと数字が出たのが速度であった、というのが本当のところで、実際はメモリ削減が主目的で始めました。というのも、ISeq 自体が結構メモリ食っていて、その上で fork すると大変な感じで増えるので、マルチプロセスではあまり食わないように、とか、そういうことを狙っていました。が、メモリ削減については、全くの手つかずです。というわけで、いい加減なところで終わっています。
とりあえず、こういうのがあったときに、どう使われるのかな、という動機で、2.3 で実験的に導入してもらいました。
メモリ削減については、
■(1) プロセス単体では、出来る箇所を read only でバイナリを参照するだけにする
■(2) n 個のマルチプロセスでは、バイナリを mmap で共有することで、消費メモリを 1/n にすることを目指す
ということが出来れば良いと思っていました。(1) はまったくやっておらず(全部読み込み、現状と同じようにコピーが走ります)、(2) は (1) をやっていないので意味が無い。実は、lazy によって、(2) の目が若干あったので、効くかなとやってみたのですが、殆ど効果がなかった。なぜ効果が無かったのか、まだよく見ていないのですが。
(1) については、抜本的にデータ構造を変更しないといけなくて、実は iseq まわりのデータ構造の変更は、それが理由です。理由ですが、十分に対応できなかった。
というわけで、誰かやりませかね。面白いと思うのですが。
コンパイル済みバイナリを、ファイルへストアするツールであり、require でコンパイル済みバイナリをロードするライブラリを、sample/iseq_load.rb として同梱しているのですが、いかんせん sample なので、使いづらい。
なので、gem として用意しました。yomikomu gemです。
インストールすると、kakidasu というコマンドラインツールと、yomikomu.rb というライブラリが導入されます。
$ kakidasu
とすることで、lib 以下のすべてのファイル(添付ライブラリはもとより、Gemでインストールされたものもすべて)をコンパイルします。
$ kakidasu [file or dir]
とすることで、指定もできます。
使う時は、require 'yomikomu' とした以降の require や load で読み込むライブラリで、可能ならコンパイル済みバイナリから読み込むようになります。
良かったら試してみて下さい。
このどさくさに紛れて、実はもうちょっと面白い機能も突っ込んでいるのですが、それは別に紹介します。
書いたので紹介します。ISeq.translate(iseq) というメソッドが定義されていると、iseq を途中で差し替えることができるようになりました。
require 'fiddle' require 'pp' class RubyVM::InstructionSequence address = Fiddle::Handle::DEFAULT['rb_iseq_load'] func = Fiddle::Function.new(address, [Fiddle::TYPE_VOIDP] * 3, Fiddle::TYPE_VOIDP) define_singleton_method(:load_from_array) do |data, parent = nil, opt = nil| func.call(Fiddle.dlwrap(data), parent, opt).to_value end def self.translate iseq ary = iseq.to_a ary[13].each{|insn| if Array === insn && insn[0] == :putstring insn[1] = "#{insn[1]}!!" end } load_from_array(ary) end end eval("puts 'Hello World'")
結果は...。
テスト用にとりあえず入れたのですが、実は JIT とかで差し替えたものを入れる、みたいな用途が考えられます。ほんとかな。
TRICK 2015 で Most inconsistent, Most timely awards を受賞しました。ありがとうございます。どちらも一発ネタで、すぐに書けたものでした。他の人達と比べて、全く難しくなくて、とにかく恐縮です。
4件送って、時間をとてもかけたのは、やはり技巧がまったく足りず、遠藤さんの本の単なるフォロアーだったという。
__________________ _ ____________________ _ ______________________ _ _______________________ _ _______________________ _ _______________________ _ ______________________ _ ____________________ _ __________________ _ _____________ _ ________ _ _______ _ ________ _ ____________ _ __________________ _ __________________________ _ ________________________________ _ __________________________________ _ ________________________________ _ __________________________ _ __________________ _ ________________ _ __________________ _ ________________________ _ ____________________________ _ _____________________________ _ ____________________________ _ ________________________ _ __________________ _ ________________ _ ______________ _ _____________ _ _____________ _ _____________ _ ______________ _ ________________ _ __________________ _ ____________________ _ __________________ _ ________________ _ _______________ _ ______________ _ ______________ _ ______________ _ _______________ _ ________________ _ __________________ _ ______________________ _ ________________________ _ _________________________ _ ________________________ _ ______________________ _ __________________ _ _________________ _ ________________ _ _______________ _ _______________ _ _______________ _ ________________ _ _________________ _ __________________ _ _____________________ _ _______________________ _ ________________________ _ _________________________ _ ________________________ _ _______________________ _ _____________________ _ __________________ _ _____________ _ ________ _ _______ _ ________ _ ____________ _ __________________ _ ____________________ _ _____________________ _ ______________________ _ ______________________ _ ______________________ _ _____________________ _ ____________________ _ __________________ _ _______________ _ ____________ _ ___________ _ ____________ _ ______________ _ __________________ _ _____________________ _ _______________________ _ ________________________ _ _______________________ _ _____________________ _ __________________ __ BEGIN{W=18;@w=[];def method_missing(m, w=$,)(w)?(if(c= (m.size)-W)==$. @w.empty?&& return x,y=( @w.max- 2),@w.size+ 1;@w=[];c=((y/ 2)*16+8+8+x).chr print(c.downcase) else;@w<<c.abs end):m;end}
単に実行するだけ。 これも時事ネタでした。
++++ --- +++++++ --- ++++++ --- +++ +++ +++++ --- ++++++++ --- ++++++++ --- +++ +++ ++ --- +++ --- +++ --- +++ +++ ++ -------- ++++++++ -------- +++++++ -------- ++++++++ ++ -------- ++++++++ -------- +++++++ -------- ++++++++ ++ --- +++ --- +++ --- +++ ++++++++ --- ++++++++ --- ++++++++ --- +++ ++++++++ --- +++++++ --- ++++++ --- +++ START!;BEGIN{eval(($p=%q(M,@p,S=4,0,"\x1f".succ;define_method(:method_ missing){|m,*_|(m==:+@)?(@p+=1):(m==:-@)?(@p*=12345):nil;self};END{nn= ->(n,c='+'){(0..7).map{|y|(0..7).inject(S*8){|r,x|(n[y*8+x]!=0)&&(r[x] =c);r}}.join("\n")};mm=->(m){m.each_line.map{|line|line.chomp.each_cha r.map{|c|['+','-'].include?(c)?c:nil}}};jj=->(ms){pl=Array.new(8){Arra y.new(ms.length*10){S}};ms.each.with_index{|m,i|(mm.(m)).each.with_ind ex{|line,y|li ne.each.with_ind ex{|e,x|e&&pl [y][x+10*i]=e}}} ;pl.map{|e|e. join.rstrip}.joi n("\n")};pp=- >(ms){puts(jj.(m s))};ee=->(ms){@p=0;eval(jj.(ms)+'_');@p};nm=->(ns){ns.map{|n|(Fixnum= ==n)?MS[n]:P}};ss=->(tp){M.times{|i|(0..9).to_a.repeated_permutation(1 +i){|ns|i.times.each{|j|ns.insert(j*2+1,:+)};(tp==ee.(nm.(ns)))&&(pp.( eval(ns.map(&:to_s).join).to_s.split(//).map{|s|MS[s.to_i]});exit)}}}; MS=[439548674 4551063324,18446 4890904953567 02,1837441380078 5903487,91512 79806051057534,1 6204198849393 715175,915128035 1497682815,9151288054521495358,2025524961147879294,9151288054536175422 ,9151280353659813694].map{|n|nn.(n)};P=nn.(4051050536969451576,'-');AR GV.empty??ss.(@p):((ARGV.size>M)&&raise('too_many');ms=ARGV.map{|n|MS[ n.to_i]||raise("too_big")};(ms.size-1).times{|i|ms.insert(i*2+1,P)};$B ='BEGIN';$E='START!';$e='eval';$s=('[').succ;pp.(ms);puts;puts(%Q{#$E; #$B{#$e(($p=%q(#$p);$p.gsub(/#{$s}s*/,'')))}}))});$p.gsub(/\s*/,'')))}
コードゴルフ力がなくて長すぎ。 電卓です。単に実行すると、1 + 2 + 3 + 4 の結果を返します。
$ ruby entry.rb 3 4 5
みたいな感じで、数字をくっつけると、その数字を計算するプログラムを出します。
次があれば頑張りたいですが、まったく他の作品に追いつける気がしない。
http://www.rubyinside.com/advent2006/5-negaposi.html から、+ と - に頑張って貰う何かがテーマなのですが、次があれば、また何か。String#+@ とか入れたから、なんとかならないかな。ならなそうだな。