]> source.dussan.org Git - sonarqube.git/commitdiff
Use arrays instead of Map for SCM info
authorDuarte Meneses <duarte.meneses@sonarsource.com>
Tue, 30 Jul 2019 20:44:51 +0000 (15:44 -0500)
committerSonarTech <sonartech@sonarsource.com>
Wed, 4 Sep 2019 18:21:04 +0000 (20:21 +0200)
server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/scm/DbScmInfo.java
server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/scm/GeneratedScmInfo.java
server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/scm/ReportScmInfo.java
server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/scm/ScmInfo.java
server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/scm/ScmInfoImpl.java
server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/scm/ScmInfoRepositoryImpl.java
server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/source/NewLinesRepository.java

index 9caaa10301a8e99a9d39b4ed2e593910817ba84c..eef809a7d4d0fe5c59094f54a38e40d87ac4c6db 100644 (file)
@@ -20,8 +20,7 @@
 package org.sonar.ce.task.projectanalysis.scm;
 
 import java.util.HashMap;
-import java.util.LinkedHashMap;
-import java.util.Map;
+import java.util.List;
 import java.util.Optional;
 import java.util.function.Function;
 import javax.annotation.Nonnull;
@@ -43,23 +42,26 @@ class DbScmInfo implements ScmInfo {
     this.fileHash = fileHash;
   }
 
-  public static Optional<DbScmInfo> create(Iterable<DbFileSources.Line> lines, String fileHash) {
+  public static Optional<DbScmInfo> create(List<DbFileSources.Line> lines, String fileHash) {
     LineToChangeset lineToChangeset = new LineToChangeset();
-    Map<Integer, Changeset> lineChanges = new LinkedHashMap<>();
+    Changeset[] lineChanges = new Changeset[lines.size()];
+
+    boolean lineAdded = false;
 
     for (DbFileSources.Line line : lines) {
       Changeset changeset = lineToChangeset.apply(line);
       if (changeset == null) {
         continue;
       }
-      lineChanges.put(line.getLine(), changeset);
+      lineChanges[line.getLine() - 1] = changeset;
+      lineAdded = true;
     }
-    if (lineChanges.isEmpty()) {
+    if (!lineAdded) {
       return Optional.empty();
     }
     return Optional.of(new DbScmInfo(new ScmInfoImpl(lineChanges), fileHash));
   }
-  
+
   public String fileHash() {
     return fileHash;
   }
@@ -80,12 +82,12 @@ class DbScmInfo implements ScmInfo {
   }
 
   @Override
-  public Map<Integer, Changeset> getAllChangesets() {
+  public Changeset[] getAllChangesets() {
     return delegate.getAllChangesets();
   }
 
   /**
-   * Transforms {@link org.sonar.db.protobuf.DbFileSources.Line} into {@link Changeset} 
+   * Transforms {@link org.sonar.db.protobuf.DbFileSources.Line} into {@link Changeset}
    */
   private static class LineToChangeset implements Function<DbFileSources.Line, Changeset> {
     private final Changeset.Builder builder = Changeset.newChangesetBuilder();
@@ -96,8 +98,8 @@ class DbScmInfo implements ScmInfo {
     public Changeset apply(@Nonnull DbFileSources.Line input) {
       if (input.hasScmDate()) {
         Changeset cs = builder
-          .setRevision(input.hasScmRevision() ? input.getScmRevision() : null)
-          .setAuthor(input.hasScmAuthor() ? input.getScmAuthor() : null)
+          .setRevision(input.hasScmRevision() ? input.getScmRevision().intern() : null)
+          .setAuthor(input.hasScmAuthor() ? input.getScmAuthor().intern() : null)
           .setDate(input.getScmDate())
           .build();
         if (cache.containsKey(cs)) {
index 0656564c66941ecb18439a8ddee5abd6baa5bcbe..71ed37e721a94e996b2d7b6b852696882ab9d4ba 100644 (file)
  */
 package org.sonar.ce.task.projectanalysis.scm;
 
-import java.util.LinkedHashMap;
-import java.util.Map;
-import java.util.Set;
-import java.util.stream.Collectors;
-
 import static com.google.common.base.Preconditions.checkState;
 
 public class GeneratedScmInfo implements ScmInfo {
   private final ScmInfoImpl delegate;
 
-  public GeneratedScmInfo(Map<Integer, Changeset> changesets) {
-    delegate = new ScmInfoImpl(changesets);
+  public GeneratedScmInfo(Changeset[] lineChangeset) {
+    delegate = new ScmInfoImpl(lineChangeset);
   }
 
-  public static ScmInfo create(long analysisDate, Set<Integer> lines) {
-    checkState(!lines.isEmpty(), "No changesets");
+  public static ScmInfo create(long analysisDate, int lines) {
+    checkState(lines > 0, "No changesets");
 
     Changeset changeset = Changeset.newChangesetBuilder()
       .setDate(analysisDate)
       .build();
-    Map<Integer, Changeset> changesets = lines.stream()
-      .collect(Collectors.toMap(x -> x, i -> changeset));
-    return new GeneratedScmInfo(changesets);
+    Changeset[] lineChangeset = new Changeset[lines];
+    for (int i = 0; i < lines; i++) {
+      lineChangeset[i] = changeset;
+    }
+    return new GeneratedScmInfo(lineChangeset);
   }
 
   public static ScmInfo create(long analysisDate, int[] matches, ScmInfo dbScmInfo) {
@@ -49,14 +46,14 @@ public class GeneratedScmInfo implements ScmInfo {
       .setDate(analysisDate)
       .build();
 
-    Map<Integer, Changeset> dbChangesets = dbScmInfo.getAllChangesets();
-    Map<Integer, Changeset> changesets = new LinkedHashMap<>(matches.length);
+    Changeset[] dbChangesets = dbScmInfo.getAllChangesets();
+    Changeset[] changesets = new Changeset[matches.length];
 
     for (int i = 0; i < matches.length; i++) {
       if (matches[i] > 0) {
-        changesets.put(i + 1, dbChangesets.get(matches[i]));
+        changesets[i] = dbChangesets[matches[i]];
       } else {
-        changesets.put(i + 1, changeset);
+        changesets[i] = changeset;
       }
     }
     return new GeneratedScmInfo(changesets);
@@ -78,7 +75,7 @@ public class GeneratedScmInfo implements ScmInfo {
   }
 
   @Override
-  public Map<Integer, Changeset> getAllChangesets() {
+  public Changeset[] getAllChangesets() {
     return delegate.getAllChangesets();
   }
 
index 2c73d320cd96d2754fb33e67d808e3cec0a4a8cf..8de0b9c45eb6dbbda7d7f5602f39aa3170373f32 100644 (file)
 package org.sonar.ce.task.projectanalysis.scm;
 
 import java.util.HashMap;
-import java.util.LinkedHashMap;
 import java.util.Map;
 import java.util.function.Function;
-import java.util.stream.Collectors;
-import java.util.stream.IntStream;
 import javax.annotation.concurrent.Immutable;
-import org.sonar.core.util.stream.MoreCollectors;
 import org.sonar.scanner.protocol.output.ScannerReport;
 
 import static com.google.common.base.Preconditions.checkState;
@@ -43,13 +39,17 @@ class ReportScmInfo implements ScmInfo {
   ReportScmInfo(ScannerReport.Changesets changesets) {
     requireNonNull(changesets);
     this.delegate = convertToScmInfo(changesets);
-    checkState(!delegate.getAllChangesets().isEmpty(), "Report has no changesets");
   }
 
   private static ScmInfo convertToScmInfo(ScannerReport.Changesets changesets) {
-    return new ScmInfoImpl(IntStream.rangeClosed(1, changesets.getChangesetIndexByLineCount())
-      .boxed()
-      .collect(Collectors.toMap(x -> x, new LineIndexToChangeset(changesets), MoreCollectors.mergeNotSupportedMerger(), LinkedHashMap::new)));
+    Changeset[] lineChangesets = new Changeset[changesets.getChangesetIndexByLineCount()];
+    LineIndexToChangeset lineIndexToChangeset = new LineIndexToChangeset(changesets);
+
+    for (int i = 0; i < changesets.getChangesetIndexByLineCount(); i++) {
+      lineChangesets[i] = lineIndexToChangeset.apply(i);
+    }
+
+    return new ScmInfoImpl(lineChangesets);
   }
 
   @Override
@@ -68,7 +68,7 @@ class ReportScmInfo implements ScmInfo {
   }
 
   @Override
-  public Map<Integer, Changeset> getAllChangesets() {
+  public Changeset[] getAllChangesets() {
     return this.delegate.getAllChangesets();
   }
 
@@ -79,12 +79,12 @@ class ReportScmInfo implements ScmInfo {
 
     public LineIndexToChangeset(ScannerReport.Changesets changesets) {
       this.changesets = changesets;
-      changesetCache = new HashMap<>(changesets.getChangesetCount());
+      this.changesetCache = new HashMap<>(changesets.getChangesetCount());
     }
 
     @Override
     public Changeset apply(Integer lineNumber) {
-      int changesetIndex = changesets.getChangesetIndexByLine(lineNumber - 1);
+      int changesetIndex = changesets.getChangesetIndexByLine(lineNumber);
       return changesetCache.computeIfAbsent(changesetIndex, idx -> convert(changesets.getChangeset(changesetIndex), lineNumber));
     }
 
@@ -92,8 +92,8 @@ class ReportScmInfo implements ScmInfo {
       checkState(isNotEmpty(changeset.getRevision()), "Changeset on line %s must have a revision", line);
       checkState(changeset.getDate() != 0, "Changeset on line %s must have a date", line);
       return builder
-        .setRevision(changeset.getRevision())
-        .setAuthor(isNotEmpty(changeset.getAuthor()) ? changeset.getAuthor() : null)
+        .setRevision(changeset.getRevision().intern())
+        .setAuthor(isNotEmpty(changeset.getAuthor()) ? changeset.getAuthor().intern() : null)
         .setDate(changeset.getDate())
         .build();
     }
index bbb9a5d2fea31b217f91a4aead9895c7df09ff2d..6c52c0509e38d0a4e5158b51b18234575d5d7451 100644 (file)
@@ -47,6 +47,6 @@ public interface ScmInfo {
   /**
    * Return all ChangeSets, in order, for all lines that have changesets.
    */
-  Map<Integer, Changeset> getAllChangesets();
+  Changeset[] getAllChangesets();
 
 }
index ce4e20b63aa20c9aa699a0e5bad8ad830c0d6ee3..46416371552645952a01d686a4938dd2d0c10d2a 100644 (file)
  */
 package org.sonar.ce.task.projectanalysis.scm;
 
-import java.util.Collections;
+import java.util.Arrays;
 import java.util.Comparator;
-import java.util.Map;
 import javax.annotation.concurrent.Immutable;
-import static com.google.common.base.Preconditions.checkState;
+import org.sonar.api.utils.Preconditions;
 
 @Immutable
 public class ScmInfoImpl implements ScmInfo {
   private final Changeset latestChangeset;
-  private final Map<Integer, Changeset> lineChangesets;
+  private final Changeset[] lineChangesets;
 
-  public ScmInfoImpl(Map<Integer, Changeset> lineChangesets) {
-    checkState(!lineChangesets.isEmpty(), "A ScmInfo must have at least one Changeset and does not support any null one");
-    this.lineChangesets = Collections.unmodifiableMap(lineChangesets);
+  public ScmInfoImpl(Changeset[] lineChangesets) {
+    Preconditions.checkNotNull(lineChangesets);
+    Preconditions.checkState(lineChangesets.length > 0, "ScmInfo cannot be empty");
+    this.lineChangesets = lineChangesets;
     this.latestChangeset = computeLatestChangeset(lineChangesets);
   }
 
-  private static Changeset computeLatestChangeset(Map<Integer, Changeset> lineChangesets) {
-    return lineChangesets.values().stream().max(Comparator.comparingLong(Changeset::getDate))
+  private static Changeset computeLatestChangeset(Changeset[] lineChangesets) {
+    return Arrays.stream(lineChangesets).max(Comparator.comparingLong(Changeset::getDate))
       .orElseThrow(() -> new IllegalStateException("Expecting at least one Changeset to be present"));
   }
 
@@ -48,7 +48,7 @@ public class ScmInfoImpl implements ScmInfo {
 
   @Override
   public Changeset getChangesetForLine(int lineNumber) {
-    Changeset changeset = lineChangesets.get(lineNumber);
+    Changeset changeset = lineChangesets[lineNumber - 1];
     if (changeset != null) {
       return changeset;
     }
@@ -57,11 +57,11 @@ public class ScmInfoImpl implements ScmInfo {
 
   @Override
   public boolean hasChangesetForLine(int lineNumber) {
-    return lineChangesets.containsKey(lineNumber);
+    return lineNumber - 1 < lineChangesets.length && lineChangesets[lineNumber - 1] != null;
   }
 
   @Override
-  public Map<Integer, Changeset> getAllChangesets() {
+  public Changeset[] getAllChangesets() {
     return lineChangesets;
   }
 
index 03c9e38771ababc08ad118b69550267230344339..6788e59dd18dba93b95a94a8cff5d57de24056ba 100644 (file)
  */
 package org.sonar.ce.task.projectanalysis.scm;
 
-import java.util.HashMap;
+import java.util.Arrays;
 import java.util.Map;
 import java.util.Optional;
-import java.util.Set;
-import java.util.stream.Collectors;
-import java.util.stream.IntStream;
 import org.sonar.api.utils.log.Logger;
 import org.sonar.api.utils.log.Loggers;
-import org.sonar.scanner.protocol.output.ScannerReport;
 import org.sonar.ce.task.projectanalysis.analysis.AnalysisMetadataHolder;
 import org.sonar.ce.task.projectanalysis.batch.BatchReportReader;
 import org.sonar.ce.task.projectanalysis.component.Component;
 import org.sonar.ce.task.projectanalysis.component.Component.Status;
 import org.sonar.ce.task.projectanalysis.source.SourceHashRepository;
 import org.sonar.ce.task.projectanalysis.source.SourceLinesDiff;
+import org.sonar.scanner.protocol.output.ScannerReport;
+import vlsi.utils.CompactHashMap;
 
 import static java.util.Objects.requireNonNull;
 
@@ -42,14 +40,14 @@ public class ScmInfoRepositoryImpl implements ScmInfoRepository {
   private static final Logger LOGGER = Loggers.get(ScmInfoRepositoryImpl.class);
 
   private final BatchReportReader scannerReportReader;
-  private final Map<Component, Optional<ScmInfo>> scmInfoCache = new HashMap<>();
+  private final Map<Component, Optional<ScmInfo>> scmInfoCache = new CompactHashMap<>();
   private final ScmInfoDbLoader scmInfoDbLoader;
   private final AnalysisMetadataHolder analysisMetadata;
   private final SourceLinesDiff sourceLinesDiff;
   private final SourceHashRepository sourceHashRepository;
 
   public ScmInfoRepositoryImpl(BatchReportReader scannerReportReader, AnalysisMetadataHolder analysisMetadata, ScmInfoDbLoader scmInfoDbLoader,
-                               SourceLinesDiff sourceLinesDiff, SourceHashRepository sourceHashRepository) {
+    SourceLinesDiff sourceLinesDiff, SourceHashRepository sourceHashRepository) {
     this.scannerReportReader = scannerReportReader;
     this.analysisMetadata = analysisMetadata;
     this.scmInfoDbLoader = scmInfoDbLoader;
@@ -93,14 +91,14 @@ public class ScmInfoRepositoryImpl implements ScmInfoRepository {
     if (file.getFileAttributes().getLines() == 0) {
       return Optional.empty();
     }
-    Set<Integer> newOrChangedLines = IntStream.rangeClosed(1, file.getFileAttributes().getLines()).boxed().collect(Collectors.toSet());
-    return Optional.of(GeneratedScmInfo.create(analysisMetadata.getAnalysisDate(), newOrChangedLines));
+    return Optional.of(GeneratedScmInfo.create(analysisMetadata.getAnalysisDate(), file.getFileAttributes().getLines()));
   }
 
   private static ScmInfo removeAuthorAndRevision(ScmInfo info) {
-    Map<Integer, Changeset> cleanedScmInfo = info.getAllChangesets().entrySet().stream()
-      .collect(Collectors.toMap(Map.Entry::getKey, e -> removeAuthorAndRevision(e.getValue())));
-    return new ScmInfoImpl(cleanedScmInfo);
+    Changeset[] changesets = Arrays.stream(info.getAllChangesets())
+      .map(ScmInfoRepositoryImpl::removeAuthorAndRevision)
+      .toArray(Changeset[]::new);
+    return new ScmInfoImpl(changesets);
   }
 
   private static Changeset removeAuthorAndRevision(Changeset changeset) {
index 20386f3576cfa9913be730bdf088ac321aeaf42d..55ea56c03495712f8f2c2a4c869b5fa59adfe5d1 100644 (file)
@@ -76,16 +76,17 @@ public class NewLinesRepository {
     }
 
     ScmInfo scmInfo = scmInfoOpt.get();
-    Map<Integer, Changeset> allChangesets = scmInfo.getAllChangesets();
+    Changeset[] allChangesets = scmInfo.getAllChangesets();
     Set<Integer> lines = new HashSet<>();
 
     // in SLB/PRs, we consider changes introduced in this analysis as new, hence subtracting 1.
     long referenceDate = analysisMetadataHolder.isSLBorPR() ? analysisMetadataHolder.getAnalysisDate() - 1 : periodHolder.getPeriod().getSnapshotDate();
-    for (Map.Entry<Integer, Changeset> e : allChangesets.entrySet()) {
-      if (isLineInPeriod(e.getValue().getDate(), referenceDate)) {
-        lines.add(e.getKey());
+    for (int i=0; i<allChangesets.length; i++) {
+      if (isLineInPeriod(allChangesets[i].getDate(), referenceDate)) {
+        lines.add(i+1);
       }
     }
+
     return Optional.of(lines);
   }