我决定用不同的锁定策略测量增量,并为此目的使用JMH.我正在使用JMH来检查吞吐量和平均时间以及用于检查正确性的简单自定义测试.有六种策略:
基准代码:
@State(Scope.Benchmark)
@BenchmarkMode({Mode.Throughput, Mode.AverageTime})
@OutputTimeUnit(TimeUnit.MICROSECONDS)
@Fork(1)
@Warmup(iterations = 5)
@Measurement(iterations = 5)
public class UnsafeCounter_Benchmark {
public Counter unsync, syncNoV, syncV, lock, atomic, unsafe, unsafeGA;
@Setup(Level.Iteration)
public void prepare() {
unsync = new UnsyncCounter();
syncNoV = new SyncNoVolatileCounter();
syncV = new SyncVolatileCounter();
lock = new LockCounter();
atomic = new AtomicCounter();
unsafe = new UnsafeCASCounter();
unsafeGA = new UnsafeGACounter();
}
@Benchmark
public void unsyncCount() {
unsyncCounter();
}
@CompilerControl(CompilerControl.Mode.DONT_INLINE)
public void unsyncCounter() {
unsync.increment(); …Run Code Online (Sandbox Code Playgroud) 我想了解 R 的微基准测试和 system.time() 之间的区别?他们如何在内部衡量函数执行时间?
我从 Patterson & Hennessy 书中的基本定义开始,然后按照英特尔编程参考文档了解有关 TLB 的更多信息。
从英特尔文档中,我了解了 TLB 的高级设计。例如行大小、关联性和缓存级别。但是需要详细解释 TLB 缓存如何在现代 CPU 中处理缓存未命中及其替换机制。哪些页面
从 L1 TLB移动到 L2 TLB?TLB 中的单个条目可以寻址多少页?TLB 中有多少条目?(特别是DTLB)
任何信息或参考资料都会对我有很大帮助。(如果这不是这个问题的合适论坛,请推荐合适的论坛)
谢谢你。
我尝试对我的 Spring(使用 maven)项目的一些方法进行基准测试。我需要在我的项目中的几个字段上使用 @Autowired 和 @Inject。当我运行我的项目时,它运行良好。但是 JMH 总是使用 @Autowired/@Inject 字段获取 NullPointerException。
public class Resources {
private List<Migratable> resources;
@Autowired
public void setResources(List<Migratable> migratables) {
this.resources = migratables;
}
public Collection<Migratable> getResources() {
return resources;
}
}
Run Code Online (Sandbox Code Playgroud)
我的基准课程
@State(Scope.Thread)
public class MyBenchmark {
@State(Scope.Thread)
public static class BenchmarkState {
Resources res;
@Setup
public void prepare() {
res = new Resources();
}
}
@Benchmark
public void testBenchmark(BenchmarkState state, Blackhole blackhole) {
blackhole.consume(state.res.getResources());
}
}
Run Code Online (Sandbox Code Playgroud)
当我运行我的基准测试时,它在Resources.getResources()
更具体地说是在resources.
它不能自动装配 setResources()。但是如果我运行我的项目(排除基准),它工作正常。
在进行基准测试时,如何使用 …
我正在使用 JMH 对 DOM 解析器进行基准测试。我得到了非常奇怪的结果,因为第一次迭代实际上比后面的迭代运行得更快
谁能解释为什么会发生这种情况?另外,百分位数和所有数字是什么意思,为什么它在第三次迭代后开始变得稳定?一次迭代是否意味着整个基准测试方法的一次迭代?下面是我正在运行的方法
@Benchmark
@BenchmarkMode(Mode.SingleShotTime)
@OutputTimeUnit(TimeUnit.MILLISECONDS)
@Warmup(iterations = 13, time = 1, timeUnit = TimeUnit.MILLISECONDS)
public void testMethod_no_attr() {
try {
File fXmlFile = new File("500000-6.xml");
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
Document doc = dBuilder.parse(fXmlFile);
} catch (Exception e) {
e.printStackTrace();
}
}
Run Code Online (Sandbox Code Playgroud) 我正在尝试测量运行基准测试时消耗的内存。我在互联网上发现我可以使用GC分析器来测量它。我试过了,但我不明白答案以及看到消耗的内存量。谁能解释一下结果?谢谢。
MyBenchmark.testMethod_width_2_attribute_text ss 60 32.345 ± 1.759 ms/op
MyBenchmark.testMethod_width_2_attribute_text:·gc.alloc.rate ss 60 26.904 ± 0.217 MB/sec
MyBenchmark.testMethod_width_2_attribute_text:·gc.alloc.rate.norm ss 60 14999630.400 ± 12.578 B/op
MyBenchmark.testMethod_width_2_attribute_text:·gc.churn.PS_Eden_Space ss 60 28.282 ± 15.342 MB/sec
MyBenchmark.testMethod_width_2_attribute_text:·gc.churn.PS_Eden_Space.norm ss 60 15903402.667 ± 8631257.013 B/op
MyBenchmark.testMethod_width_2_attribute_text:·gc.churn.PS_Survivor_Space ss 60 0.654 ± 0.754 MB/sec
MyBenchmark.testMethod_width_2_attribute_text:·gc.churn.PS_Survivor_Space.norm ss 60 368914.667 ± 425374.152 B/op
MyBenchmark.testMethod_width_2_attribute_text:·gc.count ss 60 26.000 counts
MyBenchmark.testMethod_width_2_attribute_text:·gc.time ss 60 105.000 ms
Run Code Online (Sandbox Code Playgroud) 多年来,x86 CPU 都支持该rdtsc指令,该指令读取当前 CPU 的“时间戳计数器”。这个计数器的确切定义随着时间的推移而改变,但在最近的 CPU 上,它是一个相对于挂钟时间以固定频率递增的计数器,因此它作为快速、准确时钟或测量时间的构建块非常有用由小段代码获取。
关于rdtsc指令的一个重要事实没有以任何特殊方式与周围的代码一起排序。像大多数指令一样,它可以相对于与它没有依赖关系的其他指令自由地重新排序。这实际上是“正常的”,对于大多数指令,它只是一种使 CPU 更快的几乎不可见的方式(这只是一种长篇大论的无序执行方式)。
因为rdtsc它很重要,因为这意味着您可能没有为您期望的代码计时。例如,给定以下序列1:
rdtsc
mov ecx, eax
mov rdi, [rdi]
mov rdi, [rdi]
rdtsc
Run Code Online (Sandbox Code Playgroud)
您可能希望rdtsc测量追逐加载负载的两个指针的延迟mov rdi, [rdi]。然而,在实践中,即使这两个加载都需要查看时间(如果它们在缓存中丢失,则为 100 秒),您将获得相当小的读取值rdtsc。问题是第二个rdtsc不等待加载完成,它只是乱序执行,所以你没有按你认为的时间间隔计时。也许这两rdtsc条指令实际上甚至在第一次加载开始之前就执行了,这取决于rdi在此示例之前的代码中是如何计算的。
到目前为止,这听起来更像是对一个没人问的问题的回答,而不是一个真正的问题,但我已经到了那里。
您有两个基本用例rdtsc:
作为一种精确的计时机制,例如,在微基准测试中。在这种情况下,您通常会rdtsc根据lfence说明防止重新订购。对于上面的示例,您可能会执行以下操作:
lfence
rdtsc
lfence
mov ecx, eax
...
lfence
rdtsc
Run Code Online (Sandbox Code Playgroud)
确保定时指令 ( ...) 不会逃逸到定时区域之外,并确保来自时间区域内的指令不会进入(可能问题不大,但它们可能会与您想要的代码竞争资源测量)。
多年后,英特尔看不起我们这些可怜的程序员,并提出了一条新指令:rdtscp. 就像rdtsc它返回时间戳计数器的读数一样,这家伙做了更多的事情:它使用时间戳读数原子地读取特定于内核的 MSR …
从Efficient R编程字节编译器和R docment r字节编译器,我了解到cmpfun可以用来将纯R函数编译成字节代码以加速并enableJIT通过启用just-in-time编译来加速.
所以,我决定像我自己使用以下代码的第一个链接那样做基准测试:
library("compiler")
library("rbenchmark")
enableJIT(3)
my_mean = function(x) {
total = 0
n = length(x)
for (each in x)
total = total + each
total / n
}
cmp_mean = cmpfun(my_mean, list(optimize = 3))
## Generate some data
x = rnorm(100000)
benchmark(my_mean(x), cmp_mean(x), mean(x), columns = c("test", "elapsed", "relative"), order = "relative", replications = 5000)
Run Code Online (Sandbox Code Playgroud)
不幸的是,结果与第一个链接所显示的不同.性能my_mean甚至比cmp_mean:
test …Run Code Online (Sandbox Code Playgroud) gcc/g++ 是否具有启用或禁用算术优化的标志,例如 wherea+a+...+a被n*awhen替换a为整数?特别是,在使用-O2or时可以禁用它-O3吗?
在下面的示例中,即使-O0将加法运算替换为单个乘法:
$ cat add1.cpp
unsigned int multiply_by_22(unsigned int a)
{
return a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a;
}
$ g++ -S -masm=intel -O0 add1.cpp
$ cat add1.s
...
imul eax, edi, 22
Run Code Online (Sandbox Code Playgroud)
即使禁用-O0(参见g++ -c -Q -O0 --help=optimizers | grep enabled)中使用的所有标志仍然会产生imul操作。
添加循环时,需要-O1将重复加法简化为单个乘法:
$ cat add2.cpp
unsigned int multiply(unsigned int a, unsigned int b)
{
unsigned int sum=0;
for(unsigned int i=0; i<b; i++)
sum …Run Code Online (Sandbox Code Playgroud)