class Usage
Definitions
attr_accessor :size
attr_accessor :count
def [](key)
Access usage attributes by key.
Signature
-
parameter
keySymbol The attribute name (:size, :count, :memory, :memsize).
Implementation
def [](key)
public_send(key)
end
def <<(allocation)
Add an allocation to this usage.
Signature
-
parameter
allocationAllocation The allocation to add.
Implementation
def << allocation
self.size += allocation.memsize
self.count += 1
return self
end
def add!(other)
Add another usage to this usage.
Signature
-
parameter
otherUsage The usage to add.
Implementation
def add!(other)
self.size += other.size
self.count += other.count
return self
end
def self.of(root, seen: Set.new.compare_by_identity, ignore: IGNORE)
Compute the usage of an object and all reachable objects from it.
The root is always visited even if it is in seen.
Signature
-
parameter
rootObject The root object to start traversal from.
-
parameter
seenHash(Object, Integer) The seen objects (should be compare_by_identity).
-
returns
Usage The usage of the object and all reachable objects from it.
Implementation
def self.of(root, seen: Set.new.compare_by_identity, ignore: IGNORE)
count = 0
size = 0
queue = [root]
while object = queue.shift
# Add the object to the seen set:
seen.add(object)
# Update the count and size:
count += 1
size += ObjectSpace.memsize_of(object)
# Add the object's reachable objects to the queue:
ObjectSpace.reachable_objects_from(object)&.each do |reachable_object|
# Skip ignored types:
next if ignore.any?{|type| reachable_object.is_a?(type)}
# Skip internal objects - they don't behave correctly when added to `seen` and create unbounded recursion:
next if reachable_object.is_a?(ObjectSpace::InternalObjectWrapper)
# Skip objects we have already seen:
next if seen.include?(reachable_object)
queue << reachable_object
end
end
return new(size, count)
end