Author: jukka
Date: Wed Mar 5 17:08:48 2014
New Revision: 1574575
URL: http://svn.apache.org/r1574575
Log:
OAK-1418: Read performance regression
Move access time stamps and counters from SessionStats to SessionDelegate
where they can be updated with less overhead.
Modified:
jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/delegate/SessionDelegate.java
jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/session/SessionStats.java
Modified:
jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/delegate/SessionDelegate.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/delegate/SessionDelegate.java?rev=1574575&r1=1574574&r2=1574575&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/delegate/SessionDelegate.java
(original)
+++
jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/delegate/SessionDelegate.java
Wed Mar 5 17:08:48 2014
@@ -17,6 +17,7 @@
package org.apache.jackrabbit.oak.jcr.delegate;
import static com.google.common.base.Preconditions.checkNotNull;
+import static java.lang.System.currentTimeMillis;
import static java.lang.System.nanoTime;
import static
org.apache.jackrabbit.api.stats.RepositoryStatistics.Type.SESSION_READ_COUNTER;
import static
org.apache.jackrabbit.api.stats.RepositoryStatistics.Type.SESSION_READ_DURATION;
@@ -25,6 +26,7 @@ import static org.apache.jackrabbit.api.
import static org.apache.jackrabbit.oak.commons.PathUtils.denotesRoot;
import java.io.IOException;
+import java.util.Date;
import java.util.Iterator;
import java.util.concurrent.atomic.AtomicLong;
@@ -69,8 +71,20 @@ public class SessionDelegate {
private final IdentifierManager idManager;
private final SessionStats sessionStats;
- private volatile long lastAccessTimeNS = nanoTime();
+ // access time stamps and counters for statistics about this session
+ private final long loginTimeMS = currentTimeMillis();
+ private final long loginTimeNS = nanoTime();
+ private long lastAccessTimeNS = loginTimeNS;
+ private long readTimeNS = loginTimeNS;
+ private long writeTimeNS = loginTimeNS;
+ private long refreshTimeNS = loginTimeNS;
+ private long saveTimeNS = loginTimeNS;
+ private long readCount = 0;
+ private long writeCount = 0;
+ private long refreshCount = 0;
+ private long saveCount = 0;
+ // repository-wide counters for statistics about all sessions
private final AtomicLong readCounter;
private final AtomicLong readDuration;
private final AtomicLong writeCounter;
@@ -119,6 +133,55 @@ public class SessionDelegate {
return nanoTime() - lastAccessTimeNS;
}
+ public long getNanosecondsSinceLogin() {
+ return nanoTime() - loginTimeNS;
+ }
+
+ public Date getLoginTime() {
+ return new Date(loginTimeMS);
+ }
+
+ private Date getTime(long ns) {
+ long nsSinceStart = ns - loginTimeNS;
+ if (nsSinceStart > 0) {
+ return new Date(loginTimeMS + nsSinceStart / 1000000);
+ } else {
+ return null;
+ }
+ }
+
+ public Date getReadTime() {
+ return getTime(readTimeNS);
+ }
+
+ public Date getWriteTime() {
+ return getTime(writeTimeNS);
+ }
+
+ public Date getRefreshTime() {
+ return getTime(refreshTimeNS);
+ }
+
+ public Date getSaveTime() {
+ return getTime(saveTimeNS);
+ }
+
+ public long getReadCount() {
+ return readCount;
+ }
+
+ public long getWriteCount() {
+ return writeCount;
+ }
+
+ public long getRefreshCount() {
+ return refreshCount;
+ }
+
+ public long getSaveCount() {
+ return saveCount;
+ }
+
public void refreshAtNextAccess() {
refreshStrategy.refreshAtNextAccess();
}
@@ -175,12 +238,14 @@ public class SessionDelegate {
long dt = nanoTime() - t0;
sessionOpCount--;
if (sessionOperation.isUpdate()) {
- sessionStats.write();
+ writeTimeNS = t0;
+ writeCount++;
writeCounter.incrementAndGet();
writeDuration.addAndGet(dt);
updateCount++;
} else {
- sessionStats.read();
+ readTimeNS = t0;
+ readCount++;
readCounter.incrementAndGet();
readDuration.addAndGet(dt);
}
@@ -396,7 +461,8 @@ public class SessionDelegate {
* @throws RepositoryException
*/
public void save(String path) throws RepositoryException {
- sessionStats.save();
+ saveTimeNS = nanoTime();
+ saveCount++;
try {
commit(root, path);
} catch (CommitFailedException e) {
@@ -407,7 +473,8 @@ public class SessionDelegate {
}
public void refresh(boolean keepChanges) {
- sessionStats.refresh();
+ refreshTimeNS = nanoTime();
+ refreshCount++;
if (keepChanges && hasPendingChanges()) {
root.rebase();
} else {
@@ -459,7 +526,8 @@ public class SessionDelegate {
throw new RepositoryException("Cannot move node at " + srcPath
+ " to " + destPath);
}
if (!transientOp) {
- sessionStats.save();
+ saveTimeNS = nanoTime();
+ saveCount++;
commit(moveRoot);
refresh(true);
}
Modified:
jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/session/SessionStats.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/session/SessionStats.java?rev=1574575&r1=1574574&r2=1574575&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/session/SessionStats.java
(original)
+++
jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/session/SessionStats.java
Wed Mar 5 17:08:48 2014
@@ -16,7 +16,6 @@
* specific language governing permissions and limitations
* under the License.
*/
-
package org.apache.jackrabbit.oak.jcr.session;
import java.io.PrintWriter;
@@ -27,7 +26,6 @@ import java.util.Date;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.AtomicReference;
import javax.jcr.RepositoryException;
@@ -40,24 +38,18 @@ public class SessionStats implements Ses
private static final long EPS = TimeUnit.MILLISECONDS.convert(1,
TimeUnit.SECONDS);
private final Exception initStackTrace = new Exception("The session was
opened here:");
- private final Date loginTimeStamp = new Date();
- private final AtomicReference<Date> lastReadAccess = new
AtomicReference<Date>();
- private final AtomicLong readCount = new AtomicLong();
- private final AtomicReference<Date> lastWriteAccess = new
AtomicReference<Date>();
- private final AtomicLong writeCount = new AtomicLong();
- private final AtomicReference<Date> lastRefresh = new
AtomicReference<Date>();
- private final AtomicLong refreshCount = new AtomicLong();
- private final AtomicReference<Date> lastSave = new AtomicReference<Date>();
- private final AtomicLong saveCount = new AtomicLong();
+
private final AtomicReference<RepositoryException> lastFailedSave =
new AtomicReference<RepositoryException>();
+ private final SessionDelegate delegate;
private final String sessionId;
private final AuthInfo authInfo;
private Map<String, Object> attributes = Collections.emptyMap();
public SessionStats(SessionDelegate sessionDelegate) {
+ this.delegate = sessionDelegate;
this.sessionId = sessionDelegate.toString();
this.authInfo = sessionDelegate.getAuthInfo();
}
@@ -66,30 +58,6 @@ public class SessionStats implements Ses
this.attributes = attributes;
}
- public void read() {
- // There is a small race here and in the following methods, which
might lead to
- // a small window of inconsistency between the date and the count.
Since the
- // effect is small and the provided information is for information
purposes
- // this is preferable to synchronizing the method.
- lastReadAccess.set(new Date());
- readCount.incrementAndGet();
- }
-
- public void write() {
- lastWriteAccess.set(new Date());
- writeCount.incrementAndGet();
- }
-
- public void refresh() {
- lastRefresh.set(new Date());
- refreshCount.incrementAndGet();
- }
-
- public void save() {
- lastSave.set(new Date());
- saveCount.incrementAndGet();
- }
-
public void failedSave(RepositoryException repositoryException) {
lastFailedSave.set(repositoryException);
}
@@ -113,17 +81,17 @@ public class SessionStats implements Ses
@Override
public String getLoginTimeStamp() {
- return formatDate(loginTimeStamp);
+ return formatDate(delegate.getLoginTime());
}
@Override
public String getLastReadAccess() {
- return formatDate(lastReadAccess.get());
+ return formatDate(delegate.getReadTime());
}
@Override
public long getReadCount() {
- return readCount.get();
+ return delegate.getReadCount();
}
@Override
@@ -133,12 +101,12 @@ public class SessionStats implements Ses
@Override
public String getLastWriteAccess() {
- return formatDate(lastWriteAccess.get());
+ return formatDate(delegate.getWriteTime());
}
@Override
public long getWriteCount() {
- return writeCount.get();
+ return delegate.getWriteCount();
}
@Override
@@ -148,12 +116,12 @@ public class SessionStats implements Ses
@Override
public String getLastRefresh() {
- return formatDate(lastRefresh.get());
+ return formatDate(delegate.getRefreshTime());
}
@Override
public long getRefreshCount() {
- return refreshCount.get();
+ return delegate.getRefreshCount();
}
@Override
@@ -163,12 +131,12 @@ public class SessionStats implements Ses
@Override
public String getLastSave() {
- return formatDate(lastSave.get());
+ return formatDate(delegate.getSaveTime());
}
@Override
public long getSaveCount() {
- return saveCount.get();
+ return delegate.getSaveCount();
}
@Override
@@ -210,7 +178,7 @@ public class SessionStats implements Ses
}
private double calculateRate(long count) {
- double dt = System.currentTimeMillis() - loginTimeStamp.getTime();
+ double dt = delegate.getNanosecondsSinceLogin() / 1000000;
if (dt > EPS) {
return count / dt;
} else {