Ruby19 osdc-090418222718-phpapp02
-
Upload
apoorvi-kapoor -
Category
Technology
-
view
520 -
download
1
Transcript of Ruby19 osdc-090418222718-phpapp02
我是誰?• 張文鈿 a.k.a. ihower
• http://ihower.idv.tw/blog/
• http://twitter.com/ihower
• 從 2006 年開始使用 Ruby
• 和多(股)公司 Rails Developer
• http://handlino.com
• http://registrano.com
2009年4月19日星期日
Agenda
• Overview
• What’s changed?
• What’s New? (External Interater, M17N, The Threading Model)
• Ruby 1.9 on Rails
2009年4月19日星期日
Ruby 1.8.6廣為使用的版本
• Ruby 1.8.6, release at 2007/3/12
• Stable
• Performance sucks
• Memory leaks
• NewRelic Report 69.4% 使用率http://railslab.newrelic.com/2009/04/01/the-state-of-the-stack-a-ruby-on-rails-benchmarking-report
2009年4月19日星期日
Ruby 1.8.7敬而遠之的版本
• Ruby 1.8.7 release at 2008/5/31
• 移植了部份 1.9 的功能
• gems, library 相容性變差 (與1.8.6不完全相容)
• JRuby 跳過 1.8.7 不實做
• NewRelic Report 14.5% 使用率
2009年4月19日星期日
Ruby 1.9尚待推廣的版本
• Ruby 1.9.0 release development version in 2007/12/25
• Ruby 1.9.1 release stable/production version in 2009/1/30
• Better performance
• Better encoding support
2009年4月19日星期日
Ruby Implementations能上 production 的
• Ruby 1.8.6, 1.8.7 (MRI, Matz’ Ruby Interpreter)
• EngineYard 將接手維護 1.8.6,預計將帶入 MBARI 的 GC patch
• Ruby 1.9.1 (YARV)
• JRuby
• 相容 Ruby1.8.6 語法,最新版涵蓋 1.9 功能。
• Ruby Enterprise Edition(REE)
• 衍生自 Ruby 1.8.6,但是大修 GC,改善 memory leak 問題
http://www.infoq.com/news/2009/01/ruby-patches-fix-leaks
2009年4月19日星期日
Ruby Implementations還不能上 production 的
• MacRuby (based on Objective-C)
• Rubinius (Engine yard project)
• MagLev (based on smalltalk)
• IronRuby (based on Microsoft .NET)
• Cardinal (based on Parrot VM)
2009年4月19日星期日
Performance (平均比 1.8 快 2~2.5 倍)
http://antoniocangiano.com/category/ruby-benchmark-suite/http://github.com/acangiano/ruby-benchmark-suite/
2009年4月19日星期日
Ubuntu : Intel® Q6600® quad-coreComputer Language Benchmarks Game
http://shootout.alioth.debian.org/
2009年4月19日星期日
Ordered Hash會照順序排
{:a=>1, :d=>4, :b=>2, :c=>3}1.8
1.9
{ :a => 1, :b=> 2, :c => 3 }.merge( :d => 4 )
{:a=>1, :b=>2, :c=>3, :d=>4}
2009年4月19日星期日
new Hash literal新的雜湊語法
config = { :foo => 1234, :bar => 6789 }
config = { foo: 1234, bar: 6789 }
1.8,1.9
1.9
Person.find(:all, :conditions => { :name => 'ihower' } )
Person.find(:all, :conditions => { name: 'ihower' } )
2009年4月19日星期日
Hash syntax不允許用逗號取代 =>
1.8 {1,2,3,4}=> {1=>2, 3=>4}
{1,2,3,4}=> syntax error, unexpected ',', expecting tASSOC1.9
2009年4月19日星期日
Hash#selecthash = { :a => 1, :b => 2, :c => 3 }hash.select{ |k, v| v > 1 }
[[:b, 2], [:c, 3]]
{:b=>2, :c=>3}
1.8
1.9
2009年4月19日星期日
Array#to_s, Hash#to_s
[1,2,3,4].to_s => "1234" {1=>2,3=>4}.to_s => "1234"
[1,2,3,4].to_s => "[1, 2, 3, 4]" {1=>2,3=>4}.to_s => "{1=>2, 3=>4}"
1.91.8
2009年4月19日星期日
case syntax移除冒號用法
name = case when x == 1 : "one" when x == 2 : "two" else "many" end
name = case when x == 1 then "one" when x == 2 then "two" else "many" end
name = case when x == 1 "one" when x == 2 "two" else "many" end
1.8 1.8,1.9
1.8,1.9
2009年4月19日星期日
block’s parameter always local區塊參數必是 local 變數
x = "foo"y = "bar"
[1,2,3].each do |x| y=x+1end
1.9[x,y] => [3, 4] [x,y] => ["foo", 4]1.8
2009年4月19日星期日
block’s parameter always local區塊參數必是 local 變數
x = "foo"y = "bar"
[1,2,3].each do |x| y=x+1end
1.9[x,y] => [3, 4] [x,y] => ["foo", 4]1.8
造成必須小心命名避免蓋掉外面的變數
2009年4月19日星期日
block-local variable明確宣告區塊內的變數是 local
bar = "ihower"
[1,2,3].each do |val| foo = val bar = val end
foo # NameError: undefined local variable or method `foo’bar => 3
bar = "ihower"
[1,2,3].each do |val; bar| bar = valend
bar => "ihower"
1.91.8,1.9
2009年4月19日星期日
block-local variable明確宣告區塊內的變數是 local
bar = "ihower"
[1,2,3].each do |val| foo = val bar = val end
foo # NameError: undefined local variable or method `foo’bar => 3
bar = "ihower"
[1,2,3].each do |val; bar| bar = valend
bar => "ihower"
1.91.8,1.9
可避免 bar 變數被蓋掉
2009年4月19日星期日
block can accept block argrments區塊參數列亦可使用區塊變數
proc1 = lambda do |a, *b, &block| p a p b p c block.callend
proc1.call(1,2,3,4) { puts "in block1" }
# 輸出1[2,3,4]"in block1"
2009年4月19日星期日
new lambda literal新的 lambda 語法
->(a) { a*3 }.(4)# => 12
lambda { |a| a*3 }.call(4)# => 12
lambda { |a| a*3 }[4]# => 12
1.8,1.9
1.8,1.9
1.9
2009年4月19日星期日
def my_if(condition, then_clause, else_clause) if condition then_clause.call else else_clause.call endend
5.times do |val| my_if (val < 3), -> { puts "#{val} is small" }, -> { puts "#{val} is big" }end
# 輸出0 is small1 is small2 is small3 is big4 is big
2009年4月19日星期日
def my_while(cond, &body) while cond.call body.call endend
a = 0my_while -> { a < 3 } do puts a a += 1end
# 輸出012
2009年4月19日星期日
BasicObject新的繼承體系 root
Class.superclass.superclass.superclass => nil
Class.superclass.superclass.superclass => BasicObjectBasicObject.superclass => nil1.9
Class.superclass.superclass => Object
BasicObject.instance_methods=> [:==, :equal?, :!, :!=, :instance_eval, :instance_exec, :__send__]
1.8
1.8,1.9
可用在 metaprogramming 時的 blank canvas
2009年4月19日星期日
standard library changes• + Rubygems
• no longer needed require ‘rubygems’
• + Rake
• no longer gem install rake
• ~ Test::Unit replaced by MiniTest
• - soap, jcode...etc, some rarely used, old libraries
2009年4月19日星期日
Iterators建立外部迭代子 to_enum
arr = [ 1, 2, "ihower" ]enum_a = arr.to_enum # 建立 Enumerators 物件 (預設用each)
enum_a.next # => 1enum_a.next # => 2enum_a.next # => "ihower"
ExternalInternalarr = [ 1, 2, "ihower" ]arr.each do |a| puts a end
# => 1# => 2# => "ihower"
1.91.8,1.9
2009年4月19日星期日
Enumerators更多範例
h = { foo: "567", bar: "890" }enum_h = h.to_enumenum_h.next # => [:foo, "567"]enum_h.next # => [:bar, "890"]
arr = [ 1, 2, "ihower" ]enum_a = arr.to_enum(:each_with_index)
enum_a.next # => [1, 0]enum_a.next # => [2, 1]enum_a.next # => ["ihower", 2]
1.9 1.9
2009年4月19日星期日
StopIteration exception同時迭代數個物件
short_enum = [1, 2, 3].to_enumlong_enum = ('a'..'z').to_enum
loop do puts "#{short_enum.next} #{long_enum.next}"end
# => 1-a# => 2-b# => 3-c
1.9
2009年4月19日星期日
StopIteration exception同時迭代數個物件
short_enum = [1, 2, 3].to_enumlong_enum = ('a'..'z').to_enum
loop do puts "#{short_enum.next} #{long_enum.next}"end
# => 1-a# => 2-b# => 3-c
用完時丟出 StopIteration 例外
1.9
2009年4月19日星期日
Enumerator from iterator亦可從 iterator method 建立
arr = [ 1, 2, "ihower" ]enum_a = arr.each # 使用迭代子函式來建立 Enumerator 物件
enum_a.next # => 1enum_a.next # => 2enum_a.next # => "ihower"
1.9
2009年4月19日星期日
Enumerators.new使用 code block 手動建立
seq = Enumerator.new do |yielder| n1 = 0 n2 = 1 loop do n3 = n1 + n2 yielder.yield n3 n1 = n2 n2 = n3 endend
seq.next # 1seq.next # 22.times { puts seq.next }# 3# 5
無窮迴圈
回傳值並在此暫停
1.9
2009年4月19日星期日
Enumerator objects are also enumerable
seq.first(10)# => [1, 2, 3, 5, 8, 13, 21, 34, 55, 89]
seq.to_a# Don’t do this if your Enumerator has infinite elements
1.9
2009年4月19日星期日
Ruby 1.8 Regexp有支援 UTF-8
• Support None (n or N), EUC (e or E), Shift_JIS (s or S), UTF-8 (u or U)
>> "中文".scan(/./u)=> ["中", "文"]
1.8,1.9
2009年4月19日星期日
Use Regexp to handle String使用 Regexp 拯救字串處理
>> "中文".scan(/./u).reverse.join=> "文中"
>> "中文".scan(/./u).size=> 2
1.8,1.9
2009年4月19日星期日
$KCODE = “U”or ruby -KU
• 變更 regular expressions 的 default encoding
• $KCODE = "U" 也可以讓 terminal 正確顯示
>> "中文"=> "\344\270\255\346\226\207">> $KCODE='u'>> "中文"=> "中文"
1.8
2009年4月19日星期日
Unicode codepoint另一種在 Ruby 1.8 拯救 UTF-8 字串的方式
>> "中文".unpack("U*")=> [20013, 25991]
>> "中文".unpack("U*").reverse.pack("U*")=> "文中"
>> "中文".unpack("U*").size=> 2
1.8,1.9
2009年4月19日星期日
Unicode codepoint(cont.)Rails ActiveSupport 使用這個技巧
>> "中文".chars # in Rails=> #<ActiveSupport::Multibyte::Chars:0x25aebbc @wrapped_string="中文">
>> "中文".chars.size => 2
1.8,1.9
2009年4月19日星期日
iconv library處理非 UTF-8 data
• C Library, it’s fast.
• convert your encoding to UTF-8
• handle it
• export back to your encoding
2009年4月19日星期日
jcode librarytoo simple, not useful
1.8 $KCODE = 'UTF8'require 'jcode'
str = "中文"str.size # 9str.jsize # 2
2009年4月19日星期日
No enough encodings supported in Ruby 1.8
• String 沒有 Encoding 機制
• Regexp 支援不夠全面
• 一直加 encoding 支援並不是辦法,總會用完 Regexp letter
• 也不能簡單解決其他問題,例如處理 #String.upcase、encoded data 是否 valid?
• $KCODE 是全域變數
• String, IO object, program source 可能都不同
2009年4月19日星期日
pick one encoding, likely Unicode, and works all data in one format? No.
Ruby 1.9 make it possible to work with data with 83 encoding.
2009年4月19日星期日
>> Encoding.name_list
=> ["ASCII-8BIT", "UTF-8", "US-ASCII", "Big5", "CP949", "Emacs-Mule", "EUC-JP", "EUC-KR", "EUC-TW", "GB18030", "GBK", "ISO-8859-1", "ISO-8859-2", "ISO-8859-3", "ISO-8859-4", "ISO-8859-5", "ISO-8859-6", "ISO-8859-7", "ISO-8859-8", "ISO-8859-9", "ISO-8859-10", "ISO-8859-11", "ISO-8859-13", "ISO-8859-14", "ISO-8859-15", "ISO-8859-16", "KOI8-R", "KOI8-U", "Shift_JIS", "UTF-16BE", "UTF-16LE", "UTF-32BE", "UTF-32LE", "Windows-1251", "BINARY", "IBM437", "CP437", "IBM737", "CP737", "IBM775", "CP775", "CP850", "IBM850", "IBM852", "CP852", "IBM855", "CP855", "IBM857", "CP857", "IBM860", "CP860", "IBM861", "CP861", "IBM862", "CP862", "IBM863", "CP863", "IBM864", "CP864", "IBM865", "CP865", "IBM866", "CP866", "IBM869", "CP869", "Windows-1258", "CP1258", "GB1988", "macCentEuro", "macCroatian", "macCyrillic", "macGreek", "macIceland", "macRoman", "macRomania", "macThai", "macTurkish", "macUkraine", "CP950", "stateless-ISO-2022-JP", "eucJP", "eucJP-ms", "euc-jp-ms", "CP51932", "eucKR", "eucTW", "GB2312", "EUC-CN", "eucCN", "GB12345", "CP936", "ISO-2022-JP", "ISO2022-JP", "ISO-2022-JP-2", "ISO2022-JP2", "ISO8859-1", "Windows-1252", "CP1252", "ISO8859-2", "Windows-1250", "CP1250", "ISO8859-3", "ISO8859-4", "ISO8859-5", "ISO8859-6", "Windows-1256", "CP1256", "ISO8859-7", "Windows-1253", "CP1253", "ISO8859-8", "Windows-1255", "CP1255", "ISO8859-9", "Windows-1254", "CP1254", "ISO8859-10", "ISO8859-11", "TIS-620", "Windows-874", "CP874", "ISO8859-13", "Windows-1257", "CP1257", "ISO8859-14", "ISO8859-15", "ISO8859-16", "CP878", "SJIS", "Windows-31J", "CP932", "csWindows31J", "MacJapanese", "MacJapan", "ASCII", "ANSI_X3.4-1968", "646", "UTF-7", "CP65000", "CP65001", "UTF8-MAC", "UTF-8-MAC", "UCS-2BE", "UCS-4BE", "UCS-4LE", "CP1251", "locale", "external", "internal"]
2009年4月19日星期日
All String are Encoded• In Ruby 1.9 a String is a collection of
encoded characters.除了 raw bytes,還包括 Encoding 資訊。
>> "中文".encoding.name=> "UTF-8"1.9
Encoding object
2009年4月19日星期日
String works in characters
>> "中文".reverse=> "文中"
>> "中文".size=> 2
>> "中文".bytesize=> 6
1.9
2009年4月19日星期日
String Indexing
>> "abc"[0]=> 97
>> "中文"[1]=> 184
>> "abc"[0]=> "a"
>> "中文"[1]=> "文"
1.91.8
>> "abc"[0].ord=> 97
2009年4月19日星期日
Transcoding改變編碼
utf8 = "測試"utf8.bytesize # 6utf8.bytes.to_a # [230, 184, 172, 232, 169, 166]
big5 = utf8.encode("big5")
big5.encoding.name # ”Big5”big5.bytesize # 4big5.bytes.to_a # [180, 250, 184, 213]
1.9
2009年4月19日星期日
Transcoding fails轉碼失敗
str = "Résumé"str.encode("big5")
=> Encoding::UndefinedConversionError: "\xC3\xA9" from UTF-8 to Big5 from (irb):2:in `encode' from (irb):2 from /usr/local/bin/irb19:12:in `<main>'
1.9
2009年4月19日星期日
Force Transcoding改變編碼,但不改 byte data
utf8 = "測試"
big5 = utf8.encode("big5")big5.valid_encoding?=> true
big5.force_encoding("utf-8")big5.valid_encoding?=> false
1.9
2009年4月19日星期日
Force Transcoding fails編碼不對無法進一步操作
big5.valid_encoding? # falsebig5 =~ /123456/
=> ArgumentError: invalid byte sequence in UTF-8 from (irb):11 from /usr/local/bin/irb19:12:in `<main>'
1.9
2009年4月19日星期日
Encoding.compatible?例如: ASCII with a bigger Encoding
ascii = "my ".force_encoding("ascii")utf8 = "Résumé"
# 檢查相容性Encoding.compatible?(ascii, utf8) #<Encoding:UTF-8>
# 相加my_resume = ascii + utf8puts my_resume # "My Résumé"puts my_resume.encoding.name # UTF-8
1.9
2009年4月19日星期日
Encoding.compatible?不相容不能加在一起
big5 = "測試".encode("big5")utf8 = "Résumé"
# 檢查相容性Encoding.compatible?(big5, utf8) # nil
# 相加big5 + utf8
=> Encoding::CompatibilityError: incompatible character encodings: Big5 and UTF-8 from (irb):25 from /usr/local/bin/irb19:12:in `<main>'
1.9
2009年4月19日星期日
String Iterationeach 被移除了
• Strings are no longer enumerable
• Ruby 1.8 each() has been removed
• Ruby 1.9 use explicit iterator
• each_line
• each_byte
• each_char
• each_codepoint
1.9
2009年4月19日星期日
program source encoding放在檔案開頭的 magic comment
# encoding: UTF-8或
#!/usr/bin/env ruby -w# encoding: UTF-8或
# coding: UTF-8或
# -*- coding: UTF-8 -*-
2009年4月19日星期日
program without magic comment如果沒有指定編碼
ruby foobar.rb # US-ASCII
ruby -e foobar.rb 或用 irb # 會看 OS 的語系設定 ($LC_CTYPE, $LANG)
ruby -KU foobar.rb # UTF-8,與 Ruby 1.8 相容的指令
2009年4月19日星期日
IO Object讀檔案
# encoding: utf-8f = File.open("big5.txt","r:big5")puts f.external_encoding # Big5puts f.gets.encoding # Big5
1.9 這是一個大五碼檔案
2009年4月19日星期日
IO Object讀檔案並自動轉碼
# encoding: utf-8f = File.open("big5.txt","r:big5:utf-8")puts f.external_encoding # Big5puts f.internal_encoding # UTF-8puts f.gets.encoding # UTF-8
1.9
2009年4月19日星期日
IO Object寫檔案
1.9# encoding: utf-8f = File.open("another_big5.txt", "w:big5")puts f.external_encoding # Big5data = "中文字"puts data.encoding.name # UTF-8f << data
2009年4月19日星期日
IO Object寫檔案
1.9# encoding: utf-8f = File.open("another_big5.txt", "w:big5")puts f.external_encoding # Big5data = "中文字"puts data.encoding.name # UTF-8f << data
寫入大五碼
2009年4月19日星期日
Regexp has encoding too
• Oniguruma enginehttp://www.geocities.jp/kosako3/oniguruma/
• Same basic API
• better performance
• support for a lot of encoding
• extended syntax
/\w/.encoding=> #<Encoding:US-ASCII>
/中文/.encoding=> #<Encoding:UTF-8>
1.9
2009年4月19日星期日
Default Encoding Overview
• String literal 按照 program source 編碼
• Symbols 和 Regexp 如果只有用到 7-bit,會是 US-ASCII,不然則按照 program source 編碼。
• IO 物件的 external_encoding 按照 OS 語系設定
• 或使用 ruby -E 指定編碼
• 或設定 Encoding.external_encoding
2009年4月19日星期日
f = Fiber.new { 2.times do puts "Fiber say hi" Fiber.yield # 將控制權轉回呼叫者 puts "Fiber say bye" end} # 不會立即執行
>> f.resume# 輸出 Fiber say hi>> f.resume# 輸出 Fiber say bye# 輸出 Fiber say hi>> f.resume# 輸出 Fiber say bye>> f.resume FiberError: dead fiber called from (irb):78:in `resume' from (irb):78 from /usr/local/bin/irb19:12:in `<main>'
1.9
2009年4月19日星期日
Fibers 用途• 實做 Enumerator 外部迭代子
• 擴充 fiber library 可以將控制權轉給別的 fiber object
• 取代難以實做的 continuation 機制(Ruby 1.8 的 continuation 從 kernel 移到 library)
• 日常生活應該用不到... zzz
2009年4月19日星期日
Native Threads
• Green threads所有 Ruby thread 共用一個 native thread
• Native (operation system) thread 每個 Ruby thread 配一個 native thread
1.9
1.8
2009年4月19日星期日
GILGiant Interpreter Lock
• 由於部份 C extension libraries 並不 thread safe,所以實作上同一時間只會有一個 Thread 在執行。(據說將來會解鎖,所以目前最好的 Ruby Threads 實做應該是 JRuby)
1.9
2009年4月19日星期日
Ruby 1.9 on Rails
• Rails 2.3.2 or edge
• mysql-ruby driver for Ruby 1.9
• Passenger(mod_rails) or Thin
2009年4月19日星期日
Upgrade issue哪裡會爆炸
• program source encoding problem
• invalid multibyte char 如果有中文在原始碼中,一定要加 # encoding: UTF-8
• encoding compatibility problem
• 資料庫撈出來的資料被認為是 ACSII-8BIT (binary),無法與 UTF-8 String 相加
• http://github.com/hectoregm/mysql-ruby (UTF-8 friendly)
• some gem, plugins are not Ruby 1.9 compatible
• http://isitruby19.com/
2009年4月19日星期日
Benchmark我的實驗
• Rails 2.3.2 production mode
• No DB, just render :text => 'hello'
• My MacBook Pro 2.2G
• httperf
2009年4月19日星期日
PerformanceReply rate [replies/s]
min avg max stddev
Ruby 1.8.6Mongrel
1.1.5
241.8 258.3 267.4 14.4
Ruby 1.8.6mod_rails
244.6 260.9 271.2 11.4
Ruby 1.9.1mod_rails
264.0 269.5 273.4 4.9
Ruby 1.8.6Thin 1.0.0
244.5 273.2 299.6 22.7
Ruby 1.9.1Thin 1.0.0
348.4 363.2 371.2 12.8
2009年4月19日星期日
PerformanceRuby 1.9 快兩倍,不表示 Rails Stack 也可以快兩倍!!
0
100
200
300
400
Reply rate [replies/s]
Ruby 1.8.6/Mongrel 1.1.5Ruby 1.8.6/mod_rails edgeRuby 1.9.1/mod_rails edgeRuby 1.8.6/Thin 1.0.0Ruby 1.9.1/Thin 1.0.0
2009年4月19日星期日
PerformanceRuby 1.9 快兩倍,不表示 Rails Stack 也可以快兩倍!!
0
100
200
300
400
Reply rate [replies/s]
Ruby 1.8.6/Mongrel 1.1.5Ruby 1.8.6/mod_rails edgeRuby 1.9.1/mod_rails edgeRuby 1.8.6/Thin 1.0.0Ruby 1.9.1/Thin 1.0.0
果然天底下沒這麼好的事
2009年4月19日星期日
Ruby challenge
• Ruby 1.9 change a lot and 1.8 is slow and should be deprecated.
• Migrate to Ruby 1.9 is the big challenge in 2009.
2009年4月19日星期日
Reference• Understanding M17n
http://blog.grayproductions.net/articles/understanding_m17n
• Books
• Programming Ruby 1.9 (Pragmatic)
• The Ruby Programming Language (O’Reilly)
• Ruby Best Practices (O’Reilly)
• The Well-Grounded Rubyist (Manning)
• Slide
• MigrationToRuby 1.9
• Ruby 1.9: What to Expect http://slideshow.rubyforge.org/ruby19.html
• Matz on Ruby 1.9
2009年4月19日星期日
Other reference links
• http://svn.ruby-lang.org/repos/ruby/tags/v1_9_1_0/NEWS
• http://blog.nuclearsquid.com/writings/ruby-1-9-what-s-new-what-s-changed
• http://blog.grayproductions.net/articles/getting_code_ready_for_ruby_19
• http://dablog.rubypal.com/2009/1/14/10-things-to-be-aware-of-in-moving-to-ruby-1-9
• http://dablog.rubypal.com/2009/1/16/son-of-10-things-to-be-aware-of-in-ruby-1-9
• http://blog.kineticweb.com/articles/2009/01/30/ruby-1-9-1-the-other-features
2009年4月19日星期日