Jor*_*iro 0 java stringbuilder capacity
我知道,为了良好的实践,StringBuilder应该使用预期内容的容量值进行初始化。否则,编译后增加大小将是一个昂贵的操作。
我的问题是,如果我们不知道预期的大小,应该如何处理?是否有一个标准值/方法来避免幕后昂贵的操作?
如果没有,如果容量大于初始化时给定的值,是否有可能在代码中发出警报/记录?
我知道,为了良好的实践, StringBuilder 应该使用预期内容的容量值进行初始化。否则,编译后增加大小将是一个昂贵的操作。
这是一个极其错误的说法。这样做是非常糟糕的做法。即使您确切知道它有多大。
如果我看到这段代码:
StringBuilder sb = new StringBuilder(in1.length() + in2.length() * 3 + loaded ? suffixLen : 0);
Run Code Online (Sandbox Code Playgroud)
那么这是另一件需要担心、测试和保持最新的事情。我会假设,如果所有这些都存在,无论出于何种原因,有人做了一些性能测试,并且实际上发现这节省了相当大的周期,并且不知何故,在一种白痴中,忽略了写一个有启发性的评论并链接到 JMH或profiler结果分析来验证这个结论。
因此,我要么煞费苦心地尝试手动精确分析更新此代码后计算是否仍然正确,要么解决问题并添加测试(然后完全困惑,当然,当配置文件审查显示此代码完全无关紧要),或者,我会经历相当大的麻烦来编写基于断言的测试用例,该测试用例将运行整个操作,然后在最后验证顶部完成的大小计算是否在事实,正确。
我认为您没有完全理解为什么双曲线过早优化是万恶之源的说法如此流行。
问题就在这里。系统99%的资源都花在了1%的代码上。这并不夸张;事实上,这可能低估了这个问题。
开发人员的时间不是无限的,即使是无限的,程序员理解代码和专注于相关部分的能力也是有限的,因为归根结底,他们是人类。因此,如果代码做了一些不相关的事情,那么花费额外的代码需要被人的眼球和大脑解析和理解是很糟糕的。从字面上看,我们谈论的数量级与您将一杯水倒入欧洲海滨的海洋中,然后观察曼哈顿水位上升的数量级相同。超出了任何衡量能力,并且完全不全面。大胆并没有充分公正地说明它的重要性。即使这段代码在 15 年里每天运行 1 亿次,在整个 15 年里,IAAS 部署成本总计可能相当于 5 美分,而且这还是对性能产生影响的情况,而这通常不会产生影响,因为现代虚拟机、GC、操作系统和 CPU 架构会做出一些疯狂的恶作剧。
此外,系统还进行了优化。优化器(例如 JVM 热点引擎)最终是模式匹配机器。他们找到常用的模式并了解如何尽可能高效地运行它们。通过以别人没有的方式编写代码,代码实际上不太可能胜过常见(惯用)情况。最有可能的是因为这并不重要,即使它确实重要,因为惯用的情况更容易得到优化。
这是一个简单的例子:
List<String> someList = new ArrayList<String>();
for (int i = 0; i < 10000; i++) someList.add(someRandomString);
String[] arrayForm = someList.toArray(new String[0]);
Run Code Online (Sandbox Code Playgroud)
你可能会这样想:嗯,好吧,我们可以稍微优化一下这段代码,然后通过new String[10000];这使系统不必分配一个公认的小对象(0 大小的字符串数组)。
你就错了。上面的代码,使用new String[0],实际上更快。怎么可能?优化器,具有模式匹配。他们认识到该模式并意识到系统可以创建所需大小的新数组,而不是将其清零,然后运行填充它的代码。而优化模式不包括new String[reqSize]系统理论上也可以实现它可以分配数组然后省略将数组清零的变体(JVM 规范保证这一点,这仅仅意味着规范保证您永远无法观察到它不是) t 归零;实际上并不意味着 JVM必须将其归零,这就是不这样做的模式优化的来源)。然而,它并没有做到这一点——不够常见,而且有些复杂。
我并不是说这new StringBuilder()一定比new StringBuilder(knownSize). 我是说:
唯一正确的做法是编写尽可能简单和干净的代码(“干净”的定义是:当你查看它时,你会跳出结论,并且这些结论是正确的。面对变化很容易调整要求,并且灵活地连接到代码库的其余部分)。如果(大如果!)现实生活中的情况会导致性能问题,您首先运行一个探查器,这样您就知道 1% 的代码以任何方式相关,然后您就可以使用 JMH 基准测试和各种方法来解决这个问题性能实验来优化它。如果您的代码是干净的,那就太好了,因为这几乎总是需要调整调用“热路径”的代码的方式或代码从“热路径”流出的位置 - 并且代码越干净,就越容易。
不必要的性能优化几乎总是会降低灵活性,并使代码更难以理解。
因此,客观地说,像这样的微观优化只会让你的代码变得更慢、更容易出错,而实际上没有任何好处。哪怕是一个微小的、几乎无法估量的。
因此,这个建议是愚蠢的。唯一正确的调用是new StringBuilder()- 没有预先配置的大小。您必须写的唯一借口new StringBuilder(presetCapacity)是,如果紧随其后有一条冗长的评论,其中列出了很多细节,或者链接到票证,则所做的确切性能研究表明这确实解决了真正的性能问题以及如何解决重新进行该研究,以及应按什么时间表重新进行研究。
| 归档时间: |
|
| 查看次数: |
127 次 |
| 最近记录: |