<!-- 
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-1871] Excessive Optional.ofNullable() from QName/QNameModule.getRevision() from NormalizedNodeOutputStreamWriter</title>
                <link>https://jira.opendaylight.org/browse/CONTROLLER-1871</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, based on Oxygen SR3 code, and see a lot (cumulated as in millions, with many tens of GBs) of &quot;TLAB Allocations&quot; related to an Optional.of() Optional.ofNullable() from QName/QNameModule.getRevision() from NormalizedNodeOutputStreamWriter.&lt;/p&gt;

&lt;p&gt;Wondering if perhaps we could improve upon this in any way? Realizing this may not be trivial, and &lt;em&gt;generally speaking&lt;/em&gt; Optional is much preferred over using a &lt;tt&gt;@Nullable&lt;/tt&gt;, but wondering if this is an exceptional case where the Optional should perhaps be avoided?&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;
Optional java.util.Optional.of(&lt;span class=&quot;code-object&quot;&gt;Object&lt;/span&gt;)	36282
Optional java.util.Optional.ofNullable(&lt;span class=&quot;code-object&quot;&gt;Object&lt;/span&gt;)	31841
Optional org.opendaylight.yangtools.yang.common.QNameModule.getRevision()	11703
Optional org.opendaylight.yangtools.yang.common.QName.getRevision()	11703
void org.opendaylight.controller.cluster.datastore.node.utils.stream.NormalizedNodeOutputStreamWriter.writeQName(QName)	11703
void org.opendaylight.controller.cluster.datastore.node.utils.stream.AbstractNormalizedNodeDataOutput.startNode(QName, &lt;span class=&quot;code-object&quot;&gt;byte&lt;/span&gt;)	8215
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;)	5324
&lt;span class=&quot;code-object&quot;&gt;boolean&lt;/span&gt; org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeWriter.wasProcessAsSimpleNode(NormalizedNode)	5324
NormalizedNodeWriter org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeWriter.write(NormalizedNode)	5324
&lt;span class=&quot;code-object&quot;&gt;boolean&lt;/span&gt; org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeWriter.writeChildren(Iterable)	4596
&lt;span class=&quot;code-object&quot;&gt;boolean&lt;/span&gt; org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeWriter.wasProcessedAsCompositeNode(NormalizedNode)	3924
NormalizedNodeWriter org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeWriter.write(NormalizedNode)	3924
&lt;span class=&quot;code-object&quot;&gt;boolean&lt;/span&gt; org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeWriter.writeChildren(Iterable)	2301
&lt;span class=&quot;code-object&quot;&gt;boolean&lt;/span&gt; org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeWriter.wasProcessedAsCompositeNode(NormalizedNode)	2284
NormalizedNodeWriter org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeWriter.write(NormalizedNode)	2284
&lt;span class=&quot;code-object&quot;&gt;boolean&lt;/span&gt; org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeWriter.writeChildren(Iterable)	1759
&lt;span class=&quot;code-object&quot;&gt;boolean&lt;/span&gt; org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeWriter$OrderedNormalizedNodeWriter.writeMapEntryNode(MapEntryNode)	1485
&lt;span class=&quot;code-object&quot;&gt;boolean&lt;/span&gt; org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeWriter.wasProcessedAsCompositeNode(NormalizedNode)	1485
NormalizedNodeWriter org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeWriter.write(NormalizedNode)	1485
void org.opendaylight.controller.cluster.datastore.node.utils.stream.AbstractNormalizedNodeDataOutput.writeNormalizedNode(NormalizedNode)	1023
void org.opendaylight.controller.cluster.datastore.persisted.DataTreeCandidateInputOutput.writeNode(NormalizedNodeDataOutput, DataTreeCandidateNode)	1023
void org.opendaylight.controller.cluster.datastore.persisted.DataTreeCandidateInputOutput.writeChildren(NormalizedNodeDataOutput, Collection)	1023
void org.opendaylight.controller.cluster.datastore.persisted.DataTreeCandidateInputOutput.writeNode(NormalizedNodeDataOutput, DataTreeCandidateNode)	1023
void org.opendaylight.controller.cluster.datastore.persisted.DataTreeCandidateInputOutput.writeChildren(NormalizedNodeDataOutput, Collection)	1023
void org.opendaylight.controller.cluster.datastore.persisted.DataTreeCandidateInputOutput.writeNode(NormalizedNodeDataOutput, DataTreeCandidateNode)	1023
void org.opendaylight.controller.cluster.datastore.persisted.DataTreeCandidateInputOutput.writeChildren(NormalizedNodeDataOutput, Collection)	1023
void org.opendaylight.controller.cluster.datastore.persisted.DataTreeCandidateInputOutput.writeNode(NormalizedNodeDataOutput, DataTreeCandidateNode)	1023
void org.opendaylight.controller.cluster.datastore.persisted.DataTreeCandidateInputOutput.writeChildren(NormalizedNodeDataOutput, Collection)	1023
void org.opendaylight.controller.cluster.datastore.persisted.DataTreeCandidateInputOutput.writeNode(NormalizedNodeDataOutput, DataTreeCandidateNode)	1023
void org.opendaylight.controller.cluster.datastore.persisted.DataTreeCandidateInputOutput.writeChildren(NormalizedNodeDataOutput, Collection)	1023
void org.opendaylight.controller.cluster.datastore.persisted.DataTreeCandidateInputOutput.writeNode(NormalizedNodeDataOutput, DataTreeCandidateNode)	1018
void org.opendaylight.controller.cluster.datastore.persisted.DataTreeCandidateInputOutput.writeChildren(NormalizedNodeDataOutput, Collection)	1018
void org.opendaylight.controller.cluster.datastore.persisted.DataTreeCandidateInputOutput.writeDataTreeCandidate(DataOutput, DataTreeCandidate)	1018
CommitTransactionPayload org.opendaylight.controller.cluster.datastore.persisted.CommitTransactionPayload.create(TransactionIdentifier, DataTreeCandidate)	1018
void org.opendaylight.controller.cluster.datastore.ShardDataTree.startCommit(SimpleShardDataTreeCohort, DataTreeCandidate)	1018
void org.opendaylight.controller.cluster.datastore.SimpleShardDataTreeCohort.commit(FutureCallback)	1018
void org.opendaylight.controller.cluster.datastore.CohortEntry.commit(FutureCallback)	1018
void org.opendaylight.controller.cluster.datastore.ShardCommitCoordinator.finishCommit(ActorRef, CohortEntry)	1018
void org.opendaylight.controller.cluster.datastore.ShardCommitCoordinator$3.onSuccess(DataTreeCandidate)	1018
void org.opendaylight.controller.cluster.datastore.ShardCommitCoordinator$3.onSuccess(&lt;span class=&quot;code-object&quot;&gt;Object&lt;/span&gt;)	1018
void org.opendaylight.controller.cluster.datastore.SimpleShardDataTreeCohort.successfulPreCommit(DataTreeCandidateTip)	1018
void org.opendaylight.controller.cluster.datastore.ShardDataTree$1.onSuccess(&lt;span class=&quot;code-object&quot;&gt;Void&lt;/span&gt;)	1018
void org.opendaylight.controller.cluster.datastore.ShardDataTree$1.onSuccess(&lt;span class=&quot;code-object&quot;&gt;Object&lt;/span&gt;)	1018
void org.opendaylight.controller.cluster.datastore.SimpleShardDataTreeCohort.doUserPreCommit(FutureCallback)	1018
void org.opendaylight.controller.cluster.datastore.SimpleShardDataTreeCohort.userPreCommit(DataTreeCandidate, FutureCallback)	1018
void org.opendaylight.controller.cluster.datastore.ShardDataTree.startPreCommit(SimpleShardDataTreeCohort)	1018
void org.opendaylight.controller.cluster.datastore.SimpleShardDataTreeCohort.preCommit(FutureCallback)	1018
void org.opendaylight.controller.cluster.datastore.CohortEntry.preCommit(FutureCallback)	1018
void org.opendaylight.controller.cluster.datastore.ShardCommitCoordinator.doCommit(CohortEntry)	1018
void org.opendaylight.controller.cluster.datastore.ShardCommitCoordinator$2.onSuccess(&lt;span class=&quot;code-object&quot;&gt;Void&lt;/span&gt;)	1018
void org.opendaylight.controller.cluster.datastore.ShardCommitCoordinator$2.onSuccess(&lt;span class=&quot;code-object&quot;&gt;Object&lt;/span&gt;)	1018
void org.opendaylight.controller.cluster.datastore.SimpleShardDataTreeCohort.successfulCanCommit()	1018
void org.opendaylight.controller.cluster.datastore.ShardDataTree.lambda$processNextPendingTransaction$0(ShardDataTree$CommitEntry)	1018
void org.opendaylight.controller.cluster.datastore.ShardDataTree$$Lambda$863.1527042624.accept(&lt;span class=&quot;code-object&quot;&gt;Object&lt;/span&gt;)	1018
void org.opendaylight.controller.cluster.datastore.ShardDataTree.processNextPending(Queue, ShardDataTreeCohort$State, Consumer)	1018
void org.opendaylight.controller.cluster.datastore.ShardDataTree.processNextPendingTransaction()	1018
void org.opendaylight.controller.cluster.datastore.ShardDataTree.startCanCommit(SimpleShardDataTreeCohort)	1018
void org.opendaylight.controller.cluster.datastore.SimpleShardDataTreeCohort.canCommit(FutureCallback)	1018
void org.opendaylight.controller.cluster.datastore.CohortEntry.canCommit(FutureCallback)	1018
void org.opendaylight.controller.cluster.datastore.ShardCommitCoordinator.handleCanCommit(CohortEntry)	1018
void org.opendaylight.controller.cluster.datastore.ShardCommitCoordinator.handleReadyLocalTransaction(ReadyLocalTransaction, ActorRef, Shard)	1018
void org.opendaylight.controller.cluster.datastore.Shard.handleReadyLocalTransaction(ReadyLocalTransaction)	1018
void org.opendaylight.controller.cluster.datastore.Shard.handleNonRaftCommand(&lt;span class=&quot;code-object&quot;&gt;Object&lt;/span&gt;)	1018
void org.opendaylight.controller.cluster.raft.RaftActor.handleCommand(&lt;span class=&quot;code-object&quot;&gt;Object&lt;/span&gt;)	1018&lt;/pre&gt;
&lt;/div&gt;&lt;/div&gt;</description>
                <environment></environment>
        <key id="31014">CONTROLLER-1871</key>
            <summary>Excessive Optional.ofNullable() from QName/QNameModule.getRevision() from NormalizedNodeOutputStreamWriter</summary>
                <type id="10104" iconUrl="https://jira.opendaylight.org/secure/viewavatar?size=xsmall&amp;avatarId=10303&amp;avatarType=issuetype">Bug</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="10001">Won&apos;t Do</resolution>
                                        <assignee username="tpantelis">Tom Pantelis</assignee>
                                    <reporter username="vorburger">Michael Vorburger</reporter>
                        <labels>
                    </labels>
                <created>Tue, 13 Nov 2018 11:26:35 +0000</created>
                <updated>Wed, 14 Nov 2018 13:01:07 +0000</updated>
                            <resolved>Wed, 14 Nov 2018 13:01:07 +0000</resolved>
                                    <version>Oxygen SR3</version>
                                    <fixVersion>Neon</fixVersion>
                    <fixVersion>Oxygen SR4</fixVersion>
                    <fixVersion>Fluorine SR2</fixVersion>
                                        <due></due>
                            <votes>0</votes>
                                    <watches>3</watches>
                                                                                                                <comments>
                            <comment id="65580" author="tpantelis" created="Tue, 13 Nov 2018 15:01:42 +0000"  >&lt;p&gt;The Optional comes from QName so this should really be in yangtools. Perhaps QName could provide an @Nullable version of getRevision or store the revision as an Optional - of course that would increase the footprint but QName instances are reused so perhaps that wouldn&apos;t be significant (&lt;a href=&quot;https://jira.opendaylight.org/secure/ViewProfile.jspa?name=rovarga&quot; class=&quot;user-hover&quot; rel=&quot;rovarga&quot;&gt;rovarga&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;That said, the Optionals in this case are short-lived so really shouldn&apos;t have a significant affect on GC. &lt;/p&gt;</comment>
                            <comment id="65582" author="rovarga" created="Tue, 13 Nov 2018 15:20:18 +0000"  >&lt;p&gt;We are using Optional for return values, which are immediately handled &#8211; making them immediate candidates for on-stack allocation and (if not) extremely easy to collect. They certainly do not end up leaking out of the current thread.&lt;/p&gt;

&lt;p&gt;Storing an Optional in QName is not really a good idea until we have Valhalla-capable JDK, as it adds 16 bytes of memory overhead for each QName.&lt;/p&gt;</comment>
                            <comment id="65583" author="tpantelis" created="Tue, 13 Nov 2018 15:24:32 +0000"  >&lt;p&gt;+1&lt;/p&gt;</comment>
                            <comment id="65591" author="rovarga" created="Tue, 13 Nov 2018 17:05:04 +0000"  >&lt;p&gt;&quot;many tens of GB&quot; ... over what period of time?&lt;/p&gt;</comment>
                            <comment id="65597" author="vorburger" created="Tue, 13 Nov 2018 18:13:08 +0000"  >&lt;p&gt;The scale test where this is from ran for only about 5h.  IRL it&apos;s much worse.&lt;/p&gt;</comment>
                            <comment id="65599" author="rovarga" created="Tue, 13 Nov 2018 18:24:29 +0000"  >&lt;p&gt;Well, according to &lt;a href=&quot;https://shipilev.net/jvm-anatomy-park/4-tlab-allocation/&quot; class=&quot;external-link&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener&quot;&gt;https://shipilev.net/jvm-anatomy-park/4-tlab-allocation/&lt;/a&gt; , TLAB can easily perform allocations to the tune of 2.5GB/s &#8211; making the overhead &apos;couple of seconds in a 5 hour run&apos;.&lt;/p&gt;</comment>
                            <comment id="65627" author="rovarga" created="Wed, 14 Nov 2018 13:01:07 +0000"  >&lt;p&gt;This is a reasonable use of API design. We will not go back to nullables.&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|i03ke7:</customfieldvalue>

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