Skip to content

perf: use Arrays.copyOf/copyOfRange instead of manual new Array + arraycopy#3150

Merged
He-Pin merged 2 commits into
mainfrom
perf/arrays-copyOf
Jun 23, 2026
Merged

perf: use Arrays.copyOf/copyOfRange instead of manual new Array + arraycopy#3150
He-Pin merged 2 commits into
mainfrom
perf/arrays-copyOf

Conversation

@He-Pin

@He-Pin He-Pin commented Jun 23, 2026

Copy link
Copy Markdown
Member

Motivation

Several places allocate a new array then immediately copy from an existing array using System.arraycopy. java.util.Arrays.copyOf and copyOfRange combine allocation and copy in a single call that the JIT can intrinsify more effectively.

Modification

  • ByteString.scala: 3 sites (clearTemp, resizeTemp, fromArray) — replace new Array[Byte] + System.arraycopy with java.util.Arrays.copyOf / copyOfRange
  • ImmutableLongMap.scala: replace full array copy with values.clone()
  • SnapshotSerializer.scala: replace partial copy with java.util.Arrays.copyOfRange

Result

Fewer lines, potentially faster due to JIT intrinsification of the combined allocate+copy operation. ByteString builder operations benefit most as they are in frequently-called paths.

Tests

  • sbt "actor/compile" "remote/compile" "persistence/compile" — passed

References

Refs #3136

…aycopy

Motivation:
Several places allocate a new array then immediately copy from an
existing array using System.arraycopy. java.util.Arrays.copyOf and
copyOfRange combine allocation and copy in a single call that the JIT
can intrinsify more effectively.

Modification:
- ByteString.scala: 3 sites — clearTemp, resizeTemp, fromArray
  replace new Array[Byte] + System.arraycopy with
  java.util.Arrays.copyOf / copyOfRange
- ImmutableLongMap.scala: replace full array copy with values.clone()
- SnapshotSerializer.scala: replace partial copy with
  java.util.Arrays.copyOfRange

Result:
Fewer lines, potentially faster due to JIT intrinsification of the
combined allocate+copy operation. ByteString builder operations
benefit most as they are in frequently-called paths.

Tests:
sbt "actor/compile" "remote/compile" "persistence/compile" — passed

References:
Refs #3136
…zeTemp

Motivation:
`ByteStringBuilder._temp` is initially `null` until the first call to
`++=` or `putByte`. `resizeTemp` was unconditionally calling
`java.util.Arrays.copyOf(_temp, size)` which throws
`NullPointerException` when passed a `null` source array. This bug was
introduced by the earlier "perf: use Arrays.copyOf/copyOfRange" commit
in the same PR, which replaced the previous `new Array[Byte](size)`
followed by `System.arraycopy(src, 0, dst, 0, n)` pattern — the old
pattern was safe because the arraycopy length was `0` when `_temp` was
`null`, masking the missing null check.

Modification:
Guard the call with `if (_temp eq null) new Array[Byte](size) else
java.util.Arrays.copyOf(_temp, size)`, so the first resize allocates a
fresh array and subsequent resizes retain the copyOf fast path.

Result:
`ByteStringBuilder` no longer throws NPE on the very first write when
the internal buffer has not yet been allocated.

Tests:
sbt "actor/compile" -- passed
sbt "actor-tests/Test/testOnly *ByteStringSpec" -- passed (relevant
directional tests; the NPE was also reachable from stream/Pekko usage).

References:
Discovered during internal review of PR #3150.

@pjfanning pjfanning left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm

@pjfanning pjfanning left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tests are broken

@pjfanning pjfanning left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm

@He-Pin
He-Pin merged commit 58a9bf0 into main Jun 23, 2026
9 checks passed
@He-Pin
He-Pin deleted the perf/arrays-copyOf branch June 23, 2026 10:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants