问题标签 [microbenchmark]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
java - google caliper 尝试将基准测试结果上传到 microbenchmarks.appspot.com 时出现多个 500 错误
尝试为正在运行的基准测试上传 JSON 结果文件时,我看到了多个HTTP 500
错误。Caliper
日志中充满了与以下类似的异常:
但是,我的帐户下的页面上确实显示了一份报告/runs
,因此它似乎至少可以上传其中的一些。对指定的 URL执行curl POST
任何失败的试验都会导致相同的错误。
有没有其他人遇到过这些错误?我的配置中是否缺少某些内容?
卡尺config.properties
:
卡尺版本:
系统属性:
此外,错误日志建议手动上传失败的结果。但是,我在Microbenchmarks Appspot 页面上看不到任何上传结果的选项。
编辑 1:基准启动命令:
c - 缓存命中、未命中和预测 - 对性能的影响
我编写了以下玩具基准。
基本上,它以不同的步幅遍历数组。然后我绘制了结果:
(结果被平滑)
当 stride 为 ~128 时,CPU 可以将所有要访问的数据放入 L1 Cache 中。鉴于访问的线性,未来的读取可能是可以预测的。
我的问题是,为什么在那之后平均阅读时间不断增加?我对 stride=~128 的推理也适用于大于该值的值。
谢谢!
r - 为什么是“测量的负执行时间!” 出现错误?(以及如何处理它?)
我开始了解这个microbenchmark
R
包的一些功能。我从 Hadley Wickham 的这个出版物中实现了一个示例代码,并收到一个错误,我找不到任何准确的信息,我无法处理。提前感谢您的任何解释/提示等。
示例代码:
控制台输出:
更新。这是我的seesionInfo()
控制台输出:
更新 2.包的作者要求我提供一些进一步的信息:
R 变量
R.version
R.version _
platform x86_64-w64-mingw32
arch x86_64
os mingw32
system x86_64, mingw32
status
major 3
minor 0.2
year 2013
month 09
day 25
svn rev 63987
language R
version.string R version 3.0.2 (2013-09-25) 昵称飞盘帆船我电脑中 CPU 的品牌、型号和速度:
处理器:Intel(R) Core(TM) i7-2600K CPU @ 3.40GHz 3.70 GHz
内存:16,0 GB
系统类型:64位
更新 3。
我注意到上面代码的修改之一确实返回了正确的结果:
java - 在构造函数中设置 Java 集合的大小是否更好?
如果我知道当时的大小,将大小传递Collection
给构造函数会更好吗?在扩展和分配/重新分配Collection
方面的节省效果是否显着?Collection
如果我知道的最小尺寸Collection
但不知道上限怎么办。至少以最小的尺寸创建它仍然值得吗?
java - 如何在没有 maven 的情况下使用 Caliper 基准测试版快照?
我被要求使用 Google 的 Caliper 项目来创建一些微基准测试。我非常想使用最新的 beta 快照的注释功能,但是除了一些小例子之外,我很难找到关于如何实际运行这个东西的好文档……有一个视频教程可以指导用户新的 Maven 集成功能,我也被要求不要使用。
现在我只是从他们的一个中剥离了一个小例子,并用我从另一个 SO 问题中收集到的一些其他信息进行了修改:
运行它会告诉我我没有设置大小的默认值。我无法追踪我应该把它放在哪里。
通过注释掉 @Param 行并为 setUp 中的数组声明赋予硬值来完全删除“大小”只会导致它决定“没有要进行的实验”,我想这是有道理的。
如果有任何最新的资源或教程可以指出我做错了什么(可能很多,老实说)我会非常感激。
编辑:
根据一些建议,我已对此进行了更新:
我正在运行 beta 快照并将 Benchmarks 类作为参数传递。我收到以下信息:
它似乎没有检测到任何仪器。我没有传入任何内容,因为它在文档中提到它只是使用默认分配、运行时(这对我的目的来说很好)。
双重编辑:发现了那个问题,愚蠢的错误。一旦我确认它会做一个快速的记录。
java - 分支预测不起作用吗?
关于这个问题,答案指定未排序的数组需要更多时间,因为它未能通过分支预测测试。但是如果我们在程序中做一个小的改动:
在这里我已经替换(来自原始问题)
和
未排序的数组给出了大约。同样的结果,我想问为什么分支预测在这种情况下不起作用?
java - 什么可以解释编写对堆位置的引用的巨大性能损失?
在研究分代垃圾收集器对应用程序性能的微妙影响时,我发现在一个非常基本的操作(简单写入堆位置)的性能方面存在相当惊人的差异,即写入的值是原始值还是引用。
微基准
结果
由于整个循环几乎慢了 8 倍,因此写入本身可能慢了 10 倍以上。什么可以解释这种放缓?
写出原始数组的速度超过每纳秒 10 次写入。也许我应该问我问题的另一面:是什么让原始写作如此之快?(顺便说一句,我已经检查过了,时间与数组大小成线性关系。)
请注意,这都是单线程的;指定@Threads(2)
将增加两个测量值,但比率将相似。
一点背景知识:卡表和相关的写屏障
年轻代中的对象可能碰巧只能从老年代中的对象访问。为了避免收集活动对象,YG 收集器必须知道自上次 YG 收集以来写入老年代区域的任何引用。这是通过一种称为卡表的“脏标志表”来实现的,它为每个 512 字节的堆块有一个标志。
当我们意识到每次写入引用都必须伴随着卡表不变的代码时,该方案的“丑陋”部分就出现了:必须标记卡表中保护被写入地址的位置一样脏。这段代码被称为写屏障。
在特定的机器代码中,如下所示:
当写入的值是原始值时,这就是相同的高级操作所需要的全部内容:
写入屏障似乎“仅”贡献了一次写入,但我的测量表明它会导致数量级的减速。我无法解释这一点。
UseCondCardMark
只会让事情变得更糟
如果条目已被标记为脏,则有一个非常模糊的 JVM 标志应该避免卡表写入。这主要在一些退化的情况下很重要,因为大量的卡表写入导致线程之间通过 CPU 缓存进行错误共享。无论如何,我尝试使用该标志:
java - 为什么 volatile 比 non-volatile 工作得更快?
阅读问题后为什么处理排序数组比处理未排序数组更快? 我们曾尝试将变量设置为 volatile(我预计,当我使用 volatile 时,它的工作速度肯定会变慢,但它的工作速度会更快)这是我没有 volatile 的代码:(它的工作时间约为 11 秒。)
输出是:
这是当我使用 arraySize 和数据变量作为 volatile 时,它的工作时间约为 7 秒:
volatile 的输出是:
我所期望的只是用 volatile 减慢这个过程,但它的工作速度更快。发生了什么事?
java - Java String = "" vs. new String("") 性能变化
我做了和这篇文章一样的测试: new String() vs literal string performance
这意味着我想测试哪个性能更好。正如我所料,结果是文字赋值更快。我不知道为什么,但是我用更多的赋值进行了测试,我注意到一些奇怪的事情:当我让程序执行超过 10.000 次的循环时,文字赋值相对而言并不比少于 10.000 的赋值快得多. 在 1.000.000 次重复时,它甚至比创建新对象还要慢。
这是我的代码:
我让它像上面写的那样运行。我刚刚学习 Java,我的老板让我做测试,在我展示测试结果后,他让我找到答案,为什么会发生这种情况。我在谷歌或stackoverflow上找不到任何东西,所以我希望有人能在这里帮助我。
谢谢!
java - 为什么边界检查没有被消除?
我编写了一个简单的基准测试,以确定在通过按位与计算数组时是否可以消除边界检查。这基本上是几乎所有哈希表所做的:它们计算
作为 的索引table
,其中或h
是hashCode
派生值。结果表明边界检查没有被消除。
我的基准测试的想法非常简单:计算两个值i
和j
,保证两者都是有效的数组索引。
i
是循环计数器。当它被用作数组索引时,边界检查就被消除了。j
计算为x & (table.length - 1)
,其中x
每次迭代都有一些值变化。当它被用作数组索引时,边界检查不会被消除。
相关部分如下:
另一个实验使用
反而。时间上的差异可能是 15%(在我尝试过的不同变体中非常一致)。我的问题:
- 除了约束检查消除之外,还有其他可能的原因吗?
- 是否有一些复杂的原因我看不出为什么没有约束检查消除
j
?
答案摘要
MarkoTopolnik 的回答表明这一切都更加复杂,并且不能保证消除边界检查是胜利,尤其是在他的计算机上,“正常”代码比“屏蔽”代码慢。我想这是因为它允许进行一些额外的优化,这在这种情况下实际上是有害的(鉴于当前 CPU 的复杂性,编译器甚至几乎无法确定)。
leventov 的回答清楚地表明,数组边界检查是在“屏蔽”中完成的,并且它的消除使代码与“正常”一样快。
Donal Fellows 指出了这样一个事实,即屏蔽不适用于零长度表,x & (0-1)
如x
. 所以编译器能做的最好的事情就是用零长度检查代替边界检查。但恕我直言,这仍然值得,因为零长度检查可以轻松移出循环。
建议的优化
由于a[x & (a.length - 1)]
当且仅当 等价抛出a.length == 0
,编译器可以执行以下操作:
- 对于每个数组访问,检查索引是否已通过按位与计算。
- 如果是这样,请检查是否有任何一个操作数被计算为长度减一。
- 如果是这样,请将边界检查替换为零长度检查。
- 让现有的优化来处理它。
这样的优化应该非常简单且便宜,因为它只查看SSA图中的父节点。与许多复杂的优化不同,它永远不会有害,因为它只是用稍微简单的检查代替了一项检查;所以没有问题,即使它不能移出循环。
我会将其发布到热点开发邮件列表。