1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74
|
#!/usr/bin/env ruby
#$: << File.expand_path('../../lib', __FILE__)
$DEBUG_TLV = true
require 'concurrent'
require 'concurrent/atomic/thread_local_var'
require 'benchmark'
require 'thread'
include Concurrent
# if we hold on to vars, but threads die, space used for TLVs should be recovered
def test_thread_gc(vars)
threads = 500.times.collect do
Thread.new do
vars.each do |var|
var.value = 1
end
end
end
threads.each(&:join)
end
puts "BEFORE THREAD GC TEST:"
puts "Ruby heap pages: #{GC.stat[:heap_length]}, Other malloc'd bytes: #{GC.stat[:malloc_increase]}"
vars = 500.times.collect { ThreadLocalVar.new(0) }
200.times do
test_thread_gc(vars)
GC.start
end
puts "AFTER THREAD GC TEST:"
puts "Ruby heap pages: #{GC.stat[:heap_length]}, Other malloc'd bytes: #{GC.stat[:malloc_increase]}"
# if we hold on to threads, but drop TLVs, space used should be reused by allocated TLVs
def tlv_gc_test_loop(queue)
while true
var = queue.pop
return if var.nil?
var.value = 1
end
end
def test_tlv_gc(queues)
500.times do
var = ThreadLocalVar.new(0)
queues.each { |q| q << var }
end
end
puts
puts "BEFORE TLV GC TEST:"
puts "Ruby heap pages: #{GC.stat[:heap_length]}, Other malloc'd bytes: #{GC.stat[:malloc_increase]}"
queues = 500.times.collect { Queue.new }
threads = queues.map do |queue|
Thread.new do
tlv_gc_test_loop(queue)
end
end
200.times do
test_tlv_gc(queues)
GC.start
end
queues.each { |q| q << nil }
threads.each(&:join)
puts "AFTER TLV GC TEST:"
puts "Ruby heap pages: #{GC.stat[:heap_length]}, Other malloc'd bytes: #{GC.stat[:malloc_increase]}"
|