[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: |
|
||||||||
| 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 |