Skip to content

Commit

Permalink
Delegate Int|Short|Long.reverseBytes to Java Stdlib (#414)
Browse files Browse the repository at this point in the history
JVM's JIT compiler can't pattern match bytes reversal,
so it's worth explicitly delegating to Java Stdlib functions,
that are intrinsics candidates.

For long values, the new implementation shows 20% perf improvement for reversal itself.

Functions depending on it, like readXXXLe or writeXXXLe also show
some moderate performance improvement from the change.
  • Loading branch information
fzhinkin authored Nov 19, 2024
1 parent e856d57 commit ad14063
Show file tree
Hide file tree
Showing 5 changed files with 50 additions and 12 deletions.
22 changes: 10 additions & 12 deletions core/common/src/-Util.kt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2017-2023 JetBrains s.r.o. and respective authors and developers.
* Copyright 2017-2024 JetBrains s.r.o. and respective authors and developers.
* Use of this source code is governed by the Apache 2.0 license that can be found in the LICENCE file.
*/

Expand Down Expand Up @@ -52,21 +52,27 @@ internal inline fun checkByteCount(byteCount: Long) {
require(byteCount >= 0) { "byteCount ($byteCount) < 0" }
}

internal fun Short.reverseBytes(): Short {
internal expect fun Short.reverseBytes(): Short

internal inline fun Short.reverseBytesCommon(): Short {
val i = toInt() and 0xffff
val reversed = (i and 0xff00 ushr 8) or
(i and 0x00ff shl 8)
return reversed.toShort()
}

internal fun Int.reverseBytes(): Int {
internal expect fun Int.reverseBytes(): Int

internal inline fun Int.reverseBytesCommon(): Int {
return (this and -0x1000000 ushr 24) or
(this and 0x00ff0000 ushr 8) or
(this and 0x0000ff00 shl 8) or
(this and 0x000000ff shl 24)
}

internal fun Long.reverseBytes(): Long {
internal expect fun Long.reverseBytes(): Long

internal inline fun Long.reverseBytesCommon(): Long {
return (this and -0x100000000000000L ushr 56) or
(this and 0x00ff000000000000L ushr 40) or
(this and 0x0000ff0000000000L ushr 24) or
Expand All @@ -79,14 +85,6 @@ internal fun Long.reverseBytes(): Long {

/* ktlint-enable no-multi-spaces indent */

internal inline infix fun Int.leftRotate(bitCount: Int): Int {
return (this shl bitCount) or (this ushr (32 - bitCount))
}

internal inline infix fun Long.rightRotate(bitCount: Int): Long {
return (this ushr bitCount) or (this shl (64 - bitCount))
}

// Syntactic sugar.
internal inline infix fun Byte.shr(other: Int): Int = toInt() shr other

Expand Down
10 changes: 10 additions & 0 deletions core/js/src/UtilsJs.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
/*
* Copyright 2010-2024 JetBrains s.r.o. and respective authors and developers.
* Use of this source code is governed by the Apache 2.0 license that can be found in the LICENCE file.
*/

package kotlinx.io

internal actual fun Short.reverseBytes(): Short = reverseBytesCommon()
internal actual fun Int.reverseBytes(): Int = reverseBytesCommon()
internal actual fun Long.reverseBytes(): Long = reverseBytesCommon()
10 changes: 10 additions & 0 deletions core/jvm/src/-UtilsJvm.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
/*
* Copyright 2010-2024 JetBrains s.r.o. and respective authors and developers.
* Use of this source code is governed by the Apache 2.0 license that can be found in the LICENCE file.
*/

package kotlinx.io

internal actual fun Short.reverseBytes(): Short = java.lang.Short.reverseBytes(this)
internal actual fun Int.reverseBytes(): Int = java.lang.Integer.reverseBytes(this)
internal actual fun Long.reverseBytes(): Long = java.lang.Long.reverseBytes(this)
10 changes: 10 additions & 0 deletions core/native/src/UtilsNative.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
/*
* Copyright 2010-2024 JetBrains s.r.o. and respective authors and developers.
* Use of this source code is governed by the Apache 2.0 license that can be found in the LICENCE file.
*/

package kotlinx.io

internal actual fun Short.reverseBytes(): Short = reverseBytesCommon()
internal actual fun Int.reverseBytes(): Int = reverseBytesCommon()
internal actual fun Long.reverseBytes(): Long = reverseBytesCommon()
10 changes: 10 additions & 0 deletions core/wasm/src/UtilsWasm.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
/*
* Copyright 2010-2024 JetBrains s.r.o. and respective authors and developers.
* Use of this source code is governed by the Apache 2.0 license that can be found in the LICENCE file.
*/

package kotlinx.io

internal actual fun Short.reverseBytes(): Short = reverseBytesCommon()
internal actual fun Int.reverseBytes(): Int = reverseBytesCommon()
internal actual fun Long.reverseBytes(): Long = reverseBytesCommon()

0 comments on commit ad14063

Please sign in to comment.