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

Nikita Amelchev updated IGNITE-29099:
-------------------------------------
    Description: 
Every cache update boxes primitive map keys on its hot path:

* \{{GridCacheSharedContext#cacheContext(int)}} and 
\{{#cacheObjectContext(int)}} look up a \{{ConcurrentHashMap<Integer, 
GridCacheContext>}}. A cache ID is a hash of the cache name, so it misses the 
\{{Integer}} cache and a new object is allocated on each call. The methods are 
called several times per operation on every node involved.
* \{{TcpCommunicationMetricsListener#updateMessageTypeMap}} checks a 
\{{Map<Short, String>}} for every sent and received message.

These allocations are pure garbage produced on NIO and striped pool threads of 
all nodes. Both lookups should use primitive keys.

  was:
JFR profiling of a FULL_SYNC transactional put (3 server nodes, 2 backups) 
shows three allocation sites that box a primitive map key on every call:

* {{GridCacheSharedContext#cacheContext(int)}} and {{#cacheObjectContext(int)}} 
- lookup in {{ConcurrentHashMap<Integer, GridCacheContext>}}. A cache ID is a 
hash of the cache name, so it misses the {{Integer}} cache. Called several 
times per transaction on each node: {{IgniteTxEntryMarshaller}}, 
{{IgniteTxEntry#initializeContext}}, {{IgniteTxStateImpl#validateTopology}}, 
{{IgniteTxStateImpl#onTxEnd}}.
* {{TcpCommunicationMetricsListener#updateMessageTypeMap}} - {{Map<Short, 
String>#containsKey(short)}} for every sent and received message.

Together these sites produce 2-3% of all allocations of a transaction.

h3. Proposed change

* {{GridCacheSharedContext}}: add a volatile copy-on-write 
{{IntMap<GridCacheContext>}} snapshot of {{ctxMap}}, rebuilt in 
{{addCacheContext}} and {{removeCacheContext}}; both lookups read the snapshot.
* {{TcpCommunicationMetricsListener}}: replace {{Map<Short, String>}} with a 
copy-on-write {{IntMap<String>}}.

h3. Result

JMH, {{gc.alloc.rate.norm}}, implicit put: the three sites disappear from the 
JFR profile, allocations per transaction drop by about 1.7% (28.6 KB -> 28.1 
KB), throughput is unchanged.

{{JmhCacheTxFullSyncBenchmark}} is added to reproduce the measurements.


> Avoid boxing of cache ID and message direct type on the cache operation hot 
> path
> --------------------------------------------------------------------------------
>
>                 Key: IGNITE-29099
>                 URL: https://issues.apache.org/jira/browse/IGNITE-29099
>             Project: Ignite
>          Issue Type: Improvement
>            Reporter: Nikita Amelchev
>            Assignee: Nikita Amelchev
>            Priority: Minor
>         Attachments: JmhCacheTxFullSyncBenchmark.java
>
>          Time Spent: 10m
>  Remaining Estimate: 0h
>
> Every cache update boxes primitive map keys on its hot path:
> * \{{GridCacheSharedContext#cacheContext(int)}} and 
> \{{#cacheObjectContext(int)}} look up a \{{ConcurrentHashMap<Integer, 
> GridCacheContext>}}. A cache ID is a hash of the cache name, so it misses the 
> \{{Integer}} cache and a new object is allocated on each call. The methods 
> are called several times per operation on every node involved.
> * \{{TcpCommunicationMetricsListener#updateMessageTypeMap}} checks a 
> \{{Map<Short, String>}} for every sent and received message.
> These allocations are pure garbage produced on NIO and striped pool threads 
> of all nodes. Both lookups should use primitive keys.



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

Reply via email to