26. Statistics
>>ObjectSpace.statistics
Number of objects : 1631452 (1291302 AST nodes, 79.15%)
Heap slot size : 40
GC cycles so far : 32
Number of heaps : 9
Total size of objects : 63728.59 KB
Total size of heaps : 119579.81 KB (55851.22 KB = 46.71% unused)
Leading free slots : 1154340 (45091.41 KB = 37.71%)
Trailing free slots : 4 (0.16 KB = 0.00%)
Number of contiguous groups of 16 slots: 76771 (40.13%)
Number of terminal objects: 8973 (0.29%)
31. ObjectSpace.statistics
Number of objects : 1643029 (1265158 AST nodes, 77.00%)
Heap slot size : 40
GC cycles so far : 31
Number of heaps : 9
Total size of objects : 64180.82 KB
Total size of heaps : 119579.42 KB (55398.60 KB = 46.33% unused)
Leading free slots : 1093423 (42711.84 KB = 35.72%)
Trailing free slots : 0 (0.00 KB = 0.00%)
Number of contiguous groups of 16 slots: 73754 (38.55%)
Number of terminal objects: 7274 (0.24%)
33. New options
RUBY_HEAP_MIN_SLOTS = 1_800_000
RUBY_GC_MALLOC_LIMIT = 50_000_000
GC.time ~1 Second
GC.num_allocations 5_634_856
GC.collections 6
34. New options
RUBY_HEAP_MIN_SLOTS = 1_800_000
RUBY_GC_MALLOC_LIMIT = 50_000_000
Number of objects : 1682325 (1272351 AST nodes, 75.63%)
Heap slot size : 40
GC cycles so far :6
Number of heaps : 1
Total size of objects : 65715.82 KB
Total size of heaps : 70312.51 KB (4596.69 KB = 6.54% unused)
Leading free slots : 39246 (1533.05 KB = 2.18%)
Trailing free slots : 0 (0.00 KB = 0.00%)
Number of contiguous groups of 16 slots: 4305 (3.83%)
Number of terminal objects: 7435 (0.41%)
38. Enhanced options
RUBY_HEAP_MIN_SLOTS = 2_100_000
RUBY_GC_MALLOC_LIMIT = 100_000_000
Number of objects : 1816515 (1297270 AST nodes, 71.42%)
Heap slot size : 40
GC cycles so far :3
Number of heaps : 1
Total size of objects : 70957.62 KB
Total size of heaps : 82031.26 KB (11073.64 KB = 13.50% unused)
Leading free slots : 0 (0.00 KB = 0.00%)
Trailing free slots : 0 (0.00 KB = 0.00%)
Number of contiguous groups of 16 slots: 5807 (4.42%)
Number of terminal objects: 7969 (0.38%)
44. The Code
class Test
attr_accessor :i_val
def initialize
@i_val = []
300_000.times do |i|
@i_val << "ruby-#{i}" * 10
end
end
def say_hello
"hello"
end
end
45. The Test
test = Test.new
GC.start
t.i_val = nil
t.say_hello
GC.start
t = []
GC.start
47. Conclusion
• be careful with the big sets of data
• don’t store big amount of data in object with long life time
• even if current request wont spend much time in GC the
next request would do it
• the more objects - the longer is mark phase
• symbols are not collected but increase mark phase time
we are dealing with gc every day, saw that brown piece in newrelic?\n
Is that that brow bar at the bottom in newrelic?\n
GC is automtic collector that reclaiming garbage or memory occupied by objects.\n\nIn some languages you manage memory manually: C, C++\n You have to free all allocations, you have to avoid memory leaks, you have deal with double free problems, dangling pointer bugs. And tons of other problems that give you permanent headache.\n\nBut we are cool dynamic devs and do not care about that.\n\n \n
GC is automtic collector that reclaiming garbage or memory occupied by objects.\n\nIn some languages you manage memory manually: C, C++\n You have to free all allocations, you have to avoid memory leaks, you have deal with double free problems, dangling pointer bugs. And tons of other problems that give you permanent headache.\n\nBut we are cool dynamic devs and do not care about that.\n\n \n
GC is automtic collector that reclaiming garbage or memory occupied by objects.\n\nIn some languages you manage memory manually: C, C++\n You have to free all allocations, you have to avoid memory leaks, you have deal with double free problems, dangling pointer bugs. And tons of other problems that give you permanent headache.\n\nBut we are cool dynamic devs and do not care about that.\n\n \n
But should we care about it?\nAnswer is yes - we should\nWe are not managing memory manually but we should know how it work.\n\n
But should we care about it?\nAnswer is yes - we should\nWe are not managing memory manually but we should know how it work.\n\n
All ruby objects are stored in heaps. Each heap have number of slots within it.\n\n
Each slot of a heap hold RVALUE structure.\nIt&#x2019;s a union of all possible ruby data objects. Even source node tree is stored in heap.\nBut that structure is not representing actual data storage. Like object references i_val table that is reference to different RVALUE objects.\n\n
\n
H_SLOTS - Number of initial slots in heap\nH_SLOTS_INC - Number of additional heap slots\nGROWTH_FACTOR - Multiplier to increase heap slots size\nG_MALLOC_LIMIT - limit of allocations before GC, literally how many times malloc has been called\nFREE_MIN - NUMBER of \n
H_SLOTS - Number of initial slots in heap\nH_SLOTS_INC - Number of additional heap slots\nGROWTH_FACTOR - Multiplier to increase heap slots size\nG_MALLOC_LIMIT - limit of allocations before GC, literally how many times malloc has been called\nFREE_MIN - NUMBER of \n
H_SLOTS - Number of initial slots in heap\nH_SLOTS_INC - Number of additional heap slots\nGROWTH_FACTOR - Multiplier to increase heap slots size\nG_MALLOC_LIMIT - limit of allocations before GC, literally how many times malloc has been called\nFREE_MIN - NUMBER of \n
H_SLOTS - Number of initial slots in heap\nH_SLOTS_INC - Number of additional heap slots\nGROWTH_FACTOR - Multiplier to increase heap slots size\nG_MALLOC_LIMIT - limit of allocations before GC, literally how many times malloc has been called\nFREE_MIN - NUMBER of \n
H_SLOTS - Number of initial slots in heap\nH_SLOTS_INC - Number of additional heap slots\nGROWTH_FACTOR - Multiplier to increase heap slots size\nG_MALLOC_LIMIT - limit of allocations before GC, literally how many times malloc has been called\nFREE_MIN - NUMBER of \n
The ideeli settings were chosen ob node purpose and average stat for that kind of node\n
Every object creation checks available allocations\nGC can run at any moment\n
At mark phase interpreter looks for a current variables references. It&#x2019;s not ref based, it&#x2019;s scope and lookup based.\n
In sweep phase any allocations are prohibited\n\n
REE specific. Stats are collected across all process life time frame so the GC cycles increasing\nAst nodes is clas varmap scope singelton etc. Terminal objects are non-object types (regex, file, float, bignum, node)\n
The last couple one do not require gc stats to be enabled.\nNum allocations is the num of objects that were allocated since the script started\n
\n
Simple code that load&#x2019;s our app env in dev mode\n
Spent 2 sec in GC, allocated 5.5m objects and made 31!!!! GC cycles\n
\n
Have 31 GC cycle, 9 heaps and 46% unused almost half of it\n
increase min slots to fit app into one heap\n
Much more better utilization, only 6% unused, but it might be dangerous as well because of it&#x2019;s only env loaded.\n
\n
Give some more space for heap, and increase malloc limit.\n
As a result decent heap utilization, low number of gc cycles\n
Memory consumption increased by 21 Mb.\n
Simple middleware the gathering GC stats\n
Sample stats got for mm node\n
Unicorn supports in between req gc. It&#x2019;s made in between of user requests. That&#x2019;s simple middleware that can be controlled. Gotcha is that wrong params may lead to significant throughput drop. \nGC.start - forces garbage collection weather or not it&#x2019;s required\n
\n
\n
\n
any of 2 last lines would have the same effect - dramatically decreasing live objects number\nWithout explicitly setting instance variable - the whole object set would live until object is in scope\n\n
Every object creation checks available allocations\n\n