我目前正在研究分布式应用程序的性能。我的目标是网络组件。目前,每个连接都有一个专用线程,在阻塞模式下处理套接字。我的目标是减少线程数量(不降低性能),如果可能的话,提高性能。
我重新设计了网络组件以使用异步通信,并尝试使用1到2个线程来处理整个网络。我做了一个简单的测试,我从一个节点在一个循环中写入,然后在另一个节点上读取,这是为了测试最大nw线程能力,我发现我的繁忙循环实现消耗了100%的cpu,每秒得到的操作比我们需要的多得多。所以我在现有的应用程序中集成了这个繁忙的循环实现。
我发现的问题是其他线程不允许这些异步nw线程获得完整的cpu,即使我有一个8核系统,我们使用的cpu不超过400%。基本上作为一名C程序员,我可以通过将我的nw线程绑定在一个核上并提高它的调度优先级来解决这个问题,这样其他线程仍然可以在其他核上运行。我不能在Java做类似的事情。关于Java线程优先级有相互矛盾的评论。我也不想降低其他线程的优先级,因为它可能有自己的副作用。
你会如何解决这个问题?
对我来说,这真的有点过早优化的味道。你有一个8核系统,只使用400%的CPU。是什么让你认为这不是IO绑定程序的教科书示例?是什么让你认为你还没有把网络IO链发挥到极致?
@彼得知道他的东西,我相信你可以破解处理器亲和性,把你的关键线程强制到一个CPU上,但问题是它会让你的程序运行得更快吗?我真的很怀疑。JavaVM模型在线程调度方面非常聪明,我建议它正确地完成了自己的工作。除非你有很好的相反证据,否则我会让它来处理日程安排。如果大多数线程都在等待IO,那么即使优先级也没有多大意义。
另外,是什么让你认为减少线程数量更好。这将大量代码从本地(即线程多路复用)转移到Java(即NIO代码)。如果你说的是1000个线程,那么我同意,但是即使是100个线程也应该是处理连接的有效方式。
二十多年来,我做了大量的线程编程,从来没有强迫过线程亲和力。当然,调整线程池的大小并正确决定在哪里应用线程池和专用线程是一门艺术,但强制虚拟机按您认为应该的方式安排线程并不能很好地利用您的时间。花一些时间与剖析器一起,找出你的程序在哪里花费时间,这将是一个更好的投资。
我有一个库来支持Linux和WindowsJava中的线程亲和力。https://github.com/peter-lawrey/Java-Thread-Affinity
如果隔离CPU,可以确保分配的CPU不会用于任何其他用途(不可屏蔽中断除外),这在Linux AFAIK中效果最好。
如果您在非阻塞NIO中使用忙等待,而不是阻塞IO,您可以获得更低的延迟结果。后者在负载下效果最好,在较低的负载下,延迟会增加。
你可能会发现这个图书馆很有趣https://github.com/peter-lawrey/Java-Chronicle它允许您每秒持久保存数百万条消息,可以选择将其保存到第二个进程。
顺便说一句:线程优先级只是一个提示,操作系统可以随意忽略它(而且经常忽略)
一个比较冷热代码的简单例子。它所做的只是反复复制一个数组并给它计时。一旦代码和数据升温,你就不会期望它变慢,但是即使在一台相当大的机器上,也只需要10毫秒的延迟就能显著降低复制的时间。
public static void main(String... args) throws InterruptedException {
int[] from = new int[60000], to = new int[60000];
for (int i = 0; i < 10; i++)
copy(from, to); // warm up
for (int i = 0; i < 10; i++) {
long start = System.nanoTime();
copy(from, to);
long time = System.nanoTime() - start;
System.out.printf("Warm copy %,d us%n", time / 1000);
}
for (int i = 0; i < 10; i++) {
Thread.sleep(10);
long start = System.nanoTime();
copy(from, to);
long time = System.nanoTime() - start;
System.out.printf("Cold copy %,d us%n", time / 1000);
}
}
private static void copy(int[] a, int[] b) {
for (int i = 0, len = a.length; i < len; i++)
b[i] = a[i];
}
指纹
Warm copy 20 us
Warm copy 20 us
Warm copy 19 us
Warm copy 23 us
Warm copy 20 us
Warm copy 20 us
Cold copy 100 us
Cold copy 80 us
Cold copy 89 us
Cold copy 92 us
Cold copy 80 us
Cold copy 112 us
主要内容:1 什么是Java 线程优先级,2 Thread类线程优先级常量,3 Java 线程优先级的例子1 什么是Java 线程优先级 每个线程都有一个优先级。优先级由1到10之间的数字表示。在大多数情况下,线程计划会根据线程的优先级来调度线程(称为抢先式调度)。但是不能保证一定被调用,因为是否被调用取决于JVM选择谁来调度。 2 Thread类线程优先级常量 public static int MIN_PRIORITY public static int NORM_PRIORITY publ
我需要一个优先级队列,它首先获得具有最高优先级值的项目。我当前正在使用队列库中的PriorityQueue类。但是,这个函数只先返回值最小的项。我尝试了一些很难看的解决方案,比如(sys.maxint-priority)作为优先级,但我只是想知道是否存在更优雅的解决方案。
问题内容: Java API线程优先级(1-10)如何转换为操作系统级别的优先级,因为大多数操作系统没有与此相匹配的线程优先级别(就数量而言)。 因此请记住,在某些情况下,具有不同优先级的两个或多个线程最终会在OS级别获得相同的优先级。 如果我的理解有需要更正,请澄清。 问题答案: 实际上,某些优先级可以映射到相同的“本地”优先级。这是列表(基于OpenJDK 6中的Hotspot代码): Sol
问题内容: 这是关于线程优先级的测试。该代码来自《 Thinking in Java p.809》 我不知道为什么我不能得到像这样的常规结果: 但是结果是随机的(每次运行时都会改变): 我在Win 7 64位JDK 7中使用i3-2350M 2C4T CPU,这有关系吗? 问题答案: Java线程优先级无效 线程优先级是高度特定于操作系统的,并且在许多操作系统上的影响通常很小。优先级有助于仅对运行
根据优先表,一元后缀递增和递减运算符比关系运算符有更多的优先级,那么为什么在这样的表达式(x++>=10)中,关系运算符首先计算,然后变量递增呢?
问题内容: 我最近才发现我认为这里有些奇怪。为什么会这样,并且处于不同的优先级?我会以为他们处于同一水平。以上证明了这一点。即使从左到右的求值对第一个给出的都是假,而第二个则给出的是真,这两个陈述都是正确的。 有人知道这背后的原因吗? (顺便说一句,我只是在这里使用了很多括号,但是是旧代码提出了这个问题) 问题答案: 因为在传统的数学表示法中,(逻辑合取)的优先级高于(逻辑合取)。 出于显而易见的