2012-12-21 18 views
8

Używam zadania cron na mojej instancji Amazon EC2 micro co 12 godzin. Pobiera plik 118 MB i analizuje go za pomocą biblioteki json. To oczywiście sprawia, że ​​instancja zabraknie pamięci. Moja instancja ma 416 MB wolnej pamięci, ale potem uruchamiam skrypt, który spada do 6 MB, a następnie zostaje zabity przez system operacyjny.Wydajny sposób analizowania 100MB ładunku JSON

Zastanawiam się, jakie są moje opcje? Czy można to wydajnie przetworzyć za pomocą Ruby, czy też muszę przejść do rzeczy niskiego poziomu, takich jak C? Mogę uzyskać bardziej zdolną instancję amazonek, ale naprawdę chcę wiedzieć, czy można to zrobić za pośrednictwem Ruby.

AKTUALIZACJA: Spojrzałem na yajl. Może dawać ci obiekty json podczas ich analizy, ale problem polega na tym, że jeśli twój plik JSON zawiera tylko 1 obiekt główny, to będzie musiał przetworzyć WSZYSTKIE pliki. Mój JSON wygląda następująco:

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

Więc jeśli mam zrobić:

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

Ponieważ mam tylko 1 główny obiekt będzie analizować całą JSON. Jeśli Obj 1/2/3 byłby rootem, to działałoby, ponieważ da mi je jeden po drugim, ale mój JSON nie jest taki, a parsuje 500 MB pamięci ...

AKTUALIZACJA # 2: Oto mniejsza wersja dużego pliku 118mb (7MB):

GONE

To parsowalnym, nie tylko trochę bajtów wyłączyć z akt sprawy, tak ci postrzegają ją jako cały. Tablica szukam jest to

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

Dzięki

+4

jest to możliwe, aby podzielić się pobieranie na 6 lub więcej segmentów, a następnie umieścić je z powrotem razem? –

+2

100 MB tekstu JSON? Co przechowujesz? Biblioteka Aleksandrii? ': P' –

+3

Dlaczego używasz JSON do tego? Nie brzmi jak odpowiedni format do pracy. Coś bardziej zorientowanego na rekord (nawet CSV) byłoby lepiej pasować. Jeśli nie możesz kontrolować formatu, to możesz ręcznie usunąć obiekt główny, aby wymusić format na JSON zorientowany na rekord. –

Odpowiedz

6

YAJL realizuje parser streamingu. Możesz go użyć do czytania JSON-a w locie, abyś mógł operować zawartością w miarę jej pojawiania się, a następnie odrzucić je (i wygenerowane z nich struktury danych), gdy skończysz z nimi. Jeśli jesteś sprytny w tej kwestii, zatrzyma cię to w granicach twojej pamięci.

Edycja: Za pomocą danych użytkownik jest naprawdę zainteresowany wyciąganiem części obiektu JSON naraz, a nie analizowaniem całego obiektu. Jest to znacznie trudniejsze i naprawdę wymaga implementacji własnego parsera. Nakrętki i śruby z nim jest to, że chcesz:

  1. Krok do tablicy zdarzeń
  2. dla każdego zdarzenia w tablicy, analizować zdarzenia
  3. Przepuścić analizowany imprezę do niektórych funkcji wywołania zwrotnego
  4. Odrzuć przeanalizowane zdarzenie i źródło wejściowe, aby zwolnić pamięć dla następnego zdarzenia.

To nie zadziała w przypadku yajl, ponieważ mamy tu do czynienia z jednym obiektem, a nie z wieloma obiektami. Aby to działało z Yajl, będziesz musiał przeanalizować JSON ręcznie, aby odkryć granice obiektów zdarzenia, a następnie przekazać każdy obiekt obiektu zdarzenia do parsera JSON w celu deserializacji. Coś takiego jak Ragel może uprościć ten proces dla ciebie.

Oczywiście łatwiej byłoby po prostu zaktualizować instancję AWS.

+0

Proszę sprawdzić moją aktualizację wyjaśniającą problem, jaki mam z yajl ... – 0xSina

+1

Można wstępnie przetworzyć JSON z sed lub czymś, aby usunąć obiekt główny, i zastąpić go nawiasami, pozostawiając ci szereg obiektów do działania na , a nie obiekt zawierający kilka tablic. –

+0

Jeśli możesz podać pierwsze ~ 500 bajtów obiektu, być może będziemy w stanie pomóc bardziej konkretnie. –

0

Coś yaji można analizować JSON jako strumień

+0

Proszę sprawdzić moją aktualizację wyjaśniającą problem, który mam z yajl ... – 0xSina

Powiązane problemy