Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/performance/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/heroku/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 使用连接字符串的Guava.Premissions时是否会影响性能?_Java_Performance_Guava_Preconditions - Fatal编程技术网

Java 使用连接字符串的Guava.Premissions时是否会影响性能?

Java 使用连接字符串的Guava.Premissions时是否会影响性能?,java,performance,guava,preconditions,Java,Performance,Guava,Preconditions,在我们的代码中,我们经常使用先决条件检查参数: Preconditions.checkArgument(expression, "1" + var + "3"); 但有时,这段代码经常被调用。这是否会对绩效产生显著的负面影响?我们应该换成电视吗 Preconditions.checkArgument(expression, "%s%s%s", 1, var, 3); ? (我希望大多数情况下条件为true。False意味着bug。)在字符串文本连接的情况下,编译器应该在编译时执行此操作,因此

在我们的代码中,我们经常使用
先决条件检查参数

Preconditions.checkArgument(expression, "1" + var + "3");
但有时,这段代码经常被调用。这是否会对绩效产生显著的负面影响?我们应该换成电视吗

Preconditions.checkArgument(expression, "%s%s%s", 1, var, 3);
?


(我希望大多数情况下条件为true。False意味着bug。)

字符串
文本连接的情况下,编译器应该在编译时执行此操作,因此不会出现运行时性能问题。至少标准JDK做到了这一点,它不是按照规范进行的(因此一些编译器可能不会对此进行优化)

对于变量,常量折叠不起作用,因此在运行时会有工作。但是,较新的Java编译器将取代字符串连接到
StringBuilder
,这应该更有效,因为它不是不变的,不像
string

这应该比使用格式化程序(如果调用的话)更快。但是,如果您不经常调用它,那么这可能会比较慢,因为连接总是发生,即使参数为true,并且方法什么也不做


总之,总而言之:我认为重写现有的调用是不值得的。但是,在新代码中,您可以毫无疑问地使用格式化程序。

如果您希望检查在大多数情况下不会引发任何异常,则没有理由使用字符串串联。在调用方法之前连接(使用
.concat
StringBuilder
)比在确定抛出异常后连接要浪费更多的时间

相反,如果抛出异常,则已经处于慢速分支中

还值得一提的是,Guava使用了一个定制的更快的格式化程序,它只接受
%s
。因此,时间损失实际上更类似于标准记录器
{}
句柄(在slf4j或log4j2中)。但是如上所述,这是在你已经在慢分支的情况下

在任何情况下,我都强烈反对你的任何建议,但我会使用以下建议:

Preconditions.checkArgument(expression, "1%s3", var);

您应该只在
%s
中放入变量,而不是常数以获得边际速度。

我编写了一个简单的测试。正如这里所建议的,使用格式化程序要快得多。性能上的差异随着调用次数的增加而增加(formatter的性能不会改变O(1))。我猜在使用简单字符串的情况下,垃圾收集器的时间会随着调用次数的增加而增加

Here is one sample result:
started with 10000000 calls and  100 runs
formatter: 0.94 (mean per run)
string: 181.11 (mean per run)
Formatter is 192.67021 times faster. (this difference grows with number of calls)
下面是代码(Java8,Guava18):

import java.util.concurrent.TimeUnit;
导入java.util.function.Consumer;
导入com.google.common.base.premissions;
导入com.google.common.base.Stopwatch;
公共类应用程序{
公共静态void main(字符串[]args){
整数计数=10000000;
int运行=100;
System.out.println(“以“+count+”调用和“+runs+”运行开始”);
Stopwatch Stopwatch=Stopwatch.createStarted();
跑步(计数,跑步,i->fast(i));
秒表;
float fastTime=(float)秒表。已用时间(TimeUnit.ms)/运行;
System.out.println(“fast:+fastTime+”(每次运行的平均值)”;
//
秒表复位();
System.out.println(“重置:+秒表时间(时间单位毫秒));
秒表。开始();
运行(计数,运行,i->慢速(i));
秒表;
float-slowTime=(float)秒表。已用时间(TimeUnit.ms)/运行;
System.out.println(“慢:+slowTime+“(每次运行的平均值)”);
浮动时间=慢时间/快时间;
System.out.println(“格式化程序的速度是“+倍+”倍。”);
}
私有静态无效运行(整数计数、整数运行、使用者函数){

对于(int c=0;c)来说,第一个实际上只是一个简单的字符串-文字连接?是的,这是问题的核心-这对性能有显著影响字符串连接可能发生在编译时,因此它不应该影响运行时性能。也就是说,如果您连接的是文字(而不是变量).变量字符串通过连接,所有常量部分在编译时放在一起。
.format()
保证具有最差的性能(必须找出那些%s的含义等)。(循环中除外)在源代码中使用
+
,让编译器找出它。1)考虑到Google Java Libraries团队必须维护他们添加的任何方法,添加不必要的方法对他们来说将是一个净损失。2)变量方法不必提供带有占位符的消息,您只需调用
String.format
,而不必添加重载。必须确保该方法存在我要指出的是,谷歌的代码有一些净的积极的好处;我没有数据说明这是否是一个性能优势。谢谢,但我必须编辑我的问题-现在使用一个变量注意,格式化程序只会在检查失败时调用,这不应该是正常情况。哦,是的,我错过了。在这种情况下,你可以也可以使用。在回答中添加了我的想法。我的想法是,提供格式化程序方法是出于性能原因,因此(“如果条件不正确,则不会发生任何事情”)@meskobalazs“更新的……编译器”是什么意思。好吧,仍然支持的任何东西:)尽管Java 6也应该这样做(可能也是5)。
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;

import com.google.common.base.Preconditions;
import com.google.common.base.Stopwatch;

public class App {

    public static void main(String[] args) {
        int count = 10000000;
        int runs = 100;
        System.out.println("started with " + count + " calls and  " + runs + "runs");
        Stopwatch stopwatch = Stopwatch.createStarted();
        run(count, runs, i->fast(i));
        stopwatch.stop();
        float fastTime = (float)stopwatch.elapsed(TimeUnit.MILLISECONDS)/ runs;
        System.out.println("fast: " + fastTime + " (mean per run)");
        //
        stopwatch.reset();
        System.out.println("reseted: "+stopwatch.elapsed(TimeUnit.MILLISECONDS));
        stopwatch.start();
        run(count, runs,  i->slow(i));
        stopwatch.stop();
        float slowTime = (float)stopwatch.elapsed(TimeUnit.MILLISECONDS)/ runs;
        System.out.println("slow: " + slowTime + " (mean per run)");
        float times = slowTime/fastTime;
        System.out.println("Formatter is " + times + " times faster." );
    }

    private static void run(int count, int runs, Consumer<Integer> function) {
        for(int c=0;c<count;c++){
            for(int r=0;r<runs;r++){
                function.accept(r);
            }
        }
    }

    private static void slow(int i) {
        Preconditions.checkArgument(true, "var was " + i);
    }

    private static void fast(int i) {
        Preconditions.checkArgument(true, "var was %s", i);
    }

}