You are viewing a plain text version of this content. The canonical link for it is here.
Posted to derby-commits@db.apache.org by ka...@apache.org on 2009/09/25 12:08:54 UTC

svn commit: r818807 - /db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/conn/GenericLanguageConnectionContext.java

Author: kahatlen
Date: Fri Sep 25 10:08:54 2009
New Revision: 818807

URL: http://svn.apache.org/viewvc?rev=818807&view=rev
Log:
DERBY-3882: Expensive cursor name lookup in network server

Statements executed via the network client are always given cursor
names on the server, even if the user has not set a cursor name. When
a statement has a cursor name, the embedded driver will check on each
execution that there is no other statement in the same connection with
the same cursor name and an open result set. To perform this check,
the list of activations in the connection is traversed and each cursor
name is compared with the cursor name of the statement to be executed.

If the number of open statements in the connection is high, which is
very likely if ClientConnectionPoolDataSource with the JDBC statement
cache is used, traversing the list of activations and performing
string comparisons may become expensive.

This patch attempts to make this operation cheaper without performing
a full rewrite and use a new data structure. It exploits that the most
common implementations of java.lang.String cache the hash code, so
calling hashCode() on the cursor names in the list will simply read
the value from an int field after warm-up. By checking if the hash
codes of the cursor names match first, we can avoid many of the string
comparisons because we know that strings with different hash codes
cannot be equal.

Modified:
    db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/conn/GenericLanguageConnectionContext.java

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/conn/GenericLanguageConnectionContext.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/conn/GenericLanguageConnectionContext.java?rev=818807&r1=818806&r2=818807&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/conn/GenericLanguageConnectionContext.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/conn/GenericLanguageConnectionContext.java Fri Sep 25 10:08:54 2009
@@ -876,6 +876,8 @@
 		int size = acts.size();
 		if (size > 0)
 		{
+            int cursorHash = cursorName.hashCode();
+
 			for (int i = 0; i < size; i++) {
 				 Activation a = (Activation) acts.get(i);
 
@@ -888,6 +890,22 @@
 
 				String executingCursorName = a.getCursorName();
 
+                // If the executing cursor has no name, or if the hash code of
+                // its name is different from the one we're looking for, it
+                // can't possibly match. Since java.lang.String caches the
+                // hash code (at least in the most common implementations),
+                // checking the hash code is cheaper than comparing the names
+                // with java.lang.String.equals(), especially if there are many
+                // open statements associated with the connection. See
+                // DERBY-3882. Note that we can only use the hash codes to
+                // determine that the names don't match. Even if the hash codes
+                // are equal, we still need to call equals() to verify that the
+                // two names actually are equal.
+                if (executingCursorName == null ||
+                        executingCursorName.hashCode() != cursorHash) {
+                    continue;
+                }
+
 				 if (cursorName.equals(executingCursorName)) {
 
 					ResultSet rs = a.getResultSet();