2010-04-19 4 views
5

Mam zestaw punktów danych, każdy opisany przez słownik. Przetwarzanie każdego punktu danych jest niezależne i przesyłam każdą z nich jako oddzielne zadanie do klastra. Każdy punkt danych ma unikalną nazwę, a moje opakowanie do przesyłania klastra po prostu wywołuje skrypt, który pobiera nazwę punktu danych i plik opisujący wszystkie punkty danych. Ten skrypt następnie uzyskuje dostęp do punktu danych z pliku i wykonuje obliczenia.Szybka serializacja JSON (i porównanie z pikle) do klastra w Pythonie?

Ponieważ każde zadanie musi załadować zestaw wszystkich punktów tylko w celu pobrania punktu do uruchomienia, chciałem zoptymalizować ten krok, serializując plik opisujący zestaw punktów w formacie łatwym do odzyskania.

Próbowałem za pomocą JSONpickle, stosując następujące metody serializacji słownika opisującą wszystkie punkty danych do pliku:

def json_serialize(obj, filename, use_jsonpickle=True): 
    f = open(filename, 'w') 
    if use_jsonpickle: 
    import jsonpickle 
    json_obj = jsonpickle.encode(obj) 
    f.write(json_obj) 
    else: 
    simplejson.dump(obj, f, indent=1) 
    f.close() 

Słownik zawiera bardzo prostych obiektów (list, smyczki, pływaków, etc.) i ma w sumie 54 000 kluczy. Plik json ma rozmiar ~ 20 megabajtów.

Załadowanie tego pliku do pamięci zajmuje około 20 sekund, co wydaje mi się bardzo powolne. Przełączyłem się na używanie pikla z tym samym dokładnym obiektem i odkryłem, że generuje on plik o rozmiarze około 7,8 megabajtów i można go załadować w ciągu 1-2 sekund. Jest to znaczna poprawa, ale nadal wydaje się, że ładowanie małego obiektu (mniej niż 100 000 wpisów) powinno być szybsze. Poza tym pikle nie są czytelne dla ludzi, co było dla mnie dużą zaletą JSON.

Czy istnieje sposób użycia JSON do uzyskania podobnych lub lepszych przyspieszeń? Jeśli nie, czy masz inne pomysły na taką strukturę?

(Czy właściwym rozwiązaniem jest po prostu "podzielenie" pliku opisującego każde zdarzenie na osobny plik i przekazanie go do skryptu uruchamiającego punkt danych w zadaniu klastra? Wydaje się, że może to doprowadzić do rozprzestrzenienia się akta).

dzięki.

Odpowiedz

7

marshal jest najszybszy, ale pickle per se nie jest - może masz na myśli cPickle (co jest dość szybki, ESP z protokołem -1.).Tak więc, oprócz kwestii czytelności, tu jest jakiś kod, aby pokazać różne możliwości:

import pickle 
import cPickle 
import marshal 
import json 

def maked(N=5400): 
    d = {} 
    for x in range(N): 
    k = 'key%d' % x 
    v = [x] * 5 
    d[k] = v 
    return d 
d = maked() 

def marsh(): 
    return marshal.dumps(d) 

def pick(): 
    return pickle.dumps(d) 

def pick1(): 
    return pickle.dumps(d, -1) 

def cpick(): 
    return cPickle.dumps(d) 

def cpick1(): 
    return cPickle.dumps(d, -1) 

def jso(): 
    return json.dumps(d) 

def rep(): 
    return repr(d) 

A oto ich prędkości na moim laptopie:

$ py26 -mtimeit -s'import pik' 'pik.marsh()' 
1000 loops, best of 3: 1.56 msec per loop 
$ py26 -mtimeit -s'import pik' 'pik.pick()' 
10 loops, best of 3: 173 msec per loop 
$ py26 -mtimeit -s'import pik' 'pik.pick1()' 
10 loops, best of 3: 241 msec per loop 
$ py26 -mtimeit -s'import pik' 'pik.cpick()' 
10 loops, best of 3: 21.8 msec per loop 
$ py26 -mtimeit -s'import pik' 'pik.cpick1()' 
100 loops, best of 3: 10 msec per loop 
$ py26 -mtimeit -s'import pik' 'pik.jso()' 
10 loops, best of 3: 138 msec per loop 
$ py26 -mtimeit -s'import pik' 'pik.rep()' 
100 loops, best of 3: 13.1 msec per loop 

tak, możesz mieć czytelność i dziesięciokrotności prędkość json.dumps z repr (poświęcasz łatwość parsowania z JavaScript i innych języków); możesz mieć absolutną maksymalną prędkość z marshal, prawie 90 razy szybciej niż json; cPickle oferuje znacznie bardziej ogólną charakterystykę (jeśli chodzi o to, co można serializować) niż json lub marshal, ale jeśli nigdy nie będziesz używać tej ogólności, możesz równie dobrze uzyskać marshal (lub repr, jeśli ludzka czytelność przyspieszy).

Jeśli chodzi o pomysł "krojenia", zamiast wielu plików, warto rozważyć bazę danych (wiele rekordów) - możesz nawet uciec bez rzeczywistej serializacji, jeśli korzystasz z danych ma to jakiś rozpoznawalny "schemat".

+0

Dziękuję bardzo za twoją pouczającą odpowiedź, to było bardzo pomocne. Jakie bazy danych poleciłbyś w pythonie? Wolałbym rzeczy, które nie wymagają samodzielnych serwerów baz danych - lub jeszcze lepiej, które są wbudowane w Pythona, może jak sqlite - nad tymi, które robią. Jakieś przemyślenia na ten temat? Czy podejście bazodanowe w Pythonie będzie rywalizować z czasem pikle dla przypadku testowego w słowniku dla ~ 50 000 kluczy, z których trzeba wyciąć konkretny wpis? Jeśli przejdę do DB, napiszę niestandardowy kod, aby serializować do CSV, aby moje pliki mogły być udostępniane i czytane przez innych użytkowników. – user248237dfsf

+0

Jeśli korzystasz z wbudowanego DB, to sqlite jest najlepszy, ale jak każdy inny wbudowany DB, nie kupuje on żadnego przetwarzania równoległego, w tym przypadku dużej mocy obliczeniowej podejścia DB. Jak trudne jest jednak uruchomienie procesu PostgreSQL? I TERAZ uzyskasz idealną równoległość dostępu do danych i duży wzrost wydajności. (Zapisywanie CSV lub innych formularzy do SQL DB i odrzucanie zawartości DB z powrotem do dowolnej postaci, jest prostą pracą z prostymi skrypty pomocnicze, oczywiście - to niezależne od wybranego silnika DB). –

1

Myślę, że stoisz tutaj w obliczu kompromisu: ludzka czytelność ma koszt wydajności i dużego rozmiaru pliku. Tak więc, spośród wszystkich metod serializacji dostępnych w Pythonie, JSON jest nie tylko najbardziej czytelny, ale także najwolniejszy.

Gdybym musiał dążyć do wydajności (i zwartości plików), wybrałbym marshall. Możesz albo zebrać cały zestaw z dump() i load() lub, opierając się na swoim pomyśle na cięcie, zmontuj oddzielne części zestawu danych w oddzielne pliki. W ten sposób otworzysz drzwi do równoległego przetwarzania danych - jeśli masz na to ochotę.

Oczywiście w dokumentacji są różne rodzaje ograniczeń i ostrzeżeń, więc jeśli zdecydujesz się je odtworzyć, przejdź na stronę pickle.

+0

JSON jest wolniejszy niż XML? To nie wydaje się właściwe ... –