<!-- 
RSS generated by JIRA (9.7.1#970001-sha1:2222b88b221c4928ef0de3161136cc90c8356a66) at Thu Feb 08 08:51:48 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>MongoDB Jira</title>
    <link>https://jira.mongodb.org</link>
    <description>This file is an XML representation of an issue</description>
    <language>en-us</language>    <build-info>
        <version>9.7.1</version>
        <build-number>970001</build-number>
        <build-date>13-04-2023</build-date>
    </build-info>


<item>
            <title>[JAVA-236] Slow memory leak caused by non-static ThreadLocal in DBTCPConnector</title>
                <link>https://jira.mongodb.org/browse/JAVA-236</link>
                <project id="10006" key="JAVA">Java Driver</project>
                    <description>&lt;p&gt;As discussed in &lt;a href=&quot;http://groups.google.com/group/mongodb-user/browse_thread/thread/c73351031d6f98e5/9eb7f536cc98f5d4#9eb7f536cc98f5d4:&quot; class=&quot;external-link&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener&quot;&gt;http://groups.google.com/group/mongodb-user/browse_thread/thread/c73351031d6f98e5/9eb7f536cc98f5d4#9eb7f536cc98f5d4:&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It appears that DBTcpConnector uses a non-static ThreadLocal &quot;MyPort&quot; in order to provide a per-(thread, object) connection cache.&lt;/p&gt;

&lt;p&gt;Using non-static ThreadLocals is (probably!) fine, but in this instance when the DBTcpConnector is closed, MyPort is not removed from the ThreadLocal map resulting in a leak of hash map elements, DBTcpConnectors, etc etc.&lt;/p&gt;

&lt;p&gt;At (initially) 2 open/close connectors per second this uses up a 4GB heap in about 4 hours, with performance gradually worsening as more time is spent in GC.&lt;/p&gt;

&lt;p&gt;An analysis of the use of non-static thread local variables is provided here: &lt;a href=&quot;http://www.0xcafefeed.com/tag/threadlocal/&quot; class=&quot;external-link&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener&quot;&gt;http://www.0xcafefeed.com/tag/threadlocal/&lt;/a&gt;. Since Java 1.5, there is a ThreadLocal::remove function that is intended to allow lifecycle management of the ThreadLocals. Care might need to be taken to remove it in all the threads contexts it has been accessed in?&lt;/p&gt;

&lt;p&gt;I spent 5 minutes trying the remove, and it wasn&apos;t immediately clear it had worked, but I had to move onto other things, so I just removed the ThreadLocal bit (since in the code I was working on, each connection is only accessed from one thread anyway). Removing all ThreadLocal constructs (ie just instantiating 1 MyPort per DBTCPConnector) fixed the leak.&lt;/p&gt;

&lt;p&gt;Personally I&apos;d just write my own static ThreadLocal object map in order to ensure I had control over removing it, and didn&apos;t need to worry about the various ThreadLocal idiosyncrasies. There was an example of one I came across when researching the leak that looked quite clean. I can probably dig it out if you can&apos;t find it/are interested.&lt;/p&gt;

&lt;p&gt;As I mentioned in the forum,  I think you should get the fix in for 2.4, because a reasonably standard usage (ie unlike mine!) can result in a very slow leak, so people are going to deploy without noticing it and then wonder why their web server gets gradually slower.&lt;/p&gt;

&lt;p&gt;Good luck, let me know if I can be any more help!&lt;/p&gt;

&lt;p&gt;Alex&lt;/p&gt;


</description>
                <environment>uname -a: &amp;quot;Linux domU-12-31-39-08-13-C5 2.6.18-xenU-ec2-v1.0 #2 SMP Mon Feb 18 14:28:43 UTC 2008 x86_64 x86_64 x86_64 GNU/Linux &amp;quot;</environment>
        <key id="13995">JAVA-236</key>
            <summary>Slow memory leak caused by non-static ThreadLocal in DBTCPConnector</summary>
                <type id="1" iconUrl="https://jira.mongodb.org/secure/viewavatar?size=xsmall&amp;avatarId=14703&amp;avatarType=issuetype">Bug</type>
                                            <priority id="3" iconUrl="https://jira.mongodb.org/images/icons/priorities/major.svg">Major - P3</priority>
                        <status id="6" iconUrl="https://jira.mongodb.org/images/icons/statuses/closed.png" description="The issue is considered finished, the resolution is correct. Issues which are closed can be reopened.">Closed</status>
                    <statusCategory id="3" key="done" colorName="success"/>
                                    <resolution id="9">Done</resolution>
                                        <assignee username="eliot">Eliot Horowitz</assignee>
                                    <reporter username="apiggott@ikanow.com">Alex Piggott</reporter>
                        <labels>
                    </labels>
                <created>Fri, 17 Dec 2010 14:26:19 +0000</created>
                <updated>Tue, 3 May 2011 18:05:26 +0000</updated>
                            <resolved>Fri, 17 Dec 2010 15:05:42 +0000</resolved>
                                    <version>2.3</version>
                                    <fixVersion>2.4</fixVersion>
                                    <component>API</component>
                                        <votes>0</votes>
                                    <watches>1</watches>
                                                                                                                <comments>
                            <comment id="30843" author="antoine" created="Tue, 3 May 2011 18:05:26 +0000"  >&lt;p&gt;Modified close() method of dbtcpconnector a bit.&lt;br/&gt;
If the client now call close from all thread used with a Mongo Instance, it will clean up the ThreadLocal.&lt;/p&gt;</comment>
                            <comment id="30842" author="auto" created="Tue, 3 May 2011 18:03:56 +0000"  >&lt;p&gt;Author:&lt;/p&gt;
{u&apos;login&apos;: u&apos;agirbal&apos;, u&apos;name&apos;: u&apos;agirbal&apos;, u&apos;email&apos;: u&apos;antoine@10gen.com&apos;}
&lt;p&gt;Message: &lt;a href=&quot;https://jira.mongodb.org/browse/JAVA-236&quot; title=&quot;Slow memory leak caused by non-static ThreadLocal in DBTCPConnector&quot; class=&quot;issue-link&quot; data-issue-key=&quot;JAVA-236&quot;&gt;&lt;del&gt;JAVA-236&lt;/del&gt;&lt;/a&gt;: make it possible to clean up ThreadLocal&lt;br/&gt;
Branch: master&lt;br/&gt;
&lt;a href=&quot;https://github.com/mongodb/mongo-java-driver/commit/433853014b5a5b3c440431521811606edc0a6509&quot; class=&quot;external-link&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener&quot;&gt;https://github.com/mongodb/mongo-java-driver/commit/433853014b5a5b3c440431521811606edc0a6509&lt;/a&gt;&lt;/p&gt;</comment>
                            <comment id="21526" author="eliot" created="Fri, 17 Dec 2010 15:55:56 +0000"  >&lt;p&gt;Mongo sorts all of that out.&lt;br/&gt;
It has an internal connection pool and will re-open new sockets, etc...&lt;/p&gt;</comment>
                            <comment id="21525" author="apiggott@ikanow.com" created="Fri, 17 Dec 2010 15:53:38 +0000"  >&lt;p&gt;(By the way, I&apos;d be quite surprised if your change actually fixed the leak - setting _myPort to null does nothing since there&apos;s still a reference to it in the master ThreadLocal map.&lt;/p&gt;

&lt;p&gt;_myPort.remove();&lt;/p&gt;

&lt;p&gt;or just the remove is necessary according to the documentation. As I say, that didn&apos;t seem to work for me but I was doing 100 different things at the time so I probably just cocked it up somehow.&lt;/p&gt;

&lt;p&gt;However, it also looked like you needed to call remove() from each thread it had been accessed from, which would be a nightmare in the general case. &lt;/p&gt;

&lt;p&gt;That&apos;s why I might have a synchronized non-static non-threadlocal hash map in your DBTCPConnector where I stored a MyPort for each thread if accessing that object - avoiding (slightly) abusing ThreadLocal which doesn&apos;t have a very nice lifecycle management API and using one you control... &lt;/p&gt;

&lt;p&gt;A static threadlocal with a hashmap for the objects so you didn&apos;t need to do any synchronization control should also work, though you&apos;d have to write some code to periodically cleanup entries containing objects closed from different threads, messy but not too painful. There&apos;d be a slight risk that a load of objects got stuck with references in a thread sitting unused in a tomcat connection pool of course.&lt;br/&gt;
)&lt;/p&gt;</comment>
                            <comment id="21524" author="apiggott@ikanow.com" created="Fri, 17 Dec 2010 15:33:38 +0000"  >&lt;p&gt;Eliot:&lt;/p&gt;

&lt;p&gt;&quot;but why are you opening new Mongo instances all the time? &lt;br/&gt;
You should create 1 per JVM and leave it forever ideally.&quot;&lt;/p&gt;

&lt;p&gt;Don&apos;t ask me, I just inherited this code recently!&lt;/p&gt;

&lt;p&gt;One reason I can see for how it&apos;s done is that we might want to move the MongoDB around without restarting our user-facing servers. So currently for each request we get we look in a properties file and get the hostname/port of the server. Whether that&apos;s a sensible strategy (vs say updating DNS, or storing several Mongos in a map) is certainly debatable, but we&apos;re too close to deploying for me to want to make any significant changes at this point.&lt;/p&gt;

&lt;p&gt;So a quick question: if the MongoDB goes down, do you get an exception at the user layer and then need to close/re-open the Mongo object yourself, or does Mongo catch the exception and try opening a new connection itself? If Mongo sorts all that out, I might just bite the bullet and move to a single Mongo instance...&lt;/p&gt;</comment>
                            <comment id="21522" author="eliot" created="Fri, 17 Dec 2010 14:56:17 +0000"  >&lt;p&gt;We should fix this, but why are opening new Mongo instances all the time?&lt;br/&gt;
You should create 1 per JVM and leave it forever ideally.&lt;/p&gt;</comment>
                    </comments>
                    <attachments>
                    </attachments>
                <subtasks>
                    </subtasks>
                <customfields>
                                                                                                                                                                                                                                                                                                                                                                    <customfield id="customfield_15850" key="com.atlassian.jira.plugins.jira-development-integration-plugin:devsummary">
                        <customfieldname>Development</customfieldname>
                        <customfieldvalues>
                            
                        </customfieldvalues>
                    </customfield>
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    <customfield id="customfield_12550" key="com.pyxis.greenhopper.jira:gh-lexo-rank">
                        <customfieldname>Rank</customfieldname>
                        <customfieldvalues>
                            <customfieldvalue>2|hrhci7:</customfieldvalue>

                        </customfieldvalues>
                    </customfield>
                                                                <customfield id="customfield_10558" key="com.pyxis.greenhopper.jira:gh-global-rank">
                        <customfieldname>Rank (Obsolete)</customfieldname>
                        <customfieldvalues>
                            <customfieldvalue>14826</customfieldvalue>
                        </customfieldvalues>
                    </customfield>
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            </customfields>
    </item>
</channel>
</rss>