2012-04-10 20 views
5

Mam program Java, który przygotowuje dane do dość złożonej i dużej struktury danych w pamięci (kilka GB) i serializuje je na dysk, a także inny program, który odczytuje zserializowaną strukturę danych w pamięci. Zaskoczyło mnie, że krok deserializacji jest dość powolny i że jest związany z procesorem. (100% użycia procesora w top, ale tylko od 3 do 5 MB/s odczytu z iotop, który jest bardzo niski, co powinno być sekwencyjne odczyty na dysku twardym). Procesor jest dość nowy (Core i7-3820), struktura mieści się w pamięci, nie jest skonfigurowana przestrzeń wymiany.Dlaczego powiązanie procesora Java jest zależne od procesora?

Dlaczego tak się dzieje? Czy istnieje alternatywny sposób serializowania obiektów w Javie, które nie mają procesora jako wąskiego gardła?

Oto kod deserializacji, w przypadku jest to ważne:

FileInputStream f = new FileInputStream(path); 
ObjectInputStream of = new ObjectInputStream(f); 
Object obj = of.readObject(); 
+1

IIRC używa odbicie magicznego porównywalna do sposobu pracy NET serializers. To jest powolne. Jest koncepcyjnie łatwe, ale "dużo pisania" - aby uniknąć tego wszystkiego - rób to ręcznie. Oznacza to, że obiekty rekursywnie rekursywnie, field-by-field, do strumienia binarnego. I odwrotnie do ładowania. – harold

+1

Może to pomóc: http://vanillajava.blogspot.co.uk/2011/10/serialization-using-bytebuffer-and.html – assylias

+0

Czy możesz spróbować owijać 'FileInputStream' za pomocą' BufferedInputStream'? –

Odpowiedz

4

Deserializacji jest dość kosztowne. Jeśli użyjesz ogólnej deserializacji, użyjesz wiele refleksji i tworzenia obiektów.

Istnieje wiele alternatyw, które są szybsze i najczęściej generowane kodu zamiast refleksji.

http://code.google.com/p/thrift-protobuf-compare/wiki/Benchmarking

Będziesz pamiętać, że jednym z najszybciej korzysta Externalizable które mogą być rozwiązaniem dla Ciebie. Oznacza to dodanie niestandardowych metod serializacji i deserializacji obiektów.

Pisałem dużo najszybsze podejść ale to uniknąć tworzenia żadnych przedmiotów poprzez recykling je lub wykorzystując dane w pliku w miejscu (czyli bez konieczności ich deserializowania)

2

Trudno powiedzieć, nie patrząc na to z profiler lub wiedząc wiele o faktycznej hierarchii struktury twojego obiektu, ale zakładam, że jeśli jest "dość skomplikowany" i rzędu "kilku GB", prawdopodobnie masz do czynienia z tysiącami pojedynczych obiektów.

Zgaduję, że Twój występ został zabity przez odbicie Java. Odbicie służy do konstruowania obiektów ze strumienia, o którym wiadomo, że jest co najmniej dwa rzędy wielkości wolniejsze od wywoływania konstruktorów bezpośrednio w kodzie. Jeśli więc twój obiekt ma mnóstwo "małych" obiektów, Reflection poświęci wiele czasu na ich rekonstrukcję.

Jedno można spróbować (jeśli nie już) byłoby zadeklarować następującą linię w górnej części każdej z klas Serializable:

private static final long serialVersionUID = [some number]L; 

Jeśli nie deklaruje tego identyfikatora, Java będzie musiała to obliczyć, więc zapiszesz kilka cykli procesora, deklarując to.

Dla dalszego odniesienia:

http://oreilly.com/catalog/javarmi/chapter/ch10.html

Powiązane problemy