]> source.dussan.org Git - sonarqube.git/blob
a5751ae8cb3df837589b00e5a2d45804ba7884f6
[sonarqube.git] /
1 /*
2  * SonarQube, open source software quality management tool.
3  * Copyright (C) 2008-2014 SonarSource
4  * mailto:contact AT sonarsource DOT com
5  *
6  * SonarQube is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 3 of the License, or (at your option) any later version.
10  *
11  * SonarQube is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
19  */
20
21 package org.sonar.server.benchmark;
22
23 import com.google.common.collect.Maps;
24 import org.apache.commons.io.FileUtils;
25 import org.apache.commons.lang.StringUtils;
26 import org.junit.Rule;
27 import org.junit.Test;
28 import org.slf4j.Logger;
29 import org.slf4j.LoggerFactory;
30 import org.sonar.server.es.EsClient;
31 import org.sonar.server.source.index.SourceLineDoc;
32 import org.sonar.server.source.index.SourceLineIndex;
33 import org.sonar.server.source.index.SourceLineIndexDefinition;
34 import org.sonar.server.source.index.SourceLineIndexer;
35 import org.sonar.server.source.index.SourceLineResultSetIterator;
36 import org.sonar.server.tester.ServerTester;
37
38 import java.util.Iterator;
39 import java.util.List;
40 import java.util.Timer;
41 import java.util.concurrent.atomic.AtomicLong;
42
43 import static org.assertj.core.api.Assertions.assertThat;
44
45 /**
46  * Performance tests of the Elasticsearch index sourcelines
47  * <ul>
48  *   <li>throughput of indexing of documents</li>
49  *   <li>size of ES data directory</li>
50  *   <li>time to request index</li>
51  * </ul>
52  */
53 public class SourceIndexBenchmarkTest {
54
55   private static final Logger LOGGER = LoggerFactory.getLogger("benchmarkSourceIndexing");
56   private static final long FILES = 1000L;
57   private static final int LINES_PER_FILE = 3220;
58
59   @Rule
60   public ServerTester tester = new ServerTester();
61
62   @Rule
63   public Benchmark benchmark = new Benchmark();
64
65   @Test
66   public void benchmark() throws Exception {
67     // index source lines
68     benchmarkIndexing();
69
70     // execute some queries
71     benchmarkQueries();
72   }
73
74   private void benchmarkIndexing() {
75     LOGGER.info("Indexing source lines");
76
77     SourceIterator files = new SourceIterator(FILES, LINES_PER_FILE);
78     ProgressTask progressTask = new ProgressTask(LOGGER, "files of " + LINES_PER_FILE + " lines", files.count());
79     Timer timer = new Timer("SourceIndexer");
80     timer.schedule(progressTask, ProgressTask.PERIOD_MS, ProgressTask.PERIOD_MS);
81
82     long start = System.currentTimeMillis();
83     tester.get(SourceLineIndexer.class).index(files);
84     long end = System.currentTimeMillis();
85
86     timer.cancel();
87     long period = end - start;
88     long nbLines = files.count.get() * LINES_PER_FILE;
89     long throughputPerSecond = 1000L * nbLines / period;
90     LOGGER.info(String.format("%d lines indexed in %d ms (%d docs/second)", nbLines, period, throughputPerSecond));
91     benchmark.expectAround("Throughput to index source lines", throughputPerSecond, 7800, Benchmark.DEFAULT_ERROR_MARGIN_PERCENTS);
92
93     // be sure that physical files do not evolve during estimation of size
94     tester.get(EsClient.class).prepareOptimize(SourceLineIndexDefinition.INDEX).get();
95     long dirSize = FileUtils.sizeOfDirectory(tester.getEsServerHolder().getHomeDir());
96     LOGGER.info(String.format("ES dir: " + FileUtils.byteCountToDisplaySize(dirSize)));
97     benchmark.expectBetween("ES dir size (b)", dirSize, 103L * FileUtils.ONE_MB, 109L * FileUtils.ONE_MB);
98   }
99
100   private void benchmarkQueries() {
101     SourceLineIndex index = tester.get(SourceLineIndex.class);
102     for (int i = 1; i <= 100; i++) {
103       long start = System.currentTimeMillis();
104       List<SourceLineDoc> result = index.getLines("FILE" + i, 20, 150);
105       long end = System.currentTimeMillis();
106       assertThat(result).hasSize(131);
107       LOGGER.info("Request: {} docs in {} ms", result.size(), end - start);
108     }
109     // TODO assertions
110   }
111
112   private static class SourceIterator implements Iterator<SourceLineResultSetIterator.SourceFile> {
113     private final long nbFiles;
114     private final int nbLinesPerFile;
115     private int currentProject = 0;
116     private AtomicLong count = new AtomicLong(0L);
117
118     SourceIterator(long nbFiles, int nbLinesPerFile) {
119       this.nbFiles = nbFiles;
120       this.nbLinesPerFile = nbLinesPerFile;
121     }
122
123     public AtomicLong count() {
124       return count;
125     }
126
127     @Override
128     public boolean hasNext() {
129       return count.get() < nbFiles;
130     }
131
132     @Override
133     public SourceLineResultSetIterator.SourceFile next() {
134       String fileUuid = "FILE" + count.get();
135       SourceLineResultSetIterator.SourceFile file = new SourceLineResultSetIterator.SourceFile(fileUuid, System.currentTimeMillis());
136       for (int indexLine = 1; indexLine <= nbLinesPerFile; indexLine++) {
137         SourceLineDoc line = new SourceLineDoc(Maps.<String, Object>newHashMap());
138         line.setFileUuid(fileUuid);
139         line.setLine(indexLine);
140         line.setHighlighting(StringUtils.repeat("HIGHLIGHTING", 5));
141         line.setItConditions(4);
142         line.setItCoveredConditions(2);
143         line.setItLineHits(2);
144         line.setOverallConditions(8);
145         line.setOverallCoveredConditions(2);
146         line.setOverallLineHits(2);
147         line.setUtConditions(8);
148         line.setUtCoveredConditions(2);
149         line.setUtLineHits(2);
150         line.setProjectUuid("PROJECT" + currentProject);
151         line.setScmAuthor("a_guy");
152         line.setScmRevision("ABCDEFGHIJKL");
153         line.setSource(StringUtils.repeat("SOURCE", 10));
154         file.addLine(line);
155       }
156       count.incrementAndGet();
157       if (count.get() % 500 == 0) {
158         currentProject++;
159       }
160       return file;
161     }
162
163     @Override
164     public void remove() {
165       throw new UnsupportedOperationException();
166     }
167   }
168
169 }