标签: microbenchmark

通过JMH测量sun.misc.Unsafe.compareAndSwap中的奇怪行为

我决定用不同的锁定策略测量增量,并为此目的使用JMH.我正在使用JMH来检查吞吐量和平均时间以及用于检查正确性的简单自定义测试.有六种策略:

  • 原子计数
  • ReadWrite锁定计数
  • 与volatile同步
  • 同步块没有volatile
  • sun.misc.Unsafe.compareAndSwap
  • sun.misc.Unsafe.getAndAdd
  • 不同步计数

基准代码:

@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)

java cas microbenchmark jmh

5
推荐指数
1
解决办法
750
查看次数

使用 R 微基准测试和 system.time 有什么区别?

我想了解 R 的微基准测试和 system.time() 之间的区别?他们如何在内部衡量函数执行时间?

performance r microbenchmark

5
推荐指数
1
解决办法
889
查看次数

intel中的TLB结构

我从 Patterson & Hennessy 书中的基本定义开始,然后按照英特尔编程参考文档了解有关 TLB 的更多信息。

从英特尔文档中,我了解了 TLB 的高级设计。例如行大小、关联性和缓存级别。但是需要详细解释 TLB 缓存如何在现代 CPU 中处理缓存未命中及其替换机制。哪些页面
从 L1 TLB移动到 L2 TLB?TLB 中的单个条目可以寻址多少页?TLB 中有多少条目?(特别是DTLB)

任何信息或参考资料都会对我有很大帮助。(如果这不是这个问题的合适论坛,请推荐合适的论坛)

谢谢你。

processor intel tlb microbenchmark

5
推荐指数
1
解决办法
3066
查看次数

JMH Benchmark 在 Spring(with maven) 项目中使用 Autowired 字段获取 NullPointerException

我尝试对我的 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()。但是如果我运行我的项目(排除基准),它工作正常。
在进行基准测试时,如何使用 …

benchmarking spring microbenchmark maven jmh

5
推荐指数
1
解决办法
795
查看次数

JMH - 奇怪的基准测试结果

我正在使用 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)

java benchmarking microbenchmark jmh

5
推荐指数
1
解决办法
719
查看次数

JMH中的分配率是什么意思

我正在尝试测量运行基准测试时消耗的内存。我在互联网上发现我可以使用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)

java garbage-collection microbenchmark jmh

5
推荐指数
1
解决办法
1064
查看次数

rdtscp 的“半围栏”行为是怎么回事?

多年来,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 …

performance x86 assembly microbenchmark rdtsc

5
推荐指数
0
解决办法
301
查看次数

为什么 CPUID + RDTSC 不可靠?

我正在尝试在 x86-64 处理器上分析执行时间的代码。我指的是这篇英特尔白皮书,并且还浏览了其他 SO 线程,讨论了在此处此处使用 RDTSCP 与 CPUID+RDTSC 的主题。

在上面提到的白皮书中,使用 CPUID+RDTSC 的方法被称为不可靠,并且也使用统计数据进行了证明。

CPUID+RDTSC 不可靠的原因可能是什么?

此外,同一白皮书中的图 1(最小值行为图)和图 2(方差行为图)中的图具有“方波”模式。什么解释了这种模式?

x86 intel microbenchmark rdtsc cpuid

5
推荐指数
1
解决办法
531
查看次数

在启用JIT的情况下,编译的R代码实​​际上比纯R慢

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)

jit bytecode r microbenchmark

5
推荐指数
1
解决办法
175
查看次数

禁用算术优化的 gcc 标志

gcc/g++ 是否具有启用或禁用算术优化的标志,例如 wherea+a+...+an*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)

c x86 gcc compiler-optimization microbenchmark

5
推荐指数
1
解决办法
165
查看次数