- r - 以节省内存的方式增长 data.frame
- ruby-on-rails - ruby/ruby on rails 内存泄漏检测
- android - 无法解析导入android.support.v7.app
- UNIX 域套接字与共享内存(映射文件)
我正在 Linux 机器(AMD 6 核,16 GB RAM)上使用 JVM(Oracle 1.7 64 位),以了解应用程序中的线程数如何影响性能。我希望测量上下文切换在什么时候会降低性能。
我创建了一个创建线程执行池的小应用程序:
Executors.newFixedThreadPool(numThreads)
我每次运行程序都会调整numThreads
,看看效果。
然后我将 numThread
个作业(java.util.concurrent.Callable
的实例)提交到池中。每一个都增加一个AtomicInteger
,做一些工作(创建一个随机整数数组并将其打乱),然后 hibernate 一段时间。这个想法是模拟 Web 服务调用。最后,作业将自身重新提交到池中,因此我始终有 numThreads
个作业工作。
我正在衡量吞吐量,例如每分钟处理的作业数。
有了几千个线程,我每分钟可以处理多达 400,000 个作业。超过 8000 个线程,结果开始变化很大,这表明上下文切换正在成为一个问题。但是我可以继续将线程数增加到 30,000,并且仍然可以获得更高的吞吐量(每分钟 420,000 到 570,000 个作业)。
现在的问题是:我得到一个 java.lang.OutOfMemoryError: Unable to create new native thread
有超过 31,000 个作业。我试过设置 -Xmx6000M
这没有帮助。我试过玩 -Xss
但这也无济于事。
我读到 ulimit
可能很有用,但随着 ulimit -u 64000
的增加并没有改变任何东西。
信息:
[root@apollo ant]# ulimit -a
core file size (blocks, -c) 0
data seg size (kbytes, -d) unlimited
scheduling priority (-e) 0
file size (blocks, -f) unlimited
pending signals (-i) 127557
max locked memory (kbytes, -l) 64
max memory size (kbytes, -m) unlimited
open files (-n) 1024
pipe size (512 bytes, -p) 8
POSIX message queues (bytes, -q) 819200
real-time priority (-r) 0
stack size (kbytes, -s) 8192
cpu time (seconds, -t) unlimited
max user processes (-u) 1024
virtual memory (kbytes, -v) unlimited
file locks (-x) unlimited
所以问题 #1:我必须做什么才能创建更大的线程池?
问题 #2:我应该在什么阶段看到上下文切换真正降低吞吐量并导致进程停止?
这是一些结果,在我对其进行修改以进行更多处理(如所建议的那样)并开始记录平均响应时间(如所建议的那样)之后。
// ( (n_cores x t_request) / (t_request - t_wait) ) + 1
// 300 ms wait, 10ms work, roughly 310ms per job => ideal response time, 310ms
// ideal num threads = 1860 / 10 + 1 = 187 threads
//
// results:
//
// 100 => 19,000 thruput, 312ms response, cpu < 50%
// 150 => 28,500 thruput, 314ms response, cpu 50%
// 180 => 34,000 thruput, 318ms response, cpu 60%
// 190 => 35,800 thruput, 317ms response, cpu 65%
// 200 => 37,800 thruput, 319ms response, cpu 70%
// 230 => 42,900 thruput, 321ms response, cpu 80%
// 270 => 50,000 thruput, 324ms response, cpu 80%
// 350 => 64,000 thruput, 329ms response, cpu 90%
// 400 => 72,000 thruput, 335ms response, cpu >90%
// 500 => 87,500 thruput, 343ms response, cpu >95%
// 700 => 100,000 thruput, 430ms response, cpu >99%
// 1000 => 100,000 thruput, 600ms response, cpu >99%
// 2000 => 105,000 thruput, 1100ms response, cpu >99%
// 5000 => 131,000 thruput, 1600ms response, cpu >99%
// 10000 => 131,000 thruput, 2700ms response, cpu >99%, 16GB Virtual size
// 20000 => 140,000 thruput, 4000ms response, cpu >99%, 27GB Virtual size
// 30000 => 133,000 thruput, 2800ms response, cpu >99%, 37GB Virtual size
// 40000 => - thruput, -ms response, cpu >99%, >39GB Virtual size => java.lang.OutOfMemoryError: unable to create new native thread
我将它们解释为:
1) 即使应用程序在 96.7% 的时间内处于 hibernate 状态,仍然需要完成大量线程切换2) 上下文切换是可测量的,并显示在响应时间中。
这里有趣的是,在调整应用程序时,您可能会选择可接受的响应时间,例如 400 毫秒,并增加线程数,直到您获得该响应时间,在这种情况下,这将使应用程序处理大约 95一分钟一千个请求。
人们经常说理想的线程数接近核心数。在具有等待时间(阻塞线程,例如等待数据库或 Web 服务响应)的应用程序中,计算需要考虑到这一点(参见上面的公式)。但是,当您查看结果或调整到特定响应时间时,即使是理论上的理想也不是实际理想。
最佳答案
I get a java.lang.OutOfMemoryError: Unable to create new native thread with more than about 31,000 jobs. I have tried setting -Xmx6000M which doesn't help. I tried playing with -Xss but that doesn't help either.
-Xmx 设置没有帮助,因为线程堆栈不是从堆中分配的。
发生的情况是 JVM 正在向操作系统请求一个内存段(堆外!)来保存堆栈,而操作系统 拒绝该请求。最可能的原因是 ulimit 或操作系统内存资源问题:
“数据段大小”ulimit 是无限的,所以这应该不是问题。
这样就剩下内存资源了。一次 1Mb 的 30,000 个线程约为 30Gb,这比您拥有的物理内存多得多。我的猜测是 30Gb 的虚拟内存有足够的交换空间,但是您将边界推得太远了。
-Xss 设置应该会有所帮助,但您需要使请求的堆栈大小小于默认大小 1m
。此外,还有一个硬性的最小尺寸。
Question #1: What do I have to do to be able to create a bigger thread pool?
将默认堆栈大小减小到当前值以下,或增加可用虚拟内存量。 (不建议使用后者,因为看起来您已经严重过度分配了。)
Question #2: At what stage should I expect to see context switching really reducing throughput and causing the process to grind to a halt?
这是无法预测的。这将高度依赖于线程实际在做什么。事实上,我认为您的基准测试不会给您答案,告诉您真正的多线程应用程序将如何运行。
Oracle 网站显示 this关于线程堆栈空间的话题:
In Java SE 6, the default on Sparc is 512k in the 32-bit VM, and 1024k in the 64-bit VM. On x86 Solaris/Linux it is 320k in the 32-bit VM and 1024k in the 64-bit VM.
On Windows, the default thread stack size is read from the binary (java.exe). As of Java SE 6, this value is 320k in the 32-bit VM and 1024k in the 64-bit VM.
You can reduce your stack size by running with the -Xss option. For example:
java -server -Xss64k
Note that on some versions of Windows, the OS may round up thread stack sizes using very coarse granularity. If the requested size is less than the default size by 1K or more, the stack size is rounded up to the default; otherwise, the stack size is rounded up to a multiple of 1 MB.
64k is the least amount of stack space allowed per thread.
关于java - 具有数千个线程的内存设置,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14545924/
这是代码片段。 请说出这种用小内存存储大数据的算法是什么。 public static void main(String[] args) { long longValue = 21474836
所以我使用 imap 从 gmail 和 outlook 接收电子邮件。 Gmail 像这样编码 =?UTF-8?B?UmU6IM69zq3OvyDOtc68zrHOuc67IG5ldyBlbWFpb
很久以前就学会了 C 代码;想用 Scheme 尝试一些新的和不同的东西。我正在尝试制作一个接受两个参数并返回两者中较大者的过程,例如 (define (larger x y) (if (> x
Azure 恢复服务保管库有两个备份配置选项 - LRS 与 GRS 这是一个有关 Azure 恢复服务保管库的问题。 当其驻留区域发生故障时,如何处理启用异地冗余的恢复服务保管库?如果未为恢复服务启
说,我有以下实体: @Entity public class A { @Id @GeneratedValue private Long id; @Embedded private
我有下一个问题。 我有下一个标准: criteria.add(Restrictions.in("entity.otherEntity", getOtherEntitiesList())); 如果我的
如果这是任何类型的重复,我会提前申请,但我找不到任何可以解决我的具体问题的内容。 这是我的程序: import java.util.Random; public class CarnivalGame{
我目前正在使用golang创建一个聚合管道,在其中使用“$ or”运算符查询文档。 结果是一堆需要分组的未分组文档,这样我就可以进入下一阶段,找到两个数据集之间的交集。 然后将其用于在单独的集合中进行
是否可以在正则表达式中创建 OR 条件。 我正在尝试查找包含此类模式的文件名列表的匹配项 第一个案例 xxxxx-hello.file 或者案例二 xxxx-hello-unasigned.file
该程序只是在用户输入行数时创建菱形的形状,因此它有 6 个 for 循环; 3 个循环创建第一个三角形,3 个循环创建另一个三角形,通过这 2 个三角形和 6 个循环,我们得到了一个菱形,这是整个程序
我有一个像这样的查询字符串 www.google.com?Department=Education & Finance&Department=Health 我有这些 li 标签,它们的查询字符串是这样
我有一个带有静态构造函数的类,我用它来读取 app.config 值。如何使用不同的配置值对类进行单元测试。我正在考虑在不同的应用程序域中运行每个测试,这样我就可以为每个测试执行静态构造函数 - 但我
我正在寻找一个可以容纳多个键的容器,如果我为其中一个键值输入保留值(例如 0),它会被视为“或”搜索。 map, int > myContainer; myContainer.insert(make_
我正在为 Web 应用程序创建数据库,并正在寻找一些建议来对可能具有多种类型的单个实体进行建模,每种类型具有不同的属性。 作为示例,假设我想为“数据源”对象创建一个关系模型。所有数据源都会有一些共享属
(1) =>CREATE TABLE T1(id BIGSERIAL PRIMARY KEY, name TEXT); CREATE TABLE (2) =>INSERT INTO T1 (name)
我不确定在使用别名时如何解决不明确的列引用。 假设有两个表,a 和 b,它们都有一个 name 列。如果我加入这两个表并为结果添加别名,我不知道如何为这两个表引用 name 列。我已经尝试了一些变体,
我的查询是: select * from table where id IN (1,5,4,3,2) 我想要的与这个顺序完全相同,不是从1...5,而是从1,5,4,3,2。我怎样才能做到这一点? 最
我正在使用 C# 代码执行动态生成的 MySQL 查询。抛出异常: CREATE TABLE dump ("@employee_OID" VARCHAR(50)); "{"You have an er
我有日期 2016-03-30T23:59:59.000000+0000。我可以知道它的格式是什么吗?因为如果我使用 yyyy-MM-dd'T'HH:mm:ss.SSS,它会抛出异常 最佳答案 Sim
我有一个示例模式,它的 SQL Fiddle 如下: http://sqlfiddle.com/#!2/6816b/2 这个 fiddle 只是根据 where 子句中的条件查询示例数据库,如下所示:
我是一名优秀的程序员,十分优秀!