我想计算x次运行的平均执行时间(即10次)...我可以使用main方法中的循环轻松执行10次,但是如何存储执行时间&计算平均值?我觉得这很简单,但我现在正在画一个空白......感谢先进!
import java.util.Arrays;
import java.util.Random;
public class OptQSort1 {
static boolean insertionSortCalled = false;
private static final Random random = new Random();
private static final int RANDOM_INT_RANGE = 9999;
private static int[] randomArray(int size) {
// Randomize data (array)
final int[] arr = new int[size];
for (int i = 0; i < arr.length; i++) {
arr[i] = random.nextInt(RANDOM_INT_RANGE);
}
return arr;
}
// Sort
private static void sort(int[] arr) {
if (arr.length > 0)
sortInPlace(arr, 0, arr.length - 1);
}
private static void sortInPlace(int[] arr, int left, int right) {
// OptQSort1:
int size = right - left + 1;
if (size < 10 && !insertionSortCalled) {
insertionSortCalled = true;
insertionSort(arr, 0, arr.length - 1);
}
if (left >= right)
return; // sorted
final int range = right - left + 1;
int pivot = random.nextInt(range) + left;
int newPivot = partition(arr, left, right, pivot);
sortInPlace(arr, left, newPivot - 1);
sortInPlace(arr, newPivot + 1, right);
}
private static int partition(int[] arr, int left, int right, int pivot) {
int pivotVal = arr[pivot];
swapArrayVals(arr, pivot, right);
int storeIndex = left;
for (int i = left; i <= (right - 1); i++) {
if (arr[i] < pivotVal) {
swapArrayVals(arr, i, storeIndex);
storeIndex++;
}
}
swapArrayVals(arr, storeIndex, right);
return storeIndex;
}
private static void swapArrayVals(int[] arr, int from, int to) {
int fromVal = arr[from];
int toVal = arr[to];
arr[from] = toVal;
arr[to] = fromVal;
}
public static void insertionSort(int[] arr, int left, int right) {
int in, out;
for (out = left + 1; out <= right; out++) {
int temp = arr[out];
in = out;
while (in > left && arr[in - 1] >= temp) {
arr[in] = arr[in - 1];
--in;
}
arr[in] = temp;
}
}
public static void main(String[] args) {
long StartTime = System.nanoTime();
int runCount = 0;
// Array size
int[] arr = randomArray(1000);
int[] copy = Arrays.copyOf(arr, arr.length);
// Print original data (array)
System.out.println("The starting/unsorted array: \n"
+ Arrays.toString(arr));
sort(arr);
do {
// check the result
Arrays.sort(copy);
if (Arrays.equals(arr, copy)) {
System.out.println("The ending/sorted array: \n"
+ Arrays.toString(arr));
// print time
long TotalTime = System.nanoTime() - StartTime;
System.out.println("Total elapsed time (milliseconds) " + "is: "
+ TotalTime + "\n");
runCount++;
}
} while (runCount < 10);
}
}
答案 0 :(得分:4)
要计算平均时间,您需要时间总和。时间总和是总时间,因此您甚至不需要知道个别时间或记录它们。只需采用端到端时间并除以计数。
int count = ...
long start = System.nanoTime();
for(int i=0;i<count;i++) {
// do something
}
long time = System.nanoTime() - start;
long averageTime = time/count;
在您完成至少10,000次迭代之前,JIT不会完全预热,因此如果可行,您可能会忽略前11,000次。
一种简单的方法是
int count = ...
long start = 0;
for(int i=-11000;i<count;i++) {
if(i == 0) start = System.nanoTime();
// do something
}
long time = System.nanoTime() - start;
long averageTime = time/count;
顺便说一句:只在测试时间内包含您想要的时间。例如,生成随机数可能需要比排序本身更长的时间,这可能会产生误导性的结果。
编辑:确定何时编译方法或循环的编译阈值由-XX:CompileThresholed=
控制,在服务器JVM上默认为10000,在客户端JVM上默认为1500。 http://www.oracle.com/technetwork/java/javase/tech/vmoptions-jsp-140102.html
-XX:CompileThreshold=10000 Number of method invocations/branches before
compiling [-client: 1,500]
答案 1 :(得分:4)
您可以通过测量代码的10次迭代的总时间来计算平均值,然后将其除以10。
e.g:
public static void main(String[] args) {
long start = System.currentTimeMillis();
for (int i = 0; i < 10; ++i) {
doSort();
}
long elapsed = System.currentTimeMillis() - start;
long average = elapsed / 10;
}
作为一个有用的提示,请使用命名常量而不是迭代次数的文字值:
private final static int ITERATIONS = 10;
public static void main(String[] args) {
long start = System.currentTimeMillis();
for (int i = 0; i < ITERATIONS; ++i) {
doSort();
}
long elapsed = System.currentTimeMillis() - start;
long average = elapsed / ITERATIONS;
}
这意味着如果您想要运行50或100次迭代,您只需在一个地方更改数字。
您还应该意识到,从这种实验中获得准确的计时结果非常困难。最好包括一个“预热”阶段,以允许JIT评估和优化代码,并获得更多的迭代次数:
private static final int WARMUP_ITERATIONS = 10000;
private static final int RUN_ITERATIONS = 100000;
public static void main(String[] args) {
// Warmup with no timing
for (int i = 0; i < WARMUP_ITERATIONS; ++i) {
doSort();
}
// Now the real test
long start = System.currentTimeMillis();
for (int i = 0; i < RUN_ITERATIONS; ++i) {
doSort();
}
long elapsed = System.currentTimeMillis() - start;
long average = elapsed / RUN_ITERATIONS;
}
答案 2 :(得分:1)
您可以使用整数列表来存储每次运行的结果,但是您不需要它来计算平均值,只需将总时间除以运行次数。 顺便说一下,你的测量结果不是很好: 1)包括随机阵列的生成 2)没有进行10次运行
答案 3 :(得分:1)
执行前:
long start = System.currentTimeMillis();
执行后:
long end = System.currentTimeMillis();
每次都在这样的ArrayList
中添加:
times.add(end-start);
获得平均时间:
Long total = 0;
for(Long l : times)
total += l;
System.out.println("Average Time: "+(total/times.size()));
注意返回值的时间单位是毫秒。
答案 4 :(得分:0)
只需保留第二个long
值,即Totaltime
值的运行总计。当循环退出时,只需除以runCount
。
或者,创建一个ArrayList<Long>
来存储时间。每次运行一次,将Totaltime
添加到阵列。循环退出后,您可以平均值并计算其他统计数据(最小值/最大值,标准差等)。