Czy jest proste, bezproblemowe podejście do serializacji w Scali / Java, która jest podobna do Pythona? Marynata to martwe rozwiązanie, które jest rozsądnie wydajne w przestrzeni i czasie (tj. Nie absmal), ale nie obchodzi nie dba o dostępność krzyżową, wersjonowanie itp. I pozwala na opcjonalne dostosowywanie.

Co mi wiadomo:

Kryo i protostuff są najbliższymi rozwiązaniami, które znalazłem, ale zastanawiam się, czy jest coś jeszcze (lub jeśli jest jakiś sposób, aby użyć tych, o których powinienem być świadomy). Proszę podać przykłady użytkowania! Idealnie obejmują również benchmarki.

37
Yang 29 wrzesień 2011, 02:47

5 odpowiedzi

Najlepsza odpowiedź

Edytuj 2020-02-19: Należy pamiętać, jak wspomniano o @federico poniżej, ta odpowiedź nie jest już ważna, ponieważ repozytorium zostało zarchiwizowane przez właściciela.

Scala ma teraz Scala-Materieflowanie, który działa jako dobry lub lepszy niż Kyro w zależności od scenariusza - patrz slajdy 34- 39 w Ta prezentacja.

9
Arnon Rotem-Gal-Oz 19 luty 2020, 20:04

Właściwie myślę, że będziesz najlepiej wyłączyć z Kryo (nie jestem świadomy alternatyw, które oferują mniej schematu określające inne niż protokoły innych niż binarne). Wspominasz, że marynata nie jest podatna na spowolnienia i gd. Kryo dostaje bez rejestracji klas, ale Kryo jest nadal szybszy i mniej nadęty niż marynata nawet bez rejestracji klas. Zobacz następujący mikro-benchmark (oczywiście weź go z ziarnem soli, ale to właśnie mógłbym zrobić łatwo):

Python Migle.

import pickle
import time
class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age
people = [Person("Alex", 20), Person("Barbara", 25), Person("Charles", 30), Person("David", 35), Person("Emily", 40)]
for i in xrange(10000):
    output = pickle.dumps(people, -1)
    if i == 0: print len(output)
start_time = time.time()
for i in xrange(10000):
    output = pickle.dumps(people, -1)
print time.time() - start_time    

Wyjścia 174 bajtów i 1,18-1.23 sekundy dla mnie (Python 2.7.1 na 64-bitowym Linuksie)

Scala Kryo.

import com.esotericsoftware.kryo._
import java.io._
class Person(val name: String, val age: Int)
object MyApp extends App {
  val people = Array(new Person("Alex", 20), new Person("Barbara", 25), new Person("Charles", 30), new Person("David", 35), new Person("Emily", 40))
  val kryo = new Kryo
  kryo.setRegistrationOptional(true)
  val buffer = new ObjectBuffer(kryo)
  for (i <- 0 until 10000) {
    val output = new ByteArrayOutputStream
    buffer.writeObject(output, people)
    if (i == 0) println(output.size)
  }
  val startTime = System.nanoTime
  for (i <- 0 until 10000) {
    val output = new ByteArrayOutputStream
    buffer.writeObject(output, people)
  }
  println((System.nanoTime - startTime) / 1e9)
}

Wyjścia 68 bajtów dla mnie i 30-40 ms (Kryo 1.04, Scala 2.9.1, Java 1.6.0.26 Hotspot JVM na 64-bitowym systemie Linux). Dla porównania wyświetla 51 bajtów i 18-25 ms, jeśli zarejestruję zajęcia.

Porównanie

Kryo wykorzystuje około 40% przestrzeni i 3% czasu, gdy Python Marynata, gdy nie rejestruje zajęcia, i około 30% przestrzeni i 2% czasu podczas rejestracji klas. I zawsze możesz napisać niestandardowy serializator, gdy chcesz większej kontroli.

11
Mike 1 październik 2011, 09:55

Biblioteka Chill jest po prostu niesamowita. Wykorzystuje Kryo do serializacji, ale jest ultra prosty w użyciu. Również ładny: zapewnia typ MEATLOCKER [X], który sprawia, że każda x serializowalna.

7
ib84 26 kwiecień 2013, 10:09

Polecam Sbinary. Wykorzystuje imprecici, które są rozwiązane w czasie kompilacji, więc jest bardzo skuteczny i typeafe. Jest wyposażony w wbudowaną obsługę wielu wspólnych datatypów SCALA. Musisz ręcznie napisać kod serializacji dla swoich klas (Case), ale łatwo jest to zrobić.

Przykład użycia dla prostego ADT

4
Jesper Nordenberg 29 wrzesień 2011, 08:01

Inną dobrą opcją jest ostatnie (2016) {x0}}:

  • mały i prawie zależność - mniej (podstawowa biblioteka zależy tylko na bezkształtne ).
  • rozszerzenie : Możesz określić własne serializatory dla swoich typów i można tworzyć niestandardowe backences, czyli, można użyć tej samej biblioteki dla różnych formatów serializacji (kolekcje, JSON, BSON itp .); Można również dostosować inne części zachowania serializacji jak obsługa Nulls.
  • Elastyczność i wygoda: Domyślny format serializacji jest w porządku dla większości zastosowań, ale może być dostosowany prawie arbitralnie z obsługą wygodnych konwerterów DSL.
  • statyczna serializacja bez odbicia : bezkształtne makra generyczne służą do dostarczania serialnizatorów dla dowolnych typów, co oznacza, że nie jest używana żadna odbicia.

Na przykład:

Kilkarz na bazie żonka zapewnia również dodatkowe funkcje, readString() / writeString() i readAst() / writeAst() / {

import io.github.netvl.picopickle.backends.jawn.JsonPickler._

case class A(x: Int, y: String)

writeString(A(10, "hi")) shouldEqual """{"x":10,"y":"hi"}"""
readString[A]("""{"x":10,"y":"hi"}""") shouldEqual A(10, "hi")
0
VonC 20 marzec 2016, 01:23