Scala/Java中的简单,无障碍,零样板序列化类似于Python的Pickle?

Yan*_*ang 36 python java serialization scala pickle

在Scala/Java中是否有一种简单,无障碍的序列化方法,类似于Python的pickle?Pickle是一个简单易懂的解决方案,在空间和时间上相当有效(即不是非常糟糕),但不关心跨语言的可访问性,版本控制等,并允许可选的自定义.

我所知道的:

Kryo和protostuff是我发现的最接近的解决方案,但我想知道是否还有其他任何东西(或者是否有某些方法可以使用这些我应该注意的).请包括用法示例!理想情况下还包括基准测试.

Mik*_*ike 11

我实际上认为你最好用kryo(我不知道除了非二进制协议之外提供更少模式定义的替代方案).你提到泡菜不容易受到kryo没有注册课程的减速和膨胀的影响,但即使没有注册课程,kryo仍然比pickle更快,更少臃肿.请参阅以下微基准测试(显然需要使用它,但这是我可以轻松完成的):

Python泡菜

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    
Run Code Online (Sandbox Code Playgroud)

我输出174个字节和1.18-1.23秒(64位Linux上的Python 2.7.1)

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)
}
Run Code Online (Sandbox Code Playgroud)

为我和30-40ms输出68个字节(Kryo 1.04,Scala 2.9.1,64位Linux上的Java 1.6.0.26热点JVM).为了比较,如果我注册类,它输出51个字节和18-25ms.

对照

Kryo在没有注册类时使用大约40%的空间和3%的时间作为Python pickle,在注册类时占用大约30%的空间和2%的时间.当您想要更多控制时,您总是可以编写自定义序列化程序.

  • 在Kryo 2.x中,使用kryo.setInstantiatorStrategy(new StdInstantiatorStrategy())来获取基于反射的构造函数实例化,而不使用任何0-arg构造函数. (7认同)
  • 如果你正在使用sun/oracle jvm,你可以使用https://github.com/magro/kryo-serializers来反序列化没有0-arg构造函数的对象:只需将"new Kryo"更改为"new KryoReflectionFactorySupport". (5认同)

Arn*_*-Oz 9

Scala现在有Scala-pickling,它的表现与Kyro一样好或更好,具体取决于场景 - 请参阅演示文稿中的幻灯片34-39 .


ib8*_*b84 7

Twitter的寒意库真是太棒了.它使用Kryo进行序列化,但使用起来非常简单.同样不错:提供一个MeatLocker [X]类型,使任何X成为Serializable.