Ticket #4626: 4626.patch

File 4626.patch, 7.7 KB (added by simon04, 3 years ago)
  • src/org/openstreetmap/josm/data/validation/ValidationTask.java

    diff --git a/src/org/openstreetmap/josm/data/validation/ValidationTask.java b/src/org/openstreetmap/josm/data/validation/ValidationTask.java
    index 02b857898..dbf80fb39 100644
    a b package org.openstreetmap.josm.data.validation;  
    33
    44import org.openstreetmap.josm.data.osm.OsmPrimitive;
    55import org.openstreetmap.josm.data.preferences.sources.ValidatorPrefHelper;
     6import org.openstreetmap.josm.data.validation.tests.MapCSSTagChecker;
    67import org.openstreetmap.josm.gui.MainApplication;
    78import org.openstreetmap.josm.gui.MapFrame;
    89import org.openstreetmap.josm.gui.PleaseWaitRunnable;
    import org.openstreetmap.josm.gui.layer.ValidatorLayer;  
    1011import org.openstreetmap.josm.gui.progress.ProgressMonitor;
    1112import org.openstreetmap.josm.gui.progress.swing.PleaseWaitProgressMonitor;
    1213import org.openstreetmap.josm.gui.util.GuiHelper;
     14import org.openstreetmap.josm.tools.Logging;
     15import org.openstreetmap.josm.tools.Utils;
    1316
    1417import java.util.ArrayList;
    1518import java.util.Collection;
    1619import java.util.List;
     20import java.util.concurrent.ExecutionException;
     21import java.util.concurrent.ForkJoinPool;
     22import java.util.concurrent.Future;
     23import java.util.concurrent.atomic.AtomicInteger;
     24import java.util.function.Consumer;
     25import java.util.stream.Collectors;
    1726
    1827import static org.openstreetmap.josm.tools.I18n.tr;
    1928
    import static org.openstreetmap.josm.tools.I18n.tr;  
    2130 * Asynchronous task for running a collection of tests against a collection of primitives
    2231 */
    2332public class ValidationTask extends PleaseWaitRunnable {
    24     private Collection<Test> tests;
     33    private final ArrayList<Test> tests;
    2534    private final Collection<OsmPrimitive> validatedPrimitives;
    2635    private final Collection<OsmPrimitive> formerValidatedPrimitives;
    2736    private boolean canceled;
    2837    private List<TestError> errors;
     38    private static final ForkJoinPool THREAD_POOL = Utils.newForkJoinPool(
     39            ValidatorPrefHelper.PREFIX + ".numberOfThreads", "validator-%d", Thread.NORM_PRIORITY);
    2940
    3041    /**
    3142     * Constructs a new {@code ValidationTask}
    public class ValidationTask extends PleaseWaitRunnable {  
    4758        super(tr("Validating"), progressMonitor, false /*don't ignore exceptions */);
    4859        this.validatedPrimitives = validatedPrimitives;
    4960        this.formerValidatedPrimitives = formerValidatedPrimitives;
    50         this.tests = tests;
     61        this.tests = new ArrayList<>(tests);
    5162    }
    5263
    5364    @Override
    public class ValidationTask extends PleaseWaitRunnable {  
    7788        if (tests == null || tests.isEmpty())
    7889            return;
    7990        errors = new ArrayList<>();
    80         getProgressMonitor().setTicksCount(tests.size() * validatedPrimitives.size());
    81         int testCounter = 0;
    82         for (Test test : tests) {
    83             if (canceled)
    84                 return;
    85             testCounter++;
    86             getProgressMonitor().setCustomText(tr("Test {0}/{1}: Starting {2}", testCounter, tests.size(), test.getName()));
     91
     92        AtomicInteger testCounter = new AtomicInteger();
     93        runParallel(test -> {
    8794            test.setBeforeUpload(false);
    8895            test.setPartialSelection(formerValidatedPrimitives != null);
    89             test.startTest(getProgressMonitor().createSubTaskMonitor(validatedPrimitives.size(), false));
    90             test.visit(validatedPrimitives);
    91             test.endTest();
    92             errors.addAll(test.getErrors());
    93             test.clear();
    94         }
    95         tests = null;
     96            test.startTest(null);
     97        });
     98        runParallel(test -> {
     99            getProgressMonitor().setCustomText(tr("Test {0}/{1}: Starting {2}", testCounter.incrementAndGet(), tests.size(), test.getName()));
     100            if (test instanceof MapCSSTagChecker) {
     101                // VARIANT 1
     102                validatedPrimitives.parallelStream()
     103                        .filter(test::isPrimitiveUsable)
     104                        .forEach(p -> p.accept(test));
     105            } else {
     106                test.visit(validatedPrimitives);
     107            }
     108        });
     109        runParallel(Test::endTest);
     110        errors = tests.stream().flatMap(test -> test.getErrors().stream()).collect(Collectors.toList());
     111
     112        runParallel(Test::clear);
     113        tests.clear();
     114        tests.trimToSize();
     115
    96116        if (Boolean.TRUE.equals(ValidatorPrefHelper.PREF_USE_IGNORE.get())) {
    97117            getProgressMonitor().setCustomText("");
    98118            getProgressMonitor().subTask(tr("Updating ignored errors ..."));
    public class ValidationTask extends PleaseWaitRunnable {  
    103123        }
    104124    }
    105125
     126    private void runParallel(Consumer<Test> testConsumer) {
     127        try {
     128            Future<?> future = THREAD_POOL.submit(() -> tests.parallelStream().forEach(testConsumer));
     129            future.get();
     130        } catch (InterruptedException | ExecutionException e) {
     131            if (e.getCause() instanceof RuntimeException) {
     132                throw ((RuntimeException) e.getCause());
     133            }
     134            Logging.warn(e);
     135            Thread.currentThread().interrupt();
     136        }
     137    }
     138
    106139    /**
    107140     * Gets the validation errors accumulated until this moment.
    108141     * @return The list of errors
  • src/org/openstreetmap/josm/data/validation/tests/MapCSSTagChecker.java

    diff --git a/src/org/openstreetmap/josm/data/validation/tests/MapCSSTagChecker.java b/src/org/openstreetmap/josm/data/validation/tests/MapCSSTagChecker.java
    index bf38cd13f..2442933c3 100644
    a b public class MapCSSTagChecker extends Test.TagTest {  
    238238     */
    239239    @Override
    240240    public void check(OsmPrimitive p) {
    241         for (TestError e : getErrorsForPrimitive(p, ValidatorPrefHelper.PREF_OTHER.get())) {
    242             addIfNotSimilar(e, errors);
     241        Collection<TestError> errorsForPrimitive = getErrorsForPrimitive(p, ValidatorPrefHelper.PREF_OTHER.get());
     242        if (errorsForPrimitive.isEmpty()) {
     243            return;
     244        }
     245        synchronized (errors) {
     246            for (TestError e : errorsForPrimitive) {
     247                addIfNotSimilar(e, errors);
     248            }
    243249        }
    244250    }
    245251
    public class MapCSSTagChecker extends Test.TagTest {  
    382388        mpAreaCache.clear();
    383389
    384390        Set<OsmPrimitive> surrounding = new HashSet<>();
    385         for (Entry<String, Set<MapCSSTagCheckerRule>> entry : checks.entrySet()) {
     391        // VARIANT 2
     392        checks.entrySet().parallelStream().forEach(entry -> {
    386393            if (isCanceled()) {
    387                 break;
     394                return;
    388395            }
    389396            if (urlPredicate != null && !urlPredicate.test(entry.getKey())) {
    390                 continue;
     397                return;
    391398            }
    392399            visit(entry.getKey(), entry.getValue(), selection, surrounding);
    393         }
     400        });
    394401    }
    395402
    396403    /**
    public class MapCSSTagChecker extends Test.TagTest {  
    464471            if (tested.contains(p))
    465472                continue;
    466473            Collection<TestError> additionalErrors = getErrorsForPrimitive(p, includeOtherSeverity);
    467             for (TestError e : additionalErrors) {
    468                 if (e.getPrimitives().stream().anyMatch(tested::contains))
    469                     addIfNotSimilar(e, errors);
     474            if (additionalErrors.isEmpty())
     475                continue;
     476            synchronized (errors) {
     477                for (TestError e : additionalErrors) {
     478                    if (e.getPrimitives().stream().anyMatch(tested::contains)) {
     479                        addIfNotSimilar(e, errors);
     480                    }
     481                }
    470482            }
    471483        }
    472484