diff --git a/src/main/java/com/avaje/ebean/config/AutoTuneConfig.java b/src/main/java/com/avaje/ebean/config/AutoTuneConfig.java
index fba744528..2b1ff7996 100644
--- a/src/main/java/com/avaje/ebean/config/AutoTuneConfig.java
+++ b/src/main/java/com/avaje/ebean/config/AutoTuneConfig.java
@@ -230,5 +230,6 @@ public class AutoTuneConfig {
profilingBase = p.getInt("autoTune.profilingBase", profilingBase);
profilingRate = p.getDouble("autoTune.profilingRate", profilingRate);
profilingFile = p.get("autoTune.profilingFile", profilingFile);
+ profilingUpdateFrequency = p.getInt("autoTune.profilingUpdateFrequency", profilingUpdateFrequency);
}
}
diff --git a/src/main/java/com/avaje/ebeaninternal/server/autotune/service/AutoTuneAllCollection.java b/src/main/java/com/avaje/ebeaninternal/server/autotune/service/AutoTuneAllCollection.java
new file mode 100644
index 000000000..6ff6ff300
--- /dev/null
+++ b/src/main/java/com/avaje/ebeaninternal/server/autotune/service/AutoTuneAllCollection.java
@@ -0,0 +1,61 @@
+package com.avaje.ebeaninternal.server.autotune.service;
+
+import com.avaje.ebeaninternal.server.autotune.model.Autotune;
+
+import java.util.Collection;
+
+/**
+ * Event where all tuned query information is collected.
+ *
+ * This is for writing the "all" file on shutdown when using runtime tuning.
+ *
+ */
+public class AutoTuneAllCollection {
+
+ final Autotune document = new Autotune();
+
+ final BaseQueryTuner queryTuner;
+
+ /**
+ * Construct to collect/report all tuned queries.
+ */
+ public AutoTuneAllCollection(BaseQueryTuner queryTuner) {
+ this.queryTuner = queryTuner;
+ loadAllTuned();
+ }
+
+ /**
+ * Return the number of origin elements in the document.
+ */
+ public int size() {
+ return document.getOrigin().size();
+ }
+
+ /**
+ * Return the Autotune document object.
+ */
+ public Autotune getDocument() {
+ return document;
+ }
+
+ /**
+ * Write the document as an xml file.
+ */
+ public void writeFile(String filePrefix) {
+
+ AutoTuneXmlWriter writer = new AutoTuneXmlWriter();
+ writer.write(document, filePrefix);
+ }
+
+ /**
+ * Loads all the existing query tuning into the document.
+ */
+ private void loadAllTuned() {
+
+ Collection all = queryTuner.getAll();
+ for (TunedQueryInfo tuned: all) {
+ document.getOrigin().add(tuned.getOrigin());
+ }
+ }
+
+}
diff --git a/src/main/java/com/avaje/ebeaninternal/server/autotune/service/AutoTuneDiffCollection.java b/src/main/java/com/avaje/ebeaninternal/server/autotune/service/AutoTuneDiffCollection.java
new file mode 100644
index 000000000..f281e796b
--- /dev/null
+++ b/src/main/java/com/avaje/ebeaninternal/server/autotune/service/AutoTuneDiffCollection.java
@@ -0,0 +1,164 @@
+package com.avaje.ebeaninternal.server.autotune.service;
+
+import com.avaje.ebean.bean.ObjectGraphOrigin;
+import com.avaje.ebeaninternal.server.autotune.AutoTuneCollection;
+import com.avaje.ebeaninternal.server.autotune.model.Autotune;
+import com.avaje.ebeaninternal.server.autotune.model.Origin;
+import com.avaje.ebeaninternal.server.autotune.model.ProfileDiff;
+import com.avaje.ebeaninternal.server.autotune.model.ProfileNew;
+import com.avaje.ebeaninternal.server.querydefn.OrmQueryDetail;
+
+/**
+ * Event where profiling information is collected and processed for differences
+ * relative to the current query tuning.
+ */
+public class AutoTuneDiffCollection {
+
+ final Autotune document = new Autotune();
+
+ final AutoTuneCollection profiling;
+
+ final BaseQueryTuner queryTuner;
+
+ final boolean updateTuning;
+
+ int newCount;
+
+ int diffCount;
+
+ /**
+ * Construct to collect/report the new/diff query tuning entries.
+ */
+ public AutoTuneDiffCollection(AutoTuneCollection profiling, BaseQueryTuner queryTuner, boolean updateTuning) {
+ this.profiling = profiling;
+ this.queryTuner = queryTuner;
+ this.updateTuning = updateTuning;
+ }
+
+ /**
+ * Return true if there are no new or diff entries.
+ */
+ public boolean isEmpty() {
+ return newCount == 0 && diffCount == 0;
+ }
+
+ /**
+ * Return the underlying Autotune document object.
+ */
+ public Autotune getDocument() {
+ return document;
+ }
+
+ /**
+ * Return the number of diff entries.
+ */
+ public int getDiffCount() {
+ return diffCount;
+ }
+
+ /**
+ * Return the number of new entries.
+ */
+ public int getNewCount() {
+ return newCount;
+ }
+
+ /**
+ * Return the total new and diff entries.
+ */
+ public int getChangeCount() {
+ return newCount + diffCount;
+ }
+
+ /**
+ * Write the underlying document as an xml file.
+ */
+ public void writeFile(String filePrefix) {
+
+ AutoTuneXmlWriter writer = new AutoTuneXmlWriter();
+ writer.write(document, filePrefix);
+ }
+
+ /**
+ * Process checking profiling entries against existing query tuning.
+ */
+ public boolean process() {
+
+ for (AutoTuneCollection.Entry entry : profiling.getEntries()) {
+ addToDocument(entry);
+ }
+
+ return isEmpty();
+ }
+
+ /**
+ * Check if the entry is new or diff and add as necessary.
+ */
+ private void addToDocument(AutoTuneCollection.Entry entry) {
+
+ ObjectGraphOrigin point = entry.getOrigin();
+ OrmQueryDetail profileDetail = entry.getDetail();
+
+ // compare with the existing query tuning entry
+ OrmQueryDetail tuneDetail = queryTuner.get(point.getKey());
+ if (tuneDetail == null) {
+ addToDocumentNewEntry(entry, point);
+
+ } else if (!tuneDetail.isAutoTuneEqual(profileDetail)) {
+ addToDocumentDiffEntry(entry, point, tuneDetail);
+ }
+ }
+
+ /**
+ * Add as a diff entry.
+ */
+ private void addToDocumentDiffEntry(AutoTuneCollection.Entry entry, ObjectGraphOrigin point, OrmQueryDetail tuneDetail) {
+
+ diffCount++;
+
+ Origin origin = createOrigin(entry, point, tuneDetail.toString());
+ ProfileDiff diff = document.getProfileDiff();
+ if (diff == null) {
+ diff = new ProfileDiff();
+ document.setProfileDiff(diff);
+ }
+ diff.getOrigin().add(origin);
+ }
+
+ /**
+ * Add as a "new" entry.
+ */
+ private void addToDocumentNewEntry(AutoTuneCollection.Entry entry, ObjectGraphOrigin point) {
+
+ newCount++;
+
+ ProfileNew profileNew = document.getProfileNew();
+ if (profileNew == null) {
+ profileNew = new ProfileNew();
+ document.setProfileNew(profileNew);
+ }
+ Origin origin = createOrigin(entry, point, entry.getOriginalQuery());
+ profileNew.getOrigin().add(origin);
+ }
+
+
+ /**
+ * Create the XML Origin bean for the given entry and ObjectGraphOrigin.
+ */
+ private Origin createOrigin(AutoTuneCollection.Entry entry, ObjectGraphOrigin point, String query) {
+
+ Origin origin = new Origin();
+ origin.setKey(point.getKey());
+ origin.setBeanType(point.getBeanType());
+ origin.setDetail(entry.getDetail().toString());
+ origin.setCallStack(point.getCallStack().description("\n"));
+ origin.setOriginal(query);
+
+ if (updateTuning) {
+ queryTuner.put(origin);
+ }
+
+ return origin;
+ }
+
+}
diff --git a/src/main/java/com/avaje/ebeaninternal/server/autotune/service/AutoTuneXmlWriter.java b/src/main/java/com/avaje/ebeaninternal/server/autotune/service/AutoTuneXmlWriter.java
index de0b341c6..d4f6e4c32 100644
--- a/src/main/java/com/avaje/ebeaninternal/server/autotune/service/AutoTuneXmlWriter.java
+++ b/src/main/java/com/avaje/ebeaninternal/server/autotune/service/AutoTuneXmlWriter.java
@@ -7,12 +7,29 @@ import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import java.io.File;
+import java.text.SimpleDateFormat;
+import java.util.Date;
/**
* Simple writer for output of the AutoTune Profiling as an XML document.
*/
public class AutoTuneXmlWriter {
+ /**
+ * Write the document as xml file with the given prefix.
+ */
+ public void write(Autotune document, String filePrefix) {
+
+ SortAutoTuneDocument.sort(document);
+
+ SimpleDateFormat df = new SimpleDateFormat("yyyyMMdd-HHmmss");
+ String now = df.format(new Date());
+
+ // write the file with serverName and now suffix as we can output the profiling many times
+ File file = new File(filePrefix + "-" + now + ".xml");
+ write(document, file);
+ }
+
/**
* Write Profiling to a file as xml.
*/
diff --git a/src/main/java/com/avaje/ebeaninternal/server/autotune/service/BaseQueryTuner.java b/src/main/java/com/avaje/ebeaninternal/server/autotune/service/BaseQueryTuner.java
index 7cb600cae..03366ecbf 100644
--- a/src/main/java/com/avaje/ebeaninternal/server/autotune/service/BaseQueryTuner.java
+++ b/src/main/java/com/avaje/ebeaninternal/server/autotune/service/BaseQueryTuner.java
@@ -2,17 +2,16 @@ package com.avaje.ebeaninternal.server.autotune.service;
import com.avaje.ebean.bean.CallStack;
import com.avaje.ebean.bean.ObjectGraphNode;
-import com.avaje.ebean.bean.ObjectGraphOrigin;
import com.avaje.ebean.config.AutoTuneConfig;
import com.avaje.ebean.config.AutoTuneMode;
import com.avaje.ebeaninternal.api.SpiEbeanServer;
import com.avaje.ebeaninternal.api.SpiQuery;
-import com.avaje.ebeaninternal.server.autotune.AutoTuneCollection;
import com.avaje.ebeaninternal.server.autotune.ProfilingListener;
import com.avaje.ebeaninternal.server.autotune.model.Origin;
import com.avaje.ebeaninternal.server.querydefn.OrmQueryDetail;
import javax.persistence.PersistenceException;
+import java.util.Collection;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
@@ -52,17 +51,16 @@ public class BaseQueryTuner {
}
/**
- * Load an entry from the source tuning xml.
+ * Return all the current tuned query entries.
*/
- public void load(Origin origin) {
-
- tunedQueryInfoMap.put(origin.getKey(), new TunedQueryInfo(origin));
+ public Collection getAll() {
+ return tunedQueryInfoMap.values();
}
/**
- * Add an entry at runtime.
+ * Put a query tuning entry.
*/
- public void add(Origin origin) {
+ public void put(Origin origin) {
tunedQueryInfoMap.put(origin.getKey(), new TunedQueryInfo(origin));
}
diff --git a/src/main/java/com/avaje/ebeaninternal/server/autotune/service/DefaultAutoTuneService.java b/src/main/java/com/avaje/ebeaninternal/server/autotune/service/DefaultAutoTuneService.java
index b4cac2e75..59377738c 100644
--- a/src/main/java/com/avaje/ebeaninternal/server/autotune/service/DefaultAutoTuneService.java
+++ b/src/main/java/com/avaje/ebeaninternal/server/autotune/service/DefaultAutoTuneService.java
@@ -43,6 +43,8 @@ public class DefaultAutoTuneService implements AutoTuneService {
private final int profilingUpdateFrequency;
+ private long runtimeChangeCount;
+
public DefaultAutoTuneService(SpiEbeanServer server, ServerConfig serverConfig) {
AutoTuneConfig config = serverConfig.getAutoTuneConfig();
@@ -68,18 +70,18 @@ public class DefaultAutoTuneService implements AutoTuneService {
if (queryTuning) {
loadTuningFile();
- automaticProfiling();
+ if (isRuntimeTuningUpdates()) {
+ // periodically gather and update query tuning
+ server.getBackgroundExecutor().executePeriodically(new ProfilingUpdate(), profilingUpdateFrequency, TimeUnit.SECONDS);
+ }
}
}
- private void automaticProfiling() {
- if (isAutomaticTuningUpdate()) {
- server.getBackgroundExecutor().executePeriodically(new ProfilingUpdate(), profilingUpdateFrequency, TimeUnit.SECONDS);
- }
- }
-
- private boolean isAutomaticTuningUpdate() {
+ /**
+ * Return true if the tuning should update periodically at runtime.
+ */
+ private boolean isRuntimeTuningUpdates() {
return profilingUpdateFrequency > 0;
}
@@ -104,29 +106,33 @@ public class DefaultAutoTuneService implements AutoTuneService {
Autotune profiling = reader.read(file);
logger.info("AutoTune loading {} tuning entries", profiling.getOrigin().size());
for (Origin origin : profiling.getOrigin()) {
- queryTuner.load(origin);
+ queryTuner.put(origin);
}
}
}
+ /**
+ * Collect profiling, check for new/diff to existing tuning and apply changes.
+ */
private void runtimeTuningUpdate() {
synchronized (this) {
try {
long start = System.currentTimeMillis();
+
AutoTuneCollection profiling = profileManager.profilingCollection(false);
- ProfileCollectionEvent event = new ProfileCollectionEvent(profiling, queryTuner, false);
-
- if (!event.process()) {
+ AutoTuneDiffCollection event = new AutoTuneDiffCollection(profiling, queryTuner, true);
+ if (event.process()) {
long exeMillis = System.currentTimeMillis() - start;
- logger.debug("No tuning updates for server:{} executionMillis:{}", serverName, exeMillis);
+ logger.debug("No query tuning updates for server:{} executionMillis:{}", serverName, exeMillis);
} else {
-
- event.writeFile(profilingFile + "-" + serverName + "-tuningupdate");
+ // report the query tuning changes that have been made
+ runtimeChangeCount += event.getChangeCount();
+ event.writeFile(profilingFile + "-" + serverName + "-update");
long exeMillis = System.currentTimeMillis() - start;
- logger.info("query tuning update - new:{} diff:{} for server:{} executionMillis:{}", event.getNewCount(), event.getDiffCount(), serverName, exeMillis);
+ logger.info("query tuning updates - new:{} diff:{} for server:{} executionMillis:{}", event.getNewCount(), event.getDiffCount(), serverName, exeMillis);
}
} catch (Throwable e) {
logger.error("Error collecting or applying automatic query tuning", e);
@@ -137,15 +143,15 @@ public class DefaultAutoTuneService implements AutoTuneService {
private void saveProfilingOnShutdown(boolean reset) {
synchronized (this) {
- if (isAutomaticTuningUpdate()) {
+ if (isRuntimeTuningUpdates()) {
runtimeTuningUpdate();
- outputAggregateTuning();
+ outputAllTuning();
} else {
AutoTuneCollection profiling = profileManager.profilingCollection(reset);
- ProfileCollectionEvent event = new ProfileCollectionEvent(profiling, queryTuner, true);
+ AutoTuneDiffCollection event = new AutoTuneDiffCollection(profiling, queryTuner, false);
if (!event.process()) {
logger.info("No new or diff entries for profiling server:{}", serverName);
@@ -157,12 +163,28 @@ public class DefaultAutoTuneService implements AutoTuneService {
}
}
- private void outputAggregateTuning() {
+ /**
+ * Output all the query tuning (the "all" file).
+ *
+ * This is the originally loaded tuning plus any tuning changes picked up and applied at runtime.
+ *
+ *
+ * This "all" file can be used as the next "ebean-autotune.xml" file.
+ *
+ */
+ private void outputAllTuning() {
- //TODO outputAggregateTuning()
+ if (runtimeChangeCount == 0) {
+ logger.info("no runtime query tuning changes for server:{}", serverName);
+
+ } else {
+ AutoTuneAllCollection event = new AutoTuneAllCollection(queryTuner);
+ int size = event.size();
+ event.writeFile(profilingFile + "-" + serverName + "-all");
+ logger.info("query tuning detected [{}] changes, writing all [{}] tuning entries for server:{}", runtimeChangeCount, size, serverName);
+ }
}
-
/**
* Shutdown the listener.
*
diff --git a/src/main/java/com/avaje/ebeaninternal/server/autotune/service/ProfileCollectionEvent.java b/src/main/java/com/avaje/ebeaninternal/server/autotune/service/ProfileCollectionEvent.java
deleted file mode 100644
index bcf55c4fa..000000000
--- a/src/main/java/com/avaje/ebeaninternal/server/autotune/service/ProfileCollectionEvent.java
+++ /dev/null
@@ -1,224 +0,0 @@
-package com.avaje.ebeaninternal.server.autotune.service;
-
-import com.avaje.ebean.bean.ObjectGraphOrigin;
-import com.avaje.ebeaninternal.server.autotune.AutoTuneCollection;
-import com.avaje.ebeaninternal.server.autotune.model.Autotune;
-import com.avaje.ebeaninternal.server.autotune.model.Origin;
-import com.avaje.ebeaninternal.server.autotune.model.ProfileDiff;
-import com.avaje.ebeaninternal.server.autotune.model.ProfileEmpty;
-import com.avaje.ebeaninternal.server.autotune.model.ProfileNew;
-import com.avaje.ebeaninternal.server.querydefn.OrmQueryDetail;
-
-import java.io.File;
-import java.text.SimpleDateFormat;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.Date;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-
-/**
- * Event where profiling information collected and processed.
- *
- *
- *
- */
-public class ProfileCollectionEvent {
-
- //private static final Logger logger = LoggerFactory.getLogger(ProfileCollectionEvent.class);
-
- final Autotune document = new Autotune();
-
- final AutoTuneCollection profiling;
-
- final BaseQueryTuner queryTuner;
-
- final boolean emptyEntries;
-
- int newCount;
-
- int diffCount;
-
- public ProfileCollectionEvent(AutoTuneCollection profiling, BaseQueryTuner queryTuner, boolean emptyEntries) {
- this.profiling = profiling;
- this.queryTuner = queryTuner;
- this.emptyEntries = emptyEntries;
- }
-
- public boolean isEmpty() {
- return newCount == 0 && diffCount == 0;
- }
-
- public Autotune getDocument() {
- return document;
- }
-
- public int getDiffCount() {
- return diffCount;
- }
-
- public int getNewCount() {
- return newCount;
- }
-
- public void writeFile(String filePrefix) {
-
- SimpleDateFormat df = new SimpleDateFormat("yyyyMMdd-HHmmss");
- String now = df.format(new Date());
-
- // write the file with serverName and now suffix as we can output the profiling many times
- File file = new File(filePrefix + "-" + now + ".xml");
- AutoTuneXmlWriter writer = new AutoTuneXmlWriter();
- writer.write(document, file);
- }
-
- public boolean process() {
-
-
- Set tunerKeys = (emptyEntries) ? queryTuner.keySet() : null;
- Set profileKeys = (emptyEntries) ? new HashSet() : null;
-
- List profilingEntries = profiling.getEntries();
-
- for (AutoTuneCollection.Entry entry : profilingEntries) {
- addToDocument(entry);
- if (profileKeys != null) {
- // only collect if we are actively looking for tuning
- // entries that were not used
- profileKeys.add(entry.getOrigin().getKey());
- }
- }
-
- if (tunerKeys != null) {
- // report the origin keys that we didn't collect any profiling on
- for (String tuneKey : tunerKeys) {
- if (!profileKeys.contains(tuneKey)) {
- ProfileEmpty profileEmpty = document.getProfileEmpty();
- if (profileEmpty == null) {
- profileEmpty = new ProfileEmpty();
- document.setProfileEmpty(profileEmpty);
- }
- Origin emptyOrigin = new Origin();
- emptyOrigin.setKey(tuneKey);
- profileEmpty.getOrigin().add(emptyOrigin);
- }
- }
- }
-
- if (!isEmpty()) {
- sortDocument(document);
- }
-
- return isEmpty();
- }
-
-
- private void addToDocument(AutoTuneCollection.Entry entry) {
-
- ObjectGraphOrigin point = entry.getOrigin();
- OrmQueryDetail profileDetail = entry.getDetail();
-
- // compare with the existing query tuning entry
- OrmQueryDetail tuneDetail = queryTuner.get(point.getKey());
- if (tuneDetail == null) {
- Origin origin = addToDocumentNewEntry(entry, point);
- queryTuner.add(origin);
-
- } else if (!tuneDetail.isAutoTuneEqual(profileDetail)) {
- addToDocumentDiffEntry(entry, point, tuneDetail);
- }
- }
-
- private Origin addToDocumentDiffEntry(AutoTuneCollection.Entry entry, ObjectGraphOrigin point, OrmQueryDetail tuneDetail) {
-
- diffCount++;
-
- Origin origin = createOrigin(entry, point);
- origin.setOriginal(tuneDetail.toString());
- ProfileDiff diff = document.getProfileDiff();
- if (diff == null) {
- diff = new ProfileDiff();
- document.setProfileDiff(diff);
- }
- diff.getOrigin().add(origin);
- return origin;
- }
-
- private Origin addToDocumentNewEntry(AutoTuneCollection.Entry entry, ObjectGraphOrigin point) {
-
- newCount++;
-
- ProfileNew profileNew = document.getProfileNew();
- if (profileNew == null) {
- profileNew = new ProfileNew();
- document.setProfileNew(profileNew);
- }
- Origin origin = createOrigin(entry, point);
- origin.setOriginal(entry.getOriginalQuery());
- profileNew.getOrigin().add(origin);
- return origin;
- }
-
-
- /**
- * Create the XML Origin bean for the given entry and ObjectGraphOrigin.
- */
- private Origin createOrigin(AutoTuneCollection.Entry entry, ObjectGraphOrigin point) {
- Origin origin = new Origin();
- origin.setKey(point.getKey());
- origin.setBeanType(point.getBeanType());
- origin.setDetail(entry.getDetail().toString());
- origin.setCallStack(point.getCallStack().description("\n"));
- return origin;
- }
-
- /**
- * Set the diff and new entries by bean type followed by key.
- */
- private void sortDocument(Autotune document) {
-
- ProfileDiff profileDiff = document.getProfileDiff();
- if (profileDiff != null) {
- Collections.sort(profileDiff.getOrigin(), NAME_KEY_SORT);
- }
- ProfileNew profileNew = document.getProfileNew();
- if (profileNew != null) {
- Collections.sort(profileNew.getOrigin(), NAME_KEY_SORT);
- }
- ProfileEmpty profileEmpty = document.getProfileEmpty();
- if (profileEmpty != null) {
- Collections.sort(profileEmpty.getOrigin(), KEY_SORT);
- }
- }
-
- private static final OriginNameKeySort NAME_KEY_SORT = new OriginNameKeySort();
-
- private static final OriginKeySort KEY_SORT = new OriginKeySort();
-
- /**
- * Comparator sort by bean type then key.
- */
- private static class OriginNameKeySort implements Comparator {
-
- @Override
- public int compare(Origin o1, Origin o2) {
- int comp = o1.getBeanType().compareTo(o2.getBeanType());
- if (comp == 0) {
- comp = o1.getKey().compareTo(o2.getKey());
- }
- return comp;
- }
- }
-
- /**
- * Comparator sort by bean type then key.
- */
- private static class OriginKeySort implements Comparator {
-
- @Override
- public int compare(Origin o1, Origin o2) {
- return o1.getKey().compareTo(o2.getKey());
- }
- }
-}
diff --git a/src/main/java/com/avaje/ebeaninternal/server/autotune/service/ProfileManager.java b/src/main/java/com/avaje/ebeaninternal/server/autotune/service/ProfileManager.java
index f5a7d4e38..ff4cca43a 100644
--- a/src/main/java/com/avaje/ebeaninternal/server/autotune/service/ProfileManager.java
+++ b/src/main/java/com/avaje/ebeaninternal/server/autotune/service/ProfileManager.java
@@ -118,7 +118,6 @@ public class ProfileManager implements ProfilingListener {
AutoTuneCollection req = new AutoTuneCollection();
for (ProfileOrigin origin : profileMap.values()) {
-
BeanDescriptor> desc = server.getBeanDescriptorById(origin.getOrigin().getBeanType());
if (desc != null) {
origin.profilingCollection(desc, req, reset);
diff --git a/src/main/java/com/avaje/ebeaninternal/server/autotune/service/SortAutoTuneDocument.java b/src/main/java/com/avaje/ebeaninternal/server/autotune/service/SortAutoTuneDocument.java
new file mode 100644
index 000000000..fd3d51523
--- /dev/null
+++ b/src/main/java/com/avaje/ebeaninternal/server/autotune/service/SortAutoTuneDocument.java
@@ -0,0 +1,71 @@
+package com.avaje.ebeaninternal.server.autotune.service;
+
+import com.avaje.ebeaninternal.server.autotune.model.Autotune;
+import com.avaje.ebeaninternal.server.autotune.model.Origin;
+import com.avaje.ebeaninternal.server.autotune.model.ProfileDiff;
+import com.avaje.ebeaninternal.server.autotune.model.ProfileEmpty;
+import com.avaje.ebeaninternal.server.autotune.model.ProfileNew;
+
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+
+/**
+ * Sorts Autotune document by
+ */
+public class SortAutoTuneDocument {
+
+
+ /**
+ * Set the diff and new entries by bean type followed by key.
+ */
+ public static void sort(Autotune document) {
+
+ ProfileDiff profileDiff = document.getProfileDiff();
+ if (profileDiff != null) {
+ Collections.sort(profileDiff.getOrigin(), NAME_KEY_SORT);
+ }
+ ProfileNew profileNew = document.getProfileNew();
+ if (profileNew != null) {
+ Collections.sort(profileNew.getOrigin(), NAME_KEY_SORT);
+ }
+ ProfileEmpty profileEmpty = document.getProfileEmpty();
+ if (profileEmpty != null) {
+ Collections.sort(profileEmpty.getOrigin(), KEY_SORT);
+ }
+ List origins = document.getOrigin();
+ if (!origins.isEmpty()) {
+ Collections.sort(origins, NAME_KEY_SORT);
+ }
+ }
+
+ private static final OriginNameKeySort NAME_KEY_SORT = new OriginNameKeySort();
+
+ private static final OriginKeySort KEY_SORT = new OriginKeySort();
+
+ /**
+ * Comparator sort by bean type then key.
+ */
+ private static class OriginNameKeySort implements Comparator {
+
+ @Override
+ public int compare(Origin o1, Origin o2) {
+ int comp = o1.getBeanType().compareTo(o2.getBeanType());
+ if (comp == 0) {
+ comp = o1.getKey().compareTo(o2.getKey());
+ }
+ return comp;
+ }
+ }
+
+ /**
+ * Comparator sort by bean type then key.
+ */
+ private static class OriginKeySort implements Comparator {
+
+ @Override
+ public int compare(Origin o1, Origin o2) {
+ return o1.getKey().compareTo(o2.getKey());
+ }
+ }
+}
diff --git a/src/test/java/com/avaje/tests/autofetch/TunedQueryInfoTest.java b/src/test/java/com/avaje/tests/autofetch/TunedQueryInfoTest.java
index ba907024d..99a0ead5f 100644
--- a/src/test/java/com/avaje/tests/autofetch/TunedQueryInfoTest.java
+++ b/src/test/java/com/avaje/tests/autofetch/TunedQueryInfoTest.java
@@ -3,7 +3,9 @@ package com.avaje.tests.autofetch;
import java.util.List;
import java.util.Set;
+import com.avaje.ebeaninternal.server.autotune.model.Origin;
import org.avaje.ebeantest.LoggedSqlCollector;
+import org.jetbrains.annotations.NotNull;
import org.junit.Assert;
import org.junit.Test;
@@ -33,34 +35,6 @@ public class TunedQueryInfoTest extends BaseTestCase {
serverCacheManager.setCaching(Order.class, false);
}
- @Test
- public void withSelectNull() {
-
- init();
-
- OrmQueryDetail tunedDetail = new OrmQueryDetail();
- tunedDetail.select(null);
-
- TunedQueryInfo tunedInfo = new TunedQueryInfo(tunedDetail);
-
- Query query = server.find(Order.class).setId(1);
-
- tunedInfo.tuneQuery((SpiQuery>) query);
-
- Order order = query.findUnique();
- EntityBean eb = (EntityBean)order;
- EntityBeanIntercept ebi = eb._ebean_getIntercept();
-
- Assert.assertTrue(ebi.isFullyLoadedBean());
-
- Set loadedPropertyNames = ebi.getLoadedPropertyNames();
- Assert.assertNull(loadedPropertyNames);
-
- // invoke lazy loading
- order.getCustomer();
- }
-
-
@Test
public void withSelectEmpty() {
@@ -68,9 +42,9 @@ public class TunedQueryInfoTest extends BaseTestCase {
OrmQueryDetail tunedDetail = new OrmQueryDetail();
tunedDetail.select("");
-
- TunedQueryInfo tunedInfo = new TunedQueryInfo(tunedDetail);
-
+
+ TunedQueryInfo tunedInfo = createTunedQueryInfo(tunedDetail);
+
Query query = server.find(Order.class).setId(1);
tunedInfo.tuneQuery((SpiQuery>) query);
@@ -95,9 +69,9 @@ public class TunedQueryInfoTest extends BaseTestCase {
OrmQueryDetail tunedDetail = new OrmQueryDetail();
tunedDetail.select("somethingThatDoesNotExist");
-
- TunedQueryInfo tunedInfo = new TunedQueryInfo(tunedDetail);
-
+
+ TunedQueryInfo tunedInfo = createTunedQueryInfo(tunedDetail);
+
Query query = server.find(Order.class).setId(1);
tunedInfo.tuneQuery((SpiQuery>) query);
@@ -123,7 +97,14 @@ public class TunedQueryInfoTest extends BaseTestCase {
Assert.assertTrue(loggedSql.get(0).contains("select t0.id c0, t0.id c1 from o_order t0 where t0.id = ?"));
Assert.assertTrue(loggedSql.get(1).contains("select t0.id c0, t0.status c1,"));
}
-
+
+ @NotNull
+ private TunedQueryInfo createTunedQueryInfo(OrmQueryDetail tunedDetail) {
+ Origin origin = new Origin();
+ origin.setDetail(tunedDetail.toString());
+ return new TunedQueryInfo(origin);
+ }
+
@Test
public void withSelectSomeIncludeLazyLoaded() {
@@ -132,7 +113,7 @@ public class TunedQueryInfoTest extends BaseTestCase {
OrmQueryDetail tunedDetail = new OrmQueryDetail();
tunedDetail.select("status, customer");
- TunedQueryInfo tunedInfo = new TunedQueryInfo(tunedDetail);
+ TunedQueryInfo tunedInfo = createTunedQueryInfo(tunedDetail);
Query query = server.find(Order.class).setId(1);
@@ -167,7 +148,7 @@ public class TunedQueryInfoTest extends BaseTestCase {
OrmQueryDetail tunedDetail = new OrmQueryDetail();
tunedDetail.select("status");
- TunedQueryInfo tunedInfo = new TunedQueryInfo(tunedDetail);
+ TunedQueryInfo tunedInfo = createTunedQueryInfo(tunedDetail);
Query query = server.find(Order.class).setId(1);
diff --git a/src/test/java/com/avaje/tests/cache/TestL2CacheWithSharedBean.java b/src/test/java/com/avaje/tests/cache/TestL2CacheWithSharedBean.java
index 6d6a31df4..9fbd01a43 100644
--- a/src/test/java/com/avaje/tests/cache/TestL2CacheWithSharedBean.java
+++ b/src/test/java/com/avaje/tests/cache/TestL2CacheWithSharedBean.java
@@ -1,5 +1,7 @@
package com.avaje.tests.cache;
+import com.avaje.ebeaninternal.server.autotune.model.Origin;
+import org.jetbrains.annotations.NotNull;
import org.junit.Assert;
import org.junit.Test;
@@ -14,6 +16,13 @@ import com.avaje.tests.model.basic.FeatureDescription;
public class TestL2CacheWithSharedBean extends BaseTestCase {
+ @NotNull
+ private TunedQueryInfo createTunedQueryInfo(OrmQueryDetail tunedDetail) {
+ Origin origin = new Origin();
+ origin.setDetail(tunedDetail.toString());
+ return new TunedQueryInfo(origin);
+ }
+
@Test
public void test() {
@@ -28,7 +37,7 @@ public class TestL2CacheWithSharedBean extends BaseTestCase {
OrmQueryDetail tunedDetail = new OrmQueryDetail();
tunedDetail.select("name");
- TunedQueryInfo tunedInfo = new TunedQueryInfo(tunedDetail);
+ TunedQueryInfo tunedInfo = createTunedQueryInfo(tunedDetail);
Query query = Ebean.find(FeatureDescription.class).setId(f1.getId());
diff --git a/src/test/java/com/avaje/tests/query/autotune/TestAutoTuneProfiling.java b/src/test/java/com/avaje/tests/query/autotune/TestAutoTuneProfiling.java
index 2bcccb34a..df36e07ca 100644
--- a/src/test/java/com/avaje/tests/query/autotune/TestAutoTuneProfiling.java
+++ b/src/test/java/com/avaje/tests/query/autotune/TestAutoTuneProfiling.java
@@ -7,23 +7,52 @@ import com.avaje.tests.model.basic.Customer;
import com.avaje.tests.model.basic.Order;
import com.avaje.tests.model.basic.OrderDetail;
import com.avaje.tests.model.basic.ResetBasicData;
+import org.junit.Ignore;
import org.junit.Test;
import java.util.List;
+import java.util.Random;
public class TestAutoTuneProfiling extends BaseTestCase {
+ @Ignore
@Test
- public void test() {
+ public void test() throws InterruptedException {
ResetBasicData.reset();
+ System.out.println("Start .......");
+
for (int i = 0; i < 1; i++) {
execute();
}
-
-
collectUsage();
+
+ System.out.println("Sleeping ...");
+ sortOfBusy();
+
+ System.out.println("Run after collection");
+
+ for (int i = 0; i < 10; i++) {
+ execute();
+ }
+ collectUsage();
+
+ System.out.println("Sleeping ...");
+ sortOfBusy();
+
+ System.out.println("Run after collection");
+
+ for (int i = 0; i < 1; i++) {
+ execute();
+ }
+ }
+
+ private void sortOfBusy() {
+
+ for (int i = 0; i < 90000000; i++) {
+ new Random().nextLong();
+ }
}
diff --git a/src/test/resources/ebean.properties b/src/test/resources/ebean.properties
index fabebeacb..1aa1085c5 100644
--- a/src/test/resources/ebean.properties
+++ b/src/test/resources/ebean.properties
@@ -13,7 +13,7 @@ ebean.encryptKeyManager=com.avaje.tests.basic.encrypt.BasicEncyptKeyManager
ebean.autotune.querytuning=true
ebean.autotune.profiling=true
-
+#ebean.autotune.profilingUpdateFrequency=5
ebean.ddl.generate=true
ebean.ddl.run=true
diff --git a/src/test/resources/logback-test.xml b/src/test/resources/logback-test.xml
index 0feee6d67..153e25712 100644
--- a/src/test/resources/logback-test.xml
+++ b/src/test/resources/logback-test.xml
@@ -86,6 +86,6 @@
-
+
\ No newline at end of file