leveldb icon indicating copy to clipboard operation
leveldb copied to clipboard

Memory leak on basic operations

Open dinedal opened this issue 12 years ago • 3 comments

require 'leveldb'

db = LevelDB::DB.new("/tmp/leaktest")

GC.start
puts GC.stat

10000.times do
  db.get('foo')
  GC.start
end


puts GC.stat

Sample output:

{:count=>7, :heap_used=>897, :heap_length=>4422, :heap_increment=>1964, :heap_live_num=>28158, :heap_free_num=>336751, :heap_final_num=>0, :total_allocated_object=>207656, :total_freed_object=>179498}
{:count=>10007, :heap_used=>620, :heap_length=>4422, :heap_increment=>1964, :heap_live_num=>28165, :heap_free_num=>224051, :heap_final_num=>0, :total_allocated_object=>367680, :total_freed_object=>339515}

Just for db.get on a nonexistant key 10,000 times, looks like there were 160024 allocated objects that can not get freed

dinedal avatar Sep 17 '13 23:09 dinedal

Can you confirm that with the latest release are we all good?

DAddYE avatar Sep 20 '13 23:09 DAddYE

I'm still seeing a leak. Is there a pointer that isn't being free'd?

atomical avatar Nov 07 '13 16:11 atomical

This GC test is incorrect. The total_freed_object count increases proportional to the total_allocated_object count indicating that allocated objects are being collected.

Also keep in mind that GC.start will not execute a full mark and sweep unless you run GC.start(full_mark: true, immediate_sweep: true).

If you use ObjectSpace.count_objects you can see proper garbage collection. Going further you can dump all objects using ObjectSpace.dump_all(output: open('heap.json', 'w')) and you will see only a handle full of differences.

#!/usr/bin/env ruby

require 'leveldb'
require 'objspace'

db = LevelDB::DB.new("/tmp/leaktest")

GC.start(full_mark: true, immediate_sweep: true)
puts ObjectSpace.count_objects
# {
#     :TOTAL=>92121,
#     :FREE=>44550,
#     :T_OBJECT=>4539,
#     :T_CLASS=>1549,
#     :T_MODULE=>88,
#     :T_FLOAT=>6,
#     :T_STRING=>25147,
#     :T_REGEXP=>342,
#     :T_ARRAY=>8794,
#     :T_HASH=>387,
#     :T_STRUCT=>34,
#     :T_BIGNUM=>2,
#     :T_FILE=>3,
#     :T_DATA=>4074,
#     :T_MATCH=>1,
#     :T_COMPLEX=>1,
#     :T_RATIONAL=>1,
#     :T_NODE=>2469,
#     :T_ICLASS=>134
# }

100000.times do
  db.get('foo')
end

GC.start(full_mark: true, immediate_sweep: true)
puts ObjectSpace.count_objects
# {
#     :TOTAL=>92121,
#     :FREE=>44528,
#     :T_OBJECT=>4539,
#     :T_CLASS=>1549,
#     :T_MODULE=>88,
#     :T_FLOAT=>6,
#     :T_STRING=>25171,
#     :T_REGEXP=>341,
#     :T_ARRAY=>8793,
#     :T_HASH=>389,
#     :T_STRUCT=>34,
#     :T_BIGNUM=>2,
#     :T_FILE=>3,
#     :T_DATA=>4074,
#     :T_MATCH=>1,
#     :T_COMPLEX=>1,
#     :T_RATIONAL=>1,
#     :T_NODE=>2467,
#     :T_ICLASS=>134
# }

abargnesi avatar Jul 18 '14 13:07 abargnesi