发帖  主题  评论  推荐  标签 用户 查搜   用户 密码 自动 注册  
 
面向对象 设计模式 领域驱动设计 企业架构 框架 开发教程 微服务 CQRS 扩展性 并发编程 事件溯源 分布式 SOA

性能主题

Java性能优化要点之三: False-sharing伪共享

首页

  数据会在CPU的一个cache-line中发生竞争,每个cache-line大小是64字节,那么就用将一个对象填充满一个cache-line ,最好的办法是加入longs,当然在Java 8中@Contended,这样可以不允许多个对象拥挤在一个cache-line中.

下面看看如何填满一个Cache-line,我们进行填满与无填满一个Cache-line的测试,测试代码如下:

public final class FalseSharing implements Runnable {

  private static AtomicLong[] longs = new AtomicLong[NUM_THREADS];

  ....//此处有无填充和有填充区别,见后面

  public static void runTest() throws InterruptedException {

    Thread[] threads = new Thread[NUM_THREADS];

    for (int i = 0; i < threads.length; i++)

      threads[i] = new Thread(new FalseSharing(i));

    for (Thread t : threads) { t.start(); }

    for (Thread t : threads) { t.join(); }

  }

 

  public void run() {

    long i = ITERATIONS + 1;

    while (0 != --i) { longs[arrayIndex].set(i); }

  }

}

 

没有填充的代码如下:

public final class FalseSharing implements Runnable {

  private static AtomicLong[] longs = new AtomicLong[NUM_THREADS];

  static {

    for (int i = 0; i < longs.length; i++) {

      longs[i] = new AtomicLong();

    }

  }

  ...

}

下面是填满一个Cacheline的AtomicLong代码:

public final class FalseSharing implements Runnable {

  private static PaddedAtomicLong[] longs = new PaddedAtomicLong[NUM_THREADS];

  static {

    for (int i = 0; i < longs.length; i++) {

      longs[i] = new PaddedAtomicLong();

    }

  }

  ...

  public static long sumPaddingToPreventOptimisation(final int index) {

    PaddedAtomicLong v = longs[index];

    return v.p1 + v.p2 + v.p3 + v.p4 + v.p5 + v.p6;

  }

 

  public static class PaddedAtomicLong extends AtomicLong {

    public volatile long p1, p2, p3, p4, p5, p6 = 7L;

  }

}

测试性能结果:

图中红色图块表示没有填满Cache-line发生了伪共享,而蓝色色块是填满了,随着线程数的增加,伪共享增加了执行时间。性能差。

下页

Disruptor

 

 

解道移动版 | 关注解道 | 联系解道 | 关于解道 | 广告联系 | 网站地图 | 设为首页

沪ICP证12033263 如有意见请与我们联系 Powered by JdonFramework
返回顶部