Ответ 1
Scala теперь имеет Scala -pickling, который работает как хорошо или лучше, чем Kyro, в зависимости от сценария - см. слайды 34-39 в этой.
Есть ли простой, беспроблемный подход к сериализации в Scala/Java, который похож на Python pickle? Pickle - это мертвое простое решение, которое разумно эффективно в пространстве и времени (то есть не является абсурдным), но не заботится о возможности межязыкового доступа, управления версиями и т.д. И допускает дополнительную настройку.
Что я знаю:
Kryo и protostuff - самые близкие решения, которые я нашел, но мне интересно, есть ли там что-нибудь еще (или если есть способ использовать их, о которых я должен знать). Пожалуйста, включите примеры использования! В идеале также включают контрольные показатели.
Scala теперь имеет Scala -pickling, который работает как хорошо или лучше, чем Kyro, в зависимости от сценария - см. слайды 34-39 в этой.
Я на самом деле думаю, что вам будет лучше с kryo (я не знаю альтернатив, которые предлагают меньше схем, определяющих другие, чем не-двоичные протоколы). Вы отмечаете, что рассол не восприимчив к замедлению и раздуванию, что крио получает без регистрации классов, но kryo все еще быстрее и менее раздувается, чем рассол, даже без регистрации классов. См. Следующий микро-бенчмарк (очевидно, возьмите его с солью, но это то, что я могу сделать легко):
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
Вывод 174 байта и 1,18-1,23 секунды для меня (Python 2.7.1 на 64-разрядной Linux)
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)
}
Вывод 68 байтов для меня и 30-40 мс (Kryo 1.04, Scala 2.9.1, Java 1.6.0.26 hotspot JVM на 64-разрядной Linux). Для сравнения, он выдает 51 байт и 18-25 мс, если я зарегистрирую классы.
Kryo использует около 40% пространства и 3% времени, когда Python раскроет, когда не регистрирует классы, и около 30% пространства и 2% времени при регистрации классов. И вы всегда можете написать собственный сериализатор, если хотите больше контроля.
Twitter chill library просто потрясающе. Он использует Kryo для сериализации, но очень прост в использовании. Также приятно: предоставляет тип MeatLocker [X], который делает любой X сериализуемым.
Я бы рекомендовал SBinary. Он использует implicits, которые разрешаются во время компиляции, поэтому он очень эффективен и типичен. Он поставляется со встроенной поддержкой многих распространенных типов данных Scala. Вы должны вручную написать код сериализации для своих (case) классов, но это легко сделать.
Еще один хороший вариант - недавний (2016) **netvl/picopickle**
:
- Маленький и почти без зависимостей (основная библиотека зависит только от shapeless).
- Расширяемость. Вы можете определить свои собственные сериализаторы для своих типов, и вы можете создавать собственные бэкэнды, то есть вы можете использовать одну и ту же библиотеку для разных форматов сериализации (коллекции, JSON, BSON и т.д..); другие части поведения сериализации, такие как обработка нулей, также могут быть настроены.
- Гибкость и удобство: формат сериализации по умолчанию подходит для большинства целей, но может быть настроен практически произвольно с поддержкой из удобных конвертеров DSL.
- Статическая сериализация без отражения: бесформенный Общие макросы используются для предоставления сериализаторов для произвольных типов, что означает отсутствие отражения.
Например:
Ящик, основанный на ястрефе, также предоставляет дополнительные функции
readString()
/writeString()
иreadAst()
/writeAst()
, которые [де] сериализуют объекты для строк и JSON AST для строк соответственно:
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")