@kstokoz wrote:
Hi Akka Team,
I was recently doing performance optimization for our project which is using Akka Http and was looking into ByteString.compact method for specifically
ByteStrings
class:final class ByteStrings private (private[akka] val bytestrings: Vector[ByteString1], val length: Int) extends ByteString { .... def compact: CompactByteString = { if (isCompact) bytestrings.head.compact else { val ar = new Array[Byte](length) var pos = 0 bytestrings.foreach { b => b.copyToArray(ar, pos, b.length) pos += b.length } ByteString1C(ar) } }
uses
copyToArray
which delegates toIterableOnce
which is coyping byte by byte in the loop.I`m wondering have you considered using ByteBuffer instead of Array like this:
def compact: CompactByteString = { if (isCompact) bytestrings.head.compact else { val bb = ByteBuffer.alocate(length) bytestrings.foreach { b => bb.put(b.asByteBuffer) } ByteString1C(bb.array()) } }
which would be using
ByteBuffer.put()
which is optimised if both ByteBuffers (source and destination) are instance of HeapByteBuffer to use bulk copy?public ByteBuffer put(ByteBuffer src) { if (src instanceof HeapByteBuffer) { if (src == this) throw createSameBufferException(); HeapByteBuffer sb = (HeapByteBuffer)src; int n = sb.remaining(); if (n > remaining()) throw new BufferOverflowException(); System.arraycopy(sb.hb, sb.ix(sb.position()), hb, ix(position()), n); sb.position(sb.position() + n); position(position() + n); } else if (src.isDirect()) { int n = src.remaining(); if (n > remaining()) throw new BufferOverflowException(); src.get(hb, ix(position()), n); position(position() + n); } else { super.put(src); } return this; }
In Akka HTTP I think it would give a lot of improvements when parsing incoming http message (as those bytestring already backed with HeapByteBuffer) when dealing with TLS and in Framing where
ByteString.compact
is used a lot.Regards,
Kyrylo
Posts: 2
Participants: 2