Skip to content

Instantly share code, notes, and snippets.

@aphlysia
Last active December 28, 2015 22:49
Show Gist options
  • Save aphlysia/7574373 to your computer and use it in GitHub Desktop.
Save aphlysia/7574373 to your computer and use it in GitHub Desktop.
ruby で調べた事メモ

thread

queue に入れたデータを multithread で処理して結果を results へ入れる例

require 'thread'

queue = Queue.new
5.times {|i| queue.push i}

thread_n = 3 # つくられるスレッドの数
mutex = Mutex.new
results = {}
threads = []
thread_n.times do
  queue.push(nil)
  t = Thread.new do
    while x = queue.pop
      sleep(1)
      mutex.synchronize do
        results[x] = x * x
      end
    end
  end
  threads.push(t)
end

threads.each {|t| t.join}

puts results

ポイントは、

  • queuenil を入れておくことで、while を抜けるようにする
    • nil 入れずに queue が空になると thread は停止するので、join のところでコケる。その場合はまた別の待ち方が必要
    • whilequeue.pop のかわりに queue.empty? をしてしまうと、その後 pop するまでの間に別の thread が pop してしまう恐れがあるのでダメ
  • スレッドの外へ渡す共有データを操作する処理は、mutex.synchronize へブロックを渡して実行する
    • 同時に更新してしまうことを避けるため

なお、処理途中で queue に追加するような場合は上のコードだと途中で止まっちゃうのでダメ。

Net::SSH

ssh ごしに実行したコマンドの結果のとりかたについて

小さい場合は

x = ssh.exec(cmd)

というのでよいけど、x には全データが入るので、大きい場合にはメモリが一杯になる。

以下のようにすれば、適当な大きさごとに処理できる。

ssh.exec! "grep something /some/files" do |ch, stream, data|
  if stream == :stderr
    puts "ERROR: #{data}"
  else
    puts data
  end
end

ただし、data の区切りは適当 (行ごととは限らない & 1文字の区切りとは限らない)。なので、行ごととか文字ごと処理したなら自前でがんばらないといけない。という話

検証で "あ" をたくさん書いたファイルを cat してみた。なお、utf8 で "あ" は次のとおり e3 81 82 の3バイト。

> puts 'あ'.bytes.map{|x| x.to_s(16)}.join(' ')
e3 81 82
> ssh.exec!("cat /tmp/test.txt") {|ch, stream, data|
	puts '---begin---';
	puts data.bytesize;
	puts 'head: ' + data.bytes.map{|x| x.to_s(16)}[0..5].join(' ');
	puts 'tail: ' + data.bytes.map{|x| x.to_s(16)}[-5..-1].join(' ');
	puts 'valid_encoding?: ' + data.valid_encoding?.to_s;
	puts '---end---'
}
---begin---
16384
head: e3 81 82 e3 81 82
tail: 82 e3 81 82 e3
valid_encoding?: true
---end---
---begin---
16384
head: 81 82 e3 81 82 e3
tail: e3 81 82 e3 81
valid_encoding?: true
---end---
---begin---
16384
head: 82 e3 81 82 e3 81
tail: 81 82 e3 81 82
valid_encoding?: true
---end---
---begin---
9211
head: e3 81 82 e3 81 82
tail: 82 e3 81 82 a
valid_encoding?: true
---end---

というふうに、"あ" の途中で区切られて送られている。data は String のくせに!でも valid_encoding?true が返るのがはぜだろう??

stable sort

sort() and sort_by() are not stable. You can use stable sort as following code.

i = 0
list.sort_by {|x| [x, i += 1]}

http://docs.ruby-lang.org/ja/1.9.3/method/Enumerable/i/sort_by.html

debug

def debug
  yield
rescue => ex
  puts "---class---\n#{ex.class}\n---message---\n#{ex.message}\n---backtrace---\n#{ex.backtrace.join("\n")}\n----------"
end

debug {
  # テストしたいコード
}

的な。

ダミーの logger

logger = Object.new
def logger.info(*args); end
def logger.debug(*args); end
def logger.warn(*args); end
def logger.error(*args); end

ensure で return すると例外がもみ消されるのでやってはいけない!

def f
  begin
    raise 'hoge'
  ensure
  end
end
f() # => RuntimeError
def g
  begin
    raise 'hoge'
  ensure
    return
  end
end
g() # => nil
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment