[MDSAL-387] Excessive HashMap.resize() from IdentifiableItemCodec.serialize() Created: 13/Nov/18  Updated: 03/Dec/18  Resolved: 03/Dec/18

Status: Resolved
Project: mdsal
Component/s: None
Affects Version/s: Oxygen SR3
Fix Version/s: Fluorine SR2, 3.0.3

Type: Improvement Priority: Medium
Reporter: Michael Vorburger Assignee: Robert Varga
Resolution: Done Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Issue Links:
Relates
relates to YANGTOOLS-917 Allow OffsetMaps to be efficiently in... Resolved

 Description   

I'm looking at a Java Flight Recording obtained from (internal) scale lab testing, based on Oxygen SR3 code, and see extensive "TLAB Allocations" related to an excessive HashMap.resize() from IdentifiableItemCodec.serialize().

Wondering if perhaps we could improve this by pre-allocating correctly sized Map?

HashMap$Node[] java.util.HashMap.resize()	7552
Object java.util.HashMap.putVal(int, Object, Object, boolean, boolean)	7552
Object java.util.HashMap.put(Object, Object)	7366
YangInstanceIdentifier$NodeIdentifierWithPredicates org.opendaylight.mdsal.binding.dom.codec.impl.IdentifiableItemCodec.serialize(InstanceIdentifier$IdentifiableItem)	2842
Object org.opendaylight.mdsal.binding.dom.codec.impl.IdentifiableItemCodec.serialize(Object)	2842
void org.opendaylight.mdsal.binding.dom.codec.impl.KeyedListNodeCodecContext.addYangPathArgument(InstanceIdentifier$PathArgument, List)	1699
DataContainerCodecContext org.opendaylight.mdsal.binding.dom.codec.impl.DataObjectCodecContext.bindingPathArgumentChild(InstanceIdentifier$PathArgument, List)	1699
DataContainerCodecContext org.opendaylight.mdsal.binding.dom.codec.impl.BindingCodecContext.getCodecContextNode(InstanceIdentifier, List)	1699
Map$Entry org.opendaylight.mdsal.binding.dom.codec.impl.BindingCodecContext.newWriter(InstanceIdentifier, NormalizedNodeStreamWriter)	1692
Map$Entry org.opendaylight.mdsal.binding.dom.codec.impl.BindingNormalizedNodeCodecRegistry.toNormalizedNode(InstanceIdentifier, DataObject)	1692
Map$Entry org.opendaylight.controller.md.sal.binding.impl.BindingToNormalizedNodeCodec.toNormalizedNode(InstanceIdentifier, DataObject)	1692
void org.opendaylight.controller.md.sal.binding.impl.AbstractWriteTransaction.put(LogicalDatastoreType, InstanceIdentifier, DataObject, boolean)	1692
void org.opendaylight.openflowplugin.common.txchain.TransactionChainManager.writeToTransaction(LogicalDatastoreType, InstanceIdentifier, DataObject, boolean)	1692
void org.opendaylight.openflowplugin.impl.device.DeviceContextImpl.writeToTransaction(LogicalDatastoreType, InstanceIdentifier, DataObject)	1692
Void org.opendaylight.openflowplugin.impl.statistics.StatisticsGatheringUtils.lambda$deleteAllKnownFlows$6(InstanceIdentifier, TxFacade, Optional)	1145
Object org.opendaylight.openflowplugin.impl.statistics.StatisticsGatheringUtils$$Lambda$1924.1642152062.apply(Object)	1145
Object com.google.common.util.concurrent.AbstractTransformFuture$TransformFuture.doTransform(Function, Object)	1145
Object com.google.common.util.concurrent.AbstractTransformFuture$TransformFuture.doTransform(Object, Object)	1145
void com.google.common.util.concurrent.AbstractTransformFuture.run()	1145
void com.google.common.util.concurrent.MoreExecutors$DirectExecutor.execute(Runnable)	1145
void com.google.common.util.concurrent.AbstractFuture.executeListener(Runnable, Executor)	1145
void com.google.common.util.concurrent.AbstractFuture.addListener(Runnable, Executor)	1145
void com.google.common.util.concurrent.AbstractFuture$TrustedFuture.addListener(Runnable, Executor)	1145
ListenableFuture com.google.common.util.concurrent.AbstractTransformFuture.create(ListenableFuture, Function, Executor)	1145
ListenableFuture com.google.common.util.concurrent.Futures.transform(ListenableFuture, Function, Executor)	1145
void org.opendaylight.openflowplugin.impl.statistics.StatisticsGatheringUtils.deleteAllKnownFlows(TxFacade, InstanceIdentifier, DeviceFlowRegistry)	1145
void org.opendaylight.openflowplugin.impl.services.AbstractMultipartRequestOnTheFlyCallback.startCollecting()	1145
void org.opendaylight.openflowplugin.impl.services.AbstractMultipartRequestOnTheFlyCallback.onSuccess(OfHeader)	1145
void org.opendaylight.openflowplugin.impl.services.AbstractMultipartRequestOnTheFlyCallback.onSuccess(Object)	1145
boolean org.opendaylight.openflowjava.protocol.impl.core.connection.OutboundQueueEntry.complete(OfHeader)	1145
boolean org.opendaylight.openflowjava.protocol.impl.core.connection.StackedSegment.completeEntry(OutboundQueueEntry, OfHeader)	1145
OutboundQueueEntry org.opendaylight.openflowjava.protocol.impl.core.connection.StackedSegment.pairRequest(OfHeader)	1145
boolean org.opendaylight.openflowjava.protocol.impl.core.connection.AbstractStackedOutboundQueue.pairRequest(OfHeader)	1145
boolean org.opendaylight.openflowjava.protocol.impl.core.connection.AbstractOutboundQueueManager.onMessage(OfHeader)	1145
void org.opendaylight.openflowjava.protocol.impl.core.connection.ConnectionAdapterImpl.consumeDeviceMessage(DataObject)	1145
void org.opendaylight.openflowjava.protocol.impl.core.connection.AbstractConnectionAdapterStatistics.consume(DataObject)	1145
void org.opendaylight.openflowjava.protocol.impl.core.connection.ConnectionAdapterImpl.consume(DataObject)	1145
void org.opendaylight.openflowjava.protocol.impl.core.DelegatingInboundHandler.channelRead(ChannelHandlerContext, Object)	1145
void io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(Object)	1145
void io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext, Object)	1145
ChannelHandlerContext io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(Object)	1145
void io.netty.channel.ChannelInboundHandlerAdapter.channelRead(ChannelHandlerContext, Object)	1145
void org.opendaylight.openflowjava.protocol.impl.core.connection.AbstractOutboundQueueManager.channelRead(ChannelHandlerContext, Object)	1145
void io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(Object)	1145
void io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext, Object)	1145
ChannelHandlerContext io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(Object)	1145
void io.netty.handler.codec.MessageToMessageDecoder.channelRead(ChannelHandlerContext, Object)	1145
void io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(Object)	1145
void io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext, Object)	1145
ChannelHandlerContext io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(Object)	1145
void io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ChannelHandlerContext, CodecOutputList, int)	1145
void io.netty.handler.codec.ByteToMessageDecoder.channelRead(ChannelHandlerContext, Object)	1145
void io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(Object)	1145
void io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext, Object)	1145
ChannelHandlerContext io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(Object)	1145
void io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ChannelHandlerContext, CodecOutputList, int)	1145
void io.netty.handler.codec.ByteToMessageDecoder.channelRead(ChannelHandlerContext, Object)	1145
void io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(Object)	1145
void io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext, Object)	1145
ChannelHandlerContext io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(Object)	1145
void io.netty.handler.timeout.IdleStateHandler.channelRead(ChannelHandlerContext, Object)	1145
void org.opendaylight.openflowjava.protocol.impl.core.IdleHandler.channelRead(ChannelHandlerContext, Object)	1145
void io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(Object)	1145
void io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext, Object)	1145


 Comments   
Comment by Michael Vorburger [ 13/Nov/18 ]

There is something similar very here in another code path here as well:

HashMap$Node[] java.util.HashMap.resize()	200
Object java.util.HashMap.putVal(int, Object, Object, boolean, boolean)	200
Object java.util.HashMap.put(Object, Object)	200
ModifiedNode org.opendaylight.yangtools.yang.data.impl.schema.tree.ModifiedNode.modifyChild(YangInstanceIdentifier$PathArgument, ModificationApplyOperation, Version)	81
OperationWithModification org.opendaylight.yangtools.yang.data.impl.schema.tree.InMemoryDataTreeModification.resolveModificationFor(YangInstanceIdentifier)	81
void org.opendaylight.yangtools.yang.data.impl.schema.tree.InMemoryDataTreeModification.write(YangInstanceIdentifier, NormalizedNode)	81
void org.opendaylight.controller.sal.core.spi.data.SnapshotBackedWriteTransaction.write(YangInstanceIdentifier, NormalizedNode)	81
Comment by Robert Varga [ 13/Nov/18 ]

I do both cases are HashMap's lazy initialization to default size, in this case it's certainly okay.

Comment by Michael Vorburger [ 26/Nov/18 ]

rovarga seems to be making changes in this area, apparently in reaction to his -1 & -2 on changes I proposed related to this which he didn't like, but has not tagged the respective changes with this JIRA... so just to clarify, may I ask, does that work address what was raised in this issue:

so should this be closed as Done? If so, for which ODL release? Post-Neon, Neon, Fluorine, Oxygen?

Or is this still TBD by building on top of your recent work?

Tx.

Comment by Robert Varga [ 26/Nov/18 ]

Most of this was refactored as part of adoption of YANGTOOLS-917, with the last bit being specialization of single-leaf keys.

Generated at Wed Feb 07 20:09:40 UTC 2024 using Jira 8.20.10#820010-sha1:ace47f9899e9ee25d7157d59aa17ab06aee30d3d.