2012-08-09 111 views
0

我目前正在研究分布式应用程序的性能。我的目标是一个网络组件。目前,对于每个连接,都有一个专用的线程在阻塞模式下处理套接字。我的目标是减少线程数量(不会降低性能),并在可能的情况下提高性能。Java中的高优先级线程

我重新设计了网络组件以使用异步通信,并试图使用1到2个线程进行整个网络处理。我做了一个简单的测试,我在一个循环中写了一个节点并在另一个节点上读取,这是为了测试max nw线程能力,并且我发现我的繁忙循环实现消耗了100%cpu,并且每秒获得更多操作,要求。所以我在现有的应用程序中集成了这个繁忙循环实现。

问题我发现其他线程不允许这些异步nw线程获得完整的CPU,即使我有一个8核心系统,我们没有使用超过400%的cpu。基本上是一个C程序员,我可以通过将我的nw线程绑定到核心并提高其调度优先级来解决此问题,以便其他线程仍可以在其他核心上运行。我无法在Java中做类似的工作。有关Java线程优先级的评论有冲突。另外我不想减少其他线程的优先级,因为它可能有其自身的副作用。

你会如何解决这个问题?

+0

[看这篇文章](http://stackoverflow.com/questions/2238272/java-thread-affinity),这是关于一种设置线程的处理器亲和力,当你使用Java,虽然它是真的使用JNI来完成这项工作。 – 2012-08-09 17:30:02

+0

您希望有两个线程处理所有网络流量。至多会使用100%的两个内核。你在100%运行四个内核,所以从这里的信息看,你可能没有问题。是什么让你觉得你有问题? – 2012-08-09 17:49:20

+0

抱歉不明确。新流量目前由8个线程处理,并且它们不会消耗超过100%的cpu。 400%是整个应用程序负载。我想通过使用单个(或2个)异步nw线程来减少线程数量。 – user1588261 2012-08-09 17:59:28

回答

3

我有一个库在Linux和Windows上支持Java中的线程关联。 https://github.com/peter-lawrey/Java-Thread-Affinity

如果隔离CPU,则可以确保您分配的CPU不会用于其他任何内容(非屏蔽中断除外)这在Linux AFAIK中效果最佳。


如果您使用非阻塞NIO忙于等待阻塞IO,则可以获得较低延迟结果。后者在负载下工作得最好,在较低负载下延迟可以增加。

你可能会发现这个库很有趣https://github.com/peter-lawrey/Java-Chronicle它允许你每秒钟持有数百万条消息,可选择到第二个进程。

BTW:线程优先级只是一个暗示,该操作系统是免费的忽略它(常常)


一个简单的例子VS冷码比较温暖。它所做的只是重复复制一个数组并重新定时。一旦代码和数据变暖,你不会期望它会变慢,但所需要的只是一个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 
+0

我可以问一下吗?所以有一种方式,用Java来分配一个CPU来完成你的工作? – Eugene 2012-08-09 18:12:28

+0

在Linux上,您可以告诉操作系统不要在CPU上安排任何事情,然后您可以为该CPU分配特定的线程(或进程)。它是间接的,但它的工作原理非常好。我对Windows或MAC操作系统没有相同的控制 – 2012-08-09 18:30:42

+0

这是惊人的,我不知道这个,所以很想测试你写的库。谢谢! – Eugene 2012-08-09 18:32:49

1

这真的嫌过早优化的给我。你有一个8核心系统,只使用400%的CPU。是什么让你认为这不是IO界限程序的教科书范例?是什么让你觉得你还没有完成你的网络IO链?

@Peter知道他的东西,我确信你可以破解处理器的亲和力,并强制你的关键线程到一个单一的CPU,但问题是它会让你的程序运行得更快吗?我真诚地怀疑它。模型Java虚拟机是聪明的线程调度,我建议它正在适当地做它的工作。除非你有相反的证据,否则我会让它处理日程安排。如果大多数线程正在等待IO,则优先级意味着很少。

另外,是什么让你觉得减少线程数是多少更好。这将很多来自本地的代码(即线程多路复用)移动到Java域(即NIO代码)。如果你正在谈论1000线程,那么我会同意,但即使是100线程也应该是处理连接的有效方法。

我已经完成了超过二十年的大量线程编程,并且我从来不必强制线程关联。当然,确定线程池的大小并就如何应用线程池与专用线程做出正确的决定是一种艺术,但强制VM按照您认为应该的方式安排线程并不能很好地利用您的时间。花一些时间与一个探查器找出你的程序花费的时间将是一个更好的投资恕我直言。

+0

在我的实验中,我只有1个异步网络线程正在遍历所有端点。我期待这个线程将抓住100%的CPU。当我在isoloation中运行此测试时,情况正是如此,但是当我打开其他功能并因此启用更多线程时,情况有很大不同。看来linux调度程序不允许将该线程调度为100%,即使在8核心系统负载不超过400%的情况下也是如此。 – user1588261 2012-08-10 05:09:31

+0

你正在做所有终点的繁忙循环?哇。看起来像一个真正可疑的架构。每个终点的线程真的不成立?有多少个终点?如果你不使用NIO来替换每个线程的终点,那么我不能相信你的方式更好。但很难知道@ user1588261而不知道细节。 – Gray 2012-08-10 14:07:50

相关问题