Skip to content

Commit

Permalink
Merge pull request #23 from ScorexFoundation/alloc-optimizations
Browse files Browse the repository at this point in the history
Allocation optimizations
  • Loading branch information
aslesarenko authored Oct 15, 2020
2 parents 3dc334f + 46d58b5 commit ee9a2b9
Show file tree
Hide file tree
Showing 4 changed files with 30 additions and 7 deletions.
9 changes: 5 additions & 4 deletions src/main/scala/scorex/util/encode/Base16.scala
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,11 @@ object Base16 extends BytesEncoder {
}

def decode(input: String): Try[Array[Byte]] = {
var (isError, errorMsg) = if (input.length % 2 == 0) {
(false, "")
} else {
(true, s"invalid length ${input.length} of Hex data")
var isError = false
var errorMsg = ""
if (input.length % 2 != 0) {
isError = true
errorMsg = s"invalid length ${input.length} of Hex data"
}

val out = Array.ofDim[Byte](input.length / 2)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,11 @@ class VLQByteBufferWriter(b: ByteArrayBuilder) extends Writer with VLQWriter {
this
}

@inline override def putBytes(xs: Array[Byte], offset: Int, length: Int): this.type = {
b.append(xs, offset, length)
this
}

@inline override def length(): Int = b.length()

@inline override def result(): ByteArrayBuilder = b
Expand Down
15 changes: 12 additions & 3 deletions src/main/scala/scorex/util/serialization/VLQWriter.scala
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ trait VLQWriter extends Writer {
if ((value & ~0x7FL) == 0) {
buffer(position) = value.asInstanceOf[Byte]
position += 1
putBytes(util.Arrays.copyOf(buffer, position))
putBytes(buffer, 0, position)
return this
} else {
buffer(position) = ((value.asInstanceOf[Int] & 0x7F) | 0x80).toByte
Expand All @@ -116,10 +116,19 @@ trait VLQWriter extends Writer {
// see https://rosettacode.org/wiki/Variable-length_quantity for implementations in other languages
}

// TODO optimize: it is possible to further significantly optimize this method
// by directly packing bits into bytes and putting bytes into the writer.
// this can be done without any additional memory garbage (BitSet, toByteArray, copyOf).
@inline override def putBits(xs: Array[Boolean]): this.type = {
if (xs.isEmpty) return this
val bitSet = new util.BitSet(xs.length)
xs.zipWithIndex.foreach { case (bool, i) => bitSet.set(i, bool)}
val len = xs.length
val bitSet = new util.BitSet(len)
var i = 0
while (i < len) {
val bool = xs(i)
bitSet.set(i, bool)
i += 1
}
// pad the byte array to fix the "no bit was set" behaviour
// see https://stackoverflow.com/questions/11209600/how-do-i-convert-a-bitset-initialized-with-false-in-a-byte-containing-0-in-java
val bytes = util.Arrays.copyOf(bitSet.toByteArray, (xs.length + 7) / 8)
Expand Down
8 changes: 8 additions & 0 deletions src/main/scala/scorex/util/serialization/Writer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,14 @@ trait Writer {
*/
def putBytes(xs: Array[Byte]): this.type

/**
* Encode a slice of array of bytes.
* @param xs an array to take bytes from
* @param offset first byte of the slice
* @param length of the slice (number of bytes)
*/
def putBytes(xs: Array[Byte], offset: Int, length: Int): this.type

/**
* Encode an array of boolean values as a bit array
*
Expand Down

0 comments on commit ee9a2b9

Please sign in to comment.