This is an automated email from the ASF dual-hosted git repository.

anton-vinogradov pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ignite.git


The following commit(s) were added to refs/heads/master by this push:
     new 090bc163559 IGNITE-28836 DirectMessageWriter: reduce per-field 
overhead and per-message allocations on the message serialization hot path 
(#13296)
090bc163559 is described below

commit 090bc163559688361c1d1ab70e542a9611984bad
Author: Anton Vinogradov <[email protected]>
AuthorDate: Tue Jul 14 20:38:08 2026 +0300

    IGNITE-28836 DirectMessageWriter: reduce per-field overhead and per-message 
allocations on the message serialization hot path (#13296)
---
 .../internal/direct/DirectMessageWriter.java       | 118 +++++++++++++--------
 1 file changed, 73 insertions(+), 45 deletions(-)

diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/direct/DirectMessageWriter.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/direct/DirectMessageWriter.java
index 134e11f53cd..319aae7b7e9 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/direct/DirectMessageWriter.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/direct/DirectMessageWriter.java
@@ -67,6 +67,18 @@ public class DirectMessageWriter implements MessageWriter {
     /** Buffer for writing. */
     private ByteBuffer buf;
 
+    /**
+     * Cached stream of the current state item. Avoids re-resolving {@code 
state.item().stream} on every primitive
+     * write; updated only when the current item changes (buffer set / nested 
write enter or exit).
+     */
+    private DirectByteBufferStream curStream;
+
+    /** Reusable writer for compressed payload serialization. Lazily created; 
thread-confined like the writer itself. */
+    private DirectMessageWriter tmpWriter;
+
+    /** Reusable scratch buffer for compressed payload serialization. Retained 
at the largest size seen so far. */
+    private ByteBuffer tmpBuf;
+
     /** @param msgFactory Message factory. */
     public DirectMessageWriter(final MessageFactory msgFactory) {
         this(msgFactory, DFLT_NETWORK_COMPRESSION);
@@ -91,7 +103,9 @@ public class DirectMessageWriter implements MessageWriter {
     @Override public void setBuffer(ByteBuffer buf) {
         this.buf = buf;
 
-        state.item().stream.setBuffer(buf);
+        curStream = state.item().stream;
+
+        curStream.setBuffer(buf);
     }
 
     /**
@@ -105,7 +119,7 @@ public class DirectMessageWriter implements MessageWriter {
 
     /** {@inheritDoc} */
     @Override public boolean writeHeader(short type) {
-        DirectByteBufferStream stream = state.item().stream;
+        DirectByteBufferStream stream = curStream;
 
         stream.writeShort(type);
 
@@ -114,7 +128,7 @@ public class DirectMessageWriter implements MessageWriter {
 
     /** {@inheritDoc} */
     @Override public boolean writeByte(byte val) {
-        DirectByteBufferStream stream = state.item().stream;
+        DirectByteBufferStream stream = curStream;
 
         stream.writeByte(val);
 
@@ -123,7 +137,7 @@ public class DirectMessageWriter implements MessageWriter {
 
     /** {@inheritDoc} */
     @Override public boolean writeShort(short val) {
-        DirectByteBufferStream stream = state.item().stream;
+        DirectByteBufferStream stream = curStream;
 
         stream.writeShort(val);
 
@@ -132,7 +146,7 @@ public class DirectMessageWriter implements MessageWriter {
 
     /** {@inheritDoc} */
     @Override public boolean writeInt(int val) {
-        DirectByteBufferStream stream = state.item().stream;
+        DirectByteBufferStream stream = curStream;
 
         stream.writeInt(val);
 
@@ -141,7 +155,7 @@ public class DirectMessageWriter implements MessageWriter {
 
     /** {@inheritDoc} */
     @Override public boolean writeLong(long val) {
-        DirectByteBufferStream stream = state.item().stream;
+        DirectByteBufferStream stream = curStream;
 
         stream.writeLong(val);
 
@@ -150,7 +164,7 @@ public class DirectMessageWriter implements MessageWriter {
 
     /** {@inheritDoc} */
     @Override public boolean writeFloat(float val) {
-        DirectByteBufferStream stream = state.item().stream;
+        DirectByteBufferStream stream = curStream;
 
         stream.writeFloat(val);
 
@@ -159,7 +173,7 @@ public class DirectMessageWriter implements MessageWriter {
 
     /** {@inheritDoc} */
     @Override public boolean writeDouble(double val) {
-        DirectByteBufferStream stream = state.item().stream;
+        DirectByteBufferStream stream = curStream;
 
         stream.writeDouble(val);
 
@@ -168,7 +182,7 @@ public class DirectMessageWriter implements MessageWriter {
 
     /** {@inheritDoc} */
     @Override public boolean writeChar(char val) {
-        DirectByteBufferStream stream = state.item().stream;
+        DirectByteBufferStream stream = curStream;
 
         stream.writeChar(val);
 
@@ -177,7 +191,7 @@ public class DirectMessageWriter implements MessageWriter {
 
     /** {@inheritDoc} */
     @Override public boolean writeBoolean(boolean val) {
-        DirectByteBufferStream stream = state.item().stream;
+        DirectByteBufferStream stream = curStream;
 
         stream.writeBoolean(val);
 
@@ -186,7 +200,7 @@ public class DirectMessageWriter implements MessageWriter {
 
     /** {@inheritDoc} */
     @Override public boolean writeByteArray(@Nullable byte[] val) {
-        DirectByteBufferStream stream = state.item().stream;
+        DirectByteBufferStream stream = curStream;
 
         stream.writeByteArray(val);
 
@@ -195,7 +209,7 @@ public class DirectMessageWriter implements MessageWriter {
 
     /** {@inheritDoc} */
     @Override public boolean writeByteArray(byte[] val, long off, int len) {
-        DirectByteBufferStream stream = state.item().stream;
+        DirectByteBufferStream stream = curStream;
 
         stream.writeByteArray(val, off, len);
 
@@ -204,7 +218,7 @@ public class DirectMessageWriter implements MessageWriter {
 
     /** {@inheritDoc} */
     @Override public boolean writeShortArray(@Nullable short[] val) {
-        DirectByteBufferStream stream = state.item().stream;
+        DirectByteBufferStream stream = curStream;
 
         stream.writeShortArray(val);
 
@@ -213,7 +227,7 @@ public class DirectMessageWriter implements MessageWriter {
 
     /** {@inheritDoc} */
     @Override public boolean writeIntArray(@Nullable int[] val) {
-        DirectByteBufferStream stream = state.item().stream;
+        DirectByteBufferStream stream = curStream;
 
         stream.writeIntArray(val);
 
@@ -222,7 +236,7 @@ public class DirectMessageWriter implements MessageWriter {
 
     /** {@inheritDoc} */
     @Override public boolean writeLongArray(@Nullable long[] val) {
-        DirectByteBufferStream stream = state.item().stream;
+        DirectByteBufferStream stream = curStream;
 
         stream.writeLongArray(val);
 
@@ -231,7 +245,7 @@ public class DirectMessageWriter implements MessageWriter {
 
     /** {@inheritDoc} */
     @Override public boolean writeLongArray(long[] val, int len) {
-        DirectByteBufferStream stream = state.item().stream;
+        DirectByteBufferStream stream = curStream;
 
         stream.writeLongArray(val, len);
 
@@ -240,7 +254,7 @@ public class DirectMessageWriter implements MessageWriter {
 
     /** {@inheritDoc} */
     @Override public boolean writeFloatArray(@Nullable float[] val) {
-        DirectByteBufferStream stream = state.item().stream;
+        DirectByteBufferStream stream = curStream;
 
         stream.writeFloatArray(val);
 
@@ -249,7 +263,7 @@ public class DirectMessageWriter implements MessageWriter {
 
     /** {@inheritDoc} */
     @Override public boolean writeDoubleArray(@Nullable double[] val) {
-        DirectByteBufferStream stream = state.item().stream;
+        DirectByteBufferStream stream = curStream;
 
         stream.writeDoubleArray(val);
 
@@ -258,7 +272,7 @@ public class DirectMessageWriter implements MessageWriter {
 
     /** {@inheritDoc} */
     @Override public boolean writeCharArray(@Nullable char[] val) {
-        DirectByteBufferStream stream = state.item().stream;
+        DirectByteBufferStream stream = curStream;
 
         stream.writeCharArray(val);
 
@@ -267,7 +281,7 @@ public class DirectMessageWriter implements MessageWriter {
 
     /** {@inheritDoc} */
     @Override public boolean writeBooleanArray(@Nullable boolean[] val) {
-        DirectByteBufferStream stream = state.item().stream;
+        DirectByteBufferStream stream = curStream;
 
         stream.writeBooleanArray(val);
 
@@ -276,7 +290,7 @@ public class DirectMessageWriter implements MessageWriter {
 
     /** {@inheritDoc} */
     @Override public boolean writeString(String val) {
-        DirectByteBufferStream stream = state.item().stream;
+        DirectByteBufferStream stream = curStream;
 
         stream.writeString(val);
 
@@ -285,7 +299,7 @@ public class DirectMessageWriter implements MessageWriter {
 
     /** {@inheritDoc} */
     @Override public boolean writeBitSet(BitSet val) {
-        DirectByteBufferStream stream = state.item().stream;
+        DirectByteBufferStream stream = curStream;
 
         stream.writeBitSet(val);
 
@@ -294,7 +308,7 @@ public class DirectMessageWriter implements MessageWriter {
 
     /** {@inheritDoc} */
     @Override public boolean writeUuid(UUID val) {
-        DirectByteBufferStream stream = state.item().stream;
+        DirectByteBufferStream stream = curStream;
 
         stream.writeUuid(val);
 
@@ -303,7 +317,7 @@ public class DirectMessageWriter implements MessageWriter {
 
     /** {@inheritDoc} */
     @Override public boolean writeIgniteUuid(IgniteUuid val) {
-        DirectByteBufferStream stream = state.item().stream;
+        DirectByteBufferStream stream = curStream;
 
         stream.writeIgniteUuid(val);
 
@@ -312,7 +326,7 @@ public class DirectMessageWriter implements MessageWriter {
 
     /** {@inheritDoc} */
     @Override public boolean 
writeAffinityTopologyVersion(AffinityTopologyVersion val) {
-        DirectByteBufferStream stream = state.item().stream;
+        DirectByteBufferStream stream = curStream;
 
         stream.writeAffinityTopologyVersion(val);
 
@@ -321,11 +335,11 @@ public class DirectMessageWriter implements MessageWriter 
{
 
     /** {@inheritDoc} */
     @Override public boolean writeMessage(@Nullable Message msg, boolean 
compress) {
-        DirectByteBufferStream stream = state.item().stream;
+        DirectByteBufferStream stream = curStream;
 
         if (compress)
             writeCompressedMessage(
-                tmpWriter -> tmpWriter.state.item().stream.writeMessage(msg, 
tmpWriter),
+                w -> w.state.item().stream.writeMessage(msg, w),
                 msg == null,
                 stream
             );
@@ -337,7 +351,7 @@ public class DirectMessageWriter implements MessageWriter {
 
     /** {@inheritDoc} */
     @Override public boolean writeCacheObject(@Nullable CacheObject obj) {
-        DirectByteBufferStream stream = state.item().stream;
+        DirectByteBufferStream stream = curStream;
 
         stream.writeCacheObject(obj);
 
@@ -346,7 +360,7 @@ public class DirectMessageWriter implements MessageWriter {
 
     /** {@inheritDoc} */
     @Override public boolean writeKeyCacheObject(KeyCacheObject obj) {
-        DirectByteBufferStream stream = state.item().stream;
+        DirectByteBufferStream stream = curStream;
 
         stream.writeKeyCacheObject(obj);
 
@@ -355,7 +369,7 @@ public class DirectMessageWriter implements MessageWriter {
 
     /** {@inheritDoc} */
     @Override public boolean writeGridLongList(@Nullable GridLongList ll) {
-        DirectByteBufferStream stream = state.item().stream;
+        DirectByteBufferStream stream = curStream;
 
         stream.writeGridLongList(ll);
 
@@ -364,7 +378,7 @@ public class DirectMessageWriter implements MessageWriter {
 
     /** {@inheritDoc} */
     @Override public <T> boolean writeObjectArray(T[] arr, MessageArrayType 
type) {
-        DirectByteBufferStream stream = state.item().stream;
+        DirectByteBufferStream stream = curStream;
 
         stream.writeObjectArray(arr, type, this);
 
@@ -373,7 +387,7 @@ public class DirectMessageWriter implements MessageWriter {
 
     /** {@inheritDoc} */
     @Override public <T> boolean writeCollection(Collection<T> col, 
MessageCollectionType type) {
-        DirectByteBufferStream stream = state.item().stream;
+        DirectByteBufferStream stream = curStream;
 
         stream.writeCollection(col, type, this);
 
@@ -382,11 +396,11 @@ public class DirectMessageWriter implements MessageWriter 
{
 
     /** {@inheritDoc} */
     @Override public <K, V> boolean writeMap(Map<K, V> map, MessageMapType 
type, boolean compress) {
-        DirectByteBufferStream stream = state.item().stream;
+        DirectByteBufferStream stream = curStream;
 
         if (compress)
             writeCompressedMessage(
-                tmpWriter -> tmpWriter.state.item().stream.writeMap(map, type, 
tmpWriter),
+                w -> w.state.item().stream.writeMap(map, type, w),
                 map == null,
                 stream
             );
@@ -398,7 +412,7 @@ public class DirectMessageWriter implements MessageWriter {
 
     /** {@inheritDoc} */
     @Override public boolean writeIgniteProductVersion(IgniteProductVersion 
ver) {
-        DirectByteBufferStream stream = state.item().stream;
+        DirectByteBufferStream stream = curStream;
 
         stream.writeIgniteProductVersion(ver);
 
@@ -407,7 +421,7 @@ public class DirectMessageWriter implements MessageWriter {
 
     /** {@inheritDoc} */
     @Override public boolean writeGridCacheVersion(GridCacheVersion ver) {
-        DirectByteBufferStream stream = state.item().stream;
+        DirectByteBufferStream stream = curStream;
 
         stream.writeGridCacheVersion(ver);
 
@@ -443,12 +457,18 @@ public class DirectMessageWriter implements MessageWriter 
{
     @Override public void beforeNestedWrite() {
         state.forward();
 
-        state.item().stream.setBuffer(buf);
+        curStream = state.item().stream;
+
+        curStream.setBuffer(buf);
     }
 
     /** {@inheritDoc} */
     @Override public void afterNestedWrite(boolean finished) {
         state.backward(finished);
+
+        curStream = state.item().stream;
+
+        curStream.setBuffer(buf);
     }
 
     /** {@inheritDoc} */
@@ -474,9 +494,19 @@ public class DirectMessageWriter implements MessageWriter {
         }
 
         if (!stream.serializeFinished()) {
-            ByteBuffer tmpBuf = ByteBuffer.allocateDirect(TMP_BUF_CAPACITY);
-
-            DirectMessageWriter tmpWriter = new 
DirectMessageWriter(msgFactory, compressionLvl);
+            // CompressedMessage consumes the scratch buffer in its 
constructor (deflates into its own byte array),
+            // so the buffer never escapes this method and can be reused 
across fields; heap is cheaper than direct
+            // here (no native alloc / Cleaner churn).
+            if (tmpBuf == null)
+                tmpBuf = ByteBuffer.allocate(TMP_BUF_CAPACITY);
+            else
+                tmpBuf.clear();
+
+            // Reuse the temp writer across fields/messages instead of 
allocating a fresh state stack each time.
+            if (tmpWriter == null)
+                tmpWriter = new DirectMessageWriter(msgFactory, 
compressionLvl);
+            else
+                tmpWriter.reset();
 
             tmpWriter.setBuffer(tmpBuf);
 
@@ -484,14 +514,12 @@ public class DirectMessageWriter implements MessageWriter 
{
 
             do {
                 if (tmpBuf.remaining() <= tmpBuf.capacity() / 10) {
-                    byte[] bytes = new byte[tmpBuf.position()];
+                    ByteBuffer newBuf = ByteBuffer.allocate(tmpBuf.capacity() 
* 2);
 
                     tmpBuf.flip();
-                    tmpBuf.get(bytes);
-
-                    tmpBuf = ByteBuffer.allocateDirect(tmpBuf.capacity() * 2);
+                    newBuf.put(tmpBuf);
 
-                    tmpBuf.put(bytes);
+                    tmpBuf = newBuf;
 
                     tmpWriter.setBuffer(tmpBuf);
                 }

Reply via email to