MRI红宝石穿线和性能 [英] MRI ruby threading and performance

查看:102
本文介绍了MRI红宝石穿线和性能的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

关于SO的第一个问题,但是我已经潜伏了很长时间,所以如果我违反任何规则或发布垃圾问题,您将不得不原谅我.

My first question on SO, but I've lurked for a long time now so you'll have to forgive me if I've broken any rules or posted a rubbish question.

我试图更好地了解线程,因此决定测试MRI并查看其总体性能.

I'm trying to get a better understanding of threading and I decided to test MRI and see how it performs in general.

给出以下代码(和输出),为什么线程操作比非线程变量慢得多?

Given the following code (and output), why are the threaded operations so much slower than the non-threaded variant?

class Benchmarker
  def self.go
    puts '----------Benchmark Start----------'
    start_t = Time.now
    yield
    end_t = Time.now
    puts "Operation Took: #{end_t - start_t} seconds"
    puts '----------Benchmark End------------'
  end
end

# using mutex
puts 'Benchmark 1 (threaded, mutex):'
Benchmarker.go do
  array = []
  mutex = Mutex.new
  5000.times.map do
    Thread.new do
      mutex.synchronize do
        1000.times do
          array << nil
        end
      end
    end
  end.each(&:join)
  puts array.size
end

# using threads
puts 'Benchmark 2 (threaded, no mutex):'
Benchmarker.go do
  array = []
  5000.times.map do
    Thread.new do
      1000.times do
        array << nil
      end
    end
  end.each(&:join)
  puts array.size
end

# no threads
puts 'Benchmark 3 (no threads):'
Benchmarker.go do
  array = []
  5000.times.map do
    1000.times do
      array << nil
    end
  end
  puts array.size
end

输出

Benchmark 1 (threaded, mutex):
----------Benchmark Start----------
5000000
Operation Took: 3.373886 seconds
----------Benchmark End------------
Benchmark 2 (threaded, no mutex):
----------Benchmark Start----------
5000000
Operation Took: 5.040501 seconds
----------Benchmark End------------
Benchmark 3 (no threads):
----------Benchmark Start----------
5000000
Operation Took: 0.454665 seconds
----------Benchmark End------------

谢谢.

推荐答案

一旦您遇到大量线程(5000),调度程序在线程之间进行切换的开销就远远超过了每个线程实际完成的工作量做.通常,您最多需要30-50个线程.

Once you hit a high amount of threads (5000), the amount of overhead for switching between threads by the scheduler far outweighs the amount of work that each thread actually does. Typically you want 30-50 threads max.

尝试减少线程数量,并按比例增加每个线程的工作量:

Try lowering the amount of threads and proportionally increasing the amount of work that each does:

  20.times.map do
    Thread.new do
      250000.times do
        array << nil
      end
    end
  end.each(&:join)

,您应该会看到更可比的结果.

and you should see far more comparable results.

请注意,您可能会看到下限Time(threaded) >= Time(non-threaded)-即线程版本的时间不能低于单线程版本的时间.这是因为MRI的GIL一次只能执行一个线程(它们永远不能并行运行).一些红宝石实现(例如JRuby)允许并行执行线程.

Note you will probably see the lower bound Time(threaded) >= Time(non-threaded) - that is the Threaded version's time can't be lower than single-threaded version. This is because of the MRI's GIL which allows only one thread to execute at a time (they can never run in parallel). Some ruby implementations such as JRuby allow parallel execution of threads.

这篇关于MRI红宝石穿线和性能的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆