]> source.dussan.org Git - sonarqube.git/commitdiff
Add server benchmarks
authorSimon Brandhof <simon.brandhof@sonarsource.com>
Mon, 1 Dec 2014 10:21:16 +0000 (11:21 +0100)
committerSimon Brandhof <simon.brandhof@sonarsource.com>
Mon, 1 Dec 2014 10:21:25 +0000 (11:21 +0100)
server/sonar-data-test/src/test/java/org/sonar/server/benchmark/IssueIndexBenchmarkTest.java
server/sonar-data-test/src/test/java/org/sonar/server/benchmark/ProgressTask.java [new file with mode: 0644]
server/sonar-data-test/src/test/java/org/sonar/server/benchmark/SourceIndexBenchmarkTest.java [new file with mode: 0644]
server/sonar-server/src/test/java/org/sonar/server/es/EsServerHolder.java
server/sonar-server/src/test/java/org/sonar/server/tester/ServerTester.java

index 6d1eee42a1919dc99f35adf4c6766cad09825146..820d1b6a9f765421e2b86f482822d213022b6d68 100644 (file)
@@ -24,6 +24,7 @@ import com.google.common.collect.Iterables;
 import com.google.common.collect.Iterators;
 import com.google.common.collect.Lists;
 import com.google.common.collect.Maps;
+import org.apache.commons.io.FileUtils;
 import org.apache.commons.lang.math.RandomUtils;
 import org.junit.ClassRule;
 import org.junit.Test;
@@ -41,13 +42,13 @@ import org.sonar.server.issue.index.IssueIndexer;
 import org.sonar.server.search.QueryContext;
 import org.sonar.server.search.Result;
 import org.sonar.server.tester.ServerTester;
+import org.sonar.server.user.MockUserSession;
 
 import java.util.Arrays;
 import java.util.Date;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Timer;
-import java.util.TimerTask;
 import java.util.concurrent.atomic.AtomicLong;
 
 public class IssueIndexBenchmarkTest {
@@ -88,7 +89,7 @@ public class IssueIndexBenchmarkTest {
   private void benchmarkIssueIndexing() {
     LOGGER.info("Indexing issues");
     IssueIterator issues = new IssueIterator(PROJECTS, FILES_PER_PROJECT, ISSUES_PER_FILE);
-    ProgressTask progressTask = new ProgressTask("issues", issues.count());
+    ProgressTask progressTask = new ProgressTask(LOGGER, "issues", issues.count());
     Timer timer = new Timer("IssuesIndex");
     timer.schedule(progressTask, ProgressTask.PERIOD_MS, ProgressTask.PERIOD_MS);
 
@@ -98,10 +99,12 @@ public class IssueIndexBenchmarkTest {
 
     timer.cancel();
     long period = end - start;
-    LOGGER.info(String.format("%d issues indexed in %d ms (%d/second)", issues.count.get(), period, 1000 * issues.count.get() / period));
+    LOGGER.info(String.format("%d issues indexed in %d ms (%d docs/second)", issues.count.get(), period, 1000 * issues.count.get() / period));
+    LOGGER.info(String.format("Index disk: " + FileUtils.byteCountToDisplaySize(FileUtils.sizeOfDirectory(tester.getEsServerHolder().getHomeDir()))));
   }
 
   private void benchmarkQueries() {
+    MockUserSession.set().setUserGroups("sonar-users");
     benchmarkQuery("all issues", IssueQuery.builder().build());
     benchmarkQuery("project issues", IssueQuery.builder().projectUuids(Arrays.asList("PROJECT33")).build());
     benchmarkQuery("file issues", IssueQuery.builder().componentUuids(Arrays.asList("FILE333")).build());
@@ -197,33 +200,4 @@ public class IssueIndexBenchmarkTest {
     }
     return Iterators.cycle(values);
   }
-
-  static class ProgressTask extends TimerTask {
-    public static final long PERIOD_MS = 60000L;
-
-    private final String label;
-    private final AtomicLong counter;
-    private long previousCount = 0L;
-    private long previousTime = 0L;
-
-    public ProgressTask(String label, AtomicLong counter) {
-      this.label = label;
-      this.counter = counter;
-      this.previousTime = System.currentTimeMillis();
-    }
-
-    @Override
-    public void run() {
-      long currentCount = counter.get();
-      long now = System.currentTimeMillis();
-      LOGGER.info("{} {} indexed ({} {}/second)",
-        currentCount, label, documentsPerSecond(currentCount - previousCount, now - previousTime), label);
-      this.previousCount = currentCount;
-      this.previousTime = now;
-    }
-  }
-
-  static int documentsPerSecond(long nbIssues, long time) {
-    return (int) Math.round(nbIssues / (time / 1000.0));
-  }
 }
diff --git a/server/sonar-data-test/src/test/java/org/sonar/server/benchmark/ProgressTask.java b/server/sonar-data-test/src/test/java/org/sonar/server/benchmark/ProgressTask.java
new file mode 100644 (file)
index 0000000..4b51612
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.server.benchmark;
+
+import org.slf4j.Logger;
+
+import java.util.TimerTask;
+import java.util.concurrent.atomic.AtomicLong;
+
+class ProgressTask extends TimerTask {
+
+  public static final long PERIOD_MS = 60000L;
+
+  private final Logger logger;
+  private final String label;
+  private final AtomicLong counter;
+  private long previousCount = 0L;
+  private long previousTime = 0L;
+
+  public ProgressTask(Logger logger, String label, AtomicLong counter) {
+    this.logger = logger;
+    this.label = label;
+    this.counter = counter;
+    this.previousTime = System.currentTimeMillis();
+  }
+
+  @Override
+  public void run() {
+    long currentCount = counter.get();
+    long now = System.currentTimeMillis();
+    logger.info("{} {} indexed ({} docs/second)",
+      currentCount, label, documentsPerSecond(currentCount - previousCount, now - previousTime), label);
+    this.previousCount = currentCount;
+    this.previousTime = now;
+  }
+
+  private int documentsPerSecond(long nbDocs, long time) {
+    return (int) Math.round(nbDocs / (time / 1000.0));
+  }
+}
diff --git a/server/sonar-data-test/src/test/java/org/sonar/server/benchmark/SourceIndexBenchmarkTest.java b/server/sonar-data-test/src/test/java/org/sonar/server/benchmark/SourceIndexBenchmarkTest.java
new file mode 100644 (file)
index 0000000..e3c8212
--- /dev/null
@@ -0,0 +1,150 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+package org.sonar.server.benchmark;
+
+import com.google.common.collect.Maps;
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.lang.StringUtils;
+import org.junit.ClassRule;
+import org.junit.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.sonar.server.source.index.SourceLineDoc;
+import org.sonar.server.source.index.SourceLineIndex;
+import org.sonar.server.source.index.SourceLineIndexer;
+import org.sonar.server.source.index.SourceLineResultSetIterator;
+import org.sonar.server.tester.ServerTester;
+
+import java.util.Iterator;
+import java.util.List;
+import java.util.Timer;
+import java.util.concurrent.atomic.AtomicLong;
+
+import static org.fest.assertions.Assertions.assertThat;
+
+public class SourceIndexBenchmarkTest {
+
+  private static final Logger LOGGER = LoggerFactory.getLogger("benchmarkSources");
+
+  final static long FILES = 10000L;
+  static final int LINES_PER_FILE = 200;
+
+  @ClassRule
+  public static ServerTester tester = new ServerTester();
+
+  @Test
+  public void benchmark() throws Exception {
+    // index source lines
+    benchmarkIndexing();
+
+    // execute some queries
+    benchmarkQueries();
+  }
+
+  private void benchmarkIndexing() {
+    LOGGER.info("Indexing source lines");
+
+    SourceIterator files = new SourceIterator(FILES, LINES_PER_FILE);
+    ProgressTask progressTask = new ProgressTask(LOGGER, "files of " + LINES_PER_FILE + " lines", files.count());
+    Timer timer = new Timer("SourceIndexer");
+    timer.schedule(progressTask, ProgressTask.PERIOD_MS, ProgressTask.PERIOD_MS);
+
+    long start = System.currentTimeMillis();
+    tester.get(SourceLineIndexer.class).index(files);
+    long end = System.currentTimeMillis();
+
+    timer.cancel();
+    long period = end - start;
+    long nbDocs = files.count.get() * LINES_PER_FILE;
+    LOGGER.info(String.format("%d files indexed in %d ms (%d docs/second)", nbDocs, period, 1000 * nbDocs / period));
+    LOGGER.info(String.format("Index disk: " + FileUtils.byteCountToDisplaySize(FileUtils.sizeOfDirectory(tester.getEsServerHolder().getHomeDir()))));
+
+  }
+
+  private void benchmarkQueries() {
+    SourceLineIndex index = tester.get(SourceLineIndex.class);
+    for (int i = 1; i <= 100; i++) {
+      long start = System.currentTimeMillis();
+      List<SourceLineDoc> result = index.getLines("FILE" + i, 20, 150);
+      long end = System.currentTimeMillis();
+      assertThat(result).hasSize(131);
+      LOGGER.info("Request: {} docs in {} ms", result.size(), end - start);
+    }
+  }
+
+  private static class SourceIterator implements Iterator<SourceLineResultSetIterator.SourceFile> {
+    private final long nbFiles;
+    private final int nbLinesPerFile;
+    private int currentProject = 0;
+    private AtomicLong count = new AtomicLong(0L);
+
+    SourceIterator(long nbFiles, int nbLinesPerFile) {
+      this.nbFiles = nbFiles;
+      this.nbLinesPerFile = nbLinesPerFile;
+    }
+
+    public AtomicLong count() {
+      return count;
+    }
+
+    @Override
+    public boolean hasNext() {
+      return count.get() < nbFiles;
+    }
+
+    @Override
+    public SourceLineResultSetIterator.SourceFile next() {
+      String fileUuid = "FILE" + count.get();
+      SourceLineResultSetIterator.SourceFile file = new SourceLineResultSetIterator.SourceFile(fileUuid, System.currentTimeMillis());
+      for (int indexLine = 1; indexLine <= nbLinesPerFile; indexLine++) {
+        SourceLineDoc line = new SourceLineDoc(Maps.<String, Object>newHashMap());
+        line.setFileUuid(fileUuid);
+        line.setLine(indexLine);
+        line.setHighlighting(StringUtils.repeat("HIGHLIGHTING", 5));
+        line.setItConditions(4);
+        line.setItCoveredConditions(2);
+        line.setItLineHits(2);
+        line.setOverallConditions(8);
+        line.setOverallCoveredConditions(2);
+        line.setOverallLineHits(2);
+        line.setUtConditions(8);
+        line.setUtCoveredConditions(2);
+        line.setUtLineHits(2);
+        line.setProjectUuid("PROJECT" + currentProject);
+        line.setScmAuthor("a_guy");
+        line.setScmRevision("ABCDEFGHIJKL");
+        line.setSource(StringUtils.repeat("SOURCE", 10));
+        file.addLine(line);
+      }
+      count.incrementAndGet();
+      if (count.get() % 500 == 0) {
+        currentProject++;
+      }
+      return file;
+    }
+
+    @Override
+    public void remove() {
+      throw new UnsupportedOperationException();
+    }
+  }
+
+}
index 28810012ff5ffb64746a31e3a41b122f2b1e7f72..713cb3ed6a6476b528eaad98d23fd3b0cfc81885 100644 (file)
@@ -38,13 +38,15 @@ public class EsServerHolder {
   private static EsServerHolder HOLDER = null;
   private final String clusterName, nodeName;
   private final int port;
+  private final File homeDir;
   private final SearchServer server;
 
-  private EsServerHolder(SearchServer server, String clusterName, String nodeName, int port) {
+  private EsServerHolder(SearchServer server, String clusterName, String nodeName, int port, File homeDir) {
     this.server = server;
     this.clusterName = clusterName;
     this.nodeName = nodeName;
     this.port = port;
+    this.homeDir = homeDir;
   }
 
   public String getClusterName() {
@@ -63,6 +65,10 @@ public class EsServerHolder {
     return server;
   }
 
+  public File getHomeDir() {
+    return homeDir;
+  }
+
   private void reset() {
     TransportClient client = new TransportClient(ImmutableSettings.settingsBuilder()
       .put("node.name", nodeName)
@@ -101,7 +107,7 @@ public class EsServerHolder {
       properties.setProperty(ProcessConstants.PATH_HOME, homeDir.getAbsolutePath());
       SearchServer server = new SearchServer(new Props(properties));
       server.start();
-      HOLDER = new EsServerHolder(server, clusterName, nodeName, port);
+      HOLDER = new EsServerHolder(server, clusterName, nodeName, port, homeDir);
     }
     HOLDER.reset();
     return HOLDER;
index 8514dcfa3ce8403ffd70226529da39622e945c9e..e444f2be0fa3206405a18a3c031b37b3e2dc0090 100644 (file)
@@ -58,6 +58,7 @@ public class ServerTester extends ExternalResource {
   private static final String PROP_PREFIX = "mediumTests.";
 
   private Platform platform;
+  private EsServerHolder esServerHolder;
   private final File homeDir = TestUtils.newTempDir("tmp-sq-");
   private final List components = Lists.newArrayList(WsTester.class);
   private final Properties initialProps = new Properties();
@@ -79,8 +80,7 @@ public class ServerTester extends ExternalResource {
     try {
       Properties properties = new Properties();
       properties.putAll(initialProps);
-      EsServerHolder esServerHolder = EsServerHolder.get();
-
+      esServerHolder = EsServerHolder.get();
       properties.setProperty(ProcessConstants.CLUSTER_NAME, esServerHolder.getClusterName());
       properties.setProperty(ProcessConstants.CLUSTER_NODE_NAME, esServerHolder.getNodeName());
       properties.setProperty(ProcessConstants.SEARCH_PORT, String.valueOf(esServerHolder.getPort()));
@@ -126,6 +126,7 @@ public class ServerTester extends ExternalResource {
     } catch (Exception e) {
       LOG.error("Fail to stop web server", e);
     }
+    esServerHolder = null;
     FileUtils.deleteQuietly(homeDir);
   }
 
@@ -193,6 +194,10 @@ public class ServerTester extends ExternalResource {
     return get(WsTester.class);
   }
 
+  public EsServerHolder getEsServerHolder() {
+    return esServerHolder;
+  }
+
   private void checkStarted() {
     if (platform == null || !platform.isStarted()) {
       throw new IllegalStateException("Not started");