mirror of
https://github.com/ebean-orm/ebean.git
synced 2024-04-21 10:51:47 +00:00
#1231 - Performance: Only use CallStack when using AutoTune (automatic query tuning or profiling)
This commit is contained in:
@@ -26,14 +26,16 @@ public final class CallStack implements Serializable {
|
||||
|
||||
private final StackTraceElement[] callStack;
|
||||
|
||||
private final int hc;
|
||||
|
||||
public CallStack(StackTraceElement[] callStack, int zeroHash, int pathHash) {
|
||||
this.callStack = callStack;
|
||||
this.zeroHash = enc(zeroHash);
|
||||
this.pathHash = enc(pathHash);
|
||||
this.hc = computeHashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
private int computeHashCode() {
|
||||
int hc = 0;
|
||||
for (StackTraceElement aCallStack : callStack) {
|
||||
hc = 92821 * hc + aCallStack.hashCode();
|
||||
@@ -41,6 +43,10 @@ public final class CallStack implements Serializable {
|
||||
return hc;
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return hc;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj == this) {
|
||||
|
||||
@@ -32,6 +32,15 @@ public class AutoTuneConfig {
|
||||
public AutoTuneConfig() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if we are profiling or query tuning.
|
||||
*
|
||||
* If we are not doing either then we don't need a CallStack.
|
||||
*/
|
||||
public boolean isActive() {
|
||||
return profiling || queryTuning;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the name of the file that holds the query tuning information.
|
||||
*/
|
||||
|
||||
@@ -10,5 +10,5 @@ public interface CallStackFactory {
|
||||
/**
|
||||
* Create and return the CallStack given the stack trace elements.
|
||||
*/
|
||||
CallStack createCallStack(StackTraceElement[] finalTrace);
|
||||
CallStack createCallStack();
|
||||
}
|
||||
|
||||
@@ -2,13 +2,56 @@ package io.ebeaninternal.server.core;
|
||||
|
||||
import io.ebean.bean.CallStack;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* Default CallStackFactory where the Hash function for StackTraceElement includes the line number.
|
||||
*/
|
||||
public class DefaultCallStackFactory implements CallStackFactory {
|
||||
|
||||
private static final int IGNORE_LEADING_ELEMENTS = 5;
|
||||
|
||||
private static final String IO_EBEAN = "io.ebean";
|
||||
|
||||
private final int maxCallStack;
|
||||
|
||||
DefaultCallStackFactory(int maxCallStack) {
|
||||
this.maxCallStack = maxCallStack;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CallStack createCallStack(StackTraceElement[] finalTrace) {
|
||||
public CallStack createCallStack() {
|
||||
StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
|
||||
|
||||
// ignore the first 6 as they are always avaje stack elements
|
||||
int startIndex = IGNORE_LEADING_ELEMENTS;
|
||||
|
||||
// find the first non-avaje stackElement
|
||||
for (; startIndex < stackTrace.length; startIndex++) {
|
||||
if (!stackTrace[startIndex].getClassName().startsWith(IO_EBEAN)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int stackLength = stackTrace.length - startIndex;
|
||||
if (stackLength > maxCallStack) {
|
||||
// maximum of maxCallStack stackTrace elements
|
||||
stackLength = maxCallStack;
|
||||
}
|
||||
|
||||
// create the 'interesting' part of the stackTrace
|
||||
StackTraceElement[] finalTrace = new StackTraceElement[stackLength];
|
||||
System.arraycopy(stackTrace, startIndex, finalTrace, 0, stackLength);
|
||||
|
||||
if (stackLength < 1) {
|
||||
// this should not really happen
|
||||
throw new RuntimeException("StackTraceElement size 0? stack: " + Arrays.toString(stackTrace));
|
||||
}
|
||||
|
||||
return createCallStack(finalTrace);
|
||||
}
|
||||
|
||||
private CallStack createCallStack(StackTraceElement[] finalTrace) {
|
||||
return new CallStack(finalTrace, finalTrace[0].hashCode(), pathHash(finalTrace));
|
||||
}
|
||||
|
||||
|
||||
@@ -103,7 +103,6 @@ import javax.persistence.NonUniqueResultException;
|
||||
import javax.persistence.OptimisticLockException;
|
||||
import javax.persistence.PersistenceException;
|
||||
import javax.sql.DataSource;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
@@ -123,10 +122,6 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(DefaultServer.class);
|
||||
|
||||
private static final int IGNORE_LEADING_ELEMENTS = 5;
|
||||
|
||||
private static final String IO_EBEAN = "io.ebean";
|
||||
|
||||
private final ServerConfig serverConfig;
|
||||
|
||||
private final String serverName;
|
||||
@@ -139,9 +134,7 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
|
||||
private final DataTimeZone dataTimeZone;
|
||||
|
||||
private final CallStackFactory callStackFactory = new DefaultCallStackFactory();
|
||||
|
||||
private final int maxCallStack;
|
||||
private final CallStackFactory callStackFactory;
|
||||
|
||||
/**
|
||||
* Ebean defaults this to true but for EJB compatible behaviour set this to
|
||||
@@ -254,7 +247,7 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
this.updateAllPropertiesInBatch = serverConfig.isUpdateAllPropertiesInBatch();
|
||||
this.collectQueryOrigins = serverConfig.isCollectQueryOrigins();
|
||||
this.collectQueryStatsByNode = serverConfig.isCollectQueryStatsByNode();
|
||||
this.maxCallStack = serverConfig.getMaxCallStack();
|
||||
this.callStackFactory = initCallStackFactory(serverConfig);
|
||||
|
||||
this.rollbackOnChecked = serverConfig.isTransactionRollbackOnChecked();
|
||||
|
||||
@@ -284,6 +277,17 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
ShutdownManager.registerEbeanServer(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the CallStackFactory depending if AutoTune is being used.
|
||||
*/
|
||||
private CallStackFactory initCallStackFactory(ServerConfig serverConfig) {
|
||||
if (!serverConfig.getAutoTuneConfig().isActive()) {
|
||||
// use a common CallStack for performance as we don't care with no AutoTune
|
||||
return new NoopCallStackFactory();
|
||||
}
|
||||
return new DefaultCallStackFactory(serverConfig.getMaxCallStack());
|
||||
}
|
||||
|
||||
private void configureServerPlugins() {
|
||||
|
||||
autoTuneService.startup();
|
||||
@@ -380,6 +384,11 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
return transactionManager.getDataSource();
|
||||
}
|
||||
|
||||
// @Override
|
||||
// public DataSource getReadOnlyDataSource() {
|
||||
// return transactionManager.getReadOnlyDataSource();
|
||||
// }
|
||||
|
||||
@Override
|
||||
public ReadAuditPrepare getReadAuditPrepare() {
|
||||
return readAuditPrepare;
|
||||
@@ -2147,35 +2156,7 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
*/
|
||||
@Override
|
||||
public CallStack createCallStack() {
|
||||
|
||||
StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
|
||||
|
||||
// ignore the first 6 as they are always avaje stack elements
|
||||
int startIndex = IGNORE_LEADING_ELEMENTS;
|
||||
|
||||
// find the first non-avaje stackElement
|
||||
for (; startIndex < stackTrace.length; startIndex++) {
|
||||
if (!stackTrace[startIndex].getClassName().startsWith(IO_EBEAN)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int stackLength = stackTrace.length - startIndex;
|
||||
if (stackLength > maxCallStack) {
|
||||
// maximum of maxCallStack stackTrace elements
|
||||
stackLength = maxCallStack;
|
||||
}
|
||||
|
||||
// create the 'interesting' part of the stackTrace
|
||||
StackTraceElement[] finalTrace = new StackTraceElement[stackLength];
|
||||
System.arraycopy(stackTrace, startIndex, finalTrace, 0, stackLength);
|
||||
|
||||
if (stackLength < 1) {
|
||||
// this should not really happen
|
||||
throw new RuntimeException("StackTraceElement size 0? stack: " + Arrays.toString(stackTrace));
|
||||
}
|
||||
|
||||
return callStackFactory.createCallStack(finalTrace);
|
||||
return callStackFactory.createCallStack();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
package io.ebeaninternal.server.core;
|
||||
|
||||
import io.ebean.bean.CallStack;
|
||||
|
||||
/**
|
||||
* A CallStackFactory we can use when we don't use AutoTune.
|
||||
*/
|
||||
class NoopCallStackFactory implements CallStackFactory {
|
||||
|
||||
private final CallStack COMMON = new CallStack(Thread.currentThread().getStackTrace(), 0, 0);
|
||||
|
||||
@Override
|
||||
public CallStack createCallStack() {
|
||||
return COMMON;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user