Skip to content

IGNITE-28520 Auto-generate message serialization / marshalling / deployment#13095

Open
anton-vinogradov wants to merge 251 commits into
apache:masterfrom
anton-vinogradov:ignite-28520
Open

IGNITE-28520 Auto-generate message serialization / marshalling / deployment#13095
anton-vinogradov wants to merge 251 commits into
apache:masterfrom
anton-vinogradov:ignite-28520

Conversation

@anton-vinogradov

@anton-vinogradov anton-vinogradov commented Apr 30, 2026

Copy link
Copy Markdown
Contributor

What

Extends the annotation-driven message codegen (previously serialization-only) to
marshalling and deployment: a message's wire read/write, marshalling and
deployment are now generated from declarative field annotations, replacing
hand-written writeTo/readFrom, prepareMarshal/finishUnmarshal and prepareDeployment.

Main directions

  1. Generated marshaller & deployer companions. MessageProcessor now emits
    <Msg>Marshaller and <Msg>Deployer next to <Msg>Serializer, driven by
    @Marshalled / @MarshalledCollection / @MarshalledMap (with @Order /
    @NioField). Hand-written marshalling/deployment hooks are removed from messages.

  2. Uniform factory dispatch. MessageFactory resolves all three by direct type —
    serializer() / marshaller() / deployer() — via one
    register(directType, supplier, serializer, marshaller, deployer). Callers use the
    static facades MessageSerializer.writeTo/readFrom, MessageMarshaller.marshal/unmarshal,
    GridCacheMessageDeployer.deploy; an ArchUnit rule (MessageSerializationArchitectureTest)
    enforces it.

  3. Comm & discovery wired to it. GridIoManager / GridCacheIoManager /
    IgniteTxManager and the TCP/ZK discovery I/O call MessageMarshaller.marshal/unmarshal;
    discovery custom messages (MetadataUpdateProposedMessage, BinaryMetadataVersionInfo, …)
    move from MarshallableMessage hooks to @Marshalled.

  4. Deployment collapsed. GridCacheMessageDeployer is now only the codegen interface
    plus the factory-resolving facade; per-field static bridges dropped, GridCacheMessage#deploy*
    accessed directly.

  5. Marshalling stays off the NIO threads. The NIO codec does only serialization
    (writeTo/readFrom); the actual marshal/unmarshal runs on the sender and worker
    threads. @NioField + unmarshalNio are the explicit, minimal exception — only the
    handful of fields needed for early dispatch are unmarshalled on the NIO thread.

Side effects (mechanical — skim)

  • Rename to a consistent vocabulary (bulk of the diff, purely mechanical):
    • prepareMarshalmarshal, finishUnmarshalunmarshal,
      finishUnmarshalNiounmarshalNio (on MarshallableMessage / MessageMarshaller);
    • CacheObject#prepareMarshal(ctx) / finishUnmarshal(ctx)marshal / unmarshal;
    • deployment prepareDeployment + prepare*Deployment helpers → deploy / deploy*;
    • test renames: MarshallerCacheFreeFinishTest…UnmarshalTest,
      MessageFinishUnmarshalOnceTestMessageUnmarshalOnceTest.
  • Build/CI: .mvn/jvm.config opens jdk.compiler for the codegen tests
    (Google compile-testing); commit-check.yml now surfaces the real compile error
    behind the generated-class "cannot find symbol" cascade.

Performance

JMH-verified: serialization hot path unchanged (Δ ≈ 0 vs master); marshalling adds
~1.8 ns/message of factory dispatch (<0.5% of the actual U.marshal, ~µs); zero extra
allocations.

@anton-vinogradov anton-vinogradov changed the title IGNITE-28520 Auto-generate prepareMarshalCacheObjects to replace hand-written CO traversal in GridCacheMessage subclasses IGNITE-28520 Auto-generate message serialization / marshalling / deployment Jul 1, 2026
anton-vinogradov and others added 8 commits July 2, 2026 12:08
…r communication)

JmhCacheFullCycleBenchmark: client + 2 data nodes, put/get/putAll/invoke
x {POJO, byte[4K]} x {ATOMIC, TRANSACTIONAL}, AverageTime + GC profiler.
IoThroughputBench: manual-run entry point for the ignored
GridIoManagerBenchmark0 (message ping-pong latency/throughput).

Measured vs master (merge-base): parity within ~2 percent on time/op,
allocations per op identical within 0.5 percent.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@anton-vinogradov

Copy link
Copy Markdown
Contributor Author

Performance: branch vs master (merge-base), full client-to-server cycle

Benchmark: JmhCacheFullCycleBenchmark (added in 31691de) — client node + 2 data nodes in-process, every op goes through communication both ways. Ops cover distinct message families: put (single atomic update / implicit-tx prepare+finish), putAll(10) (batch update), get (near get with a CacheObject payload), invoke (entry processor marshalled into the request). Values: multi-field POJO (binary object) and raw byte[4096]. JMH AverageTime, 5x2s warmup + 8x2s measurement, 1 thread, JDK 17, each atomicity mode in a fresh JVM, runs strictly sequential on an idle machine.

TRANSACTIONAL, µs/op (avgt ± err):

op master branch Δ
get POJO 61.9 ± 1.9 62.9 ± 0.7 +1.6%
get 4K 62.9 ± 0.8 63.6 ± 1.4 +1.0%
invoke POJO 74.5 ± 1.1 75.1 ± 2.6 +0.8%
invoke 4K 76.3 ± 0.6 77.9 ± 0.5 +2.2%
put POJO 73.5 ± 1.5 72.2 ± 1.0 −1.7%
put 4K 77.1 ± 1.4 77.8 ± 1.1 +1.0%
putAll POJO 436 ± 7 442 ± 6 +1.3%
putAll 4K 462 ± 5 463 ± 5 +0.3%

ATOMIC: same picture, 62–100 µs/op, deltas ±1–3% in both directions with overlapping error bars.

Allocations (gc.alloc.rate.norm) match within ±0.5% on every combination (e.g. tx put POJO: 12319 B/op master vs 12299 branch; invoke is ~100 B/op lower on the branch) — the generated marshalling does byte-for-byte the same work.

Additionally, GridIoManagerBenchmark0#testLatency (raw message ping-pong over GridIoManager, exercises the new per-message marshaller dispatch on send/receive): master 18.6k qps vs branch 18.3k/18.4k qps (two runs, A/B/A) — parity within ~1%, which is also the run-to-run drift.

Conclusion: no measurable regression; parity within ~2% noise on time/op, identical allocation profile.

@github-actions

github-actions Bot commented Jul 3, 2026

Copy link
Copy Markdown

Possible compatibility issues. Please, check rolling upgrade cases

This PR modifies protected classes (with Order annotation).
Changes to these classes can break rolling upgrade compatibility.

Affected files:

  • modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/message/GenericValueMessage.java
  • modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/message/QueryStartRequest.java
  • modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/message/QueryTxEntry.java
  • modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/metadata/ColocationGroup.java
  • modules/codegen/src/main/java/org/apache/ignite/internal/MessageProcessor.java
  • modules/codegen/src/main/java/org/apache/ignite/internal/idto/IDTOSerializerGenerator.java
  • modules/core/src/main/java/org/apache/ignite/internal/managers/communication/ErrorMessage.java
  • modules/core/src/main/java/org/apache/ignite/internal/managers/communication/GridIoMessage.java
  • modules/core/src/main/java/org/apache/ignite/internal/managers/communication/IgniteIoTestMessage.java
  • modules/core/src/main/java/org/apache/ignite/internal/managers/eventstorage/GridEventStorageMessage.java
  • modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheEntryPredicateAdapter.java
  • modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheInvokeDirectResult.java
  • modules/core/src/main/java/org/apache/ignite/internal/processors/cache/DynamicCacheChangeRequest.java
  • modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheEntryInfo.java
  • modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheIdMessage.java
  • modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheMessage.java
  • modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheReturn.java
  • modules/core/src/main/java/org/apache/ignite/internal/processors/cache/StoredCacheData.java
  • modules/core/src/main/java/org/apache/ignite/internal/processors/cache/binary/BinaryMetadataVersionInfo.java
  • modules/core/src/main/java/org/apache/ignite/internal/processors/cache/binary/MetadataUpdateProposedMessage.java
  • modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/GridCacheTtlUpdateRequest.java
  • modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/GridDistributedLockRequest.java
  • modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/GridDistributedLockResponse.java
  • modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/GridDistributedTxPrepareRequest.java
  • modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/GridNearUnlockRequest.java
  • modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtLockRequest.java
  • modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtLockResponse.java
  • modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTxFinishResponse.java
  • modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTxPrepareRequest.java
  • modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTxPrepareResponse.java
  • modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtUnlockRequest.java
  • modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/TransactionAttributesAwareRequest.java
  • modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/atomic/AtomicApplicationAttributesAwareRequest.java
  • modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/atomic/GridDhtAtomicNearResponse.java
  • modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/atomic/GridDhtAtomicSingleUpdateRequest.java
  • modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/atomic/GridDhtAtomicUpdateRequest.java
  • modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/atomic/GridDhtAtomicUpdateResponse.java
  • modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/atomic/GridNearAtomicFullUpdateRequest.java
  • modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/atomic/GridNearAtomicSingleUpdateFilterRequest.java
  • modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/atomic/GridNearAtomicSingleUpdateInvokeRequest.java
  • modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/atomic/GridNearAtomicSingleUpdateRequest.java
  • modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/atomic/GridNearAtomicUpdateResponse.java
  • modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/atomic/UpdateErrors.java
  • modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/preloader/GridDhtForceKeysRequest.java
  • modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/preloader/GridDhtForceKeysResponse.java
  • modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/preloader/GridDhtPartitionSupplyMessage.java
  • modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/preloader/GridDhtPartitionsFullMessage.java
  • modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/preloader/GridDhtPartitionsSingleMessage.java
  • modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/CacheVersionedValue.java
  • modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearGetRequest.java
  • modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearGetResponse.java
  • modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearSingleGetRequest.java
  • modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearSingleGetResponse.java
  • modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTxPrepareRequest.java
  • modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTxPrepareResponse.java
  • modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/snapshot/IncrementalSnapshotAwareMessage.java
  • modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/snapshot/IncrementalSnapshotVerifyResult.java
  • modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/GridCacheQueryRequest.java
  • modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/GridCacheQueryResponse.java
  • modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheContinuousQueryEntry.java
  • modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxEntry.java
  • modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxKey.java
  • modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/TxEntryValueHolder.java
  • modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/TxLocksRequest.java
  • modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/TxLocksResponse.java
  • modules/core/src/main/java/org/apache/ignite/internal/processors/cache/verify/PartitionHashRecord.java
  • modules/core/src/main/java/org/apache/ignite/internal/processors/cache/verify/TransactionsHashRecord.java
  • modules/core/src/main/java/org/apache/ignite/internal/processors/cache/version/GridCacheVersion.java
  • modules/core/src/main/java/org/apache/ignite/internal/processors/cluster/ChangeGlobalStateMessage.java
  • modules/core/src/main/java/org/apache/ignite/internal/processors/continuous/StartRequestData.java
  • modules/core/src/main/java/org/apache/ignite/internal/processors/datastreamer/DataStreamerRequest.java
  • modules/core/src/main/java/org/apache/ignite/internal/processors/metastorage/persistence/DistributedMetaStorageCasMessage.java
  • modules/core/src/main/java/org/apache/ignite/internal/processors/metastorage/persistence/DistributedMetaStorageUpdateMessage.java
  • modules/core/src/main/java/org/apache/ignite/internal/processors/plugin/PluginsDataBagItem.java
  • modules/core/src/main/java/org/apache/ignite/internal/processors/query/schema/operation/SchemaAddQueryEntityOperation.java
  • modules/core/src/main/java/org/apache/ignite/internal/processors/rest/handlers/task/GridTaskResultResponse.java
  • modules/core/src/main/java/org/apache/ignite/internal/processors/service/ServiceDeploymentRequest.java
  • modules/core/src/main/java/org/apache/ignite/internal/processors/service/ServiceSingleNodeDeploymentResult.java
  • modules/core/src/main/java/org/apache/ignite/spi/discovery/SerializableDataBagItemWrapper.java
  • modules/core/src/main/java/org/apache/ignite/spi/discovery/tcp/internal/TcpDiscoveryNode.java
  • modules/core/src/main/java/org/apache/ignite/spi/discovery/tcp/messages/TcpDiscoveryAbstractTraceableMessage.java
  • modules/core/src/main/java/org/apache/ignite/spi/discovery/tcp/messages/TcpDiscoveryNodeAddFinishedMessage.java
  • modules/core/src/test/java/org/apache/ignite/internal/codegen/MessageProcessorTest.java
  • modules/core/src/test/java/org/apache/ignite/spi/communication/tcp/TestDelayMessage.java
  • modules/core/src/test/java/org/apache/ignite/spi/discovery/tcp/ExploitMessage.java
  • modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/msg/GridH2CacheObject.java

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants