You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The Java protobuf implementation cleverly caches Strings and ByteStrings when calculating message size and serializing messages. This saves a string iteration - protokt has to iterate once to find the size of a String's byte array representation, and then once to write it.
We can cache similarly and even do this for wrapper types. In fact, we can do slightly better than protobuf-java on String fields by only copying lazily and never calling CodedInputStream.readString() at all - only convert to a String when requested.
This makes OptimizedSizeofConverter obsolete.
Here's a general idea of what the implementation might look like:
classCachingReference<S:Any, T:Any>(
@Volatile privatevarref:Any,
privatevalconverter:Converter<S, T>
) {
val wrapped:S
get() =
ref.let {
if (converter.wrapper.java.isAssignableFrom(it::class.java)) {
@Suppress("UNCHECKED_CAST")
it asS
} else {
@Suppress("UNCHECKED_CAST")
val converted = converter.wrap(it asT)
ref = converted
converted
}
}
val unwrapped:T
get() =
ref.let {
if (converter.wrapped.java.isAssignableFrom(it::class.java)) {
@Suppress("UNCHECKED_CAST")
it asT
} else {
@Suppress("UNCHECKED_CAST")
val converted = converter.unwrap(it asS)
ref = converted
converted
}
}
}
classCachingModelprivateconstructor(
privateval_name:CachingReference<String, ByteArray>,
privateval_uuid:CachingReference<java.util.UUID, ByteArray>,
privateval_instant:CachingReference<java.time.Instant, com.toasttab.protokt.Timestamp>,
privateval_duration:CachingReference<java.time.Duration, com.toasttab.protokt.Duration>?,
val unknown:Map<Int, Unknown>
) :KtMessage {
// Only generated if a wrapped type is usedprivateconstructor(
name:Any?,
uuid: java.util.UUID,
instant:Any?,
duration:Any?,
unknown:Map<Int, Unknown>
) :this(
CachingReference(name ?:"", StringConverter),
CachingReference(uuid, UuidConverter),
CachingReference(
requireNotNull(instant) {
"instant specified nonnull with (protokt.property).non_null but was null"
},
InstantConverter
),
duration?.let { CachingReference(it, DurationConverter) },
unknown
)
overrideval messageSize by lazy { sizeof() }
val name:String
get() =_name.wrapped
val uuid: java.util.UUID
get() =_uuid.wrapped
val instant: java.time.Instant
get() =_instant.wrapped
val duration: java.time.Duration?
get() =_duration?.wrapped
overridefunserialize(serializer:KtMessageSerializer) {
if (_name.unwrapped.isNotEmpty()) {
serializer.write(Tag(10)).write(_name.unwrapped)
}
if (_uuid.unwrapped.isNotEmpty()) {
serializer.write(Tag(18)).write(_uuid.unwrapped)
}
serializer.write(Tag(50)).write(_instant.unwrapped)
if (_duration!=null) {
serializer.write(Tag(58)).write(_duration.unwrapped)
}
if (unknown.isNotEmpty()) {
serializer.writeUnknown(unknown)
}
}
privatefunsizeof(): Int {
var res =0if (_name.unwrapped.isNotEmpty()) {
res += sizeof(Tag(1)) + sizeof(_name.unwrapped)
}
if (_uuid.unwrapped.isNotEmpty()) {
res += sizeof(Tag(2)) + sizeof(_uuid.unwrapped)
}
res += sizeof(Tag(6)) + sizeof(_instant.unwrapped)
if (_duration!=null) {
res += sizeof(Tag(7)) + sizeof(_duration.unwrapped)
}
res += unknown.values.sumBy { it.sizeof() }
return res
}
overridefunequals(other:Any?): Boolean=
other isCachingModel&&
other.name == name &&
other.uuid == uuid &&
other.instant == instant &&
other.duration == duration &&
other.unknown == unknown
overridefunhashCode(): Int {
var result = unknown.hashCode()
result =31* result + name.hashCode()
result =31* result + uuid.hashCode()
result =31* result + instant.hashCode()
result =31* result + duration.hashCode()
return result
}
overridefuntoString(): String="CachingModel("+"name=$name, "+"uuid=$uuid, "+"instant=$instant, "+"duration=$duration, "+"unknown=$unknown)"funcopy(dsl:CachingModelDsl.() ->Unit) =CachingModel4 {
name =this@CachingModel.name
uuid =this@CachingModel.uuid
instant =this@CachingModel.instant
duration =this@CachingModel.duration
unknown =this@CachingModel.unknown
dsl()
}
classCachingModelDsl {
var name =""var uuid: java.util.UUID?=nullvar instant: java.time.Instant?=nullvar duration: java.time.Duration?=nullvar unknown:Map<Int, Unknown> = emptyMap()
set(newValue) { field = copyMap(newValue) }
funbuild() =CachingModel(
name,
requireNotNull(uuid) {
"uuid wrapped and not specified and has no default value"
},
instant,
duration,
unknown
)
}
companionobject Deserializer : KtDeserializer<CachingModel>, (CachingModelDsl.() ->Unit) -> CachingModel {
overridefundeserialize(deserializer:KtMessageDeserializer): CachingModel {
var name:ByteArray?=nullvar uuid:ByteArray?=nullvar instant: com.toasttab.protokt.Timestamp?=nullvar duration: com.toasttab.protokt.Duration?=nullvar unknown:MutableMap<Int, Unknown>?=nullwhile (true) {
when (deserializer.readTag()) {
0->returnCachingModel(
name,
// Has to be done eagerly in case no default is possible and it would be illegalUuidConverter.wrap(uuid ?:Bytes.empty.bytes),
instant,
duration,
finishMap(unknown)
)
10-> name = deserializer.readByteArray()
18-> uuid = deserializer.readByteArray()
50-> instant =
deserializer.readMessage(com.toasttab.protokt.Timestamp)
58-> duration =
deserializer.readMessage(com.toasttab.protokt.Duration)
else-> unknown =
(unknown ?:mutableMapOf()).also {
processUnknown(deserializer, it)
}
}
}
}
overridefuninvoke(dsl:CachingModelDsl.() ->Unit) =CachingModelDsl().apply(dsl).build()
}
}
The text was updated successfully, but these errors were encountered:
The Java protobuf implementation cleverly caches Strings and ByteStrings when calculating message size and serializing messages. This saves a string iteration - protokt has to iterate once to find the size of a String's byte array representation, and then once to write it.
We can cache similarly and even do this for wrapper types. In fact, we can do slightly better than protobuf-java on String fields by only copying lazily and never calling CodedInputStream.readString() at all - only convert to a String when requested.
This makes OptimizedSizeofConverter obsolete.
Here's a general idea of what the implementation might look like:
The text was updated successfully, but these errors were encountered: