<!-- 
RSS generated by JIRA (9.7.1#970001-sha1:2222b88b221c4928ef0de3161136cc90c8356a66) at Thu Feb 08 08:51:46 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-221] Try to remove synchronized in DBApiLayer finalize</title>
                <link>https://jira.mongodb.org/browse/JAVA-221</link>
                <project id="10006" key="JAVA">Java Driver</project>
                    <description>&lt;p&gt;See &lt;a href=&quot;https://jira.mongodb.org/browse/JAVA-207&quot; title=&quot;performance impact with multiple concurrent queries&quot; class=&quot;issue-link&quot; data-issue-key=&quot;JAVA-207&quot;&gt;&lt;del&gt;JAVA-207&lt;/del&gt;&lt;/a&gt;&lt;/p&gt;</description>
                <environment></environment>
        <key id="13811">JAVA-221</key>
            <summary>Try to remove synchronized in DBApiLayer finalize</summary>
                <type id="4" iconUrl="https://jira.mongodb.org/secure/viewavatar?size=xsmall&amp;avatarId=14710&amp;avatarType=issuetype">Improvement</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="antoine">Antoine Girbal</assignee>
                                    <reporter username="eliot">Eliot Horowitz</reporter>
                        <labels>
                    </labels>
                <created>Sun, 28 Nov 2010 04:53:29 +0000</created>
                <updated>Wed, 22 Dec 2010 23:58:14 +0000</updated>
                            <resolved>Mon, 13 Dec 2010 16:46:22 +0000</resolved>
                                                    <fixVersion>2.4</fixVersion>
                                    <component>Performance</component>
                                        <votes>2</votes>
                                    <watches>6</watches>
                                                                                                                <comments>
                            <comment id="21311" author="auto" created="Fri, 10 Dec 2010 19:43:24 +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-221&quot; title=&quot;Try to remove synchronized in DBApiLayer finalize&quot; class=&quot;issue-link&quot; data-issue-key=&quot;JAVA-221&quot;&gt;&lt;del&gt;JAVA-221&lt;/del&gt;&lt;/a&gt;: remove call to killcursor in finalize, to prevent blocking GC&lt;br/&gt;
&lt;a href=&quot;https://github.com/mongodb/mongo-java-driver/commit/a25e594f5b7012a8c29843000b6e5dc2c3b53e59&quot; class=&quot;external-link&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener&quot;&gt;https://github.com/mongodb/mongo-java-driver/commit/a25e594f5b7012a8c29843000b6e5dc2c3b53e59&lt;/a&gt;&lt;/p&gt;</comment>
                            <comment id="20992" author="auto" created="Thu, 2 Dec 2010 21:31:47 +0000"  >&lt;p&gt;Author:&lt;/p&gt;
{&apos;login&apos;: &apos;agirbal&apos;, &apos;name&apos;: &apos;agirbal&apos;, &apos;email&apos;: &apos;antoine@10gen.com&apos;}
&lt;p&gt;Message: &lt;a href=&quot;https://jira.mongodb.org/browse/JAVA-221&quot; title=&quot;Try to remove synchronized in DBApiLayer finalize&quot; class=&quot;issue-link&quot; data-issue-key=&quot;JAVA-221&quot;&gt;&lt;del&gt;JAVA-221&lt;/del&gt;&lt;/a&gt;: kill cursor should not be called if id is 0&lt;br/&gt;
SUPPORT-76: several bugs found in input reader, which may read too much&lt;br/&gt;
/mongodb/mongo-java-driver/commit/677125648a00002b99462e2406ab8e6a0192ae6f&lt;/p&gt;</comment>
                            <comment id="20991" author="auto" created="Thu, 2 Dec 2010 21:31:45 +0000"  >&lt;p&gt;Author:&lt;/p&gt;
{&apos;login&apos;: &apos;agirbal&apos;, &apos;name&apos;: &apos;agirbal&apos;, &apos;email&apos;: &apos;antoine@10gen.com&apos;}
&lt;p&gt;Message: &lt;a href=&quot;https://jira.mongodb.org/browse/JAVA-221&quot; title=&quot;Try to remove synchronized in DBApiLayer finalize&quot; class=&quot;issue-link&quot; data-issue-key=&quot;JAVA-221&quot;&gt;&lt;del&gt;JAVA-221&lt;/del&gt;&lt;/a&gt;: made finalize call killcursors right away&lt;br/&gt;
/mongodb/mongo-java-driver/commit/5a7f983f5dcd250b96749864575fed3762ba4fd7&lt;/p&gt;</comment>
                            <comment id="20990" author="auto" created="Thu, 2 Dec 2010 21:31:43 +0000"  >&lt;p&gt;Author:&lt;/p&gt;
{&apos;login&apos;: &apos;agirbal&apos;, &apos;name&apos;: &apos;agirbal&apos;, &apos;email&apos;: &apos;antoine@10gen.com&apos;}
&lt;p&gt;Message: &lt;a href=&quot;https://jira.mongodb.org/browse/JAVA-221&quot; title=&quot;Try to remove synchronized in DBApiLayer finalize&quot; class=&quot;issue-link&quot; data-issue-key=&quot;JAVA-221&quot;&gt;&lt;del&gt;JAVA-221&lt;/del&gt;&lt;/a&gt;: Try to remove synchronized in DBApiLayer finalize&lt;br/&gt;
Addition of a background thread per database, that takes care of cleaning up dead cursors.&lt;br/&gt;
/mongodb/mongo-java-driver/commit/4f49990a7d304d9806cb6f80ef92c517fc3a449d&lt;/p&gt;</comment>
                            <comment id="20945" author="eliot" created="Wed, 1 Dec 2010 21:48:46 +0000"  >&lt;p&gt;Once a cursor is exhausted, the server closes automatically and we should not call kill cursors on it.&lt;/p&gt;

&lt;p&gt;The reason .close() is so important is for people who do this&lt;/p&gt;

&lt;p&gt;c = coll.find().sort( ... )&lt;/p&gt;

&lt;p&gt;while ( c.next() )&lt;br/&gt;
  if ( x ) &lt;br/&gt;
    break;&lt;/p&gt;

&lt;p&gt;i..e they read some non-pre determined amount of data from the cursor.&lt;/p&gt;

&lt;p&gt;some people can do thousands of these per second, which can cause problems on the sever.&lt;/p&gt;</comment>
                            <comment id="20943" author="antoine" created="Wed, 1 Dec 2010 21:45:44 +0000"  >&lt;p&gt;ok just note that it will generate a lot more individual msg to servers.&lt;br/&gt;
Also if the thread interval is 1s, that should be short enough to prevent memory issue on server.&lt;br/&gt;
It depends how many cursors we can expect to potentially open in 1s.&lt;br/&gt;
Anyway I changed code to send msg per cursor.&lt;/p&gt;

&lt;p&gt;On another note: isnt the cursor supposed to close itself on server side once exhausted?&lt;br/&gt;
My test does a cursor.toArray() which grabs all objects.&lt;br/&gt;
Then when cursor is finalized, driver sends a msg to server to kill cursor, but server prints out line:&lt;br/&gt;
Wed Dec  1 13:38:15 &lt;span class=&quot;error&quot;&gt;&amp;#91;conn61&amp;#93;&lt;/span&gt; killcursors: found 0 of 1&lt;br/&gt;
I&apos;ve tested with old/new driver and with both the server prints out thousands of these lines.&lt;br/&gt;
Is this expected behavior, or should driver know not to send kill msg if it read all objs?&lt;/p&gt;</comment>
                            <comment id="20886" author="eliot" created="Wed, 1 Dec 2010 14:34:23 +0000"  >&lt;p&gt;The reason why close() exists is that its easy for a client to eat a ton of resources on the server in some cases, and its much better to get them closed asap.&lt;/p&gt;

&lt;p&gt;Also its problematic if the JVM dies before the background thread cleans them up.&lt;/p&gt;

&lt;p&gt;Most people don&apos;t call close explicitly, so I think its better for it to kill the cursor immediately.&lt;/p&gt;

&lt;p&gt;Can always adjust later.&lt;/p&gt;</comment>
                            <comment id="20878" author="antoine" created="Wed, 1 Dec 2010 07:36:34 +0000"  >&lt;p&gt;basically it&apos;s a tradeoff.&lt;br/&gt;
Solution A:&lt;/p&gt;
&lt;ul class=&quot;alternate&quot; type=&quot;square&quot;&gt;
	&lt;li&gt;close() sends msg to server right away to close single cursor&lt;/li&gt;
	&lt;li&gt;only adds to deadCursorIds in case there was an exception during close, so that thread will take care of it later&lt;/li&gt;
	&lt;li&gt;this means that under normal operation, driver will send msg to DB upon close of every cursor&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;Solution B:&lt;/p&gt;
&lt;ul class=&quot;alternate&quot; type=&quot;square&quot;&gt;
	&lt;li&gt;close() adds cursor to deadCursorIds&lt;/li&gt;
	&lt;li&gt;at regular interval (e.g. 1s) a background thread sends a msg to DB to close cursors, with multiple cursors in 1 msg&lt;/li&gt;
	&lt;li&gt;basically it reduces messaging and can be more scalable. Drawback is that there may be a slight delay before actual close (e.g. 1s)&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;Right now I chose solution B because it should be faster under load.&lt;br/&gt;
But if we need A for a reason I&apos;m missing, let me know.&lt;/p&gt;</comment>
                            <comment id="20860" author="eliot" created="Wed, 1 Dec 2010 01:45:47 +0000"  >&lt;p&gt;Yes, cursor.close() should close immediately.&lt;/p&gt;</comment>
                            <comment id="20858" author="scotthernandez" created="Wed, 1 Dec 2010 01:10:33 +0000"  >&lt;p&gt;If I call close on the cursor I expect it to be closed immediately. What is the reason for not doing that?&lt;/p&gt;</comment>
                            <comment id="20857" author="antoine" created="Wed, 1 Dec 2010 00:40:01 +0000"  >&lt;p&gt;committed patch earlier, commit ebf3c729ff070ba9bc9dd862fccc5a6d42ca0982&lt;br/&gt;
only difference with original plan is that cursor.close() or finalize() does not send msg to db by itself, instead it adds entry in dead cursor list which is a concurrent queue.&lt;br/&gt;
This is so that the cleaner thread can close dead cursors as a batch.&lt;br/&gt;
Concurrent queue as good concurrency speed so shouldnt be an issue.&lt;br/&gt;
Patched driver shows 10-20% speed improvement.&lt;/p&gt;</comment>
                            <comment id="20799" author="eliot" created="Tue, 30 Nov 2010 01:42:52 +0000"  >&lt;p&gt;Looks good.&lt;/p&gt;</comment>
                            <comment id="20789" author="antoine" created="Mon, 29 Nov 2010 22:42:15 +0000"  >&lt;p&gt;implementation plan:&lt;/p&gt;
&lt;ul class=&quot;alternate&quot; type=&quot;square&quot;&gt;
	&lt;li&gt;dead cursors are stored a synced list&lt;/li&gt;
	&lt;li&gt;cleanup() is only called by a cleanup thread. Right now that thread lives in the DBApiLayer class (looks like most specific code is in there)&lt;/li&gt;
	&lt;li&gt;find() does not call cleanup()&lt;/li&gt;
	&lt;li&gt;result.close() will try to close cursor by itself, if there is exception then it will add it to the list of dead cursor&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;The thread will check every 1s if there are cursors to be closed, should be good enough.&lt;br/&gt;
this should result in no syncing for queries under normal operations.&lt;br/&gt;
let me know if sounds good.&lt;/p&gt;</comment>
                            <comment id="20755" author="eliot" created="Mon, 29 Nov 2010 06:25:14 +0000"  >&lt;p&gt;Moving cleanCursor logic to a background thread would make sense.&lt;/p&gt;
</comment>
                            <comment id="20754" author="antoine" created="Mon, 29 Nov 2010 06:22:37 +0000"  >&lt;p&gt;ok trying to understand the principle of cursor cleanup.&lt;br/&gt;
it seems:&lt;br/&gt;
1) whenever find() is called, it will try to clean up cursors using cleanCursors()&lt;br/&gt;
2) when close() is called on a Result object, it syncs and adds its cursor in dead list. Then calls cleanCursors()&lt;br/&gt;
3) cleanCursors() does a sync to swap the dead cursors list to a new one&lt;/p&gt;

&lt;p&gt;This means that:&lt;/p&gt;
&lt;ul class=&quot;alternate&quot; type=&quot;square&quot;&gt;
	&lt;li&gt;1 sync is done for every find()&lt;/li&gt;
	&lt;li&gt;2 syncs are done for every close()&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;we can try to get rid of locks, the cleanest would be to use a background thread in charge of cleaning dead cursors.&lt;br/&gt;
In the spirit of this comment:&lt;br/&gt;
        // check without synchronisation ( double check pattern will avoid having two threads do the cleanup )&lt;br/&gt;
        // maybe the whole cleanCursor logic should be moved to a background thread anyway&lt;/p&gt;

&lt;p&gt;It also has the advantage of not slowing user threads for cursor cleanup.&lt;/p&gt;</comment>
                    </comments>
                <issuelinks>
                            <issuelinktype id="10011">
                    <name>Depends</name>
                                                                <inwardlinks description="is depended on by">
                                        <issuelink>
            <issuekey id="13609">JAVA-207</issuekey>
        </issuelink>
                            </inwardlinks>
                                    </issuelinktype>
                    </issuelinks>
                <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|hrhckv:</customfieldvalue>

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