- mongodb - 在 MongoDB mapreduce 中,如何展平值对象?
- javascript - 对象传播与 Object.assign
- html - 输入类型 ="submit"Vs 按钮标签它们可以互换吗?
- sql - 使用 MongoDB 而不是 MS SQL Server 的优缺点
在调查 little debate 时w.r.t.使用 "" + n
和 Integer.toString(int)
将整数原语转换为字符串我写了这个 JMH微基准:
@Fork(1)
@OutputTimeUnit(TimeUnit.MILLISECONDS)
@State(Scope.Benchmark)
public class IntStr {
protected int counter;
@GenerateMicroBenchmark
public String integerToString() {
return Integer.toString(this.counter++);
}
@GenerateMicroBenchmark
public String stringBuilder0() {
return new StringBuilder().append(this.counter++).toString();
}
@GenerateMicroBenchmark
public String stringBuilder1() {
return new StringBuilder().append("").append(this.counter++).toString();
}
@GenerateMicroBenchmark
public String stringBuilder2() {
return new StringBuilder().append("").append(Integer.toString(this.counter++)).toString();
}
@GenerateMicroBenchmark
public String stringFormat() {
return String.format("%d", this.counter++);
}
@Setup(Level.Iteration)
public void prepareIteration() {
this.counter = 0;
}
}
java version "1.8.0_05"
Java(TM) SE Runtime Environment (build 1.8.0_05-b13)
Java HotSpot(TM) 64-Bit Server VM (build 25.5-b02, mixed mode)
Benchmark Mode Samples Mean Mean error Units
b.IntStr.integerToString thrpt 20 32317.048 698.703 ops/ms
b.IntStr.stringBuilder0 thrpt 20 28129.499 421.520 ops/ms
b.IntStr.stringBuilder1 thrpt 20 28106.692 1117.958 ops/ms
b.IntStr.stringBuilder2 thrpt 20 20066.939 1052.937 ops/ms
b.IntStr.stringFormat thrpt 20 2346.452 37.422 ops/ms
StringBuilder
由于创建
StringBuilder
的额外开销,类的速度较慢对象并附加一个空字符串。使用
String.format(String, ...)
甚至更慢,一个数量级左右。
java version "1.7.0_55"
OpenJDK Runtime Environment (mageia-2.4.7.1.mga4-x86_64 u55-b13)
OpenJDK 64-Bit Server VM (build 24.51-b03, mixed mode)
Benchmark Mode Samples Mean Mean error Units
b.IntStr.integerToString thrpt 20 31249.306 881.125 ops/ms
b.IntStr.stringBuilder0 thrpt 20 39486.857 663.766 ops/ms
b.IntStr.stringBuilder1 thrpt 20 41072.058 484.353 ops/ms
b.IntStr.stringBuilder2 thrpt 20 20513.913 466.130 ops/ms
b.IntStr.stringFormat thrpt 20 2068.471 44.964 ops/ms
StringBuilder.append(int)
用这个 JVM 看起来快得多?看着
StringBuilder
类源代码没有发现特别有趣的东西 - 所讨论的方法几乎与
Integer#toString(int)
相同.有趣的是,附加
Integer.toString(int)
的结果(
stringBuilder2
微基准测试)似乎并没有更快。
java version "1.7.0_55"
Java(TM) SE Runtime Environment (build 1.7.0_55-b13)
Java HotSpot(TM) 64-Bit Server VM (build 24.55-b03, mixed mode)
Benchmark Mode Samples Mean Mean error Units
b.IntStr.integerToString thrpt 20 32502.493 501.928 ops/ms
b.IntStr.stringBuilder0 thrpt 20 39592.174 428.967 ops/ms
b.IntStr.stringBuilder1 thrpt 20 40978.633 544.236 ops/ms
$ /usr/java/default/bin/java -XX:+PrintFlagsFinal 2>/dev/null | grep String
bool OptimizeStringConcat = true {C2 product}
intx PerfMaxStringConstLength = 1024 {product}
bool PrintStringTableStatistics = false {product}
uintx StringTableSize = 60013 {product}
$ java -XX:+PrintFlagsFinal 2>/dev/null | grep String
bool OptimizeStringConcat = true {C2 product}
intx PerfMaxStringConstLength = 1024 {product}
bool PrintStringTableStatistics = false {product}
uintx StringTableSize = 60013 {product}
bool UseStringCache = false {product}
UseStringCache
选项在 Java 8 中被删除,没有替换,所以我怀疑这有什么区别。其余选项似乎具有相同的设置。
AbstractStringBuilder
源代码的并排对比,
StringBuilder
和
Integer
来自
src.zip
的类文件显示没有什么值得注意的。除了大量的外观和文档更改之外,
Integer
现在有一些对无符号整数和
StringBuilder
的支持已稍微重构以与
StringBuffer
共享更多代码.这些更改似乎都不会影响
StringBuilder#append(int)
使用的代码路径,虽然我可能错过了一些东西。
IntStr#integerToString()
生成的汇编代码的比较和
IntStr#stringBuilder0()
有趣得多。为
IntStr#integerToString()
生成的代码的基本布局两种 JVM 都相似,尽管 Oracle JDK 8u5 似乎更具侵略性 w.r.t.在
Integer#toString(int)
中内联一些调用代码。与 Java 源代码有明确的对应关系,即使对于汇编经验极少的人也是如此。
IntStr#stringBuilder0()
的汇编代码然而,却完全不同。 Oracle JDK 8u5 生成的代码再次与 Java 源代码直接相关——我可以轻松识别相同的布局。相反,OpenJDK 7 生成的代码对于未受过训练的人来说几乎无法识别(就像我的一样)。
new StringBuilder()
调用似乎被删除了,就像在
StringBuilder
中创建数组一样。构造函数。此外,反汇编插件无法像在 JDK 8 中那样提供尽可能多的源代码引用。
StringBuilder
插入手写低级代码的结果。操作。我不确定为什么这种优化不会在我的 JVM 8 实现中发生,或者为什么没有为
Integer#toString(int)
实现相同的优化在 JVM 7 中。我想熟悉 JRE 源代码相关部分的人必须回答这些问题......
最佳答案
TL;博士: append
中的副作用显然打破 StringConcat 优化。
原始问题和更新中的分析非常好!
为了完整起见,以下是一些缺失的步骤:
-XX:+PrintInlining
对于 7u55 和 8u5。在 7u55 中,您将看到如下内容:@ 16 org.sample.IntStr::inlineSideEffect (25 bytes) force inline by CompilerOracle
@ 4 java.lang.StringBuilder::<init> (7 bytes) inline (hot)
@ 18 java.lang.StringBuilder::append (8 bytes) already compiled into a big method
@ 21 java.lang.StringBuilder::toString (17 bytes) inline (hot)
@ 16 org.sample.IntStr::inlineSideEffect (25 bytes) force inline by CompilerOracle
@ 4 java.lang.StringBuilder::<init> (7 bytes) inline (hot)
@ 3 java.lang.AbstractStringBuilder::<init> (12 bytes) inline (hot)
@ 1 java.lang.Object::<init> (1 bytes) inline (hot)
@ 18 java.lang.StringBuilder::append (8 bytes) inline (hot)
@ 2 java.lang.AbstractStringBuilder::append (62 bytes) already compiled into a big method
@ 21 java.lang.StringBuilder::toString (17 bytes) inline (hot)
@ 13 java.lang.String::<init> (62 bytes) inline (hot)
@ 1 java.lang.Object::<init> (1 bytes) inline (hot)
@ 55 java.util.Arrays::copyOfRange (63 bytes) inline (hot)
@ 54 java.lang.Math::min (11 bytes) (intrinsic)
@ 57 java.lang.System::arraycopy (0 bytes) (intrinsic)
StringBuilder
之后似乎没有调用任何内容。方法——这是字符串优化生效的一个很好的迹象。事实上,如果你用 -XX:-OptimizeStringConcat
运行 7u55 ,子调用将重新出现,性能下降到 8u5 级别。 src/share/vm/opto/stringopts.cpp
hg log src/share/vm/opto/stringopts.cpp
找出那里的最新变化。其中一位候选人是:changeset: 5493:90abdd727e64
user: iveresov
date: Wed Oct 16 11:13:15 2013 -0700
summary: 8009303: Tiered: incorrect results in VM tests stringconcat...
@Fork(5)
@Warmup(iterations = 5)
@Measurement(iterations = 5)
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
@State(Scope.Benchmark)
public class IntStr {
private int counter;
@GenerateMicroBenchmark
public String inlineSideEffect() {
return new StringBuilder().append(counter++).toString();
}
@GenerateMicroBenchmark
public String spliceSideEffect() {
int cnt = counter++;
return new StringBuilder().append(cnt).toString();
}
}
Benchmark Mode Samples Mean Mean error Units
o.s.IntStr.inlineSideEffect avgt 25 65.460 1.747 ns/op
o.s.IntStr.spliceSideEffect avgt 25 64.414 1.323 ns/op
Benchmark Mode Samples Mean Mean error Units
o.s.IntStr.inlineSideEffect avgt 25 84.953 2.274 ns/op
o.s.IntStr.spliceSideEffect avgt 25 65.386 1.194 ns/op
StringBuilder
移动链,在整个链之前做。此外,切换到平均时间和 ns/op。这是 JDK 7u55:
Benchmark Mode Samples Mean Mean error Units
o.s.IntStr.integerToString avgt 25 153.805 1.093 ns/op
o.s.IntStr.stringBuilder0 avgt 25 128.284 6.797 ns/op
o.s.IntStr.stringBuilder1 avgt 25 131.524 3.116 ns/op
o.s.IntStr.stringBuilder2 avgt 25 254.384 9.204 ns/op
o.s.IntStr.stringFormat avgt 25 2302.501 103.032 ns/op
Benchmark Mode Samples Mean Mean error Units
o.s.IntStr.integerToString avgt 25 153.032 3.295 ns/op
o.s.IntStr.stringBuilder0 avgt 25 127.796 1.158 ns/op
o.s.IntStr.stringBuilder1 avgt 25 131.585 1.137 ns/op
o.s.IntStr.stringBuilder2 avgt 25 250.980 2.773 ns/op
o.s.IntStr.stringFormat avgt 25 2123.706 25.105 ns/op
stringFormat
实际上在 8u5 中要快一些,所有其他测试都相同。这巩固了原始问题的主要罪魁祸首 SB 链中的副作用断裂的假设。
关于java - 为什么 StringBuilder#append(int) 在 Java 7 中比在 Java 8 中更快?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23756966/
我需要将文本放在 中在一个 Div 中,在另一个 Div 中,在另一个 Div 中。所以这是它的样子: #document Change PIN
奇怪的事情发生了。 我有一个基本的 html 代码。 html,头部, body 。(因为我收到了一些反对票,这里是完整的代码) 这是我的CSS: html { backgroun
我正在尝试将 Assets 中的一组图像加载到 UICollectionview 中存在的 ImageView 中,但每当我运行应用程序时它都会显示错误。而且也没有显示图像。 我在ViewDidLoa
我需要根据带参数的 perl 脚本的输出更改一些环境变量。在 tcsh 中,我可以使用别名命令来评估 perl 脚本的输出。 tcsh: alias setsdk 'eval `/localhome/
我使用 Windows 身份验证创建了一个新的 Blazor(服务器端)应用程序,并使用 IIS Express 运行它。它将显示一条消息“Hello Domain\User!”来自右上方的以下 Ra
这是我的方法 void login(Event event);我想知道 Kotlin 中应该如何 最佳答案 在 Kotlin 中通配符运算符是 * 。它指示编译器它是未知的,但一旦知道,就不会有其他类
看下面的代码 for story in book if story.title.length < 140 - var story
我正在尝试用 C 语言学习字符串处理。我写了一个程序,它存储了一些音乐轨道,并帮助用户检查他/她想到的歌曲是否存在于存储的轨道中。这是通过要求用户输入一串字符来完成的。然后程序使用 strstr()
我正在学习 sscanf 并遇到如下格式字符串: sscanf("%[^:]:%[^*=]%*[*=]%n",a,b,&c); 我理解 %[^:] 部分意味着扫描直到遇到 ':' 并将其分配给 a。:
def char_check(x,y): if (str(x) in y or x.find(y) > -1) or (str(y) in x or y.find(x) > -1):
我有一种情况,我想将文本文件中的现有行包含到一个新 block 中。 line 1 line 2 line in block line 3 line 4 应该变成 line 1 line 2 line
我有一个新项目,我正在尝试设置 Django 调试工具栏。首先,我尝试了快速设置,它只涉及将 'debug_toolbar' 添加到我的已安装应用程序列表中。有了这个,当我转到我的根 URL 时,调试
在 Matlab 中,如果我有一个函数 f,例如签名是 f(a,b,c),我可以创建一个只有一个变量 b 的函数,它将使用固定的 a=a1 和 c=c1 调用 f: g = @(b) f(a1, b,
我不明白为什么 ForEach 中的元素之间有多余的垂直间距在 VStack 里面在 ScrollView 里面使用 GeometryReader 时渲染自定义水平分隔线。 Scrol
我想知道,是否有关于何时使用 session 和 cookie 的指南或最佳实践? 什么应该和什么不应该存储在其中?谢谢! 最佳答案 这些文档很好地了解了 session cookie 的安全问题以及
我在 scipy/numpy 中有一个 Nx3 矩阵,我想用它制作一个 3 维条形图,其中 X 轴和 Y 轴由矩阵的第一列和第二列的值、高度确定每个条形的 是矩阵中的第三列,条形的数量由 N 确定。
假设我用两种不同的方式初始化信号量 sem_init(&randomsem,0,1) sem_init(&randomsem,0,0) 现在, sem_wait(&randomsem) 在这两种情况下
我怀疑该值如何存储在“WORD”中,因为 PStr 包含实际输出。? 既然Pstr中存储的是小写到大写的字母,那么在printf中如何将其给出为“WORD”。有人可以吗?解释一下? #include
我有一个 3x3 数组: var my_array = [[0,1,2], [3,4,5], [6,7,8]]; 并想获得它的第一个 2
我意识到您可以使用如下方式轻松检查焦点: var hasFocus = true; $(window).blur(function(){ hasFocus = false; }); $(win
我是一名优秀的程序员,十分优秀!