Added basic benchmark, run with 'mvn -Dtest=Benchmark test'.

This commit is contained in:
René Jeschke 2015-07-23 12:55:11 +02:00
parent c73396f48d
commit 4a83662310

View File

@ -0,0 +1,362 @@
/*
* Copyright (C) 2011-2015 René Jeschke <rene_jeschke@yahoo.de>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.github.rjeschke.txtmark;
import java.util.Random;
import org.junit.Test;
public class Benchmark
{
// random seed to use for text generation, >= 0 sets seed, < 0 uses random
private static final long SEED = 0;
// number of runs
private static final int RUNS = 8;
// perform an additional (hidden) warm-up run
private static final boolean WARMUP_RUN = true;
private static final int MIN_WORD_LENGTH = 3;
private static final int MAX_WORD_LENGTH = 10;
private static final int MAX_LINE_LENGTH = 80;
private static final int LINES_PER_PARAGRAPH = 20;
// number of paragraphs to create
private static final int NUM_PARAGRAPHS = 30;
// scratch area
private static int REF_COUNTER = 0;
private static String createWord(final Random rnd, final int minLength, final int maxLength)
{
final int len = rnd.nextInt(maxLength - minLength) + minLength;
final char[] ret = new char[len];
for (int i = 0; i < len; i++)
{
ret[i] = (char)('a' + rnd.nextInt(26));
}
return new String(ret);
}
private interface WLDecorator
{
public String decorate(String word);
}
private interface ParagraphDecorator
{
public void startParagraph(StringBuilder out);
public void endParagraph(StringBuilder out);
}
private final static String createText(
final WLDecorator wordDecorator,
final WLDecorator lineDecorator,
final ParagraphDecorator paragraphDecorator)
{
final Random rnd = new Random();
if (SEED >= 0)
{
rnd.setSeed(SEED);
}
final StringBuilder sb = new StringBuilder();
final StringBuilder line = new StringBuilder();
boolean initParagraph = true;
for (int lineLength = 0, lineCount = 0, paraCount = 0; paraCount < NUM_PARAGRAPHS;)
{
if (initParagraph)
{
if (paragraphDecorator != null)
{
paragraphDecorator.startParagraph(sb);
}
initParagraph = false;
}
final String word = createWord(rnd, MIN_WORD_LENGTH, MAX_WORD_LENGTH);
final String decorated = wordDecorator != null ? wordDecorator.decorate(word) : word;
lineLength += word.length();
line.append(decorated);
if (lineLength < MAX_LINE_LENGTH)
{
lineLength++;
line.append(' ');
}
else
{
if (lineDecorator != null)
{
sb.append(lineDecorator.decorate(line.toString()));
}
else
{
sb.append(line);
}
sb.append('\n');
lineCount++;
lineLength = 0;
line.setLength(0);
if (lineCount >= LINES_PER_PARAGRAPH)
{
lineCount = 0;
sb.append('\n');
paraCount++;
if (paragraphDecorator != null)
{
paragraphDecorator.endParagraph(sb);
}
initParagraph = true;
}
}
}
return sb.toString();
}
private final static WLDecorator EMPHASIS = new WLDecorator()
{
@Override
public String decorate(final String word)
{
return "*" + word + "*";
}
};
private final static WLDecorator STRONG = new WLDecorator()
{
@Override
public String decorate(final String word)
{
return "**" + word + "**";
}
};
private final static WLDecorator EMPHASIS_STRONG = new WLDecorator()
{
@Override
public String decorate(final String word)
{
return "***" + word + "***";
}
};
private final static WLDecorator INLINE_CODE = new WLDecorator()
{
@Override
public String decorate(final String word)
{
return "`" + word + "`";
}
};
private final static WLDecorator LINKS = new WLDecorator()
{
@Override
public String decorate(final String word)
{
return "[" + word + "](http://www.example.com/" + word + ")";
}
};
private final static WLDecorator REF_LINKS = new WLDecorator()
{
@Override
public String decorate(final String word)
{
final int id = REF_COUNTER++;
return "[" + word + "][id" + id + "]";
}
};
private final static ParagraphDecorator REF_LINKS_PARA = new ParagraphDecorator()
{
private int startId = 0;
@Override
public void startParagraph(final StringBuilder out)
{
this.startId = REF_COUNTER;
}
@Override
public void endParagraph(final StringBuilder out)
{
for (int i = this.startId; i < REF_COUNTER; i++)
{
out.append("[id");
out.append(i);
out.append("]: http://www.example.com/");
out.append(i);
out.append('\n');
}
}
};
private final static WLDecorator HTML_WRAP = new WLDecorator()
{
@Override
public String decorate(final String word)
{
return "<span>" + word + "</span>";
}
};
private final static WLDecorator MANUAL_LINE_BREAKS = new WLDecorator()
{
@Override
public String decorate(final String word)
{
return word + " ";
}
};
private final static WLDecorator CODE_LINES = new WLDecorator()
{
@Override
public String decorate(final String word)
{
return " " + word;
}
};
private final static WLDecorator BLOCK_QUOTE = new WLDecorator()
{
@Override
public String decorate(final String word)
{
return "> " + word;
}
};
private static class Settings
{
private final WLDecorator wordDecorator;
private final WLDecorator lineDecorator;
private final ParagraphDecorator paragraphDecorator;
private final String name;
private Settings(final String name)
{
this(name, null, null, null);
}
private Settings(final String name, final WLDecorator wordDecorator)
{
this(name, wordDecorator, null, null);
}
private Settings(final String name, final WLDecorator wordDecorator, final WLDecorator lineDecorator)
{
this(name, wordDecorator, lineDecorator, null);
}
private Settings(final String name, final WLDecorator wordDecorator, final WLDecorator lineDecorator,
final ParagraphDecorator paragraphDecorator)
{
this.name = name;
this.wordDecorator = wordDecorator;
this.lineDecorator = lineDecorator;
this.paragraphDecorator = paragraphDecorator;
}
}
private final static Settings[] SETTINGS =
{
new Settings("default"),
new Settings("manual linebreaks", null, MANUAL_LINE_BREAKS),
new Settings("emphasis", EMPHASIS),
new Settings("strong", STRONG),
new Settings("emphasis+strong", EMPHASIS_STRONG),
new Settings("inline code", INLINE_CODE),
new Settings("full links", LINKS),
new Settings("<span> wrap", HTML_WRAP),
new Settings("code blocks", null, CODE_LINES),
new Settings("blockquote", null, BLOCK_QUOTE),
new Settings("ref links", REF_LINKS, null, REF_LINKS_PARA),
};
private static long timedProcess(final String text)
{
final long t0 = System.nanoTime();
Processor.process(text);
final long t1 = System.nanoTime();
return t1 - t0;
}
private static void runTest(final Settings settings, final int runs)
{
final String testText = createText(settings.wordDecorator, settings.lineDecorator, settings.paragraphDecorator);
if (WARMUP_RUN)
{
System.gc();
timedProcess(testText);
}
final long[] times = new long[runs];
for (int i = 0; i < runs; i++)
{
System.gc();
times[i] = timedProcess(testText);
}
System.out.printf("%20s |", settings.name);
long sum = 0;
for (int i = 0; i < runs; i++)
{
System.out.printf(" %8d |", times[i] / 1000);
sum += times[i];
}
System.out.printf(" %8d |", sum / (runs * 1000));
System.out.println();
}
@Test
public void benchmark()
{
System.out.printf("%20s |", "Performance test");
for (int i = 0; i < RUNS; i++)
{
System.out.printf(" %8s |", "run #" + (i + 1));
}
System.out.printf(" %8s |", "average");
System.out.println();
System.out.print("---------------------|");
for (int i = 0; i < RUNS + 1; i++)
{
System.out.print("----------|");
}
System.out.println();
for (final Settings s : SETTINGS)
{
runTest(s, RUNS);
}
System.out.print("---------------------|");
for (int i = 0; i < RUNS + 1; i++)
{
System.out.print("----------|");
}
System.out.println();
System.out.println("All times are given in milliseconds");
}
}