diff --git a/noisemodelling-jdbc/src/main/java/org/noise_planet/noisemodelling/jdbc/LDENComputeRaysOut.java b/noisemodelling-jdbc/src/main/java/org/noise_planet/noisemodelling/jdbc/LDENComputeRaysOut.java index b690815a2..54c3b33eb 100644 --- a/noisemodelling-jdbc/src/main/java/org/noise_planet/noisemodelling/jdbc/LDENComputeRaysOut.java +++ b/noisemodelling-jdbc/src/main/java/org/noise_planet/noisemodelling/jdbc/LDENComputeRaysOut.java @@ -25,7 +25,7 @@ public LDENComputeRaysOut(PropagationProcessPathData pathData, LDENPropagationPr @Override - public IComputeRaysOut subProcess(int receiverStart, int receiverEnd) { + public IComputeRaysOut subProcess() { return new ThreadComputeRaysOut(this); } diff --git a/noisemodelling-jdbc/src/main/java/org/noise_planet/noisemodelling/jdbc/LDENPointNoiseMapFactory.java b/noisemodelling-jdbc/src/main/java/org/noise_planet/noisemodelling/jdbc/LDENPointNoiseMapFactory.java index ebc9af974..32a105f32 100644 --- a/noisemodelling-jdbc/src/main/java/org/noise_planet/noisemodelling/jdbc/LDENPointNoiseMapFactory.java +++ b/noisemodelling-jdbc/src/main/java/org/noise_planet/noisemodelling/jdbc/LDENPointNoiseMapFactory.java @@ -26,6 +26,7 @@ import org.noise_planet.noisemodelling.emission.DirectionAttributes; import org.noise_planet.noisemodelling.emission.RailWayLW; import org.noise_planet.noisemodelling.pathfinder.*; +import org.noise_planet.noisemodelling.pathfinder.utils.ProfilerThread; import org.noise_planet.noisemodelling.propagation.*; import org.noise_planet.noisemodelling.propagation.ComputeRaysOutAttenuation; import org.slf4j.Logger; @@ -41,7 +42,7 @@ /** * */ -public class LDENPointNoiseMapFactory implements PointNoiseMap.PropagationProcessDataFactory, PointNoiseMap.IComputeRaysOutFactory { +public class LDENPointNoiseMapFactory implements PointNoiseMap.PropagationProcessDataFactory, PointNoiseMap.IComputeRaysOutFactory, ProfilerThread.Metric { LDENConfig ldenConfig; TableWriter tableWriter; Thread tableWriterThread; @@ -59,6 +60,21 @@ public LDENPointNoiseMapFactory(Connection connection, LDENConfig ldenConfig) { this.connection = connection; } + @Override + public String[] getColumnNames() { + return new String[] {"jdbc_stack"}; + } + + @Override + public String[] getCurrentValues() { + return new String[] {Long.toString(ldenData.queueSize.get())}; + } + + @Override + public void tick(long currentMillis) { + + } + public void insertTrainDirectivity() { directionAttributes.clear(); directionAttributes.put(0, new LDENPropagationProcessData.OmnidirectionalDirection()); @@ -310,7 +326,7 @@ private String forgeCreateTable(String tableName) { sb.append(" (IDRECEIVER bigint NOT NULL"); sb.append(", IDSOURCE bigint NOT NULL"); } else { - sb.append(" (IDRECEIVER SERIAL PRIMARY KEY"); + sb.append(" (IDRECEIVER bigint NOT NULL"); } for (int idfreq = 0; idfreq < ldenConfig.propagationProcessPathData.freq_lvl.size(); idfreq++) { sb.append(", HZ"); @@ -318,20 +334,28 @@ private String forgeCreateTable(String tableName) { sb.append(" numeric(5, 2)"); } sb.append(", LAEQ numeric(5, 2), LEQ numeric(5, 2)"); - if(!ldenConfig.mergeSources) { - sb.append(", PRIMARY KEY(IDRECEIVER, IDSOURCE)"); - } sb.append(")"); return sb.toString(); } + private String forgePkTable(String tableName) { + StringBuilder sb = new StringBuilder("alter table "); + sb.append(tableName); + if (!ldenConfig.mergeSources) { + sb.append(" ADD PRIMARY KEY(IDRECEIVER, IDSOURCE)"); + } else { + sb.append(" ADD PRIMARY KEY(IDRECEIVER)"); + } + return sb.toString(); + } + @Override public void run() { // Drop and create tables try(Statement sql = connection.createStatement()) { if(ldenConfig.exportRays) { sql.execute(String.format("DROP TABLE IF EXISTS %s", ldenConfig.raysTable)); - sql.execute("CREATE TABLE "+ldenConfig.raysTable+"(pk serial primary key, the_geom geometry, IDRECEIVER bigint NOT NULL, IDSOURCE bigint NOT NULL)"); + sql.execute("CREATE TABLE "+ldenConfig.raysTable+"(pk bigint auto_increment, the_geom geometry, IDRECEIVER bigint NOT NULL, IDSOURCE bigint NOT NULL)"); } if(ldenConfig.computeLDay) { sql.execute(String.format("DROP TABLE IF EXISTS %s", ldenConfig.lDayTable)); @@ -374,6 +398,20 @@ public void run() { break; } } + // Set primary keys + LOGGER.info("Write done, apply primary keys"); + if(ldenConfig.computeLDay) { + sql.execute(forgePkTable(ldenConfig.lDayTable)); + } + if(ldenConfig.computeLEvening) { + sql.execute(forgePkTable(ldenConfig.lEveningTable)); + } + if(ldenConfig.computeLNight) { + sql.execute(forgePkTable(ldenConfig.lNightTable)); + } + if(ldenConfig.computeLDEN) { + sql.execute(forgePkTable(ldenConfig.lDenTable)); + } } catch (SQLException e) { LOGGER.error("SQL Writer exception", e); LOGGER.error(e.getLocalizedMessage(), e.getNextException()); diff --git a/noisemodelling-jdbc/src/main/java/org/noise_planet/noisemodelling/jdbc/PointNoiseMap.java b/noisemodelling-jdbc/src/main/java/org/noise_planet/noisemodelling/jdbc/PointNoiseMap.java index a46f4011d..89555c67f 100644 --- a/noisemodelling-jdbc/src/main/java/org/noise_planet/noisemodelling/jdbc/PointNoiseMap.java +++ b/noisemodelling-jdbc/src/main/java/org/noise_planet/noisemodelling/jdbc/PointNoiseMap.java @@ -18,6 +18,7 @@ import org.locationtech.jts.geom.Geometry; import org.locationtech.jts.index.strtree.STRtree; import org.noise_planet.noisemodelling.pathfinder.ComputeRays; +import org.noise_planet.noisemodelling.pathfinder.utils.ProfilerThread; import org.noise_planet.noisemodelling.propagation.ComputeRaysOutAttenuation; import org.noise_planet.noisemodelling.pathfinder.FastObstructionTest; import org.noise_planet.noisemodelling.pathfinder.IComputeRaysOut; @@ -45,12 +46,32 @@ public class PointNoiseMap extends JdbcNoiseMap { private IComputeRaysOutFactory computeRaysOutFactory; private Logger logger = LoggerFactory.getLogger(PointNoiseMap.class); private int threadCount = 0; + private ProfilerThread profilerThread; public PointNoiseMap(String buildingsTableName, String sourcesTableName, String receiverTableName) { super(buildingsTableName, sourcesTableName); this.receiverTableName = receiverTableName; } + + /** + * Computation stacks and timing are collected by this class in order + * to profile the execution of the simulation + * @return Instance of ProfilerThread or null + */ + public ProfilerThread getProfilerThread() { + return profilerThread; + } + + /** + * Computation stacks and timing are collected by this class in order + * to profile the execution of the simulation + * @param profilerThread Instance of ProfilerThread + */ + public void setProfilerThread(ProfilerThread profilerThread) { + this.profilerThread = profilerThread; + } + public void setComputeRaysOutFactory(IComputeRaysOutFactory computeRaysOutFactory) { this.computeRaysOutFactory = computeRaysOutFactory; } @@ -249,6 +270,10 @@ public IComputeRaysOut evaluateCell(Connection connection, int cellI, int cellJ, ComputeRays computeRays = new ComputeRays(threadData); + if(profilerThread != null) { + computeRays.setProfilerThread(profilerThread); + } + if(threadCount > 0) { computeRays.setThreadCount(threadCount); } diff --git a/noisemodelling-pathfinder/src/main/java/org/noise_planet/noisemodelling/pathfinder/ComputeRays.java b/noisemodelling-pathfinder/src/main/java/org/noise_planet/noisemodelling/pathfinder/ComputeRays.java index 2ee14395b..96f268d04 100644 --- a/noisemodelling-pathfinder/src/main/java/org/noise_planet/noisemodelling/pathfinder/ComputeRays.java +++ b/noisemodelling-pathfinder/src/main/java/org/noise_planet/noisemodelling/pathfinder/ComputeRays.java @@ -44,10 +44,13 @@ import org.locationtech.jts.math.Vector2D; import org.locationtech.jts.math.Vector3D; import org.locationtech.jts.triangulate.quadedge.Vertex; +import org.noise_planet.noisemodelling.pathfinder.utils.ProfilerThread; +import org.noise_planet.noisemodelling.pathfinder.utils.ReceiverStatsMetric; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.*; +import java.util.concurrent.ConcurrentLinkedDeque; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; @@ -65,6 +68,7 @@ public class ComputeRays { private final static double MAX_RATIO_HULL_DIRECT_PATH = 4; private int threadCount; private PropagationProcessData data; + private ProfilerThread profilerThread; private STRtree rTreeOfGeoSoil; private final static Logger LOGGER = LoggerFactory.getLogger(ComputeRays.class); @@ -166,6 +170,24 @@ public ComputeRays(PropagationProcessData data) { this.threadCount = runtime.availableProcessors(); } + /** + * Computation stacks and timing are collected by this class in order + * to profile the execution of the simulation + * @return Instance of ProfilerThread or null + */ + public ProfilerThread getProfilerThread() { + return profilerThread; + } + + /** + * Computation stacks and timing are collected by this class in order + * to profile the execution of the simulation + * @param profilerThread Instance of ProfilerThread + */ + public void setProfilerThread(ProfilerThread profilerThread) { + this.profilerThread = profilerThread; + } + public int getThreadCount() { return threadCount; } @@ -347,22 +369,20 @@ public static int[] asWallArray(MirrorReceiverResult res) { return walls; } - public List computeReflexion(Coordinate receiverCoord, - Coordinate srcCoord, boolean favorable, List nearBuildingsWalls) { -// for(FastObstructionTest.Wall wall : nearBuildingsWalls) { -// System.out.println(String.format(Locale.ROOT, "walls.add(new FastObstructionTest.Wall(new Coordinate(%.2f,%.2f), new Coordinate(%.2f,%.2f) , %d));", wall.p0.x, wall.p0.y, wall.p1.x, wall.p1.y, wall.getBuildingId())); -// } + public List computeReflexion(Coordinate receiverCoord, Coordinate srcCoord, boolean favorable, + List nearBuildingsWalls, + List receiverReflections) { // Compute receiver mirror LineSegment srcReceiver = new LineSegment(srcCoord, receiverCoord); LineIntersector linters = new RobustLineIntersector(); List reflexionPropagationPaths = new ArrayList<>(); - - MirrorReceiverIterator.It mirroredReceivers = new MirrorReceiverIterator.It(receiverCoord, nearBuildingsWalls, - srcReceiver, Integer.MAX_VALUE, data.reflexionOrder, data.maxSrcDist); - - for (MirrorReceiverResult receiverReflection : mirroredReceivers) { + for (MirrorReceiverResult receiverReflection : receiverReflections) { + // Check propagation distance limitation + if(receiverReflection.getReceiverPos().distance3D(srcCoord) > data.maxSrcDist) { + break; + } // Print wall reflections //System.out.println(Arrays.toString(asWallArray(receiverReflection))); List rayPath = new ArrayList<>(data.reflexionOrder + 2); @@ -376,6 +396,12 @@ public List computeReflexion(Coordinate receiverCoord, linters.computeIntersection(seg.p0, seg.p1, receiverReflection.getReceiverPos(), destinationPt); + + // Check first wall distance reflection limitation + if(linters.hasIntersection() && new Coordinate( + linters.getIntersection(0)).distance(srcCoord) > data.maxRefDist) { + break; + } while (linters.hasIntersection() && MirrorReceiverIterator.wallPointTest(seg, destinationPt)) { // There are a probable reflection point on the segment Coordinate reflectionPt = new Coordinate( @@ -959,8 +985,8 @@ public List directPath(Coordinate srcCoord, * @return Minimal power level (dB) or maximum attenuation (dB) */ private double[] receiverSourcePropa(SourcePointInfo src, - Coordinate receiverCoord, int rcvId, - List nearBuildingsWalls, List debugInfo, IComputeRaysOut dataOut) { + Coordinate receiverCoord, int rcvId, List debugInfo, + IComputeRaysOut dataOut,List nearBuildingsWalls, List mirrorReceiverResults) { Coordinate srcCoord = src.position; int srcId = src.sourcePrimaryKey; double sourceLi = src.li; @@ -975,7 +1001,8 @@ private double[] receiverSourcePropa(SourcePointInfo src, // Process specular reflection if (data.reflexionOrder > 0) { - List propagationPaths_all = computeReflexion(receiverCoord, srcCoord, false, nearBuildingsWalls); + List propagationPaths_all = computeReflexion(receiverCoord, srcCoord, + false, nearBuildingsWalls, mirrorReceiverResults); propagationPaths.addAll(propagationPaths_all); } @@ -1047,10 +1074,13 @@ private double addLineSource(LineString source, Coordinate receiverCoord, int sr public void computeRaysAtPosition(Coordinate receiverCoord, int idReceiver, List debugInfo, IComputeRaysOut dataOut, ProgressVisitor progressVisitor) { // List of walls within maxReceiverSource distance HashSet processedLineSources = new HashSet(); //Already processed Raw source (line and/or points) - Set wallsReceiver = new HashSet<>(); + List wallsReceiver = new ArrayList<>(); + List mirrorReceiverResults = new ArrayList<>(); if (data.reflexionOrder > 0) { wallsReceiver.addAll(data.freeFieldFinder.getLimitsInRange( data.maxRefDist, receiverCoord, false)); + new MirrorReceiverIterator.It(receiverCoord, wallsReceiver, + Integer.MAX_VALUE, data.reflexionOrder, data.maxSrcDist).forEach(mirrorReceiverResults::add); } double searchSourceDistance = data.maxSrcDist; Envelope receiverSourceRegion = new Envelope(receiverCoord.x @@ -1126,8 +1156,8 @@ public void computeRaysAtPosition(Coordinate receiverCoord, int idReceiver, List wallsSource.addAll(data.freeFieldFinder.getLimitsInRange( data.maxRefDist, srcCoord, false)); } - double[] power = receiverSourcePropa(src, receiverCoord, idReceiver, - new ArrayList<>(wallsSource), debugInfo, dataOut); + double[] power = receiverSourcePropa(src, receiverCoord, idReceiver + , debugInfo, dataOut, wallsReceiver, mirrorReceiverResults); double global = ComputeRays.sumArray(power.length, ComputeRays.dbaToW(power)); totalPowerRemaining -= src.globalWj; if (power.length > 0) { @@ -1169,27 +1199,29 @@ public void runDebug(IComputeRaysOut computeRaysOut, List // maxSrcDist meters ProgressVisitor propaProcessProgression = data.cellProg; - int splitCount = threadCount; ThreadPool threadManager = new ThreadPool( - splitCount, - splitCount + 1, Long.MAX_VALUE, + threadCount, + threadCount + 1, Long.MAX_VALUE, TimeUnit.SECONDS); - int maximumReceiverBatch = (int) Math.ceil(data.receivers.size() / (double) splitCount); - int endReceiverRange = 0; - while (endReceiverRange < data.receivers.size()) { + + ConcurrentLinkedDeque receiversToCompute = new ConcurrentLinkedDeque<>(); + // receiversToCompute is a stack of receiver to compute + // all concurrent threads will consume this stack in order to keep the number of working + // concurrent thread until the end + for(int receiverId =0; receiverId < data.receivers.size(); receiverId++) { + receiversToCompute.add(receiverId); + } + for(int idThread = 0; idThread < threadCount; idThread++) { if (propaProcessProgression != null && propaProcessProgression.isCanceled()) { break; } - int newEndReceiver = Math.min(endReceiverRange + maximumReceiverBatch, data.receivers.size()); - RangeReceiversComputation batchThread = new RangeReceiversComputation(endReceiverRange, - newEndReceiver, this, debugInfo, propaProcessProgression, - computeRaysOut.subProcess(endReceiverRange, newEndReceiver)); + RangeReceiversComputation batchThread = new RangeReceiversComputation(receiversToCompute, this, debugInfo, propaProcessProgression, + computeRaysOut.subProcess()); if (threadCount != 1) { threadManager.executeBlocking(batchThread); } else { batchThread.run(); } - endReceiverRange = newEndReceiver; } threadManager.shutdown(); try { @@ -1218,18 +1250,16 @@ private double getIntersectedDistance(Geometry geo) { } private static final class RangeReceiversComputation implements Runnable { - private final int startReceiver; // Included - private final int endReceiver; // Excluded + private ConcurrentLinkedDeque receiversToCompute; private ComputeRays propagationProcess; private List debugInfo; private ProgressVisitor progressVisitor; private IComputeRaysOut dataOut; - public RangeReceiversComputation(int startReceiver, int endReceiver, ComputeRays propagationProcess, + public RangeReceiversComputation(ConcurrentLinkedDeque receiversToCompute, ComputeRays propagationProcess, List debugInfo, ProgressVisitor progressVisitor, IComputeRaysOut dataOut) { - this.startReceiver = startReceiver; - this.endReceiver = endReceiver; + this.receiversToCompute = receiversToCompute; this.propagationProcess = propagationProcess; this.debugInfo = debugInfo; this.progressVisitor = progressVisitor; @@ -1239,20 +1269,35 @@ public RangeReceiversComputation(int startReceiver, int endReceiver, ComputeRays @Override public void run() { try { - for (int idReceiver = startReceiver; idReceiver < endReceiver; idReceiver++) { + while(!receiversToCompute.isEmpty()) { + int idReceiver = receiversToCompute.pop(); if (progressVisitor != null) { if (progressVisitor.isCanceled()) { break; } } Coordinate receiverCoord = propagationProcess.data.receivers.get(idReceiver); + long start = 0; + if(propagationProcess.profilerThread != null) { + start = propagationProcess.profilerThread.timeTracker.get(); + } propagationProcess.computeRaysAtPosition(receiverCoord, idReceiver, debugInfo, dataOut, progressVisitor); + // Save computation time for this receiver + if(propagationProcess.profilerThread != null && + propagationProcess.profilerThread.getMetric(ReceiverStatsMetric.class) != null) { + propagationProcess.profilerThread.getMetric(ReceiverStatsMetric.class).onEndComputation(idReceiver, + (int) (propagationProcess.profilerThread.timeTracker.get() - start)); + } + if (progressVisitor != null) { progressVisitor.endStep(); } + } + } catch (NoSuchElementException ex) { + // ignore as it is expected at the end of the computation } catch (Exception ex) { LOGGER.error(ex.getLocalizedMessage(), ex); if (progressVisitor != null) { diff --git a/noisemodelling-pathfinder/src/main/java/org/noise_planet/noisemodelling/pathfinder/ComputeRaysOut.java b/noisemodelling-pathfinder/src/main/java/org/noise_planet/noisemodelling/pathfinder/ComputeRaysOut.java index 2cd39e081..b50468409 100644 --- a/noisemodelling-pathfinder/src/main/java/org/noise_planet/noisemodelling/pathfinder/ComputeRaysOut.java +++ b/noisemodelling-pathfinder/src/main/java/org/noise_planet/noisemodelling/pathfinder/ComputeRaysOut.java @@ -89,7 +89,7 @@ public double[] addPropagationPaths(long sourceId, double sourceLi, long receive } @Override - public IComputeRaysOut subProcess(int receiverStart, int receiverEnd) { + public IComputeRaysOut subProcess() { return new ThreadRaysOut(this); } @@ -183,8 +183,8 @@ public void finalizeReceiver(final long receiverId) { } @Override - public IComputeRaysOut subProcess(int receiverStart, int receiverEnd) { - return multiThreadParent.subProcess(receiverStart, receiverEnd); + public IComputeRaysOut subProcess() { + return multiThreadParent.subProcess(); } } } diff --git a/noisemodelling-pathfinder/src/main/java/org/noise_planet/noisemodelling/pathfinder/IComputeRaysOut.java b/noisemodelling-pathfinder/src/main/java/org/noise_planet/noisemodelling/pathfinder/IComputeRaysOut.java index 2374f0d41..ba0568a98 100644 --- a/noisemodelling-pathfinder/src/main/java/org/noise_planet/noisemodelling/pathfinder/IComputeRaysOut.java +++ b/noisemodelling-pathfinder/src/main/java/org/noise_planet/noisemodelling/pathfinder/IComputeRaysOut.java @@ -19,9 +19,7 @@ public interface IComputeRaysOut { void finalizeReceiver(long receiverId); /** * If the implementation does not support thread concurrency, this method is called to return an instance - * @param receiverStart - * @param receiverEnd * @return */ - IComputeRaysOut subProcess(int receiverStart, int receiverEnd); + IComputeRaysOut subProcess(); } diff --git a/noisemodelling-pathfinder/src/main/java/org/noise_planet/noisemodelling/pathfinder/MirrorReceiverIterator.java b/noisemodelling-pathfinder/src/main/java/org/noise_planet/noisemodelling/pathfinder/MirrorReceiverIterator.java index 7e3e4e924..0dc840f74 100644 --- a/noisemodelling-pathfinder/src/main/java/org/noise_planet/noisemodelling/pathfinder/MirrorReceiverIterator.java +++ b/noisemodelling-pathfinder/src/main/java/org/noise_planet/noisemodelling/pathfinder/MirrorReceiverIterator.java @@ -47,7 +47,6 @@ public class MirrorReceiverIterator implements Iterator { private final Coordinate receiverCoord; private final List nearBuildingsWalls; - private final LineSegment srcReceiver; private final double distanceLimitation; private final double propagationLimitation; // Wall stack @@ -55,11 +54,10 @@ public class MirrorReceiverIterator implements Iterator { private MirrorReceiverResult current = null; private final int maxDepth; - private MirrorReceiverIterator(Coordinate receiverCoord, List nearBuildingsWalls, - LineSegment srcReceiver, double distanceLimitation, int maxDepth, double propagationLimitation) { + private MirrorReceiverIterator(Coordinate receiverCoord, List nearBuildingsWalls + , double distanceLimitation, int maxDepth, double propagationLimitation) { this.receiverCoord = receiverCoord; this.nearBuildingsWalls = nearBuildingsWalls; - this.srcReceiver = srcReceiver; this.distanceLimitation = distanceLimitation; this.wallIdentifierIt = new CrossTableIterator(maxDepth, nearBuildingsWalls.size()); this.propagationLimitation = propagationLimitation; @@ -98,17 +96,12 @@ private void fetchNext() { } if (isCCW) { Coordinate intersectionPt = wall.project(receiverIm); - if (wall.distance(srcReceiver) < distanceLimitation) // Test maximum distance constraint - { - Coordinate mirrored = new Coordinate(2 * intersectionPt.x - - receiverIm.x, 2 * intersectionPt.y - - receiverIm.y, receiverIm.z); - if (srcReceiver.p0.distance(mirrored) < propagationLimitation) { - next = new MirrorReceiverResult(mirrored, - parent, wallId, wall.getBuildingId()); - break; - } - } + Coordinate mirrored = new Coordinate(2 * intersectionPt.x + - receiverIm.x, 2 * intersectionPt.y + - receiverIm.y, receiverIm.z); + next = new MirrorReceiverResult(mirrored, + parent, wallId, wall.getBuildingId()); + break; } // MirrorReceiverResult has not been found with this wall // Do not fetch sub-reflections @@ -178,16 +171,14 @@ public static boolean wallPointTest(LineSegment wall1, Coordinate pt) { public static final class It implements Iterable { private final Coordinate receiverCoord; private final List nearBuildingsWalls; - private final LineSegment srcReceiver; private final double distanceLimitation; private final int maxDepth; private final double propagationLimitation; public It(Coordinate receiverCoord, List nearBuildingsWalls, - LineSegment srcReceiver, double distanceLimitation, int maxDepth, double propagationLimitation) { + double distanceLimitation, int maxDepth, double propagationLimitation) { this.receiverCoord = receiverCoord; this.nearBuildingsWalls = nearBuildingsWalls; - this.srcReceiver = srcReceiver; this.distanceLimitation = distanceLimitation; this.maxDepth = maxDepth; this.propagationLimitation = propagationLimitation; @@ -195,7 +186,7 @@ public It(Coordinate receiverCoord, List nearBuildings @Override public java.util.Iterator iterator() { - return new MirrorReceiverIterator(receiverCoord, nearBuildingsWalls, srcReceiver, distanceLimitation, + return new MirrorReceiverIterator(receiverCoord, nearBuildingsWalls, distanceLimitation, maxDepth,propagationLimitation); } } diff --git a/noisemodelling-pathfinder/src/main/java/org/noise_planet/noisemodelling/pathfinder/PropagationProcessData.java b/noisemodelling-pathfinder/src/main/java/org/noise_planet/noisemodelling/pathfinder/PropagationProcessData.java index 479d1ed86..7ead5b124 100644 --- a/noisemodelling-pathfinder/src/main/java/org/noise_planet/noisemodelling/pathfinder/PropagationProcessData.java +++ b/noisemodelling-pathfinder/src/main/java/org/noise_planet/noisemodelling/pathfinder/PropagationProcessData.java @@ -55,7 +55,7 @@ */ public class PropagationProcessData { public static final double DEFAULT_MAX_PROPAGATION_DISTANCE = 1200; - public static final double DEFAULT_MAXIMUM_REF_DIST = 50; + public static final double DEFAULT_MAXIMUM_REF_DIST = 700; public static final double DEFAULT_RECEIVER_DIST = 1.0; public static final double DEFAULT_GS = 0.0; public static final String YAW_DATABASE_FIELD = "YAW"; diff --git a/noisemodelling-pathfinder/src/main/java/org/noise_planet/noisemodelling/pathfinder/utils/JVMMemoryMetric.java b/noisemodelling-pathfinder/src/main/java/org/noise_planet/noisemodelling/pathfinder/utils/JVMMemoryMetric.java new file mode 100644 index 000000000..936f292a3 --- /dev/null +++ b/noisemodelling-pathfinder/src/main/java/org/noise_planet/noisemodelling/pathfinder/utils/JVMMemoryMetric.java @@ -0,0 +1,53 @@ +/** + * NoiseMap is a scientific computation plugin for OrbisGIS developed in order to + * evaluate the noise impact on urban mobility plans. This model is + * based on the French standard method NMPB2008. It includes traffic-to-noise + * sources evaluation and sound propagation processing. + *

+ * This version is developed at French IRSTV Institute and at IFSTTAR + * (http://www.ifsttar.fr/) as part of the Eval-PDU project, funded by the + * French Agence Nationale de la Recherche (ANR) under contract ANR-08-VILL-0005-01. + *

+ * Noisemap is distributed under GPL 3 license. Its reference contact is Judicaël + * Picaut . It is maintained by Nicolas Fortin + * as part of the "Atelier SIG" team of the IRSTV Institute . + *

+ * Copyright (C) 2011 IFSTTAR + * Copyright (C) 2011-2012 IRSTV (FR CNRS 2488) + *

+ * Noisemap is free software: you can redistribute it and/or modify it under the + * terms of the GNU General Public License as published by the Free Software + * Foundation, either version 3 of the License, or (at your option) any later + * version. + *

+ * Noisemap is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU General Public License for more details. + *

+ * You should have received a copy of the GNU General Public License along with + * Noisemap. If not, see . + *

+ * For more information, please consult: + * or contact directly: + * info_at_ orbisgis.org + */ +package org.noise_planet.noisemodelling.pathfinder.utils; + +public class JVMMemoryMetric implements ProfilerThread.Metric { + @Override + public String[] getColumnNames() { + return new String[] {"jvm_used_heap_mb", "jvm_max_heap_mb"}; + } + + @Override + public String[] getCurrentValues() { + Runtime r = Runtime.getRuntime(); + return new String[] {Long.toString((r.totalMemory() - r.freeMemory()) / 1048576L), + Long.toString(r.totalMemory() / 1048576L)}; + } + + @Override + public void tick(long currentMillis) { + + } +} diff --git a/noisemodelling-pathfinder/src/main/java/org/noise_planet/noisemodelling/pathfinder/utils/ProfilerThread.java b/noisemodelling-pathfinder/src/main/java/org/noise_planet/noisemodelling/pathfinder/utils/ProfilerThread.java new file mode 100644 index 000000000..5aa59d9b5 --- /dev/null +++ b/noisemodelling-pathfinder/src/main/java/org/noise_planet/noisemodelling/pathfinder/utils/ProfilerThread.java @@ -0,0 +1,192 @@ +/** + * NoiseMap is a scientific computation plugin for OrbisGIS developed in order to + * evaluate the noise impact on urban mobility plans. This model is + * based on the French standard method NMPB2008. It includes traffic-to-noise + * sources evaluation and sound propagation processing. + *

+ * This version is developed at French IRSTV Institute and at IFSTTAR + * (http://www.ifsttar.fr/) as part of the Eval-PDU project, funded by the + * French Agence Nationale de la Recherche (ANR) under contract ANR-08-VILL-0005-01. + *

+ * Noisemap is distributed under GPL 3 license. Its reference contact is Judicaël + * Picaut . It is maintained by Nicolas Fortin + * as part of the "Atelier SIG" team of the IRSTV Institute . + *

+ * Copyright (C) 2011 IFSTTAR + * Copyright (C) 2011-2012 IRSTV (FR CNRS 2488) + *

+ * Noisemap is free software: you can redistribute it and/or modify it under the + * terms of the GNU General Public License as published by the Free Software + * Foundation, either version 3 of the License, or (at your option) any later + * version. + *

+ * Noisemap is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU General Public License for more details. + *

+ * You should have received a copy of the GNU General Public License along with + * Noisemap. If not, see . + *

+ * For more information, please consult: + * or contact directly: + * info_at_ orbisgis.org + */ +package org.noise_planet.noisemodelling.pathfinder.utils; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.util.*; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicLong; + +public class ProfilerThread implements Runnable { + public Logger log = LoggerFactory.getLogger(ProfilerThread.class); + public AtomicLong timeTracker = new AtomicLong(System.currentTimeMillis()); + private AtomicBoolean doRun = new AtomicBoolean(true); + private int writeInterval = 60; + private int flushInterval = 300; + private File outputFile; + long start; + private Map metricsIndex = new HashMap<>(); + private List metrics = new ArrayList<>(); + + public ProfilerThread(File outputFile) { + this.outputFile = outputFile; + start = System.currentTimeMillis(); + addMetric(new TimeMetric(timeTracker, start)); + } + + public void addMetric(Metric metric) { + metrics.add(metric); + metricsIndex.put(metric.getClass().getName(), metrics.size() - 1); + } + + /** + * @param writeInterval In seconds, intervals for writing new metrics in the csv file + */ + public void setWriteInterval(int writeInterval) { + this.writeInterval = writeInterval; + } + + /** + * @param flushInterval Time in seconds between each effective write on the hard drive + */ + public void setFlushInterval(int flushInterval) { + this.flushInterval = flushInterval; + } + + @Override + public void run() { + long lastWrite = 0; + long lastFlush = 0; + try(BufferedWriter b = new BufferedWriter(new FileWriter(outputFile))) { + StringBuilder sb = new StringBuilder(); + for(Metric m : metrics) { + for(String columnName : m.getColumnNames()) { + if(sb.length() != 0) { + sb.append(","); + } + sb.append(columnName); + } + } + sb.append("\n"); + b.write(sb.toString()); + b.flush(); + while (doRun.get()) { + timeTracker.set(System.currentTimeMillis()); + for(Metric m : metrics) { + m.tick(timeTracker.get()); + } + try { + if((timeTracker.get() - lastWrite) / 1000.0 >= writeInterval ) { + lastWrite = timeTracker.get(); + sb = new StringBuilder(); + for(Metric m : metrics) { + for(String metricValue : m.getCurrentValues()) { + if(sb.length() != 0) { + sb.append(","); + } + sb.append(metricValue); + } + } + sb.append("\n"); + b.write(sb.toString()); + } else { + Thread.sleep(2); + } + if((timeTracker.get() - lastFlush) / 1000.0 >= flushInterval ) { + lastFlush = timeTracker.get(); + b.flush(); + } + } catch (InterruptedException ex) { + break; + } + } + } catch (IOException ex) { + log.error("Error while writing file", ex); + } + } + + public void stop() { + doRun.set(false); + } + + public T getMetric(Class metricClass) { + Integer mIndex = metricsIndex.get(metricClass.getName()); + if(mIndex != null) { + Metric o = metrics.get(mIndex); + if (metricClass.isInstance(o)) { + return metricClass.cast(o); + } else { + return null; + } + } else { + return null; + } + } + + private class TimeMetric implements Metric { + AtomicLong timeTracker; + long startTime; + + public TimeMetric(AtomicLong timeTracker, long startTime) { + this.timeTracker = timeTracker; + this.startTime = startTime; + } + + @Override + public String[] getColumnNames() { + return new String[] {"time"}; + } + + @Override + public String[] getCurrentValues() { + return new String[] {String.format(Locale.ROOT, "%.2f", (timeTracker.get() - start) / 1e3)}; + } + + @Override + public void tick(long currentMillis) { + + } + } + + /** + * Metric is a collection of statistics to write on the profile csv file + */ + public interface Metric { + String[] getColumnNames(); + String[] getCurrentValues(); + + /** + * Called with little intervals in order to process metrics on the same thread than + * the call to getCurrentValues + * @param currentMillis Time + */ + void tick(long currentMillis); + } +} diff --git a/noisemodelling-pathfinder/src/main/java/org/noise_planet/noisemodelling/pathfinder/utils/ProgressMetric.java b/noisemodelling-pathfinder/src/main/java/org/noise_planet/noisemodelling/pathfinder/utils/ProgressMetric.java new file mode 100644 index 000000000..3d1d52b44 --- /dev/null +++ b/noisemodelling-pathfinder/src/main/java/org/noise_planet/noisemodelling/pathfinder/utils/ProgressMetric.java @@ -0,0 +1,64 @@ +/** + * NoiseMap is a scientific computation plugin for OrbisGIS developed in order to + * evaluate the noise impact on urban mobility plans. This model is + * based on the French standard method NMPB2008. It includes traffic-to-noise + * sources evaluation and sound propagation processing. + *

+ * This version is developed at French IRSTV Institute and at IFSTTAR + * (http://www.ifsttar.fr/) as part of the Eval-PDU project, funded by the + * French Agence Nationale de la Recherche (ANR) under contract ANR-08-VILL-0005-01. + *

+ * Noisemap is distributed under GPL 3 license. Its reference contact is Judicaël + * Picaut . It is maintained by Nicolas Fortin + * as part of the "Atelier SIG" team of the IRSTV Institute . + *

+ * Copyright (C) 2011 IFSTTAR + * Copyright (C) 2011-2012 IRSTV (FR CNRS 2488) + *

+ * Noisemap is free software: you can redistribute it and/or modify it under the + * terms of the GNU General Public License as published by the Free Software + * Foundation, either version 3 of the License, or (at your option) any later + * version. + *

+ * Noisemap is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU General Public License for more details. + *

+ * You should have received a copy of the GNU General Public License along with + * Noisemap. If not, see . + *

+ * For more information, please consult: + * or contact directly: + * info_at_ orbisgis.org + */ +package org.noise_planet.noisemodelling.pathfinder.utils; + +import org.h2gis.api.ProgressVisitor; + +import java.util.Locale; + +/** + * Metric that write progression value in percentage + */ +public class ProgressMetric implements ProfilerThread.Metric { + private ProgressVisitor progressVisitor; + + public ProgressMetric(ProgressVisitor progressVisitor) { + this.progressVisitor = progressVisitor; + } + + @Override + public String[] getColumnNames() { + return new String[] {"progression"}; + } + + @Override + public String[] getCurrentValues() { + return new String[] {String.format(Locale.ROOT, "%.2f", progressVisitor.getProgression() * 100.0)}; + } + + @Override + public void tick(long currentMillis) { + + } +} diff --git a/noisemodelling-pathfinder/src/main/java/org/noise_planet/noisemodelling/pathfinder/utils/ReceiverStatsMetric.java b/noisemodelling-pathfinder/src/main/java/org/noise_planet/noisemodelling/pathfinder/utils/ReceiverStatsMetric.java new file mode 100644 index 000000000..de7864c66 --- /dev/null +++ b/noisemodelling-pathfinder/src/main/java/org/noise_planet/noisemodelling/pathfinder/utils/ReceiverStatsMetric.java @@ -0,0 +1,89 @@ +/** + * NoiseMap is a scientific computation plugin for OrbisGIS developed in order to + * evaluate the noise impact on urban mobility plans. This model is + * based on the French standard method NMPB2008. It includes traffic-to-noise + * sources evaluation and sound propagation processing. + *

+ * This version is developed at French IRSTV Institute and at IFSTTAR + * (http://www.ifsttar.fr/) as part of the Eval-PDU project, funded by the + * French Agence Nationale de la Recherche (ANR) under contract ANR-08-VILL-0005-01. + *

+ * Noisemap is distributed under GPL 3 license. Its reference contact is Judicaël + * Picaut . It is maintained by Nicolas Fortin + * as part of the "Atelier SIG" team of the IRSTV Institute . + *

+ * Copyright (C) 2011 IFSTTAR + * Copyright (C) 2011-2012 IRSTV (FR CNRS 2488) + *

+ * Noisemap is free software: you can redistribute it and/or modify it under the + * terms of the GNU General Public License as published by the Free Software + * Foundation, either version 3 of the License, or (at your option) any later + * version. + *

+ * Noisemap is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU General Public License for more details. + *

+ * You should have received a copy of the GNU General Public License along with + * Noisemap. If not, see . + *

+ * For more information, please consult: + * or contact directly: + * info_at_ orbisgis.org + */ +package org.noise_planet.noisemodelling.pathfinder.utils; + +import org.apache.commons.math3.stat.descriptive.DescriptiveStatistics; + +import java.util.concurrent.ConcurrentLinkedDeque; + +/** + * Generate stats about receiver computation time + */ +public class ReceiverStatsMetric implements ProfilerThread.Metric { + public static final String RECEIVER_COMPUTATION_TIME = "RECEIVER_COMPUTATION_TIME"; + private ConcurrentLinkedDeque receiverProfiles = new ConcurrentLinkedDeque<>(); + private DescriptiveStatistics stats = new DescriptiveStatistics(); + + public ReceiverStatsMetric() { + } + + @Override + public void tick(long currentMillis) { + while (!receiverProfiles.isEmpty()) { + ReceiverProfile receiverProfile = receiverProfiles.pop(); + stats.addValue(receiverProfile.computationTime); + } + } + + @Override + public String[] getColumnNames() { + return new String[] {"receiver_min","receiver_median","receiver_mean","receiver_max"}; + } + + public void onEndComputation(int receiverId, int computationTime) { + receiverProfiles.add(new ReceiverProfile(receiverId, computationTime)); + } + + @Override + public String[] getCurrentValues() { + String[] res = new String[] { + Integer.toString((int)stats.getMin()), + Integer.toString((int)stats.getPercentile(50)), + Integer.toString((int)stats.getMean()), + Integer.toString((int)stats.getMax()) + }; + stats.clear(); + return res; + } + + public static class ReceiverProfile { + public int receiverId; + public int computationTime; + + public ReceiverProfile(int receiverId, int computationTime) { + this.receiverId = receiverId; + this.computationTime = computationTime; + } + } +} \ No newline at end of file diff --git a/noisemodelling-pathfinder/src/test/java/org/noise_planet/noisemodelling/pathfinder/TestWallReflection.java b/noisemodelling-pathfinder/src/test/java/org/noise_planet/noisemodelling/pathfinder/TestWallReflection.java index 2290c37ed..7e148e5c2 100644 --- a/noisemodelling-pathfinder/src/test/java/org/noise_planet/noisemodelling/pathfinder/TestWallReflection.java +++ b/noisemodelling-pathfinder/src/test/java/org/noise_planet/noisemodelling/pathfinder/TestWallReflection.java @@ -108,7 +108,7 @@ public void testWallVisibility () { public static List getReceiverImages(Coordinate receiver, Coordinate source, List walls, int order) { MirrorReceiverIterator.It mirrorReceiverResults = - new MirrorReceiverIterator.It(receiver, walls, new LineSegment(source, receiver), 9999, order, 9999); + new MirrorReceiverIterator.It(receiver, walls, 9999, order, 9999); List res = new ArrayList<>(); for(MirrorReceiverResult r : mirrorReceiverResults) { @@ -240,7 +240,7 @@ public void testWallReceiverImage() { Coordinate source = new Coordinate(9, 4); MirrorReceiverIterator.It mirrorReceiverResults = - new MirrorReceiverIterator.It(receiver, walls, new LineSegment(source, receiver), 20, 2, 40); + new MirrorReceiverIterator.It(receiver, walls, 20, 2, 40); Iterator it = mirrorReceiverResults.iterator(); wallTest(new Coordinate(0, 2), new int[]{0}, it.next()); wallTest(new Coordinate(6, 2), new int[]{0, 4}, it.next()); @@ -340,7 +340,10 @@ public void testPath() throws ParseException, LayerDelaunayError { data.maxRefDist, source, false); assertEquals(13, walls.size()); List paths; - paths = computeRays.computeReflexion(receiver, source, false, walls); + List mirrorReceiverResults = new ArrayList<>(); + new MirrorReceiverIterator.It(receiver, walls, + Integer.MAX_VALUE, data.reflexionOrder, data.maxSrcDist).forEach(mirrorReceiverResults::add); + paths = computeRays.computeReflexion(receiver, source, false, walls, mirrorReceiverResults); assertEquals(1, paths.size()); List pts = paths.get(0).getPointList(); assertEquals(3, pts.size()); @@ -352,7 +355,10 @@ public void testPath() throws ParseException, LayerDelaunayError { assertEquals(0, receiver.distance(pts.get(2).coordinate), 1e-6); data.reflexionOrder = 2; - paths = computeRays.computeReflexion(receiver, source, false, walls); + mirrorReceiverResults = new ArrayList<>(); + new MirrorReceiverIterator.It(receiver, walls, + Integer.MAX_VALUE, data.reflexionOrder, data.maxSrcDist).forEach(mirrorReceiverResults::add); + paths = computeRays.computeReflexion(receiver, source, false, walls, mirrorReceiverResults); assertEquals(2, paths.size()); pts = paths.get(1).getPointList(); // 2 ref points diff --git a/noisemodelling-propagation/src/main/java/org/noise_planet/noisemodelling/propagation/ComputeRaysOutAttenuation.java b/noisemodelling-propagation/src/main/java/org/noise_planet/noisemodelling/propagation/ComputeRaysOutAttenuation.java index fb7ad659c..b71bea9bd 100644 --- a/noisemodelling-propagation/src/main/java/org/noise_planet/noisemodelling/propagation/ComputeRaysOutAttenuation.java +++ b/noisemodelling-propagation/src/main/java/org/noise_planet/noisemodelling/propagation/ComputeRaysOutAttenuation.java @@ -240,7 +240,7 @@ public double[] computeAttenuation(PropagationProcessPathData pathData, long sou } @Override - public IComputeRaysOut subProcess(int receiverStart, int receiverEnd) { + public IComputeRaysOut subProcess() { return new ThreadRaysOut(this); } @@ -394,8 +394,8 @@ public void finalizeReceiver(final long receiverId) { } @Override - public IComputeRaysOut subProcess(int receiverStart, int receiverEnd) { - return multiThreadParent.subProcess(receiverStart, receiverEnd); + public IComputeRaysOut subProcess() { + return multiThreadParent.subProcess(); } } } diff --git a/noisemodelling-tutorial-01/src/main/java/org/noise_planet/nmtutorial01/main.java b/noisemodelling-tutorial-01/src/main/java/org/noise_planet/nmtutorial01/main.java index 60d5862f2..0af852110 100644 --- a/noisemodelling-tutorial-01/src/main/java/org/noise_planet/nmtutorial01/main.java +++ b/noisemodelling-tutorial-01/src/main/java/org/noise_planet/nmtutorial01/main.java @@ -7,6 +7,7 @@ import org.h2gis.functions.io.csv.CSVDriverFunction; import org.h2gis.functions.io.geojson.GeoJsonRead; import org.h2gis.utilities.SFSUtilities; +import org.noise_planet.noisemodelling.pathfinder.utils.JVMMemoryMetric; import org.noise_planet.noisemodelling.pathfinder.utils.KMLDocument; import org.noise_planet.noisemodelling.jdbc.LDENConfig; import org.noise_planet.noisemodelling.jdbc.LDENPointNoiseMapFactory; @@ -14,6 +15,8 @@ import org.noise_planet.noisemodelling.pathfinder.FastObstructionTest; import org.noise_planet.noisemodelling.pathfinder.IComputeRaysOut; import org.noise_planet.noisemodelling.pathfinder.RootProgressVisitor; +import org.noise_planet.noisemodelling.pathfinder.utils.ProfilerThread; +import org.noise_planet.noisemodelling.pathfinder.utils.ProgressMetric; import org.noise_planet.noisemodelling.propagation.ComputeRaysOutAttenuation; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -115,7 +118,7 @@ public static void main(String[] args) throws SQLException, IOException { LDENPointNoiseMapFactory tableWriter = new LDENPointNoiseMapFactory(connection, ldenConfig); - tableWriter.setKeepRays(true); + tableWriter.setKeepRays(false); pointNoiseMap.setPropagationProcessDataFactory(tableWriter); pointNoiseMap.setComputeRaysOutFactory(tableWriter); @@ -135,8 +138,16 @@ public static void main(String[] args) throws SQLException, IOException { long start = System.currentTimeMillis(); // Iterate over computation areas + ProfilerThread profilerThread = new ProfilerThread(new File("target/profile.csv")); + profilerThread.addMetric(tableWriter); + profilerThread.addMetric(new ProgressMetric(progressLogger)); + profilerThread.addMetric(new JVMMemoryMetric()); + profilerThread.setWriteInterval(2); + profilerThread.setFlushInterval(15); + pointNoiseMap.setProfilerThread(profilerThread); try { tableWriter.start(); + new Thread(profilerThread).start(); // Fetch cell identifiers with receivers Map cells = pointNoiseMap.searchPopulatedCells(connection); ProgressVisitor progressVisitor = progressLogger.subProcess(cells.size()); @@ -150,8 +161,10 @@ public static void main(String[] args) throws SQLException, IOException { } } } finally { + profilerThread.stop(); tableWriter.stop(); } + long computationTime = System.currentTimeMillis() - start; logger.info(String.format(Locale.ROOT, "Computed in %d ms, %.2f ms per receiver", computationTime,computationTime / (double)receivers.size())); // Export result tables as csv files diff --git a/wps_scripts/src/main/groovy/org/noise_planet/noisemodelling/wps/Experimental/Get_Rayz.groovy b/wps_scripts/src/main/groovy/org/noise_planet/noisemodelling/wps/Experimental/Get_Rayz.groovy index 7efdb1113..20f1b7119 100644 --- a/wps_scripts/src/main/groovy/org/noise_planet/noisemodelling/wps/Experimental/Get_Rayz.groovy +++ b/wps_scripts/src/main/groovy/org/noise_planet/noisemodelling/wps/Experimental/Get_Rayz.groovy @@ -468,7 +468,7 @@ class PropagationPathStorage extends ComputeRaysOutAttenuation { } @Override - IComputeRaysOut subProcess(int i, int i1) { + IComputeRaysOut subProcess() { return new PropagationPathStorageThread(this) } @@ -518,7 +518,7 @@ class PropagationPathStorage extends ComputeRaysOutAttenuation { } @Override - IComputeRaysOut subProcess(int receiverStart, int receiverEnd) { + IComputeRaysOut subProcess() { return null } diff --git a/wps_scripts/src/main/groovy/org/noise_planet/noisemodelling/wps/NoiseModelling/Noise_level_from_source.groovy b/wps_scripts/src/main/groovy/org/noise_planet/noisemodelling/wps/NoiseModelling/Noise_level_from_source.groovy index 55010d60c..7c491e94b 100644 --- a/wps_scripts/src/main/groovy/org/noise_planet/noisemodelling/wps/NoiseModelling/Noise_level_from_source.groovy +++ b/wps_scripts/src/main/groovy/org/noise_planet/noisemodelling/wps/NoiseModelling/Noise_level_from_source.groovy @@ -32,6 +32,9 @@ import org.locationtech.jts.geom.GeometryFactory import org.noise_planet.noisemodelling.emission.* import org.noise_planet.noisemodelling.pathfinder.* +import org.noise_planet.noisemodelling.pathfinder.utils.JVMMemoryMetric +import org.noise_planet.noisemodelling.pathfinder.utils.ProfilerThread +import org.noise_planet.noisemodelling.pathfinder.utils.ProgressMetric import org.noise_planet.noisemodelling.propagation.* import org.noise_planet.noisemodelling.jdbc.* @@ -549,8 +552,16 @@ def exec(Connection connection, input) { RootProgressVisitor progressLogger = new RootProgressVisitor(1, true, 1) logger.info("Start calculation... ") + ProfilerThread profilerThread = new ProfilerThread(new File("webapps/root/profile.csv")); + profilerThread.addMetric(ldenProcessing); + profilerThread.addMetric(new ProgressMetric(progressLogger)); + profilerThread.addMetric(new JVMMemoryMetric()); + profilerThread.setWriteInterval(300); + profilerThread.setFlushInterval(300); + pointNoiseMap.setProfilerThread(profilerThread); try { ldenProcessing.start() + new Thread(profilerThread).start(); // Iterate over computation areas int k = 0 Map cells = pointNoiseMap.searchPopulatedCells(connection); @@ -565,6 +576,7 @@ def exec(Connection connection, input) { pointNoiseMap.evaluateCell(connection, cellIndex.getLatitudeIndex(), cellIndex.getLongitudeIndex(), progressVisitor, receivers) } } finally { + profilerThread.stop(); ldenProcessing.stop() } diff --git a/wps_scripts/src/main/groovy/org/noise_planet/noisemodelling/wps/NoiseModelling/Noise_level_from_traffic.groovy b/wps_scripts/src/main/groovy/org/noise_planet/noisemodelling/wps/NoiseModelling/Noise_level_from_traffic.groovy index 0546d9427..d77fcf9e0 100644 --- a/wps_scripts/src/main/groovy/org/noise_planet/noisemodelling/wps/NoiseModelling/Noise_level_from_traffic.groovy +++ b/wps_scripts/src/main/groovy/org/noise_planet/noisemodelling/wps/NoiseModelling/Noise_level_from_traffic.groovy @@ -30,6 +30,9 @@ import org.h2gis.utilities.wrapper.ConnectionWrapper import org.noise_planet.noisemodelling.emission.* import org.noise_planet.noisemodelling.pathfinder.* +import org.noise_planet.noisemodelling.pathfinder.utils.JVMMemoryMetric +import org.noise_planet.noisemodelling.pathfinder.utils.ProfilerThread +import org.noise_planet.noisemodelling.pathfinder.utils.ProgressMetric import org.noise_planet.noisemodelling.propagation.* import org.noise_planet.noisemodelling.jdbc.* @@ -559,9 +562,16 @@ def exec(Connection connection, input) { logger.info("Start calculation... ") - + ProfilerThread profilerThread = new ProfilerThread(new File("webapps/root/profile.csv")); + profilerThread.addMetric(ldenProcessing); + profilerThread.addMetric(new ProgressMetric(progressLogger)); + profilerThread.addMetric(new JVMMemoryMetric()); + profilerThread.setWriteInterval(300); + profilerThread.setFlushInterval(300); + pointNoiseMap.setProfilerThread(profilerThread); try { ldenProcessing.start() + new Thread(profilerThread).start(); // Iterate over computation areas int k = 0 Map cells = pointNoiseMap.searchPopulatedCells(connection) @@ -581,6 +591,7 @@ def exec(Connection connection, input) { System.err.println(ex); throw ex; } finally { + profilerThread.stop(); ldenProcessing.stop() }