今年行った場所。
日本以外は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#+@ とか入れたから、なんとかならないかな。ならなそうだな。