Byte array allocation/copy hunt (#30266)

* Loads of byte array copy/allocations squashed
* Use a central place for the proto unsafe instead of ad hoc
* Extra docs on serializer toBinary about not mutating bytes after returned
* Found some more toArray:s that can potentially benefit from being unsafe
* Array handed to user callback so extra docs needed
* Unsafe reading of underlying bytes of strings fixed
This commit is contained in:
Johan Andrén 2021-06-02 17:28:37 +02:00 committed by GitHub
parent b5cbf383d6
commit e43f2be6cd
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
31 changed files with 145 additions and 98 deletions

View file

@ -10,12 +10,9 @@ import java.util
import java.util.ArrayList
import java.util.Collections
import java.util.Comparator
import scala.annotation.tailrec
import scala.collection.immutable
import scala.annotation.nowarn
import akka.actor.ActorRef
import akka.actor.ExtendedActorSystem
import akka.cluster.ddata._
@ -23,8 +20,8 @@ import akka.cluster.ddata.Replicator.Internal._
import akka.cluster.ddata.protobuf.msg.{ ReplicatedDataMessages => rd }
import akka.cluster.ddata.protobuf.msg.{ ReplicatorMessages => dm }
import akka.cluster.ddata.protobuf.msg.ReplicatorMessages.OtherMessage
import akka.protobufv3.internal.ByteString
import akka.protobufv3.internal.GeneratedMessageV3
import akka.remote.ByteStringUtils
import akka.serialization.BaseSerializer
import akka.serialization.Serialization
import akka.serialization.SerializerWithStringManifest
@ -624,7 +621,7 @@ class ReplicatedDataSerializer(val system: ExtendedActorSystem)
rd.GCounter.Entry
.newBuilder()
.setNode(uniqueAddressToProto(address))
.setValue(ByteString.copyFrom(value.toByteArray)))
.setValue(ByteStringUtils.toProtoByteStringUnsafe(value.toByteArray)))
}
b.build()
}

View file

@ -7,13 +7,11 @@ package akka.cluster.ddata.protobuf
import java.io.NotSerializableException
import java.util.concurrent.TimeUnit
import java.util.concurrent.atomic.AtomicInteger
import scala.annotation.tailrec
import scala.collection.immutable
import scala.concurrent.duration._
import scala.concurrent.duration.Duration
import scala.concurrent.duration.FiniteDuration
import akka.actor.Address
import akka.actor.ExtendedActorSystem
import akka.annotation.InternalApi
@ -28,7 +26,7 @@ import akka.cluster.ddata.Replicator._
import akka.cluster.ddata.Replicator.Internal._
import akka.cluster.ddata.VersionVector
import akka.cluster.ddata.protobuf.msg.{ ReplicatorMessages => dm }
import akka.protobufv3.internal.ByteString
import akka.remote.ByteStringUtils
import akka.serialization.BaseSerializer
import akka.serialization.Serialization
import akka.serialization.SerializerWithStringManifest
@ -267,7 +265,11 @@ class ReplicatorMessageSerializer(val system: ExtendedActorSystem)
b.setChunk(status.chunk).setTotChunks(status.totChunks)
status.digests.foreach {
case (key, digest) =>
b.addEntries(dm.Status.Entry.newBuilder().setKey(key).setDigest(ByteString.copyFrom(digest.toArray)))
b.addEntries(
dm.Status.Entry
.newBuilder()
.setKey(key)
.setDigest(ByteStringUtils.toProtoByteStringUnsafe(digest.toArrayUnsafe())))
}
status.toSystemUid.foreach(b.setToSystemUid) // can be None when sending back to a node of version 2.5.21
b.setFromSystemUid(status.fromSystemUid.get)
@ -279,7 +281,9 @@ class ReplicatorMessageSerializer(val system: ExtendedActorSystem)
val toSystemUid = if (status.hasToSystemUid) Some(status.getToSystemUid) else None
val fromSystemUid = if (status.hasFromSystemUid) Some(status.getFromSystemUid) else None
Status(
status.getEntriesList.asScala.iterator.map(e => e.getKey -> AkkaByteString(e.getDigest.toByteArray())).toMap,
status.getEntriesList.asScala.iterator
.map(e => e.getKey -> AkkaByteString.fromArrayUnsafe(e.getDigest.toByteArray()))
.toMap,
status.getChunk,
status.getTotChunks,
toSystemUid,

View file

@ -8,10 +8,8 @@ import java.io.ByteArrayInputStream
import java.io.ByteArrayOutputStream
import java.util.zip.GZIPInputStream
import java.util.zip.GZIPOutputStream
import scala.annotation.tailrec
import scala.collection.immutable.TreeMap
import akka.actor.ActorRef
import akka.actor.Address
import akka.actor.ExtendedActorSystem
@ -20,6 +18,7 @@ import akka.cluster.ddata.VersionVector
import akka.cluster.ddata.protobuf.msg.{ ReplicatorMessages => dm }
import akka.protobufv3.internal.ByteString
import akka.protobufv3.internal.MessageLite
import akka.remote.ByteStringUtils
import akka.serialization._
import akka.util.ccompat._
import akka.util.ccompat.JavaConverters._
@ -143,7 +142,7 @@ trait SerializationSupport {
val msgSerializer = serialization.findSerializerFor(m)
val builder = dm.OtherMessage
.newBuilder()
.setEnclosedMessage(ByteString.copyFrom(msgSerializer.toBinary(m)))
.setEnclosedMessage(ByteStringUtils.toProtoByteStringUnsafe(msgSerializer.toBinary(m)))
.setSerializerId(msgSerializer.identifier)
val ms = Serializers.manifestFor(msgSerializer, m)