belliottsmith commented on code in PR #4321:
URL: https://github.com/apache/cassandra/pull/4321#discussion_r2285179899


##########
src/java/org/apache/cassandra/service/accord/serializers/DepsSerializers.java:
##########
@@ -74,164 +83,294 @@ public DepsSerializer(UnversionedSerializer<Range> 
tokenRange)
         @Override
         public void serialize(D deps, DataOutputPlus out) throws IOException
         {
+            boolean keysByTxnId = forceByTxnId || deps.keyDeps.hasByTxnId();
+            boolean rangesByTxnId = forceByTxnId || 
deps.rangeDeps.hasByTxnId();
+            out.writeUnsignedVInt32((keysByTxnId ? KEYS_BY_TXNID : 0) | 
(rangesByTxnId ? RANGES_BY_TXNID : 0));
             {
                 KeyDeps keyDeps = deps.keyDeps;
                 KeySerializers.routingKeys.serialize(keyDeps.keys(), out);
-                int txnIdCount = keyDeps.txnIdCount();
-                out.writeUnsignedVInt32(txnIdCount);
-                for (int i = 0; i < txnIdCount; i++)
-                    CommandSerializers.txnId.serialize(keyDeps.txnId(i), out);
-
-                int keysToTxnIdsCount = keysToTxnIdsCount(keyDeps);
-                out.writeUnsignedVInt32(keysToTxnIdsCount);
-                for (int i = 0; i < keysToTxnIdsCount; i++)
-                    out.writeUnsignedVInt32(keysToTxnIds(keyDeps, i));
+                
CommandSerializers.txnId.serializeArray(KeyDeps.SerializerSupport.txnIds(keyDeps),
 out);
+                if (keysByTxnId) serializePackedXtoY(txnIdsToKeys(keyDeps), 
keyDeps.txnIdCount(), keyDeps.keys().size(), out);
+                else serializePackedXtoY(keysToTxnIds(keyDeps), 
keyDeps.keys().size(), keyDeps.txnIdCount(), out);
             }
             {
                 RangeDeps rangeDeps = deps.rangeDeps;
-                int rangeCount = rangeDeps.rangeCount();
-                out.writeUnsignedVInt32(rangeCount);
-                for (int i = 0; i < rangeCount; i++)
-                    tokenRange.serialize(rangeDeps.range(i), out);
-
-                int txnIdCount = rangeDeps.txnIdCount();
-                out.writeUnsignedVInt32(txnIdCount);
-                for (int i = 0; i < txnIdCount; i++)
-                    CommandSerializers.txnId.serialize(rangeDeps.txnId(i), 
out);
-
-                int rangesToTxnIdsCount = rangesToTxnIdsCount(rangeDeps);
-                out.writeUnsignedVInt32(rangesToTxnIdsCount);
-                for (int i = 0; i < rangesToTxnIdsCount; i++)
-                    out.writeUnsignedVInt32(rangesToTxnIds(rangeDeps, i));
+                KeySerializers.rangeArray.serialize(ranges(rangeDeps), out);
+                
CommandSerializers.txnId.serializeArray(RangeDeps.SerializerSupport.txnIds(rangeDeps),
 out);
+                if (rangesByTxnId) 
serializePackedXtoY(txnIdsToRanges(rangeDeps), rangeDeps.txnIdCount(), 
rangeDeps.rangeCount(), out);
+                else serializePackedXtoY(rangesToTxnIds(rangeDeps), 
rangeDeps.rangeCount(), rangeDeps.txnIdCount(), out);
             }
         }
 
+        private static void serializePackedXtoY(int[] xtoy, int xCount, int 
yCount, DataOutputPlus out) throws IOException
+        {
+            out.writeUnsignedVInt32(xtoy.length);
+
+            if ((xCount <= 1 || yCount <= 1) && (xtoy.length == xCount + 
yCount || xCount == 0 || yCount == 0))
+            {
+                // no point serializing as can be directly inferred
+                if (Invariants.isParanoid())
+                {
+                    if (xCount == 1)
+                    {
+                        Invariants.require(xtoy[0] == xtoy.length, "%d != %d", 
xtoy[0], xtoy.length);
+                        for (int i = 0 ; i < yCount ; ++i) 
Invariants.require(xtoy[1 + i] == i, "%d != %d", xtoy[1 + i], i);
+                    }
+                    else if (yCount == 1)
+                    {
+                        for (int i = 0 ; i < xCount ; ++i) 
Invariants.require(xtoy[i] == xCount + i + 1, "%d != %d", xtoy[i], xCount + i + 
1);
+                        for (int i = xCount ; i < xtoy.length ; ++i) 
Invariants.require(xtoy[i] == 0, "%d != %d", xtoy[i], 0);
+                    }
+                    else if (yCount == 0)
+                    {
+                        for (int i = 0 ; i < xCount ; ++i) 
Invariants.require(xtoy[i] == xCount, "%d != %d", xtoy[i], xCount);
+                    }
+                    else
+                    {
+                        Invariants.require(xtoy.length == 0);
+                    }
+                }
+            }
+            else
+            {
+                serializePackedInts(xtoy, 0, xCount, xtoy.length, out);
+                serializePackedInts(xtoy, xCount, xtoy.length, yCount - 1, 
out);
+            }
+        }
+
+        private static void serializePackedInts(int[] vs, int from, int to, 
int max, DataOutputPlus out) throws IOException
+        {
+            int bitsPerEntry = BitUtils.numberOfBitsToRepresent(max);
+            long buffer = 0L;
+            int bufferCount = 0;
+            for (int i = from; i < to; i++)
+            {
+                Invariants.require(vs[i] <= max);
+                buffer |= (long)vs[i] << bufferCount;
+                bufferCount = bufferCount + bitsPerEntry;
+                if (bufferCount >= 64)
+                {
+                    out.writeLong(buffer);
+                    bufferCount -= 64;
+                    buffer = vs[i] >>> (bitsPerEntry - bufferCount);
+                }
+            }
+            if (bufferCount > 0)
+                out.writeLeastSignificantBytes(buffer, (bufferCount + 7) / 8);
+        }
+
         @Override
         public D deserialize(DataInputPlus in) throws IOException
         {
+            int flags = in.readUnsignedVInt32();
             KeyDeps keyDeps;
             {
                 RoutingKeys keys = KeySerializers.routingKeys.deserialize(in);
-                int txnIdCount = in.readUnsignedVInt32();
-                TxnId[] txnIds = new TxnId[txnIdCount];
-                for (int i = 0; i < txnIdCount; i++)
-                    txnIds[i] = CommandSerializers.txnId.deserialize(in);
-
-                int keysToTxnIdsCount = in.readUnsignedVInt32();
-                int[] keysToTxnIds = new int[keysToTxnIdsCount];
-                for (int i = 0; i < keysToTxnIdsCount; i++)
-                    keysToTxnIds[i] = in.readUnsignedVInt32();
-
-                keyDeps = KeyDeps.SerializerSupport.create(keys, txnIds, 
keysToTxnIds);
+                TxnId[] txnIds = 
CommandSerializers.txnId.deserializeArray(TxnId[]::new, in);
+                int[] txnIdsToKeys = null, keysToTxnIds = null;
+                if (0 != (flags & KEYS_BY_TXNID)) txnIdsToKeys = 
deserializePackedXtoY(txnIds.length, keys.size(), in);
+                else keysToTxnIds = deserializePackedXtoY(keys.size(), 
txnIds.length, in);
+                keyDeps = KeyDeps.SerializerSupport.create(keys, txnIds, 
keysToTxnIds, txnIdsToKeys);
             }
 
             RangeDeps rangeDeps;
             {
-                int rangeCount = Ints.checkedCast(in.readUnsignedVInt32());
-                Range[] ranges = new Range[rangeCount];
-                for (int i = 0; i < rangeCount; i++)
-                    ranges[i] = tokenRange.deserialize(in);
-
-                int txnIdCount = in.readUnsignedVInt32();
-                TxnId[] txnIds = new TxnId[txnIdCount];
-                for (int i = 0; i < txnIdCount; i++)
-                    txnIds[i] = CommandSerializers.txnId.deserialize(in);
-
-                int rangesToTxnIdsCount = in.readUnsignedVInt32();
-                int[] rangesToTxnIds = new int[rangesToTxnIdsCount];
-                for (int i = 0; i < rangesToTxnIdsCount; i++)
-                    rangesToTxnIds[i] = in.readUnsignedVInt32();
-
-                rangeDeps = RangeDeps.SerializerSupport.create(ranges, txnIds, 
rangesToTxnIds);
+                Range[] ranges = KeySerializers.rangeArray.deserialize(in);
+                TxnId[] txnIds = 
CommandSerializers.txnId.deserializeArray(TxnId[]::new, in);
+                int[] txnIdsToRanges = null, rangesToTxnIds = null;
+                if (0 != (flags & RANGES_BY_TXNID)) txnIdsToRanges = 
deserializePackedXtoY(txnIds.length, ranges.length, in);
+                else rangesToTxnIds = deserializePackedXtoY(ranges.length, 
txnIds.length, in);
+                rangeDeps = RangeDeps.SerializerSupport.create(ranges, txnIds, 
rangesToTxnIds, txnIdsToRanges);
             }
             return deserialize(keyDeps, rangeDeps, in);
         }
 
+        private static int[] deserializePackedXtoY(int xCount, int yCount, 
DataInputPlus in) throws IOException
+        {
+            int length = in.readUnsignedVInt32();
+            int[] xtoy = new int[length];
+
+            if ((xCount <= 1 || yCount <= 1) && (xtoy.length == xCount + 
yCount || xCount == 0 || yCount == 0))
+            {
+                // no point serializing as can be directly inferred
+                if (xCount == 1)
+                {
+                    xtoy[0] = xtoy.length;
+                    for (int i = 0 ; i < yCount ; ++i)
+                        xtoy[1 + i] = i;
+                }
+                else if (yCount == 1)
+                {
+                    for (int i = 0 ; i < xCount ; ++i)
+                        xtoy[i] = xCount + i + 1;
+                }
+                else if (yCount == 0)
+                {
+                    for (int i = 0 ; i < xCount ; ++i)
+                        xtoy[i] = xCount;
+                }
+                else
+                {
+                    Invariants.require(length == 0);
+                }
+            }
+            else
+            {
+                deserializePackedInts(xtoy, 0, xCount, xtoy.length, in);
+                deserializePackedInts(xtoy, xCount, xtoy.length, yCount - 1, 
in);
+            }
+            return xtoy;
+        }
+
+        private static void deserializePackedInts(int[] vs, int from, int to, 
int max, DataInputPlus in) throws IOException
+        {
+            int bitsPerEntry = BitUtils.numberOfBitsToRepresent(max);
+            int mask = -1 >>> (32 - bitsPerEntry);
+            int remainingBytes = (bitsPerEntry * (to - from) + 7) / 8;
+            long buffer = 0L;
+            int bufferCount = 0;
+            for (int i = from; i < to; i++)
+            {
+                int v = (int)buffer & mask;
+                if (bufferCount >= bitsPerEntry)
+                {
+                    bufferCount -= bitsPerEntry;
+                    buffer >>>= bitsPerEntry;
+                }
+                else
+                {
+                    int newBufferCount;
+                    if (remainingBytes >= 8)
+                    {
+                        buffer = in.readLong();
+                        newBufferCount = 64;
+                        remainingBytes -= 8;
+                    }
+                    else
+                    {
+                        Invariants.require(remainingBytes > 0);
+                        newBufferCount = remainingBytes * 8;
+                        buffer = in.readLeastSignificantBytes(remainingBytes);
+                        remainingBytes = 0;
+                    }
+                    int readExtra = bitsPerEntry - bufferCount;
+                    int extraBits = (int)buffer & (mask >>> bufferCount);
+                    v |= extraBits << bufferCount;
+                    bufferCount = newBufferCount - readExtra;
+                    buffer >>>= readExtra;
+                }
+                Invariants.require(v <= max);
+                vs[i] = v;
+            }
+        }
+
         @Override
         public long serializedSize(D deps)
         {
-            long size;
+            boolean keysByTxnId = forceByTxnId || deps.keyDeps.hasByTxnId();
+            boolean rangesByTxnId = forceByTxnId || 
deps.rangeDeps.hasByTxnId();
+            long size = 1;
             {
                 KeyDeps keyDeps = deps.keyDeps;
-                size = 
KeySerializers.routingKeys.serializedSize(deps.keyDeps.keys());
-                int txnIdCount = keyDeps.txnIdCount();
-                size += sizeofUnsignedVInt(txnIdCount);
-                for (int i = 0; i < txnIdCount; i++)
-                    size += 
CommandSerializers.txnId.serializedSize(keyDeps.txnId(i));
-
-                int keysToTxnIdsCount = keysToTxnIdsCount(keyDeps);
-                size += sizeofUnsignedVInt(keysToTxnIdsCount);
-                for (int i = 0; i < keysToTxnIdsCount; i++)
-                    size += sizeofUnsignedVInt(keysToTxnIds(keyDeps, i));
+                size += 
KeySerializers.routingKeys.serializedSize(keyDeps.keys());
+                size += 
CommandSerializers.txnId.serializedArraySize(KeyDeps.SerializerSupport.txnIds(keyDeps));
+                size += keysByTxnId ? 
serializedPackedXtoYSize(txnIdsToKeys(keyDeps), keyDeps.txnIdCount(), 
keyDeps.keys().size())
+                                    : 
serializedPackedXtoYSize(keysToTxnIds(keyDeps), keyDeps.keys().size(), 
keyDeps.txnIdCount());
             }
-
             {
                 RangeDeps rangeDeps = deps.rangeDeps;
-                int rangeCount = rangeDeps.rangeCount();
-                size += sizeofUnsignedVInt(rangeCount);
-                for (int i = 0; i < rangeCount; ++i)
-                    size += tokenRange.serializedSize(rangeDeps.range(i));
-
-                int txnIdCount = rangeDeps.txnIdCount();
-                size += sizeofUnsignedVInt(txnIdCount);
-                for (int i = 0; i < txnIdCount; i++)
-                    size += 
CommandSerializers.txnId.serializedSize(rangeDeps.txnId(i));
-
-                int rangesToTxnIdsCount = rangesToTxnIdsCount(rangeDeps);
-                size += sizeofUnsignedVInt(rangesToTxnIdsCount);
-                for (int i = 0; i < rangesToTxnIdsCount; i++)
-                    size += sizeofUnsignedVInt(rangesToTxnIds(rangeDeps, i));
+                size += 
KeySerializers.rangeArray.serializedSize(ranges(rangeDeps));
+                size += 
CommandSerializers.txnId.serializedArraySize(RangeDeps.SerializerSupport.txnIds(rangeDeps));
+                size += rangesByTxnId ? 
serializedPackedXtoYSize(txnIdsToRanges(rangeDeps), rangeDeps.txnIdCount(), 
rangeDeps.rangeCount())
+                                      : 
serializedPackedXtoYSize(rangesToTxnIds(rangeDeps), rangeDeps.rangeCount(), 
rangeDeps.txnIdCount());
             }
             return size;
         }
+
+        private static long serializedPackedXtoYSize(int[] xtoy, int xCount, 
int yCount)
+        {
+            long size = VIntCoding.sizeOfUnsignedVInt(xtoy.length);
+            if ((xCount <= 1 || yCount <= 1) && (xtoy.length == xCount + 
yCount || xCount == 0 || yCount == 0))
+            {
+                // no point serializing as can be directly inferred
+            }
+            else
+            {
+                size += serializedPackedIntsSize(xtoy, 0, xCount, xtoy.length);
+                size += serializedPackedIntsSize(xtoy, xCount, xtoy.length, 
yCount - 1);
+            }
+            return size;
+        }
+
+        private static long serializedPackedIntsSize(int[] vs, int from, int 
to, int max)

Review Comment:
   this was deliberate only for consistency of callers, so 
serialize/serializedSize are consistent, but don't mind removing



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to