<!-- 
RSS generated by JIRA (8.20.10#820010-sha1:ace47f9899e9ee25d7157d59aa17ab06aee30d3d) at Wed Feb 07 19:56:39 UTC 2024

It is possible to restrict the fields that are returned in this document by specifying the 'field' parameter in your request.
For example, to request only the issue key and summary append 'field=key&field=summary' to the URL of your request.
-->
<rss version="0.92" >
<channel>
    <title>OpenDaylight JIRA</title>
    <link>https://jira.opendaylight.org</link>
    <description>This file is an XML representation of an issue</description>
    <language>en-us</language>    <build-info>
        <version>8.20.10</version>
        <build-number>820010</build-number>
        <build-date>22-06-2022</build-date>
    </build-info>


<item>
            <title>[CONTROLLER-1870] Excessive Arrays.copyOf memory allocation from AbstractNormalizedNodeDataOutput</title>
                <link>https://jira.opendaylight.org/browse/CONTROLLER-1870</link>
                <project id="10113" key="CONTROLLER">controller</project>
                    <description>&lt;p&gt;I&apos;m looking at a Java Flight Recording obtained from (internal) scale lab testing, and see extensive &quot;TLAB Allocations&quot; due to what appears to be very excessive Arrays.copyOf memory allocation from AbstractNormalizedNodeDataOutput:&lt;/p&gt;

&lt;div class=&quot;code panel&quot; style=&quot;border-width: 1px;&quot;&gt;&lt;div class=&quot;codeContent panelContent&quot;&gt;
&lt;pre class=&quot;code-java&quot;&gt;&lt;span class=&quot;code-object&quot;&gt;byte&lt;/span&gt;[] java.util.Arrays.copyOf(&lt;span class=&quot;code-object&quot;&gt;byte&lt;/span&gt;[], &lt;span class=&quot;code-object&quot;&gt;int&lt;/span&gt;)	1017
void java.io.ByteArrayOutputStream.grow(&lt;span class=&quot;code-object&quot;&gt;int&lt;/span&gt;)	808
void java.io.ByteArrayOutputStream.ensureCapacity(&lt;span class=&quot;code-object&quot;&gt;int&lt;/span&gt;)	808
void java.io.ByteArrayOutputStream.write(&lt;span class=&quot;code-object&quot;&gt;int&lt;/span&gt;)	429
void java.io.DataOutputStream.writeInt(&lt;span class=&quot;code-object&quot;&gt;int&lt;/span&gt;)	373
void com.google.common.io.ByteStreams$ByteArrayDataOutputStream.writeInt(&lt;span class=&quot;code-object&quot;&gt;int&lt;/span&gt;)	373
void org.opendaylight.controller.cluster.datastore.node.utils.stream.AbstractNormalizedNodeDataOutput.writeInt(&lt;span class=&quot;code-object&quot;&gt;int&lt;/span&gt;)	373
void org.opendaylight.controller.cluster.datastore.node.utils.stream.NormalizedNodeOutputStreamWriter.writeString(&lt;span class=&quot;code-object&quot;&gt;String&lt;/span&gt;)	373
void org.opendaylight.controller.cluster.datastore.node.utils.stream.NormalizedNodeOutputStreamWriter.writeQName(QName)	373
void org.opendaylight.controller.cluster.datastore.node.utils.stream.AbstractNormalizedNodeDataOutput.startNode(QName, &lt;span class=&quot;code-object&quot;&gt;byte&lt;/span&gt;)	195
void org.opendaylight.controller.cluster.datastore.node.utils.stream.AbstractNormalizedNodeDataOutput.leafNode(YangInstanceIdentifier$NodeIdentifier, &lt;span class=&quot;code-object&quot;&gt;Object&lt;/span&gt;)	195
&lt;span class=&quot;code-object&quot;&gt;boolean&lt;/span&gt; org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeWriter.wasProcessAsSimpleNode(NormalizedNode)	195
NormalizedNodeWriter org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeWriter.write(NormalizedNode)	195
void org.opendaylight.controller.cluster.datastore.node.utils.stream.AbstractNormalizedNodeDataOutput.writeNormalizedNode(NormalizedNode)	195
void org.opendaylight.controller.cluster.datastore.persisted.DataTreeCandidateInputOutput.writeNode(NormalizedNodeDataOutput, DataTreeCandidateNode)	195
void org.opendaylight.controller.cluster.datastore.persisted.DataTreeCandidateInputOutput.writeChildren(NormalizedNodeDataOutput, Collection)	195
void org.opendaylight.controller.cluster.datastore.persisted.DataTreeCandidateInputOutput.writeNode(NormalizedNodeDataOutput, DataTreeCandidateNode)	195
void org.opendaylight.controller.cluster.datastore.persisted.DataTreeCandidateInputOutput.writeChildren(NormalizedNodeDataOutput, Collection)	195
void org.opendaylight.controller.cluster.datastore.persisted.DataTreeCandidateInputOutput.writeNode(NormalizedNodeDataOutput, DataTreeCandidateNode)	195
void org.opendaylight.controller.cluster.datastore.persisted.DataTreeCandidateInputOutput.writeChildren(NormalizedNodeDataOutput, Collection)	195
void org.opendaylight.controller.cluster.datastore.persisted.DataTreeCandidateInputOutput.writeNode(NormalizedNodeDataOutput, DataTreeCandidateNode)	195
void org.opendaylight.controller.cluster.datastore.persisted.DataTreeCandidateInputOutput.writeChildren(NormalizedNodeDataOutput, Collection)	195
void org.opendaylight.controller.cluster.datastore.persisted.DataTreeCandidateInputOutput.writeNode(NormalizedNodeDataOutput, DataTreeCandidateNode)	195
void org.opendaylight.controller.cluster.datastore.persisted.DataTreeCandidateInputOutput.writeChildren(NormalizedNodeDataOutput, Collection)	195
void org.opendaylight.controller.cluster.datastore.persisted.DataTreeCandidateInputOutput.writeNode(NormalizedNodeDataOutput, DataTreeCandidateNode)	195
void org.opendaylight.controller.cluster.datastore.persisted.DataTreeCandidateInputOutput.writeChildren(NormalizedNodeDataOutput, Collection)	195
void org.opendaylight.controller.cluster.datastore.persisted.DataTreeCandidateInputOutput.writeNode(NormalizedNodeDataOutput, DataTreeCandidateNode)	183
void org.opendaylight.controller.cluster.datastore.persisted.DataTreeCandidateInputOutput.writeChildren(NormalizedNodeDataOutput, Collection)	183
void org.opendaylight.controller.cluster.datastore.persisted.DataTreeCandidateInputOutput.writeNode(NormalizedNodeDataOutput, DataTreeCandidateNode)	175
void org.opendaylight.controller.cluster.datastore.persisted.DataTreeCandidateInputOutput.writeChildren(NormalizedNodeDataOutput, Collection)	175
void org.opendaylight.controller.cluster.datastore.persisted.DataTreeCandidateInputOutput.writeNode(NormalizedNodeDataOutput, DataTreeCandidateNode)	175
void org.opendaylight.controller.cluster.datastore.persisted.DataTreeCandidateInputOutput.writeChildren(NormalizedNodeDataOutput, Collection)	175
void org.opendaylight.controller.cluster.datastore.persisted.DataTreeCandidateInputOutput.writeDataTreeCandidate(DataOutput, DataTreeCandidate)	175
CommitTransactionPayload org.opendaylight.controller.cluster.datastore.persisted.CommitTransactionPayload.create(TransactionIdentifier, DataTreeCandidate)	175
void org.opendaylight.controller.cluster.datastore.ShardDataTree.startCommit(SimpleShardDataTreeCohort, DataTreeCandidate)	175
void org.opendaylight.controller.cluster.datastore.SimpleShardDataTreeCohort.commit(FutureCallback)	175
void org.opendaylight.controller.cluster.datastore.CohortEntry.commit(FutureCallback)	175
void org.opendaylight.controller.cluster.datastore.ShardCommitCoordinator.finishCommit(ActorRef, CohortEntry)	175
void org.opendaylight.controller.cluster.datastore.ShardCommitCoordinator$3.onSuccess(DataTreeCandidate)	175
void org.opendaylight.controller.cluster.datastore.ShardCommitCoordinator$3.onSuccess(&lt;span class=&quot;code-object&quot;&gt;Object&lt;/span&gt;)	175
void org.opendaylight.controller.cluster.datastore.SimpleShardDataTreeCohort.successfulPreCommit(DataTreeCandidateTip)	175
void org.opendaylight.controller.cluster.datastore.ShardDataTree$1.onSuccess(&lt;span class=&quot;code-object&quot;&gt;Void&lt;/span&gt;)	175
void org.opendaylight.controller.cluster.datastore.ShardDataTree$1.onSuccess(&lt;span class=&quot;code-object&quot;&gt;Object&lt;/span&gt;)	175
void org.opendaylight.controller.cluster.datastore.SimpleShardDataTreeCohort.doUserPreCommit(FutureCallback)	175
void org.opendaylight.controller.cluster.datastore.SimpleShardDataTreeCohort.userPreCommit(DataTreeCandidate, FutureCallback)	175
void org.opendaylight.controller.cluster.datastore.ShardDataTree.startPreCommit(SimpleShardDataTreeCohort)	175
void org.opendaylight.controller.cluster.datastore.SimpleShardDataTreeCohort.preCommit(FutureCallback)	175
void org.opendaylight.controller.cluster.datastore.CohortEntry.preCommit(FutureCallback)	175
void org.opendaylight.controller.cluster.datastore.ShardCommitCoordinator.doCommit(CohortEntry)	175
void org.opendaylight.controller.cluster.datastore.ShardCommitCoordinator$2.onSuccess(&lt;span class=&quot;code-object&quot;&gt;Void&lt;/span&gt;)	175
void org.opendaylight.controller.cluster.datastore.ShardCommitCoordinator$2.onSuccess(&lt;span class=&quot;code-object&quot;&gt;Object&lt;/span&gt;)	175
void org.opendaylight.controller.cluster.datastore.SimpleShardDataTreeCohort.successfulCanCommit()	175
void org.opendaylight.controller.cluster.datastore.ShardDataTree.lambda$processNextPendingTransaction$0(ShardDataTree$CommitEntry)	175
void org.opendaylight.controller.cluster.datastore.ShardDataTree$$Lambda$868.1938452935.accept(&lt;span class=&quot;code-object&quot;&gt;Object&lt;/span&gt;)	175
void org.opendaylight.controller.cluster.datastore.ShardDataTree.processNextPending(Queue, ShardDataTreeCohort$State, Consumer)	175
void org.opendaylight.controller.cluster.datastore.ShardDataTree.processNextPendingTransaction()	175
void org.opendaylight.controller.cluster.datastore.ShardDataTree.startCanCommit(SimpleShardDataTreeCohort)	175
void org.opendaylight.controller.cluster.datastore.SimpleShardDataTreeCohort.canCommit(FutureCallback)	175
void org.opendaylight.controller.cluster.datastore.CohortEntry.canCommit(FutureCallback)	175
void org.opendaylight.controller.cluster.datastore.ShardCommitCoordinator.handleCanCommit(CohortEntry)	175
void org.opendaylight.controller.cluster.datastore.ShardCommitCoordinator.handleReadyLocalTransaction(ReadyLocalTransaction, ActorRef, Shard)	175
void org.opendaylight.controller.cluster.datastore.Shard.handleReadyLocalTransaction(ReadyLocalTransaction)	175
void org.opendaylight.controller.cluster.datastore.Shard.handleNonRaftCommand(&lt;span class=&quot;code-object&quot;&gt;Object&lt;/span&gt;)	175
void org.opendaylight.controller.cluster.raft.RaftActor.handleCommand(&lt;span class=&quot;code-object&quot;&gt;Object&lt;/span&gt;)	175&lt;/pre&gt;
&lt;/div&gt;&lt;/div&gt;</description>
                <environment></environment>
        <key id="31004">CONTROLLER-1870</key>
            <summary>Excessive Arrays.copyOf memory allocation from AbstractNormalizedNodeDataOutput</summary>
                <type id="10100" iconUrl="https://jira.opendaylight.org/secure/viewavatar?size=xsmall&amp;avatarId=10310&amp;avatarType=issuetype">Improvement</type>
                                            <priority id="3" iconUrl="https://jira.opendaylight.org/images/icons/priorities/major.svg">Medium</priority>
                        <status id="5" iconUrl="https://jira.opendaylight.org/images/icons/statuses/resolved.png" description="A resolution has been taken, and it is awaiting verification by reporter. From here issues are either reopened, or are closed.">Resolved</status>
                    <statusCategory id="3" key="done" colorName="green"/>
                                    <resolution id="10000">Done</resolution>
                                        <assignee username="tpantelis">Tom Pantelis</assignee>
                                    <reporter username="vorburger">Michael Vorburger</reporter>
                        <labels>
                    </labels>
                <created>Mon, 12 Nov 2018 17:37:01 +0000</created>
                <updated>Wed, 19 Dec 2018 00:54:51 +0000</updated>
                            <resolved>Wed, 19 Dec 2018 00:54:51 +0000</resolved>
                                    <version>Oxygen SR3</version>
                                    <fixVersion>Neon</fixVersion>
                                        <due></due>
                            <votes>0</votes>
                                    <watches>4</watches>
                                                                                                                <comments>
                            <comment id="65555" author="tpantelis" created="Mon, 12 Nov 2018 18:25:47 +0000"  >&lt;p&gt;We can pass in a larger initial size to &lt;em&gt;ByteStreams.newDataOutput&lt;/em&gt; in &lt;em&gt;CommitTransactionPayload.create&lt;/em&gt; to avoid excessive reallocations.&lt;/p&gt;</comment>
                            <comment id="65565" author="skitt@redhat.com" created="Tue, 13 Nov 2018 09:08:38 +0000"  >&lt;p&gt;Note that the JFR &#8220;stack traces&#8221; only provide a partial view:&lt;/p&gt;

&lt;div class=&quot;code panel&quot; style=&quot;border-width: 1px;&quot;&gt;&lt;div class=&quot;codeContent panelContent&quot;&gt;
&lt;pre class=&quot;code-java&quot;&gt;
&lt;span class=&quot;code-object&quot;&gt;byte&lt;/span&gt;[] java.util.Arrays.copyOf(&lt;span class=&quot;code-object&quot;&gt;byte&lt;/span&gt;[], &lt;span class=&quot;code-object&quot;&gt;int&lt;/span&gt;)	1017
void java.io.ByteArrayOutputStream.grow(&lt;span class=&quot;code-object&quot;&gt;int&lt;/span&gt;)	808
void java.io.ByteArrayOutputStream.ensureCapacity(&lt;span class=&quot;code-object&quot;&gt;int&lt;/span&gt;)	808
void java.io.ByteArrayOutputStream.write(&lt;span class=&quot;code-object&quot;&gt;int&lt;/span&gt;)	429
void java.io.DataOutputStream.writeInt(&lt;span class=&quot;code-object&quot;&gt;int&lt;/span&gt;)	373
void com.google.common.io.ByteStreams$ByteArrayDataOutputStream.writeInt(&lt;span class=&quot;code-object&quot;&gt;int&lt;/span&gt;)	373
&lt;/pre&gt;
&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;means that 1017 calls to copyOf() resulted in a new TLAB; of those 1017 calls, 808 were a result of grow(); of those 808, 429 were a result of write(); of those 429, 373 were a result of writeInt(). All the other calls aren&#8217;t explained by this output.&lt;/p&gt;</comment>
                            <comment id="65567" author="vorburger" created="Tue, 13 Nov 2018 09:30:39 +0000"  >&lt;blockquote&gt;&lt;p&gt;We can pass in a larger initial size to&#160;&lt;em&gt;ByteStreams.newDataOutput&lt;/em&gt;&#160;in&#160;&lt;em&gt;CommitTransactionPayload.create&lt;/em&gt;&#160;to avoid excessive reallocations.&lt;/p&gt;&lt;/blockquote&gt;

&lt;p&gt;You mean fixed? It will change, considerably, based on the exact NN, won&apos;t it? Or just be made a configurable max. option? But then we&apos;d overallocate.&lt;/p&gt;

&lt;p&gt;Perhaps we could do something smarter and &quot;guesstimate&quot; the req size? Like some calculation on the NormalizedNode to pre-determine how many bytes it requires when streamed. (We know the format, and it would be hard-coded to that format.)&lt;/p&gt;

&lt;p&gt;Or... couldn&apos;t we rewrite things to completely avoid a byte[] and only stream? (I haven&apos;t looked into the code.)&lt;/p&gt;</comment>
                            <comment id="65579" author="tpantelis" created="Tue, 13 Nov 2018 14:47:30 +0000"  >&lt;p&gt;Fixed (and configurable) might suffice, say 512 sounds reasonable - that would eliminate 4 re-allocations. Doing a &quot;guesstimate&quot; would require pre-walking the NN tree which would add expense.&lt;/p&gt;

&lt;p&gt;The reason it&apos;s converted to a byte[] is that the serialized format has a much smaller footprint - the payload is stored in the in-memory journal so that can be significant.&lt;/p&gt;</comment>
                            <comment id="65626" author="rovarga" created="Wed, 14 Nov 2018 13:00:30 +0000"  >&lt;p&gt;Yeah, guestimating the size will lower TLAB allocation, bug will bring down the overall performance, as we have to walk the tree twice &#8211; that certainly is not worth it.&lt;/p&gt;</comment>
                            <comment id="65881" author="tpantelis" created="Tue, 4 Dec 2018 22:58:38 +0000"  >&lt;p&gt;Submitted &lt;a href=&quot;https://git.opendaylight.org/gerrit/#/c/78433/&quot; class=&quot;external-link&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener&quot;&gt;https://git.opendaylight.org/gerrit/#/c/78433/&lt;/a&gt;&lt;/p&gt;</comment>
                            <comment id="66059" author="vorburger" created="Wed, 19 Dec 2018 00:54:23 +0000"  >&lt;p&gt;This&#160;is in Neon now, let&apos;s close this, for now; we can cherry-pick to Fluorine later, if needed?&lt;/p&gt;</comment>
                    </comments>
                    <attachments>
                    </attachments>
                <subtasks>
                    </subtasks>
                <customfields>
                                                                            <customfield id="customfield_11400" key="com.atlassian.jira.plugins.jira-development-integration-plugin:devsummary">
                        <customfieldname>Development</customfieldname>
                        <customfieldvalues>
                            
                        </customfieldvalues>
                    </customfield>
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                <customfield id="customfield_10000" key="com.pyxis.greenhopper.jira:gh-lexo-rank">
                        <customfieldname>Rank</customfieldname>
                        <customfieldvalues>
                            <customfieldvalue>0|i03kbz:</customfieldvalue>

                        </customfieldvalues>
                    </customfield>
                                                                                                                                                                                </customfields>
    </item>
</channel>
</rss>