class HMalloc

Attributes

deallocated[R]
memory[R]

Public Class Methods

new() click to toggle source
# File lib/hengine/hmalloc.rb, line 59
def initialize
  hl << "============== NEW HMALLOC ==============".red
  @expiration = 15 * 60 # seconds
  @memory = {}
  @deallocated = {}
end

Public Instance Methods

clean() click to toggle source
# File lib/hengine/hmalloc.rb, line 145
def clean()

  #GC.start(full_mark: true, immediate_sweep: true) # Start Gargabe Collection immediately and deletes every unused memory block
  #Senza l'istruzione sopra la memoria viene liberata gradualmente ad es.
  # - se ho 100 blocchi di memoria non usati ne vengolo liberati solo 40 per poi liberare la restante parte in un momento successivo
  # - se invece eseguo GC.start sopra con immediate_sweep: true viene liberata tutta la memoria non usata con effetto immediato

  to_delete = nil
  to_delete = @memory.select do |oid, node| 
    node.parentNode == nil and node.updateTimestamp  + @expiration <= Time.now.to_i 
  end
  hl << "[start cleaning]#: ...".hight_cyan
  to_delete.each do |oid, node| 
    self.dealloc(oid)
  end

end
dealloc(oid, deleteFromParent = true) click to toggle source
# File lib/hengine/hmalloc.rb, line 113
def dealloc(oid, deleteFromParent = true)
  return unless oid
  oid = oid.to_i
  node = @memory[oid]
  hl << "WARNING: #{oid} not found".red unless node
  self.hotLog("ERROR: HMalloc::dealloc(#{oid}): already deallocated") if @deallocated[oid]
  return unless node
  hl << "[HMalloc.dealloc]#:".green
  node.show(oid: oid, margin: 3)
  node.childNodes.clone.each do |childNode|
    self.dealloc2(childNode.obj, false) 
  end
  node.parentNode.childNodes.delete(node) if node.parentNode and deleteFromParent
  @memory.delete(oid)
  @deallocated[oid] = true if hsd.value("log4memory")

end
dealloc2(obj, deleteFromParent = true) click to toggle source
# File lib/hengine/hmalloc.rb, line 131
def dealloc2(obj, deleteFromParent = true)
  return unless obj
  return self.dealloc(obj.object_id, deleteFromParent)
end
get(oid) click to toggle source
# File lib/hengine/hmalloc.rb, line 109
def get(oid)
  return self.getNode(oid).obj
end
getNode(oid) click to toggle source
# File lib/hengine/hmalloc.rb, line 99
def getNode(oid)
  oid = oid.to_i
  node = @memory[oid]
  self.hotLog("ERROR: HMalloc::getNode(#{oid}): #{oid} deallocated".red) if @deallocated[oid]
  return nil unless node
  node.updateTimestamp = Time.now.to_i
  self.getNode(node.parentNode.obj.object_id) if node.parentNode # Aggiorna updateTimestamp dei genitori
  return node
end
hotLog(str) click to toggle source
# File lib/hengine/hmalloc.rb, line 141
def hotLog(str)
  HHotLogger.append(str, "log4memory")
end
malloc(obj, poid = nil) click to toggle source

poid: parent object id

# File lib/hengine/hmalloc.rb, line 67
def malloc(obj, poid = nil)
  
  oid = obj.object_id
  poid = poid.to_i
  parentNode = @memory[poid] if poid != 0
  hl.<< "WARNING malloc: poid #{poid} not found", "ERROR" if poid != 0 and !parentNode

  node = HNode.new(obj, parentNode)
  # Se abilita la seguente istruzione non viene deallocata la memoria
  #ObjectSpace.define_finalizer(obj, proc {|objectId| hl << "Finalizer of the #{objectId}" })

  hl.<< "WARNING: #{oid} already exist".red, "ERROR" if @memory.include?(oid)
  @memory[oid] = node
  parentNode.childNodes << node if parentNode
  hl.<< "[HMalloc.malloc]#: ".yellow, "DEBUG2"
  hl.<< "WARNING: No parent".red, "ERROR" if poid == 0
  node.show(oid: oid, margin: 3)
  
  return node

end
malloc2(obj, parent = nil) click to toggle source
# File lib/hengine/hmalloc.rb, line 89
def malloc2(obj, parent = nil)

  return self.malloc(obj, parent.object_id)

end
parentOf(oid) click to toggle source
# File lib/hengine/hmalloc.rb, line 95
def parentOf(oid)
  return @memory[oid.to_i].parentNode.obj.object_id if oid
end
resetMemory() click to toggle source
# File lib/hengine/hmalloc.rb, line 136
def resetMemory()
  hl << "Reset Memory ... 100%".hight_cyan
  @memory = {}
end
show() click to toggle source
# File lib/hengine/hmalloc.rb, line 163
def show
  
  hl.<< "################################################################################################".hight_white, "DEBUG2"
  hl.<< "#                                                                                              #".hight_white, "DEBUG2"
  hl.<< "#                                  Tree Hypersonic Memory Leak                                 #".hight_white, "DEBUG2"
  hl.<< "#                                                                                              #".hight_white, "DEBUG2"
  hl.<< "################################################################################################".hight_white, "DEBUG2"
  hl.<< "#                                                                                              #".hight_white, "DEBUG2"
  hl.<< "# Visualizzazione della memoria ad albero (non compare l'oid dei figli)                        #".hight_white, "DEBUG2" 
  hl.<< "#                                                                                              #".hight_white, "DEBUG2"
  hl.<< "# Le seguenti allocazioni di memoria possono essere generate in due modi:                      #".hight_white, "DEBUG2"
  hl.<< "#                                                                                              #".hight_white, "DEBUG2"
  hl.<< "#   - By connect: in questo caso la tabella sotto mostra il receiver, il metodo e i parametri  #".hight_white, "DEBUG2"
  hl.<< "#     es. tr.connect(:ondblclick, self, 'doubleClick', id: @oid, ...)                          #".hight_white, "DEBUG2"
  hl.<< "#                                                                                              #".hight_white, "DEBUG2"
  hl.<< "#   - By malloc: in questo caso la tabella sotto mostra l'oggetto usato                        #".hight_white, "DEBUG2"
  hl.<< "#     es. @oid = hm().malloc(@modelName.clone, poid).obj.object_id.to_s                        #".hight_white, "DEBUG2"
  hl.<< "#                                                                                              #".hight_white, "DEBUG2"
  hl.<< "#   - Le righe in rosso sono quelle senza parent (vericare che ce ne sia solo una)             #".hight_white, "DEBUG2"
  hl.<< "#     Se ce sono piu' di una e si vuole capire da dove proviene il metodo alloc genera         #".hight_white, "DEBUG2"
  hl.<< "#     un Warning rosso quando si esegue una malloc senza poid                                  #".hight_white, "DEBUG2"
  hl.<< "#                                                                                              #".hight_white, "DEBUG2"
  hl.<< "################################################################################################".hight_white, "DEBUG2"
  
  memory = @memory.sort_by { |oid, node| node.updateTimestamp }
  memory.each do |oid, node|
    node.showTree(oid: oid) unless node.parentNode
  end
  
  return memory

end
showAll(sorted: false) click to toggle source
# File lib/hengine/hmalloc.rb, line 196
def showAll(sorted: false)
  
  hl.<< "################################################################################################".hight_white, "DEBUG2"
  hl.<< "#                                                                                              #".hight_white, "DEBUG2"
  hl.<< "#                                    Hypersonic Memory Leak                                    #".hight_white, "DEBUG2"
  hl.<< "#                                                                                              #".hight_white, "DEBUG2"
  hl.<< "################################################################################################".hight_white, "DEBUG2"
  hl.<< "#                                                                                              #".hight_white, "DEBUG2"
  hl.<< "# Le seguenti allocazioni di memoria possono essere generate in due modi:                      #".hight_white, "DEBUG2"
  hl.<< "#                                                                                              #".hight_white, "DEBUG2"
  hl.<< "#   - By connect: in questo caso la tabella sotto mostra il receiver, il metodo e i parametri  #".hight_white, "DEBUG2"
  hl.<< "#     es. tr.connect(:ondblclick, self, 'doubleClick', id: @oid, ...)                          #".hight_white, "DEBUG2"
  hl.<< "#                                                                                              #".hight_white, "DEBUG2"
  hl.<< "#   - By malloc: in questo caso la tabella sotto mostra l'oggetto usato                        #".hight_white, "DEBUG2"
  hl.<< "#     es. @oid = hm().malloc(@modelName.clone, poid).obj.object_id.to_s                        #".hight_white, "DEBUG2"
  hl.<< "#                                                                                              #".hight_white, "DEBUG2"
  hl.<< "#   - Le righe in rosso sono quelle senza parent (vericare che ce ne sia solo una)             #".hight_white, "DEBUG2"
  hl.<< "#     Se ce sono piu' di una e si vuole capire da dove proviene il metodo alloc genera         #".hight_white, "DEBUG2"
  hl.<< "#     un Warning rosso quando si esegue una malloc senza poid                                  #".hight_white, "DEBUG2"
  hl.<< "#                                                                                              #".hight_white, "DEBUG2"
  hl.<< "################################################################################################".hight_white, "DEBUG2"
  usedMemory = "[Used Memory]#: #{@memory.length} blocks".hight_cyan
  hl.<< "#   #{usedMemory}                                                           ".hight_white, "DEBUG2"
  hl.<< "################################################################################################".hight_white, "DEBUG2"
 
  memory = (sorted) ? @memory.sort_by { |oid, node| node.updateTimestamp } : @memory
  memory.each do |oid, node| 
    node.show(oid: oid)
  end

  return memory

end
test() click to toggle source
# File lib/hengine/hmalloc.rb, line 230
def test

  m = hm()
  a1 = "LevelA-1"
  l1 = "Level 1"
  l2a = "Level 2-a"
  l2b = "Level 2-b"
  l2c = "Level 2-c"
  l3a = "Level 3-a"
  l3b = "Level 3-b"
  l3c = "Level 3-c"

  node = m.malloc2(l1)
  m.malloc2(a1)
  m.malloc2(l2a, l1)
  m.malloc2(l2b, l1)
  m.malloc2(l2c, l1)
  m.malloc2(l3a, l2a)
  m.malloc2(l3b, l2a)
  m.malloc2(l3c, l2a)

  m.show
  sleep(3)
  p m.get(l3c.object_id)
  m.clean # La cancellazione avviene solo impostazione @expiration = 3 in quanto sleep = 3
  m.show

end