2013-03-19 77 views
1

我們的程序創建一個主散列,其中每個鍵都是表示ID(大約10-20個字符)的符號。每個值都是一個空的散列。Ruby中的內存使用率高:500B正常的空散列?

主散列有大約800K條記錄。

但是我們看到ruby的內存幾乎達到了400MB。

這表明每個鍵/值對(符號+空哈希)每個消耗約500B。

這是正常的紅寶石?下面

代碼:

def load_app_ids 
     cols = get_columns AppFile 
     id_col = cols[:application_id] 

     each_record AppFile do |r| 
     @apps[r[id_col].intern] = {} 
     end 
end 

    # Takes a line, strips the record seperator, and return 
    # an array of fields 
    def split_line(line) 
     line.gsub(RecordSeperator, "").split(FieldSeperator) 
    end 

    # Run a block on each record in a file, up to 
    # @limit records 
    def each_record(filename, &block) 
     i = 0 

     path = File.join(@dir, filename) 
     File.open(path, "r").each_line(RecordSeperator) do |line| 
     # Get the line split into columns unless it is 
     # a comment 
     block.call split_line(line) unless line =~ /^#/ 

     # This import can take a loooong time. 
     print "\r#{i}" if (i+=1) % 1000 == 0 
     break if @limit and i >= @limit 
     end 
     print "\n" if i > 1000 
    end 

    # Return map of column name symbols to column number 
    def get_columns(filename) 
     path = File.join(@dir, filename) 
     description = split_line(File.open(path, &:readline)) 

     # Strip the leading comment character 
     description[0].gsub!(/^#/, "") 

     # Return map of symbol to column number 
     Hash[ description.map { |str| [ str.intern, description.index(str) ] } ] 
    end 
+0

哈希不是內存中唯一的東西,是嗎? – 2013-03-19 05:14:02

+0

我們正在閱讀文件的每一行,將盡快發佈代碼。謝謝。 – Crashalot 2013-03-19 05:42:37

+0

更新了代碼 – Crashalot 2013-03-19 06:35:59

回答

1

我會說這是正常的紅寶石。我沒有關於每個數據結構使用的空間的指標,但總的來說基本的 Ruby在這種大型結構上工作得很差。它必須考慮到鍵和值可以是任何類型的對象,雖然這對於高級編碼非常靈活,但如果不需要這種任意控制,效率會很低。

如果我這樣做是IRB

h = {} 
800000.times { |x| h[("test" + x.to_s).to_sym] = {} } 

我與使用197 MB的過程。

由於在處理過程中創建了大量的哈希值,因此您的進程佔用了更多的空間 - 每一行都有一個哈希值。 Ruby最終將清除 - 但這不會立即發生,並且內存也不會立即返回到操作系統。

編輯:我應該補充一點,我一直在使用Ruby中的各種大型數據結構 - 如果您需要它們的一般方法是在本機擴展(或ffi)中尋找代碼可以利用例如,在數組中使用受限類型。寶石narray就是數值數組,向量,矩陣等的一個很好的例子。

+0

謝謝,尼爾。任何關於字符串數組的建議?還有一種方法可以在Ruby中標記GC的對象嗎?當你說它沒有立即返回到操作系統時,需要多長時間?如果我們在標記對象(假設可能)清理之後睡了一小段時間,我們是否可以假設內存使用量會恢復到正常水平? – Crashalot 2013-03-19 09:26:08

+0

我不知道你的問題的答案,我對這一層的語言不夠熟悉。對我來說,它看起來像你正在嘗試創建代表你的slurped文件的東西,並且一旦完成就可以被查詢和/或處理。如果是這樣,我可能會推薦而不是與Ruby內部戰鬥,考慮使用像SQLite這樣的內存驅動程序(有一個使用SQLite的Ruby庫)。它可能會以更好的內存佔用量和性能特點爲您提供所需的功能。 – 2013-03-19 09:53:28