2012-12-21 47 views
8

我每隔12小時在我的amazon EC2微型實例上運行一個cron作業。它下載118MB文件並使用json庫進行解析。這當然會導致實例耗盡內存。我的實例有416MB的內存空間,但是我運行的腳本下降到6MB,然後被操作系統殺死。解析100MB JSON負載的有效方法

我想知道我在這裏有什麼選擇?是否有可能通過Ruby有效地解析這個問題,還是我必須下降到像C這樣的低層次的東西?我可以得到一個更強大的亞馬遜實例,但我真的想知道是否有可能通過Ruby來實現這一點。

更新: 我看過yajl。它可以給你json對象,因爲它解析,但問題是,如果你的JSON文件只包含1個根對象,那麼它將被迫解析所有的文件。我的JSON看起來是這樣的:

--Root 
    -Obj 1 
    -Obj 2 
    -Obj 3 

所以,如果我做的:

parser.parse(file) do |hash| 
    #do something here 
end 

因爲我只有1個對象,它將解析整個JSON。如果Obj 1/2/3是root,那麼它會工作,因爲它會給我他們一個,但我的JSON是不是這樣,它解析並吃掉了500MB的內存...

UPDATE #2: 這裏的大118MB文件的較小版本(7MB):

GONE

這是可分析的,我不只是採取一些個字節。從文件,只要你一看它整個。我尋找的數組是這個

events = json['resultsPage']['results']['event'] 

感謝

+4

是有可能的下載分成6分或更多的段,然後把他們重新走到一起? –

+2

100MB的JSON文本?你在儲存什麼?亞歷山大圖書館? ':P' –

+3

你爲什麼使用JSON呢?聽起來不像這份工作的正確格式。更多以記錄爲導向的東西(甚至CSV)會更好地匹配。如果你無法控制格式,那麼也許你可以手動剝離根對象來強制格式轉換爲面向記錄的JSON。 –

回答

6

YAJL實現流解析器。您可以使用它來即時閱讀您的JSON,這樣您就可以在內容進入時對其進行操作,然後在完成後丟棄它們(以及從它們生成的數據結構)。如果你很聰明,這會讓你保持在你的記憶極限之下。

編輯:有了您的數據,您真的有興趣一次抽出部分JSON對象,而不是解析整個對象。這是非常棘手的,而且確實需要你實現你自己的解析器。堅果和它的螺栓要:

  1. 步入事件陣列
  2. 對於數組中的每一個事件,解析事件
  3. 解析事件的傳進了一些回調函數
  4. 放棄解析的事件和源輸入以釋放下一個事件的內存。

這不適用於yajl,因爲您在這裏處理的是一個對象,而不是多個對象。爲了使它與yajl一起工作,您將需要手動解析JSON以發現事件對象邊界,然後將每個事件對象塊傳遞給JSON解析器以進行反序列化。像Ragel這樣的東西可以爲你簡化這個過程。

當然,更新AWS實例會更容易。

+0

請檢查我的更新,解釋我與yajl有關的問題... – 0xSina

+1

您可以預先解析JSON與sed或其他東西來剝離根對象,並將其替換爲括號,留下一個對象數組來操作而不是包含一堆數組的對象。 –

+0

如果您可以提供對象的第一個〜500字節,我們可能可以更具體地提供幫助。 –

0

喜歡的東西yaji可以解析JSON作爲流

+0

請檢查我的更新,解釋我與yajl遇到的麻煩... – 0xSina