[MDSAL-388] Cache successful augmentation substitutions Created: 13/Nov/18 Updated: 26/Feb/20 Resolved: 19/Nov/18 |
|
| Status: | Resolved |
| Project: | mdsal |
| Component/s: | None |
| Affects Version/s: | None |
| Fix Version/s: | Fluorine SR2, Oxygen SR4, 3.0.2 |
| 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 |
|
One of the very top "TLAB allocation" (cumulative nearing 100 GiB - that's a hell of a lot, no?) observed in a JFR from internal scale testing based on Oxygen SR3 code, which seems to contributed to excessive GC, is the code path below. I'm seeing this with slight variations, curiously always from openflowplugin (is it doing anything obviously wrong here, which could be improved?). Just wondering if there is any way that this could be optimized to cause less object allocation? Could that reflection stuff it seems to be doing here perhaps be cached? void java.lang.Class$MethodArray.<init>(int) 34969 Method java.lang.Class.getMethod0(String, Class[], boolean) 34969 Method java.lang.Class.privateGetMethodRecursive(String, Class[], boolean, Class$MethodArray) 34237 Method java.lang.Class.getMethod0(String, Class[], boolean) 34237 Method java.lang.Class.privateGetMethodRecursive(String, Class[], boolean, Class$MethodArray) 31798 Method java.lang.Class.getMethod0(String, Class[], boolean) 31798 Method java.lang.Class.privateGetMethodRecursive(String, Class[], boolean, Class$MethodArray) 20695 Method java.lang.Class.getMethod0(String, Class[], boolean) 20695 Method java.lang.Class.getMethod(String, Class[]) 11300 boolean org.opendaylight.yangtools.yang.binding.util.BindingReflections.isSubstitutionFor(Class, Class) 11300 DataContainerCodecPrototype org.opendaylight.mdsal.binding.dom.codec.impl.DataObjectCodecContext.augmentationByClassOrEquivalentClass(Class) 11300 DataContainerCodecPrototype org.opendaylight.mdsal.binding.dom.codec.impl.DataObjectCodecContext.augmentationByClass(Class) 11300 DataContainerCodecPrototype org.opendaylight.mdsal.binding.dom.codec.impl.DataObjectCodecContext.streamChildPrototype(Class) 11300 Optional org.opendaylight.mdsal.binding.dom.codec.impl.DataObjectCodecContext.possibleStreamChild(Class) 11300 Object org.opendaylight.mdsal.binding.dom.codec.impl.LazyDataObject.getAugmentationImpl(Class) 11300 Object org.opendaylight.mdsal.binding.dom.codec.impl.LazyDataObject.invoke(Object, Method, Object[]) 11300 Augmentation com.sun.proxy.$Proxy503.getAugmentation(Class) 11071 Optional org.opendaylight.openflowplugin.extension.api.GroupingResolver.getExtension(Augmentable) 11071 MatchEntry org.opendaylight.openflowplugin.extension.vendor.nicira.convertor.match.RegConvertor.convert(Extension) 11071 DataContainer org.opendaylight.openflowplugin.extension.vendor.nicira.convertor.match.RegConvertor.convert(Extension) 11071 MatchEntry org.opendaylight.openflowplugin.impl.protocol.serialization.match.MatchSerializer.lambda$null$4(ExtensionList, ByteBuf, ConvertorToOFJava) 11071 Object org.opendaylight.openflowplugin.impl.protocol.serialization.match.MatchSerializer$$Lambda$2185.946006913.apply(Object) 11071 Optional java.util.Optional.map(Function) 11071 void org.opendaylight.openflowplugin.impl.protocol.serialization.match.MatchSerializer.lambda$serializeExtensionList$6(ByteBuf, ExtensionList) 11071 void org.opendaylight.openflowplugin.impl.protocol.serialization.match.MatchSerializer$$Lambda$2182.730382268.accept(Object) 11071 void java.util.ArrayList.forEach(Consumer) 11071 void org.opendaylight.openflowplugin.impl.protocol.serialization.match.MatchSerializer.serializeExtensionList(List, ByteBuf) 11071 void org.opendaylight.openflowplugin.impl.protocol.serialization.match.MatchSerializer.lambda$serializeHeader$2(ByteBuf, List) 11071 void org.opendaylight.openflowplugin.impl.protocol.serialization.match.MatchSerializer$$Lambda$2069.1596170542.accept(Object) 11071 void java.util.Optional.ifPresent(Consumer) 11071 void org.opendaylight.openflowplugin.impl.protocol.serialization.match.MatchSerializer.serializeHeader(Match, ByteBuf) 11071 void org.opendaylight.openflowplugin.impl.protocol.serialization.match.MatchSerializer.serialize(Match, ByteBuf) 11071 void org.opendaylight.openflowplugin.impl.protocol.serialization.match.MatchSerializer.serialize(DataContainer, ByteBuf) 11071 void org.opendaylight.openflowplugin.impl.protocol.serialization.messages.FlowMessageSerializer.writeMatch(FlowMessage, ByteBuf) 11071 void org.opendaylight.openflowplugin.impl.protocol.serialization.messages.FlowMessageSerializer.writeFlow(FlowMessage, ByteBuf) 11071 void org.opendaylight.openflowplugin.impl.protocol.serialization.messages.FlowMessageSerializer.serialize(FlowMessage, ByteBuf) 11071 void org.opendaylight.openflowplugin.impl.protocol.serialization.messages.FlowMessageSerializer.serialize(DataContainer, ByteBuf) 11071 void org.opendaylight.openflowjava.protocol.impl.serialization.SerializationFactory.messageToBuffer(short, ByteBuf, DataObject) 11071 void org.opendaylight.openflowjava.protocol.impl.core.OFEncoder.encode(ChannelHandlerContext, MessageListenerWrapper, ByteBuf) 11071 void org.opendaylight.openflowjava.protocol.impl.core.OFEncoder.encode(ChannelHandlerContext, Object, ByteBuf) 11071 void io.netty.handler.codec.MessageToByteEncoder.write(ChannelHandlerContext, Object, ChannelPromise) 11071 void io.netty.channel.AbstractChannelHandlerContext.invokeWrite0(Object, ChannelPromise) 11071 void io.netty.channel.AbstractChannelHandlerContext.invokeWrite(Object, ChannelPromise) 11071 void io.netty.channel.AbstractChannelHandlerContext.write(Object, boolean, ChannelPromise) 11071 ChannelFuture io.netty.channel.AbstractChannelHandlerContext.write(Object, ChannelPromise) 11071 ChannelFuture io.netty.channel.AbstractChannelHandlerContext.write(Object) 11071 ChannelFuture io.netty.channel.DefaultChannelPipeline.write(Object) 11071 ChannelFuture io.netty.channel.AbstractChannel.write(Object) 11071 void org.opendaylight.openflowjava.protocol.impl.core.connection.AbstractOutboundQueueManager.writeMessage(OfHeader, long) 11071 void org.opendaylight.openflowjava.protocol.impl.core.connection.OutboundQueueManager.writeMessage(OfHeader, long) 11071 int org.opendaylight.openflowjava.protocol.impl.core.connection.AbstractStackedOutboundQueue.writeEntries(Channel, long) 11071 void org.opendaylight.openflowjava.protocol.impl.core.connection.AbstractOutboundQueueManager.writeAndFlush() 11071 void org.opendaylight.openflowjava.protocol.impl.core.connection.AbstractOutboundQueueManager.flush() 10043 void org.opendaylight.openflowjava.protocol.impl.core.connection.AbstractOutboundQueueManager.lambda$new$0() 10043 void org.opendaylight.openflowjava.protocol.impl.core.connection.AbstractOutboundQueueManager$$Lambda$1465.2105557852.run() 10043 void io.netty.util.concurrent.AbstractEventExecutor.safeExecute(Runnable) 10043 boolean io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasksFrom(Queue) 10043 boolean io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks() 10043 void io.netty.channel.nio.NioEventLoop.run() 10043 void io.netty.util.concurrent.SingleThreadEventExecutor$5.run() 10043 void io.netty.util.concurrent.FastThreadLocalRunnable.run() 10043 void java.lang.Thread.run() 10043 |
| Comments |
| Comment by Robert Varga [ 13/Nov/18 ] |
|
GroupingResolver is doing something funky, I am not quite sure what and why – that is leading DataObjectCodecContext off of the fast path. |
| Comment by Michael Vorburger [ 16/Nov/18 ] |
|
Reminder: Need to double check how |
| Comment by Robert Varga [ 16/Nov/18 ] |
|
Aside from me looking at GroupingResolver and screaming in anguish over public mutable collections.
vorburger if you are looking to improve things further, I would suggest looking at the reported stack trace and cleaning up OFP's use of capturing lambdas (like MatchSerializer.serializeHeader()'s use of Map.forEach()) and this wonderful pattern:
Foo nullableFoo; // I can haz two new objucts? coz is l33ter than 'if (nullableFoo != null)'! Optional.ofNullable(nullableFoo).ifPresent(nonnullFoo -> { // Moar codez goes here... })
|
| Comment by Michael Vorburger [ 16/Nov/18 ] |
|
OMG |