[ 
https://issues.apache.org/jira/browse/IGNITE-28356?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Anton Vinogradov updated IGNITE-28356:
--------------------------------------
    Description: 
The message codegen (IEP-132) can marshal a logical field into its wire 
companion by itself, yet many
messages still keep both the field and a hand-written marshal()/unmarshal() 
pair that fills the companion.
Some of those pairs carry no logic at all, and some of the companions describe 
data that is never sent.
Each item below is a problem found and the change that closes it.

A map whose values are always null.
All three producers of GridDistributedTxPrepareRequest#dhtVers put null as the 
value, so the consumer's
`ver.getValue() == null || !equals` is always true. The field becomes 
Collection<IgniteTxKey> dhtVerKeys,
dropping the value companion and 4 + 2N bytes.

A key travelling next to its own value.
GridNearTxPrepareResponse#ownedVals was a map plus two companions. The key 
moves into the value as
KeyedVersionedValue, so the field becomes a single collection. 
CacheVersionedValue already carries
cacheId, which now stops travelling twice: -(4 + 6N) bytes.

An array companion for an ordered set.
TxLocksRequest#txKeys and TxLocksResponse#txKeys kept a Set plus an array to 
write it. writeCollection
and writeObjectArray emit identical bytes, so the companion is gone; the 
runtime type stays HashSet and
the sender-side dedup is preserved.

A hand-written zip of two parallel fields.
GridNearGetRequest#keyMap was assembled by pairing keys and readersFlags by 
index. The map stays and the
conversion moves into @Marshalled(keys = ..., values = ...).

A map copied entry by entry into an empty one.
GridDhtTxPrepareRequest#owned was drained into GridNearTxRemote with putAll 
after the request was done
with it. ownedVersions now takes the map over, dropping a GridLeanMap and N 
nodes per prepare.

Blob marshalling the codegen already expresses.
LazyServiceConfigurationMessage#affKey, GenericValueMessage#val, 
QueryStartRequest#params and
QueryEntityMessage#dfltFieldValues become @Marshalled; the generated code 
matches the hand-written one
call for call. QueryEntityMessage keeps its !F.isEmpty gate, moved into the 
constructor, because
QueryEntity initializes the defaults with an empty map while the generated gate 
is != null.

Collection marshalling in an atomic request.
GridNearAtomicFullUpdateRequest#entryProcessors becomes @Marshalled; the field 
is retyped to List<Object>
because the generated code calls add(Object). The operation() == TRANSFORM 
gates stay on invokeArgs in all
three methods: dropping them only in marshal would fill invokeArgsBytes without 
deployInvokeArguments, and
a receiver with peer class loading on would get a NoClassDefFoundError instead 
of today's silent
degradation. The deploy() gate becomes entryProcessors != null, since the 
codegen nulls the companion
after restoring it.

A job payload unmarshalled with the wrong class loader.
GridJobExecuteRequest had two hand-written methods because its five payload 
fields are user classes that
only the deployment class loader can read, while GridIoManager#unmarshalPayload 
would use the
configuration one. The fields become @Marshalled and the class becomes a 
DeferredUnmarshalMessage, the
marker that exists for exactly this: GridJobProcessor unmarshals the request 
itself, with the same loader
as before. A job of a continuous task also stops sending its siblings - the 
receiver discarded them and
GridJobSessionImpl#getJobSiblings requests them from the task node when they 
are missing.

Wire companions standing in for a conditional field. Covers IGNITE-28922, to be 
closed as a duplicate.
CacheContinuousQueryEntry held keyWire/newValWire/oldValWire so that marshal() 
could hide the data of a
filtered entry. The three pairs collapse and key/newVal/oldVal go back to plain 
@Order. The invariant
becomes structural instead: a filtered entry gives its data up at
CacheContinuousQueryEventBuffer#processEntry, the only door into the buffer, so 
nothing downstream has to
remember it. Two copies this makes redundant are removed, and a filtered 
EXPIRED entry with
updateCntr == -1 is no longer sent at all - handleEvent already discarded it on 
arrival.

Wire layout is unchanged except where stated, and no path allocates more than 
before, with one exception:
a filtered entry taking the out-of-range counter path in the continuous query 
buffer now costs one object,
where the data used to be masked at serialization time instead.

  was:
GridDhtLockRequest#owned

And remove #ownedKeys && #ownedValues.

 

TxLocksRequest#txKeys

And remove TxLocksRequest#txKeysArr

 

GridNearGetRequest#keyMap

Both #keys && #readersFlags can be replaced with linked map #keyMap. Logic of 
conversion should be removed.

 


> Get rid of redundant wire companion fields and hand-written marshalling in 
> messages
> -----------------------------------------------------------------------------------
>
>                 Key: IGNITE-28356
>                 URL: https://issues.apache.org/jira/browse/IGNITE-28356
>             Project: Ignite
>          Issue Type: Task
>            Reporter: Ilya Shishkov
>            Assignee: Anton Vinogradov
>            Priority: Minor
>              Labels: IEP-132, ise
>             Fix For: 2.19
>
>          Time Spent: 14.5h
>  Remaining Estimate: 0h
>
> The message codegen (IEP-132) can marshal a logical field into its wire 
> companion by itself, yet many
> messages still keep both the field and a hand-written marshal()/unmarshal() 
> pair that fills the companion.
> Some of those pairs carry no logic at all, and some of the companions 
> describe data that is never sent.
> Each item below is a problem found and the change that closes it.
> A map whose values are always null.
> All three producers of GridDistributedTxPrepareRequest#dhtVers put null as 
> the value, so the consumer's
> `ver.getValue() == null || !equals` is always true. The field becomes 
> Collection<IgniteTxKey> dhtVerKeys,
> dropping the value companion and 4 + 2N bytes.
> A key travelling next to its own value.
> GridNearTxPrepareResponse#ownedVals was a map plus two companions. The key 
> moves into the value as
> KeyedVersionedValue, so the field becomes a single collection. 
> CacheVersionedValue already carries
> cacheId, which now stops travelling twice: -(4 + 6N) bytes.
> An array companion for an ordered set.
> TxLocksRequest#txKeys and TxLocksResponse#txKeys kept a Set plus an array to 
> write it. writeCollection
> and writeObjectArray emit identical bytes, so the companion is gone; the 
> runtime type stays HashSet and
> the sender-side dedup is preserved.
> A hand-written zip of two parallel fields.
> GridNearGetRequest#keyMap was assembled by pairing keys and readersFlags by 
> index. The map stays and the
> conversion moves into @Marshalled(keys = ..., values = ...).
> A map copied entry by entry into an empty one.
> GridDhtTxPrepareRequest#owned was drained into GridNearTxRemote with putAll 
> after the request was done
> with it. ownedVersions now takes the map over, dropping a GridLeanMap and N 
> nodes per prepare.
> Blob marshalling the codegen already expresses.
> LazyServiceConfigurationMessage#affKey, GenericValueMessage#val, 
> QueryStartRequest#params and
> QueryEntityMessage#dfltFieldValues become @Marshalled; the generated code 
> matches the hand-written one
> call for call. QueryEntityMessage keeps its !F.isEmpty gate, moved into the 
> constructor, because
> QueryEntity initializes the defaults with an empty map while the generated 
> gate is != null.
> Collection marshalling in an atomic request.
> GridNearAtomicFullUpdateRequest#entryProcessors becomes @Marshalled; the 
> field is retyped to List<Object>
> because the generated code calls add(Object). The operation() == TRANSFORM 
> gates stay on invokeArgs in all
> three methods: dropping them only in marshal would fill invokeArgsBytes 
> without deployInvokeArguments, and
> a receiver with peer class loading on would get a NoClassDefFoundError 
> instead of today's silent
> degradation. The deploy() gate becomes entryProcessors != null, since the 
> codegen nulls the companion
> after restoring it.
> A job payload unmarshalled with the wrong class loader.
> GridJobExecuteRequest had two hand-written methods because its five payload 
> fields are user classes that
> only the deployment class loader can read, while 
> GridIoManager#unmarshalPayload would use the
> configuration one. The fields become @Marshalled and the class becomes a 
> DeferredUnmarshalMessage, the
> marker that exists for exactly this: GridJobProcessor unmarshals the request 
> itself, with the same loader
> as before. A job of a continuous task also stops sending its siblings - the 
> receiver discarded them and
> GridJobSessionImpl#getJobSiblings requests them from the task node when they 
> are missing.
> Wire companions standing in for a conditional field. Covers IGNITE-28922, to 
> be closed as a duplicate.
> CacheContinuousQueryEntry held keyWire/newValWire/oldValWire so that 
> marshal() could hide the data of a
> filtered entry. The three pairs collapse and key/newVal/oldVal go back to 
> plain @Order. The invariant
> becomes structural instead: a filtered entry gives its data up at
> CacheContinuousQueryEventBuffer#processEntry, the only door into the buffer, 
> so nothing downstream has to
> remember it. Two copies this makes redundant are removed, and a filtered 
> EXPIRED entry with
> updateCntr == -1 is no longer sent at all - handleEvent already discarded it 
> on arrival.
> Wire layout is unchanged except where stated, and no path allocates more than 
> before, with one exception:
> a filtered entry taking the out-of-range counter path in the continuous query 
> buffer now costs one object,
> where the data used to be masked at serialization time instead.



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to