mirror of
https://github.com/eclipse-sailing-analytics/sailing-analytics.git
synced 2026-10-21 11:40:01 +00:00
introduced an LRU eviction cache for SailingServiceImpl.getLeaderboardByName
This commit is contained in:
1 parent
9431badcab
commit
bafab3a7a0
4 files changed
+59
-6
No files matched your search
+1
-1
@@ -68,7 +68,7 @@ public class RaceTimePanel extends TimePanel<RaceTimePanelSettings> implements R
|
||||
}
|
||||
|
||||
boolean timerAlreadyInitialized = getMin() != null && getMax() != null && timeSlider.getCurrentValue() != null;
|
||||
if(!isTimeZoomed) {
|
||||
if (!isTimeZoomed) {
|
||||
updateMinMax(raceTimesInfo);
|
||||
if (!timerAlreadyInitialized) {
|
||||
initTimerPosition(raceTimesInfo);
|
||||
|
||||
+1
-1
@@ -109,7 +109,7 @@ public interface SailingService extends RemoteService {
|
||||
|
||||
LeaderboardDTO getLeaderboardByName(String leaderboardName, Date date,
|
||||
Collection<String> namesOfRaceColumnsForWhichToLoadLegDetails, boolean waitForLatestAnalyses)
|
||||
throws NoWindException;
|
||||
throws Exception;
|
||||
|
||||
List<StrippedLeaderboardDTO> getLeaderboards();
|
||||
|
||||
|
||||
@@ -329,7 +329,6 @@ public class TimePanel<T extends TimePanelSettings> extends FormPanel implements
|
||||
/**
|
||||
* @param min must not be <code>null</code>
|
||||
* @param max must not be <code>null</code>
|
||||
* @param fireEvent TODO
|
||||
*/
|
||||
public void setMinMax(Date min, Date max, boolean fireEvent) {
|
||||
assert min != null && max != null;
|
||||
|
||||
+57
-3
@@ -241,6 +241,17 @@ public class SailingServiceImpl extends RemoteServiceServlet implements SailingS
|
||||
private final com.sap.sailing.domain.common.CountryCodeFactory countryCodeFactory;
|
||||
|
||||
private final Executor executor;
|
||||
|
||||
/**
|
||||
* In live operations, {@link #getLeaderboardByName(String, Date, Collection, boolean)} is the application's
|
||||
* bottleneck. When two clients ask the same data for the same leaderboard with their
|
||||
* <code>waitForLatestAnalyses</code> parameters set to <code>false</code>, expansion state and (quantized) time
|
||||
* stamp, no two computations should be spawned for the two clients. Instead, if the computation is still running,
|
||||
* all clients asking the same wait for the single result. Results are cached in this LRU-based evicting cache.
|
||||
*/
|
||||
private final Map<Triple<String, Date, Collection<String>>, FutureTask<LeaderboardDTO>> leaderboardByNameCache;
|
||||
private int leaderboardByNameCacheHitCount;
|
||||
private int leaderboardByNameCacheMissCount;
|
||||
|
||||
/**
|
||||
* This executor needs to be a different one than {@link #executor} because the tasks run by {@link #executor}
|
||||
@@ -276,6 +287,14 @@ public class SailingServiceImpl extends RemoteServiceServlet implements SailingS
|
||||
countryCodeFactory = com.sap.sailing.domain.common.CountryCodeFactory.INSTANCE;
|
||||
executor = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
|
||||
raceDetailsExecutor = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
|
||||
leaderboardByNameCache = new LinkedHashMap<Triple<String,Date,Collection<String>>, FutureTask<LeaderboardDTO>>() {
|
||||
private static final long serialVersionUID = 3775119859130148488L;
|
||||
private static final int MAX_ENTRIES = 100;
|
||||
@Override
|
||||
protected boolean removeEldestEntry(Map.Entry<Triple<String,Date,Collection<String>>, FutureTask<LeaderboardDTO>> eldest) {
|
||||
return size() > MAX_ENTRIES;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public void destroy() {
|
||||
@@ -349,7 +368,42 @@ public class SailingServiceImpl extends RemoteServiceServlet implements SailingS
|
||||
}
|
||||
|
||||
@Override
|
||||
public LeaderboardDTO getLeaderboardByName(String leaderboardName, Date date,
|
||||
public LeaderboardDTO getLeaderboardByName(final String leaderboardName, final Date date,
|
||||
final Collection<String> namesOfRaceColumnsForWhichToLoadLegDetails, final boolean waitForLatestAnalyses)
|
||||
throws NoWindException, InterruptedException, ExecutionException {
|
||||
Triple<String, Date, Collection<String>> key = new Triple<String, Date, Collection<String>>(
|
||||
leaderboardName, date, namesOfRaceColumnsForWhichToLoadLegDetails);
|
||||
FutureTask<LeaderboardDTO> future;
|
||||
boolean cacheHit = false;
|
||||
synchronized (leaderboardByNameCache) {
|
||||
future = leaderboardByNameCache.get(key);
|
||||
if (future == null) {
|
||||
future = new FutureTask<LeaderboardDTO>(new Callable<LeaderboardDTO>() {
|
||||
@Override
|
||||
public LeaderboardDTO call() throws Exception {
|
||||
LeaderboardDTO result = computeLeaderboardByName(leaderboardName, date,
|
||||
namesOfRaceColumnsForWhichToLoadLegDetails, waitForLatestAnalyses);
|
||||
return result;
|
||||
}
|
||||
});
|
||||
executor.execute(future);
|
||||
leaderboardByNameCache.put(key, future);
|
||||
} else {
|
||||
cacheHit = true;
|
||||
}
|
||||
}
|
||||
if (cacheHit) {
|
||||
leaderboardByNameCacheHitCount++;
|
||||
logger.info("Cache hit in getLeaderboardByName("+leaderboardName+", "+date+", "+namesOfRaceColumnsForWhichToLoadLegDetails+")");
|
||||
} else {
|
||||
leaderboardByNameCacheMissCount++;
|
||||
}
|
||||
logger.info("getLeaderboardByName cache hit vs. miss: "+leaderboardByNameCacheHitCount+"/"+leaderboardByNameCacheMissCount);
|
||||
LeaderboardDTO result = future.get();
|
||||
return result;
|
||||
}
|
||||
|
||||
private LeaderboardDTO computeLeaderboardByName(String leaderboardName, Date date,
|
||||
final Collection<String> namesOfRaceColumnsForWhichToLoadLegDetails, final boolean waitForLatestAnalyses)
|
||||
throws NoWindException {
|
||||
long startOfRequestHandling = System.currentTimeMillis();
|
||||
@@ -420,7 +474,7 @@ public class SailingServiceImpl extends RemoteServiceServlet implements SailingS
|
||||
}
|
||||
}
|
||||
}
|
||||
logger.fine("getLeaderboardByName("+leaderboardName+", "+date+", "+namesOfRaceColumnsForWhichToLoadLegDetails+") took "+
|
||||
logger.fine("computeLeaderboardByName("+leaderboardName+", "+date+", "+namesOfRaceColumnsForWhichToLoadLegDetails+") took "+
|
||||
(System.currentTimeMillis()-startOfRequestHandling)+"ms");
|
||||
return result;
|
||||
}
|
||||
@@ -2067,7 +2121,7 @@ public class SailingServiceImpl extends RemoteServiceServlet implements SailingS
|
||||
// Filling the mark passings
|
||||
Set<MarkPassing> competitorMarkPassings = race.getMarkPassings(competitor);
|
||||
if (competitorMarkPassings != null) {
|
||||
for (MarkPassing markPassing : race.getMarkPassings(competitor)) {
|
||||
for (MarkPassing markPassing : competitorMarkPassings) {
|
||||
MillisecondsTimePoint time = new MillisecondsTimePoint(markPassing.getTimePoint().asMillis());
|
||||
markPassingsData.add(new Triple<String, Date, Double>(markPassing.getWaypoint().getName(), time
|
||||
.asDate(), getCompetitorRaceDataEntry(detailType, race, competitor, time)));
|
||||
|
||||
Reference in new issue
Block a user