我已阅读How do I time a method's execution in Java?并了解计时方法执行的常规可能性(执行启动/停止计时器,使用方面等)。
我想知道Java 8的新方法引用和lambdas是否会为达到以下目标带来任何帮助。
普通代码:
String r;
r = methodCall("foo","bar");
在性能调优期间,将代码修改为类似的内容,以测量执行方法所花费的时间
String r;
time(() -> {
r = methodCall("foo", "bar"); // doesn't work as r needs to be effectively final
});
我看到我能做到
String r;
r = time1(() ->
methodCall("foo", "bar)
);
(注意结尾处缺少的分号),使用像
这样的time1方法public static <R> R time1(Supplier<R> s){
long start = System.currentTimeMillis();
R result = s.get();
System.out.println("Execution took " + (System.currentTimeMillis() - start));
return result;
}
或者我可以做
r = time2(this::methodCall, "foo", "bar");
使用像
这样的time2方法public static <A,B,R> R time2(BiFunction<A, B, R> f, A first, B second){
long start = System.currentTimeMillis();
R result = f.apply(first, second);
System.out.println("Execution took " + (System.currentTimeMillis() - start));
return result;
}
没有回报价值,我可以做得更好
time3(() -> {
System.out.println("hello");
});
(注意,分号存在)和time3一样
public static void time3(Runnable r){
long start = System.currentTimeMillis();
r.run();
System.out.println("Execution took " + (System.currentTimeMillis() - start));
}
当我有返回值时,是否有更好的解决方案?
我需要关闭才能做到吗?
答案 0 :(得分:6)
你仍然可以包装方法调用,只为没有产生任何东西的东西返回null:
public <R> R timing(Supplier<R> operation) {
long start = System.nanoTime();
R result = operation.get();
System.out.printf("Execution took %dms\n", TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - start));
return result;
}
public void timing(Runnable operation) {
this.timing(() -> { operation.run(); return null; });
}
然后这些电话基本相同:
String r = timing(() -> methodCall("foo", "bar"));
timing(() -> System.out.println("Hello"));
实际上,如果您想要使用方法参数/引用,您需要了解Java的Function api和方法签名之间的关系。
基本上,你不能动态地重新映射所有方法参数并对方法进行直接的“命名”引用(以及对参数进行varargs),你能做的最好/最接近的方法是覆盖{{1}你在n
看到的参数(或继续制作自定义BiFunction
的参数。也许有一天我们会有类似于C#的“varargs”泛型操作,但在此之前我们无法做到这一点类似于FunctionalInterface