r4032 - in trunk/src/main/java/fr/ifremer/isisfish: datastore entities types util
Author: bpoussin Date: 2014-07-10 14:25:39 +0200 (Thu, 10 Jul 2014) New Revision: 4032 Url: http://forge.codelutin.com/projects/isis-fish/repository/revisions/4032 Log: optimisation Modified: trunk/src/main/java/fr/ifremer/isisfish/datastore/ResultStorageAbstract.java trunk/src/main/java/fr/ifremer/isisfish/datastore/ResultStorageCSV.java trunk/src/main/java/fr/ifremer/isisfish/entities/PopulationGroupImpl.java trunk/src/main/java/fr/ifremer/isisfish/types/TimeStep.java trunk/src/main/java/fr/ifremer/isisfish/util/IsisCache.java trunk/src/main/java/fr/ifremer/isisfish/util/IsisCacheBackendOnGuava.java Modified: trunk/src/main/java/fr/ifremer/isisfish/datastore/ResultStorageAbstract.java =================================================================== --- trunk/src/main/java/fr/ifremer/isisfish/datastore/ResultStorageAbstract.java 2014-07-08 17:24:51 UTC (rev 4031) +++ trunk/src/main/java/fr/ifremer/isisfish/datastore/ResultStorageAbstract.java 2014-07-10 12:25:39 UTC (rev 4032) @@ -120,11 +120,11 @@ // interne avant de l'utiliser comme cle. internalValue = internalValue.intern(); result = internalValue; - if (StringUtils.startsWith(internalValue, Month.class.getName())) { + if (StringUtils.startsWith(internalValue, "Month")) { String val = StringUtils.substringAfter(internalValue, SEP); int monthNumber = Integer.parseInt(val); - result = new Month(monthNumber); - } else if (StringUtils.startsWith(internalValue, TimeStep.class.getName())) { + result = Month.MONTH[monthNumber]; + } else if (StringUtils.startsWith(internalValue, "TimeStep")) { String val = StringUtils.substringAfter(internalValue, SEP); int stepNumber = Integer.parseInt(val); result = new TimeStep(stepNumber); @@ -155,9 +155,9 @@ String result = cache.getKey(decoratedValue); if (result == null && decoratedValue != null) { if (decoratedValue instanceof Month) { - result = Month.class.getName() + SEP + ((Month)decoratedValue).getMonthNumber(); + result = "Month" + SEP + ((Month)decoratedValue).getMonthNumber(); } else if (decoratedValue instanceof TimeStep) { - result = TimeStep.class.getName() + SEP + ((TimeStep)decoratedValue).getStep(); + result = "TimeStep" + SEP + ((TimeStep)decoratedValue).getStep(); } else if (decoratedValue instanceof TopiaEntity) { result = ((TopiaEntity)decoratedValue).getTopiaId() + SEP + decoratedValue; } else { Modified: trunk/src/main/java/fr/ifremer/isisfish/datastore/ResultStorageCSV.java =================================================================== --- trunk/src/main/java/fr/ifremer/isisfish/datastore/ResultStorageCSV.java 2014-07-08 17:24:51 UTC (rev 4031) +++ trunk/src/main/java/fr/ifremer/isisfish/datastore/ResultStorageCSV.java 2014-07-10 12:25:39 UTC (rev 4032) @@ -21,6 +21,7 @@ import java.util.Arrays; import java.util.Collections; import java.util.HashMap; +import java.util.HashSet; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; @@ -67,10 +68,6 @@ * 0;2;1;4.2 * </pre> * - * TODO: - * stat du nombre de demande de resultat or pas de temps courant - * stat sur max ecart entre pas de temps courant et pas de temps demande - * * @author poussin * @version $Revision$ * @@ -89,14 +86,27 @@ /** number of step in cache */ protected int cacheStep = 13; // default to 13 months + /** Le pas de temps a partir duquel il faut sauver les resultats sur disque*/ + protected TimeStep startDiskStep = null; + + /** use to prevent to much call */ + private File directoryCache; + /** nombre total de resultat */ protected int numberOfResult = 0; /** nombre de resultat reellement stocke sur disque */ protected int numberOfResultOnDisk = 0; - /** le nombre de resultat demande qui n'etait pas dans le pas de temps courant */ - protected int numberOfPastResultAsked = 0; - /** le plus vieux pas de temps demande par rapport au pas de temps courant */ - protected int maxGapWithCurrentStep = 0; + /** le nombre de resultat demande */ + protected int numberOfResultAsked = 0; + /** le nombre de resultat lu dans le cache */ + protected int numberOfResultReadInCache = 0; + /** le nombre de resultat lu sur le disque */ + protected int numberOfResultReadOnDisk = 0; + /** + * le plus vieux pas de temps demande par rapport au pas de temps courant + * lu sur le disque + */ + protected int maxGapWithCurrentStepReadOnDisk = 0; LinkedHashMap<TimeStep, Map<String, MatrixND>> cache = new LinkedHashMap<TimeStep, Map<String, MatrixND>>() { @@ -107,7 +117,6 @@ } }; - public ResultStorageCSV(SimulationStorage simulation) { super(simulation); @@ -120,9 +129,11 @@ return String.format( "ResultStorageCSV:\n" + "\t%s results written to disk on a total of %s\n" - + "\t%s results read outside of current step\n" - + "\tthe oldest step was %s step before current step\n", - numberOfResultOnDisk, numberOfResult, numberOfPastResultAsked, maxGapWithCurrentStep); + + "\t%s results read (%s in cache and %s on disk)\n" + + "\tthe oldest step read on disk was %s step before current step\n", + numberOfResultOnDisk, numberOfResult, + numberOfResultAsked, numberOfResultReadInCache, numberOfResultReadOnDisk, + maxGapWithCurrentStepReadOnDisk); } /** @@ -130,8 +141,10 @@ * @return */ protected File getDirectory() { - File file = SimulationStorage.getResultDirectory(simulation.getDirectory()); - return file; + if (directoryCache == null) { + directoryCache = SimulationStorage.getResultDirectory(simulation.getDirectory()); + } + return directoryCache; } /** @@ -149,6 +162,34 @@ return file; } + protected HashSet<String> fileExistCache; + protected HashSet<String> getFileExistCache() { + if (fileExistCache == null) { + fileExistCache = new HashSet<String>(); + File matrixDir = getMatrixDirectory(""); + File[] resultDirs = matrixDir.listFiles(); + if (resultDirs != null) { + for (File resultDir : resultDirs) { + + Collections.addAll(fileExistCache, resultDir.list()); + } + } + } + return fileExistCache; + } + /** + * Method used to know if file result exist. Usage of File.exists take to long time + * during simulation + * @param f + * @return + */ + protected boolean fileExist(File f) { + return getFileExistCache().contains(f.getName()); + } + protected void addFileExist(File f) { + getFileExistCache().add(f.getName()); + } + protected MatrixND readMatrix(String file) throws IOException { MatrixND result = null; LineNumberReader in = null; @@ -227,6 +268,7 @@ try { File file = getDirectory(); FileUtils.deleteDirectory(file); + fileExistCache = null; } catch (IOException eee) { throw new IsisFishRuntimeException("Can't delete results", eee); } @@ -235,14 +277,7 @@ @Override protected MatrixND readResult(TimeStep step, String name) { // un peu de statistique (seulement en simulation - SimulationControl sc = SimulationContext.get().getSimulationControl(); - if (sc != null) { - TimeStep currentStep = sc.getStep(); - if (!step.equals(currentStep)) { - numberOfPastResultAsked++; - maxGapWithCurrentStep = Math.max(maxGapWithCurrentStep, currentStep.gap(step)); - } - } + numberOfResultAsked++; MatrixND result = null; @@ -252,11 +287,23 @@ } // if not found looking for result on disk - if (result == null) { + if (result != null) { + numberOfResultReadInCache++; + } else { File file = getMatrixFile(step, name); - if (file.exists()) { + if (fileExist(file)) { try { result = readMatrix(file.getPath()); + + // un peu de statistique (seulement en simulation + numberOfResultReadOnDisk++; + SimulationControl sc = SimulationContext.get().getSimulationControl(); + if (sc != null) { + TimeStep currentStep = sc.getStep(); + if (!step.equals(currentStep)) { + maxGapWithCurrentStepReadOnDisk = Math.max(maxGapWithCurrentStepReadOnDisk, currentStep.gap(step)); + } + } } catch (IOException eee) { log.error("Can't read result file: " + file, eee); } @@ -287,9 +334,6 @@ // return result; // } - /** Le pas de temps a partir duquel il faut sauver les resultats sur disque*/ - protected TimeStep startDiskStep = null; - /** * Indique s'il faut sauver sur disque les resultats * @param step @@ -370,6 +414,8 @@ out.println(); } + // result file is writen without error, add it to fileExistCache + addFileExist(file); } catch (Exception eee) { throw new IsisFishRuntimeException("Can't write result: " + file, eee); } finally { Modified: trunk/src/main/java/fr/ifremer/isisfish/entities/PopulationGroupImpl.java =================================================================== --- trunk/src/main/java/fr/ifremer/isisfish/entities/PopulationGroupImpl.java 2014-07-08 17:24:51 UTC (rev 4031) +++ trunk/src/main/java/fr/ifremer/isisfish/entities/PopulationGroupImpl.java 2014-07-10 12:25:39 UTC (rev 4032) @@ -199,10 +199,18 @@ } return result; } - + + private String toStringCache; @Override public String toString() { - return t("isisfish.populationGroup.toString", this.getPopulation(), - this.getId()); + // trop couteux d'appeler i18n, appele des millions de fois + // et est vraiment raisonnable d'avoir des string != suivant le langage + // quel impact dans les scripts utilisateurs ? +// return t("isisfish.populationGroup.toString", this.getPopulation(), +// this.getId()); + if (toStringCache == null) { + toStringCache = this.getPopulation().toString() + " Group " + this.getId(); + } + return toStringCache; } } Modified: trunk/src/main/java/fr/ifremer/isisfish/types/TimeStep.java =================================================================== --- trunk/src/main/java/fr/ifremer/isisfish/types/TimeStep.java 2014-07-08 17:24:51 UTC (rev 4031) +++ trunk/src/main/java/fr/ifremer/isisfish/types/TimeStep.java 2014-07-10 12:25:39 UTC (rev 4032) @@ -178,6 +178,7 @@ return this.step >= d.step; } + @Override public boolean equals(Object o) { if (o instanceof TimeStep) { return step == ((TimeStep) o).step; @@ -185,6 +186,7 @@ return false; } + @Override public int hashCode() { return step; } Modified: trunk/src/main/java/fr/ifremer/isisfish/util/IsisCache.java =================================================================== --- trunk/src/main/java/fr/ifremer/isisfish/util/IsisCache.java 2014-07-08 17:24:51 UTC (rev 4031) +++ trunk/src/main/java/fr/ifremer/isisfish/util/IsisCache.java 2014-07-10 12:25:39 UTC (rev 4032) @@ -33,6 +33,8 @@ import fr.ifremer.isisfish.simulator.SimulationContext; import fr.ifremer.isisfish.types.TimeStep; +import java.util.HashMap; +import java.util.Map; /** * IsisCacheOnReferenceMap utilise pour mettre les resultats de methode durant @@ -86,6 +88,15 @@ // } /** + * La representation de la methode en string, la representation commence + * par un @ si il y a l'annotation noCache trouver pour cette methode. + */ + protected Map<Method, String> methodStringCache = new HashMap<Method, String>(); + // use to compute key, isis simulation is monothread, we can instanciate it here + // to minimise object instanciation + protected StringBuilder sbKey = new StringBuilder(300); + + /** * Recupere pour un pas de temps donnes une valeur calcule pour une cle. * * @param defaultValue la valeur par defaut a retourner si elle n'est pas en @@ -98,14 +109,26 @@ totalCall++; Object result = null; - if (method.getAnnotation(Nocache.class) != null - || method.getDeclaringClass().getAnnotation(Nocache.class) != null) { + + String methodString = methodStringCache.get(method); + if (methodString == null) { + Class declaringClass = method.getDeclaringClass(); + methodString = (method.getAnnotation(Nocache.class) != null + || declaringClass.getAnnotation(Nocache.class) != null)? + "@" : ""; + methodString += declaringClass.getSimpleName() + "."+ method.getName(); + methodString = methodString.intern(); + methodStringCache.put(method, methodString); + } + + // if method have annotation 'noCache' name start with @ + if (methodString.charAt(0) == '@') { result = realCall(defaultValue); } else { // compute key and keep TimeStep objet - StringBuilder sbKey = new StringBuilder(); // le pas de temps trouve dans les arguments - TimeStep step = computeKey(sbKey, method, args); + sbKey.setLength(0); + TimeStep step = computeKey(sbKey, methodString, args); // on recupere le intern de la String car normalement en cache on // retrouve souvent les memes chaines comme cle (sinon le cache @@ -128,11 +151,9 @@ return result; } - protected TimeStep computeKey(StringBuilder sbKey, Method method, Object[] args) { + protected TimeStep computeKey(StringBuilder sbKey, String methodString, Object[] args) { TimeStep result = null; - sbKey.append(method.getDeclaringClass().getSimpleName()); - sbKey.append("."); - sbKey.append(method.getName()); + sbKey.append(methodString); for (Object o : args) { sbKey.append(";"); if (o == null) { @@ -141,7 +162,7 @@ sbKey.append(o.toString()); } else if (o instanceof TimeStep) { result = (TimeStep) o; - sbKey.append(((TimeStep) o).getStep()); + sbKey.append(result.getStep()); } else if (o instanceof TopiaEntity) { sbKey.append(((TopiaEntity) o).getTopiaId().substring(entityPackageLenght)); } else { @@ -149,7 +170,7 @@ sbKey.append(o.getClass().getSimpleName()); sbKey.append('@'); // et en lui ajoutant son adresse memoire en Hexa - sbKey.append(Integer.toHexString(System.identityHashCode(o))); + sbKey.append(System.identityHashCode(o)); } } return result; Modified: trunk/src/main/java/fr/ifremer/isisfish/util/IsisCacheBackendOnGuava.java =================================================================== --- trunk/src/main/java/fr/ifremer/isisfish/util/IsisCacheBackendOnGuava.java 2014-07-08 17:24:51 UTC (rev 4031) +++ trunk/src/main/java/fr/ifremer/isisfish/util/IsisCacheBackendOnGuava.java 2014-07-10 12:25:39 UTC (rev 4032) @@ -292,15 +292,24 @@ double standardDeviation = Math.sqrt(variance); double stepStandardDeviation = Math.sqrt(stepVariance); - return String.format("%s - \n" + String trick = ""; + if (sizeCache < biggestStepCached) { + trick = String.format( + "TRICK: for better performance you must set memory at least to %s\n", + StringUtil.convertMemory(biggestStepCached + 500 * 1024 *1024)); + } + String result = String.format("%s - \n%s" + "\tmaxMemory: %s, cacheMemory: %s, totalCached: %s, numberStep: %s, numberEntries: %s\n" + "\tStep min: %s, max: %s, mean: %s, standard deviation: %s\n" + "\tEntry min: %s, max: %s, mean: %s, standard deviation: %s\n", + trick, getClass().getSimpleName(), StringUtil.convertMemory(maxMemory), StringUtil.convertMemory(sizeCache), StringUtil.convertMemory(totalCached), numberStepCached, numberCached, StringUtil.convertMemory(smallestStepCached), StringUtil.convertMemory(biggestStepCached), StringUtil.convertMemory(stepMean), StringUtil.convertMemory((long)stepStandardDeviation), StringUtil.convertMemory(smallestCached), StringUtil.convertMemory(biggestCached), StringUtil.convertMemory(mean), StringUtil.convertMemory((long)standardDeviation) ); + + return result; }
participants (1)
-
bpoussin@users.forge.codelutin.com