]> source.dussan.org Git - sonarqube.git/commitdiff
Rename module sonar-data-test to sonar-server-benchmarks
authorSimon Brandhof <simon.brandhof@sonarsource.com>
Fri, 5 Dec 2014 16:36:29 +0000 (17:36 +0100)
committerSimon Brandhof <simon.brandhof@sonarsource.com>
Fri, 5 Dec 2014 16:36:29 +0000 (17:36 +0100)
13 files changed:
server/pom.xml
server/sonar-data-test/pom.xml [deleted file]
server/sonar-data-test/src/test/java/org/sonar/server/benchmark/BenchmarkAssertions.java [deleted file]
server/sonar-data-test/src/test/java/org/sonar/server/benchmark/IssueIndexBenchmarkTest.java [deleted file]
server/sonar-data-test/src/test/java/org/sonar/server/benchmark/ProgressTask.java [deleted file]
server/sonar-data-test/src/test/java/org/sonar/server/benchmark/SourceIndexBenchmarkTest.java [deleted file]
server/sonar-data-test/src/test/resources/logback-test.xml [deleted file]
server/sonar-server-benchmarks/pom.xml [new file with mode: 0644]
server/sonar-server-benchmarks/src/test/java/org/sonar/server/benchmark/BenchmarkAssertions.java [new file with mode: 0644]
server/sonar-server-benchmarks/src/test/java/org/sonar/server/benchmark/IssueIndexBenchmarkTest.java [new file with mode: 0644]
server/sonar-server-benchmarks/src/test/java/org/sonar/server/benchmark/ProgressTask.java [new file with mode: 0644]
server/sonar-server-benchmarks/src/test/java/org/sonar/server/benchmark/SourceIndexBenchmarkTest.java [new file with mode: 0644]
server/sonar-server-benchmarks/src/test/resources/logback-test.xml [new file with mode: 0644]

index 8e087ad3f874465e31ec51d2d364fc4a6a6e674e..e931018c0742646ec6de4073041b5b281dd19845 100644 (file)
@@ -17,6 +17,6 @@
     <module>sonar-server</module>
     <module>sonar-web</module>
     <module>sonar-ws-client</module>
-    <module>sonar-data-test</module>
+    <module>sonar-server-benchmarks</module>
   </modules>
 </project>
diff --git a/server/sonar-data-test/pom.xml b/server/sonar-data-test/pom.xml
deleted file mode 100644 (file)
index 6f0afb2..0000000
+++ /dev/null
@@ -1,84 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-  <modelVersion>4.0.0</modelVersion>
-  <parent>
-    <groupId>org.codehaus.sonar</groupId>
-    <artifactId>server</artifactId>
-    <version>5.0-SNAPSHOT</version>
-    <relativePath>..</relativePath>
-  </parent>
-  <artifactId>sonar-data-test</artifactId>
-  <name>SonarQube :: Server :: Benchmark</name>
-
-  <properties>
-    <testInclusions/>
-    <enableBenchmarkAssertions>true</enableBenchmarkAssertions>
-  </properties>
-
-  <dependencies>
-    <dependency>
-      <groupId>org.codehaus.sonar</groupId>
-      <artifactId>sonar-server</artifactId>
-      <version>${project.version}</version>
-      <scope>test</scope>
-    </dependency>
-    <dependency>
-      <groupId>org.codehaus.sonar</groupId>
-      <artifactId>sonar-server</artifactId>
-      <type>test-jar</type>
-      <version>${project.version}</version>
-      <scope>test</scope>
-    </dependency>
-    <dependency>
-      <groupId>org.codehaus.sonar</groupId>
-      <artifactId>sonar-search</artifactId>
-      <version>${project.version}</version>
-      <scope>test</scope>
-    </dependency>
-    <dependency>
-      <groupId>com.google.guava</groupId>
-      <artifactId>guava</artifactId>
-      <scope>test</scope>
-    </dependency>
-    <dependency>
-      <groupId>org.codehaus.sonar</groupId>
-      <artifactId>sonar-testing-harness</artifactId>
-      <scope>test</scope>
-    </dependency>
-  </dependencies>
-
-  <build>
-    <plugins>
-      <plugin>
-        <groupId>org.apache.maven.plugins</groupId>
-        <artifactId>maven-surefire-plugin</artifactId>
-        <configuration>
-          <skipTests>${skipServerTests}</skipTests>
-          <argLine>-Xmx1G -Xms256m -server -Djava.awt.headless=true -DenableBenchmarkAssertions=${enableBenchmarkAssertions}</argLine>
-          <includes>
-            <include>${testInclusions}</include>
-          </includes>
-        </configuration>
-      </plugin>
-    </plugins>
-  </build>
-
-  <!--
-  mvn install -DrunBenchmarks=true -DenableBenchmarkAssertions=true
-
-  -->
-  <profiles>
-    <profile>
-      <id>runBenchmarks</id>
-      <activation>
-        <property>
-          <name>runBenchmarks</name>
-        </property>
-      </activation>
-      <properties>
-        <testInclusions>org/sonar/server/benchmark/**/*.java</testInclusions>
-      </properties>
-    </profile>
-  </profiles>
-</project>
diff --git a/server/sonar-data-test/src/test/java/org/sonar/server/benchmark/BenchmarkAssertions.java b/server/sonar-data-test/src/test/java/org/sonar/server/benchmark/BenchmarkAssertions.java
deleted file mode 100644 (file)
index 33c616f..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * 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;
-
-public class BenchmarkAssertions {
-
-  private static final boolean ENABLED = "true".equals(System.getProperty("enableBenchmarkAssertions"));
-
-  static {
-    if (ENABLED) {
-      System.out.println("Assertions are calibrated for a dedicated benchmark environment. " +
-        "They can be disabled by setting the property -DenableBenchmarkAssertions=false.");
-    }
-  }
-
-}
diff --git a/server/sonar-data-test/src/test/java/org/sonar/server/benchmark/IssueIndexBenchmarkTest.java b/server/sonar-data-test/src/test/java/org/sonar/server/benchmark/IssueIndexBenchmarkTest.java
deleted file mode 100644 (file)
index 7711555..0000000
+++ /dev/null
@@ -1,206 +0,0 @@
-/*
- * 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.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;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.sonar.api.issue.Issue;
-import org.sonar.api.rule.Severity;
-import org.sonar.api.utils.internal.Uuids;
-import org.sonar.server.issue.IssueQuery;
-import org.sonar.server.issue.index.IssueAuthorizationDao;
-import org.sonar.server.issue.index.IssueAuthorizationIndexer;
-import org.sonar.server.issue.index.IssueDoc;
-import org.sonar.server.issue.index.IssueIndex;
-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.concurrent.atomic.AtomicLong;
-
-public class IssueIndexBenchmarkTest {
-
-  private static final Logger LOGGER = LoggerFactory.getLogger("benchmarkIssues");
-
-  final static int PROJECTS = 100;
-  final static int FILES_PER_PROJECT = 100;
-  final static int ISSUES_PER_FILE = 100;
-
-  @ClassRule
-  public static ServerTester tester = new ServerTester();
-
-  @Test
-  public void benchmark() throws Exception {
-    // initialization - feed issues/issueAuthorization with projects and hardcoded users
-    indexAuthorizations();
-
-    // index issues
-    benchmarkIssueIndexing();
-
-    // execute some queries
-    benchmarkQueries();
-  }
-
-  private void indexAuthorizations() {
-    LOGGER.info("Indexing issue authorizations");
-    IssueAuthorizationIndexer indexer = tester.get(IssueAuthorizationIndexer.class);
-    List<IssueAuthorizationDao.Dto> authorizations = Lists.newArrayList();
-    for (int i = 0; i < PROJECTS; i++) {
-      IssueAuthorizationDao.Dto authorization = new IssueAuthorizationDao.Dto("PROJECT" + i, System.currentTimeMillis());
-      authorization.addGroup("sonar-users");
-      authorization.addUser("admin");
-      authorizations.add(authorization);
-    }
-    long start = System.currentTimeMillis();
-    indexer.index(authorizations);
-    long period = System.currentTimeMillis() - start;
-    LOGGER.info(String.format("%d authorizations indexed in %d ms (%d docs/second)", PROJECTS, period, 1000 * PROJECTS / period));
-  }
-
-  private void benchmarkIssueIndexing() {
-    LOGGER.info("Indexing issues");
-    IssueIterator issues = new IssueIterator(PROJECTS, FILES_PER_PROJECT, ISSUES_PER_FILE);
-    ProgressTask progressTask = new ProgressTask(LOGGER, "issues", issues.count());
-    Timer timer = new Timer("IssuesIndex");
-    timer.schedule(progressTask, ProgressTask.PERIOD_MS, ProgressTask.PERIOD_MS);
-
-    long start = System.currentTimeMillis();
-    tester.get(IssueIndexer.class).index(issues);
-
-    timer.cancel();
-    long period = System.currentTimeMillis() - start;
-    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());
-    benchmarkQuery("various", IssueQuery.builder()
-      .resolutions(Arrays.asList(Issue.RESOLUTION_FIXED))
-      .assigned(true)
-      .build());
-    // TODO test facets
-  }
-
-  private void benchmarkQuery(String label, IssueQuery query) {
-    IssueIndex index = tester.get(IssueIndex.class);
-    for (int i = 0; i < 10; i++) {
-      long start = System.currentTimeMillis();
-      Result<Issue> result = index.search(query, new QueryContext());
-      long end = System.currentTimeMillis();
-      LOGGER.info("Request (" + label + "): {} docs in {} ms", result.getTotal(), end - start);
-    }
-  }
-
-  private static class IssueIterator implements Iterator<IssueDoc> {
-    private final int nbProjects, nbFilesPerProject, nbIssuesPerFile;
-    private int currentProject = 0, currentFile = 0;
-    private AtomicLong count = new AtomicLong(0L);
-    private final Iterator<String> users = cycleIterator("guy", 200);
-    private Iterator<String> rules = cycleIterator("squid:rule", 1000);
-    private final Iterator<String> severities = Iterables.cycle(Severity.ALL).iterator();
-    private final Iterator<String> statuses = Iterables.cycle(Issue.STATUSES).iterator();
-    private final Iterator<String> resolutions = Iterables.cycle(Issue.RESOLUTIONS).iterator();
-
-    IssueIterator(int nbProjects, int nbFilesPerProject, int nbIssuesPerFile) {
-      this.nbProjects = nbProjects;
-      this.nbFilesPerProject = nbFilesPerProject;
-      this.nbIssuesPerFile = nbIssuesPerFile;
-    }
-
-    public AtomicLong count() {
-      return count;
-    }
-
-    @Override
-    public boolean hasNext() {
-      return count.get() < nbProjects * nbFilesPerProject * nbIssuesPerFile;
-    }
-
-    @Override
-    public IssueDoc next() {
-      IssueDoc issue = new IssueDoc(Maps.<String, Object>newHashMap());
-      issue.setKey(Uuids.create());
-      issue.setFilePath("src/main/java/Foo" + currentFile);
-      issue.setComponentUuid("FILE" + currentFile);
-      issue.setProjectUuid("PROJECT" + currentProject);
-      issue.setActionPlanKey("PLAN" + currentProject);
-      issue.setAssignee(users.next());
-      issue.setAuthorLogin(users.next());
-      issue.setLine(RandomUtils.nextInt());
-      issue.setTechnicalCreationDate(new Date());
-      issue.setTechnicalUpdateDate(new Date());
-      issue.setFuncUpdateDate(new Date());
-      issue.setFuncCreationDate(new Date());
-      issue.setFuncCloseDate(null);
-      issue.setAttributes(null);
-      issue.setDebt(1000L);
-      issue.setEffortToFix(3.14);
-      issue.setLanguage("php");
-      issue.setReporter(users.next());
-      issue.setRuleKey(rules.next());
-      issue.setResolution(resolutions.next());
-      issue.setStatus(statuses.next());
-      issue.setSeverity(severities.next());
-      issue.setMessage(RandomUtils.nextLong() + "this is the message. Not too short.");
-      count.incrementAndGet();
-      if (count.get() % nbIssuesPerFile == 0) {
-        currentFile++;
-      }
-      if (count.get() % (nbFilesPerProject * nbIssuesPerFile) == 0) {
-        currentProject++;
-      }
-
-      return issue;
-    }
-
-    @Override
-    public void remove() {
-      throw new UnsupportedOperationException();
-    }
-  }
-
-  private static Iterator<String> cycleIterator(String prefix, int size) {
-    List<String> values = Lists.newArrayList();
-    for (int i = 0; i < size; i++) {
-      values.add(String.format("%s%d", prefix, i));
-    }
-    return Iterators.cycle(values);
-  }
-}
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
deleted file mode 100644 (file)
index 4b51612..0000000
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * 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
deleted file mode 100644 (file)
index e3c8212..0000000
+++ /dev/null
@@ -1,150 +0,0 @@
-/*
- * 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();
-    }
-  }
-
-}
diff --git a/server/sonar-data-test/src/test/resources/logback-test.xml b/server/sonar-data-test/src/test/resources/logback-test.xml
deleted file mode 100644 (file)
index 6984207..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" ?>
-
-<configuration>
-
-  <appender name="STDOUT"
-            class="ch.qos.logback.core.ConsoleAppender">
-    <encoder>
-      <pattern>
-        %d{HH:mm:ss.SSS} %-5level %logger{36} - %msg%n
-      </pattern>
-    </encoder>
-  </appender>
-
-  <logger name="org.hibernate">
-    <level value="WARN"/>
-  </logger>
-
-  <logger name="org.dbunit">
-    <level value="WARN"/>
-  </logger>
-
-  <!-- set to level DEBUG to log SQL requests executed by MyBatis -->
-  <logger name="java.sql">
-    <level value="WARN"/>
-  </logger>
-
-  <root>
-    <level value="INFO"/>
-    <appender-ref ref="STDOUT"/>
-  </root>
-
-</configuration>
diff --git a/server/sonar-server-benchmarks/pom.xml b/server/sonar-server-benchmarks/pom.xml
new file mode 100644 (file)
index 0000000..f47e9b1
--- /dev/null
@@ -0,0 +1,84 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <groupId>org.codehaus.sonar</groupId>
+    <artifactId>server</artifactId>
+    <version>5.0-SNAPSHOT</version>
+    <relativePath>..</relativePath>
+  </parent>
+  <artifactId>sonar-server-benchmarks</artifactId>
+  <name>SonarQube :: Server :: Benchmark</name>
+
+  <properties>
+    <testInclusions/>
+    <enableBenchmarkAssertions>true</enableBenchmarkAssertions>
+  </properties>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.codehaus.sonar</groupId>
+      <artifactId>sonar-server</artifactId>
+      <version>${project.version}</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.codehaus.sonar</groupId>
+      <artifactId>sonar-server</artifactId>
+      <type>test-jar</type>
+      <version>${project.version}</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.codehaus.sonar</groupId>
+      <artifactId>sonar-search</artifactId>
+      <version>${project.version}</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>com.google.guava</groupId>
+      <artifactId>guava</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.codehaus.sonar</groupId>
+      <artifactId>sonar-testing-harness</artifactId>
+      <scope>test</scope>
+    </dependency>
+  </dependencies>
+
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-surefire-plugin</artifactId>
+        <configuration>
+          <skipTests>${skipServerTests}</skipTests>
+          <argLine>-Xmx1G -Xms256m -server -Djava.awt.headless=true -DenableBenchmarkAssertions=${enableBenchmarkAssertions}</argLine>
+          <includes>
+            <include>${testInclusions}</include>
+          </includes>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+
+  <!--
+  mvn install -DrunBenchmarks=true -DenableBenchmarkAssertions=true
+
+  -->
+  <profiles>
+    <profile>
+      <id>runBenchmarks</id>
+      <activation>
+        <property>
+          <name>runBenchmarks</name>
+        </property>
+      </activation>
+      <properties>
+        <testInclusions>org/sonar/server/benchmark/**/*.java</testInclusions>
+      </properties>
+    </profile>
+  </profiles>
+</project>
diff --git a/server/sonar-server-benchmarks/src/test/java/org/sonar/server/benchmark/BenchmarkAssertions.java b/server/sonar-server-benchmarks/src/test/java/org/sonar/server/benchmark/BenchmarkAssertions.java
new file mode 100644 (file)
index 0000000..33c616f
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * 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;
+
+public class BenchmarkAssertions {
+
+  private static final boolean ENABLED = "true".equals(System.getProperty("enableBenchmarkAssertions"));
+
+  static {
+    if (ENABLED) {
+      System.out.println("Assertions are calibrated for a dedicated benchmark environment. " +
+        "They can be disabled by setting the property -DenableBenchmarkAssertions=false.");
+    }
+  }
+
+}
diff --git a/server/sonar-server-benchmarks/src/test/java/org/sonar/server/benchmark/IssueIndexBenchmarkTest.java b/server/sonar-server-benchmarks/src/test/java/org/sonar/server/benchmark/IssueIndexBenchmarkTest.java
new file mode 100644 (file)
index 0000000..7711555
--- /dev/null
@@ -0,0 +1,206 @@
+/*
+ * 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.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;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.sonar.api.issue.Issue;
+import org.sonar.api.rule.Severity;
+import org.sonar.api.utils.internal.Uuids;
+import org.sonar.server.issue.IssueQuery;
+import org.sonar.server.issue.index.IssueAuthorizationDao;
+import org.sonar.server.issue.index.IssueAuthorizationIndexer;
+import org.sonar.server.issue.index.IssueDoc;
+import org.sonar.server.issue.index.IssueIndex;
+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.concurrent.atomic.AtomicLong;
+
+public class IssueIndexBenchmarkTest {
+
+  private static final Logger LOGGER = LoggerFactory.getLogger("benchmarkIssues");
+
+  final static int PROJECTS = 100;
+  final static int FILES_PER_PROJECT = 100;
+  final static int ISSUES_PER_FILE = 100;
+
+  @ClassRule
+  public static ServerTester tester = new ServerTester();
+
+  @Test
+  public void benchmark() throws Exception {
+    // initialization - feed issues/issueAuthorization with projects and hardcoded users
+    indexAuthorizations();
+
+    // index issues
+    benchmarkIssueIndexing();
+
+    // execute some queries
+    benchmarkQueries();
+  }
+
+  private void indexAuthorizations() {
+    LOGGER.info("Indexing issue authorizations");
+    IssueAuthorizationIndexer indexer = tester.get(IssueAuthorizationIndexer.class);
+    List<IssueAuthorizationDao.Dto> authorizations = Lists.newArrayList();
+    for (int i = 0; i < PROJECTS; i++) {
+      IssueAuthorizationDao.Dto authorization = new IssueAuthorizationDao.Dto("PROJECT" + i, System.currentTimeMillis());
+      authorization.addGroup("sonar-users");
+      authorization.addUser("admin");
+      authorizations.add(authorization);
+    }
+    long start = System.currentTimeMillis();
+    indexer.index(authorizations);
+    long period = System.currentTimeMillis() - start;
+    LOGGER.info(String.format("%d authorizations indexed in %d ms (%d docs/second)", PROJECTS, period, 1000 * PROJECTS / period));
+  }
+
+  private void benchmarkIssueIndexing() {
+    LOGGER.info("Indexing issues");
+    IssueIterator issues = new IssueIterator(PROJECTS, FILES_PER_PROJECT, ISSUES_PER_FILE);
+    ProgressTask progressTask = new ProgressTask(LOGGER, "issues", issues.count());
+    Timer timer = new Timer("IssuesIndex");
+    timer.schedule(progressTask, ProgressTask.PERIOD_MS, ProgressTask.PERIOD_MS);
+
+    long start = System.currentTimeMillis();
+    tester.get(IssueIndexer.class).index(issues);
+
+    timer.cancel();
+    long period = System.currentTimeMillis() - start;
+    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());
+    benchmarkQuery("various", IssueQuery.builder()
+      .resolutions(Arrays.asList(Issue.RESOLUTION_FIXED))
+      .assigned(true)
+      .build());
+    // TODO test facets
+  }
+
+  private void benchmarkQuery(String label, IssueQuery query) {
+    IssueIndex index = tester.get(IssueIndex.class);
+    for (int i = 0; i < 10; i++) {
+      long start = System.currentTimeMillis();
+      Result<Issue> result = index.search(query, new QueryContext());
+      long end = System.currentTimeMillis();
+      LOGGER.info("Request (" + label + "): {} docs in {} ms", result.getTotal(), end - start);
+    }
+  }
+
+  private static class IssueIterator implements Iterator<IssueDoc> {
+    private final int nbProjects, nbFilesPerProject, nbIssuesPerFile;
+    private int currentProject = 0, currentFile = 0;
+    private AtomicLong count = new AtomicLong(0L);
+    private final Iterator<String> users = cycleIterator("guy", 200);
+    private Iterator<String> rules = cycleIterator("squid:rule", 1000);
+    private final Iterator<String> severities = Iterables.cycle(Severity.ALL).iterator();
+    private final Iterator<String> statuses = Iterables.cycle(Issue.STATUSES).iterator();
+    private final Iterator<String> resolutions = Iterables.cycle(Issue.RESOLUTIONS).iterator();
+
+    IssueIterator(int nbProjects, int nbFilesPerProject, int nbIssuesPerFile) {
+      this.nbProjects = nbProjects;
+      this.nbFilesPerProject = nbFilesPerProject;
+      this.nbIssuesPerFile = nbIssuesPerFile;
+    }
+
+    public AtomicLong count() {
+      return count;
+    }
+
+    @Override
+    public boolean hasNext() {
+      return count.get() < nbProjects * nbFilesPerProject * nbIssuesPerFile;
+    }
+
+    @Override
+    public IssueDoc next() {
+      IssueDoc issue = new IssueDoc(Maps.<String, Object>newHashMap());
+      issue.setKey(Uuids.create());
+      issue.setFilePath("src/main/java/Foo" + currentFile);
+      issue.setComponentUuid("FILE" + currentFile);
+      issue.setProjectUuid("PROJECT" + currentProject);
+      issue.setActionPlanKey("PLAN" + currentProject);
+      issue.setAssignee(users.next());
+      issue.setAuthorLogin(users.next());
+      issue.setLine(RandomUtils.nextInt());
+      issue.setTechnicalCreationDate(new Date());
+      issue.setTechnicalUpdateDate(new Date());
+      issue.setFuncUpdateDate(new Date());
+      issue.setFuncCreationDate(new Date());
+      issue.setFuncCloseDate(null);
+      issue.setAttributes(null);
+      issue.setDebt(1000L);
+      issue.setEffortToFix(3.14);
+      issue.setLanguage("php");
+      issue.setReporter(users.next());
+      issue.setRuleKey(rules.next());
+      issue.setResolution(resolutions.next());
+      issue.setStatus(statuses.next());
+      issue.setSeverity(severities.next());
+      issue.setMessage(RandomUtils.nextLong() + "this is the message. Not too short.");
+      count.incrementAndGet();
+      if (count.get() % nbIssuesPerFile == 0) {
+        currentFile++;
+      }
+      if (count.get() % (nbFilesPerProject * nbIssuesPerFile) == 0) {
+        currentProject++;
+      }
+
+      return issue;
+    }
+
+    @Override
+    public void remove() {
+      throw new UnsupportedOperationException();
+    }
+  }
+
+  private static Iterator<String> cycleIterator(String prefix, int size) {
+    List<String> values = Lists.newArrayList();
+    for (int i = 0; i < size; i++) {
+      values.add(String.format("%s%d", prefix, i));
+    }
+    return Iterators.cycle(values);
+  }
+}
diff --git a/server/sonar-server-benchmarks/src/test/java/org/sonar/server/benchmark/ProgressTask.java b/server/sonar-server-benchmarks/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-server-benchmarks/src/test/java/org/sonar/server/benchmark/SourceIndexBenchmarkTest.java b/server/sonar-server-benchmarks/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();
+    }
+  }
+
+}
diff --git a/server/sonar-server-benchmarks/src/test/resources/logback-test.xml b/server/sonar-server-benchmarks/src/test/resources/logback-test.xml
new file mode 100644 (file)
index 0000000..6984207
--- /dev/null
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+
+<configuration>
+
+  <appender name="STDOUT"
+            class="ch.qos.logback.core.ConsoleAppender">
+    <encoder>
+      <pattern>
+        %d{HH:mm:ss.SSS} %-5level %logger{36} - %msg%n
+      </pattern>
+    </encoder>
+  </appender>
+
+  <logger name="org.hibernate">
+    <level value="WARN"/>
+  </logger>
+
+  <logger name="org.dbunit">
+    <level value="WARN"/>
+  </logger>
+
+  <!-- set to level DEBUG to log SQL requests executed by MyBatis -->
+  <logger name="java.sql">
+    <level value="WARN"/>
+  </logger>
+
+  <root>
+    <level value="INFO"/>
+    <appender-ref ref="STDOUT"/>
+  </root>
+
+</configuration>