Java:线程本地内存分配和可扩展性

标签 java multithreading memory-management scalability

我正在尝试提高 java 应用程序的可伸缩性,该应用程序在单独的线程中处理许多小任务。但结果却出人意料地糟糕。看来内存分配根本不可扩展。这很奇怪,因为对象是在本地为每个线程分配的。 Java 内存管理器应该能够在线程的本地堆中分配它们,而无需全局锁定。 GC 线程没有显示任何显着的 Activity 。 有一个简单的测试:

private static class AllocTest implements Runnable
{
    @Override
    public void run()
    {
        for (int i = 0; i < 100000; ++i)
        {
            char[] s = new char[100];
        }
    }
}

final int THREADS_COUNT = 4;
    LinkedBlockingQueue<Runnable> taskQueue = new LinkedBlockingQueue<Runnable>(THREADS_COUNT);
    ThreadFactory threadFactory = Executors.defaultThreadFactory();
    ThreadPoolExecutor pool = new ThreadPoolExecutor(THREADS_COUNT, THREADS_COUNT, 1, TimeUnit.HOURS, taskQueue, threadFactory);
    pool.prestartAllCoreThreads();

    long startTime = System.nanoTime();
    for (int i = 0; i < 1000; ++i)
    {
        pool.getQueue().offer(new AllocTest(), 1, TimeUnit.MINUTES);
    }
    pool.shutdown();
    pool.awaitTermination(1, TimeUnit.HOURS);
    long endTime = System.nanoTime();
    System.out.print("Elapsed time: ");
    System.out.print(TimeUnit.NANOSECONDS.toMillis(endTime - startTime));

将线程计数 (THREADS_COUNT) 从 1 更改为 4,我得到几乎相同的结果: THREADS_COUNT 时间

  1. 4811
  2. 4783
  3. 4814
  4. 4823

使用“-server”VM 标志运行测试。 Java 版本 - 1.8.0_66。 尝试过的平台 - Windows 7 x64(1 个处理器,8 个内核)、SunOS 5.10 x64(2 个处理器,8 个内核)。

我希望能够对此类行为进行解释,或者对如何获得更好的可扩展性提出建议(例如一些特定的 jvm 设置)。

编辑:我知道引入一些线程本地池来重用对象而不是每次都分配它应该可以提高可伸缩性。但这只是解决方法(我目前正在尝试实现)。我实际上想找到这两个问题的答案:1)为什么提供的测试不可扩展? 2)如果不是硬件限制,如何在不修改代码的情况下让jvm高效工作?

最佳答案

看起来分配速度非常接近我的 RAM 的理论最大值。 Java 即使在 1 个线程中也能达到这个目标,所以线程数越多也好不了多少。另外,我发现我的电脑配置为在单 channel 模式下使用内存(两个 RAM 模块安装到不同颜色的插槽中)。在双模式下,我观察到两倍更好的结果。

附注谢谢大家的想法!

关于Java:线程本地内存分配和可扩展性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34816289/

相关文章:

JavaFX TableView 文本对齐

java - Android 线程间的数据流

c++ - 直观的线程安全

c++ - 为什么 boost::thread 构造函数不接受 boost::thread::attributes 参数?

c - 为 char 数组分配大小时出现段错误

c++ - 具有类作用域的动态分配堆栈内存

java - 如何防止 Netbeans 中的 PermGen 空间错误?

java - Android 将一组位图合并为一个位图

ios - Unowned 引用在取消初始化时是否设置为 'nil'?

java - JfreeChart 图中只有条形图