Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/329.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java程序的性能问题_Java_Performance_Sockets - Fatal编程技术网

Java程序的性能问题

Java程序的性能问题,java,performance,sockets,Java,Performance,Sockets,我有一个具有以下逻辑的java程序: i) Open a socket server and wait for messages from client ii) Read messages received(fixed length records of about 233 bytes). iii) on each message receive, call a process function. iv) process function does follwing - add the

我有一个具有以下逻辑的java程序:

i) Open a socket server and wait for messages from client

ii) Read messages received(fixed length records of about 233 bytes).

iii) on each message receive, call a process function.

iv) process function does follwing
 - add the record to the string builder.

 - if (length of stringbuilder > configured buffer size) {

   process this buffer

   } else {

      add the new record to buffer

   }
现在,当我用100万条记录(每233字节)尝试这个程序时,大约需要5分钟30秒才能完成。我想减少这次。这里的大部分时间都浪费在这个过程函数中

我正在检查是否可以获得一些关于如何重新组织此过程以获得更好性能的建议。
我的用例是获取记录并读取它们,直到它们达到配置的缓冲区大小,如50MB、500MB或1GB。一旦它们达到这个大小,处理它并写入文件系统。

您的系统上有多少内核?您可以创建一个线程池,其线程数量相当于,并创建一个可运行的线程池,该线程池在线程内调用进程。对你来说,这可能会加快速度


如果你只有一个核心,我们需要更多关于处理的信息。您的CPU是否与测试挂钩?什么操作系统等?

一些微优化:

使用正确的初始尺寸创建StringBuilder。1GB。 不要每次都重新创建StringBuilder;通过设置setLength0重新使用它 但我不确定这种微观优化会有多大影响。也许你可以发布更多的代码

为什么数据存储在中间缓冲区中?如果您所做的只是将其写入文件系统,那么使用BufferedWriter一次写入一条记录会更好吗? 邮件是否必须按照到达的顺序进行处理?如果没有,您可以使用ExecutorService来并行处理。
我怀疑,5:30分钟中的大部分时间都可以归结为某种形式的网络通信开销。首先,我推荐以下几点最重要:

如果您使用的是UDP,请切换到TCP。对于这种情况,使用基于流的传输可能比使用基于消息的传输获得更好的吞吐量

在客户端和服务器端,确保已使用缓冲流包装套接字流

如果客户端和服务器位于同一主机上,请使用环回IP地址,例如127.0.0.1

如果服务器端处理是CPU密集型的,并且您有多个内核,则在读取消息的线程的单独线程中进行处理

考虑使用NIO读/写数据

考虑不在服务器端将数据转换为字符形式。。。虽然如果它真的是文本,这将使处理变得困难


在您执行任何操作之前,请先分析您的客户端和服务器端应用程序,看看是否存在任何意外瓶颈。

一些信封背面的健全性检查:

您正在通过套接字发送233*1M字节=1.864Gb,这将需要 不同的时间量取决于您的带宽和NIC,但 如果你正在寻找一张100Mb的卡,请画一些基线图 在任何真正的网络延迟发生之前的20秒。事实上,这可能要高得多,除非您使用的是本地主机或强大的硬件和连接性。 使用新的Stringbytes[]将233个字节编码为一个字符串大约需要260 nson,所以您看到的是1M*0.25us=250毫秒。 因此,从bat字节到字符串并不是问题所在,我也猜StringBuilder.append并不是badit复制字符数组的原因。您将为所有这些字符串和字节缓冲区分配大量内存,这可能会导致一些速度减慢。为了避免内存流失,您可以使用Charset.newDecoder获取decoderkeep,然后重新使用,并将脱离连接的ByteBuffer直接写入可重新使用的CharBuffer。您提到了字符串的一些格式,这在出错时可能代价高昂,但除非您正在做一些复杂的事情,否则我认为这不是问题所在

问题的一个更可能的原因是网络延迟,您可以通过编写一个虚拟程序来测试该理论,该程序只读取数据并将其丢弃。 另一个可能的疑点是代码中写入文件或磁盘的部分,但没有进一步的信息,很难提供帮助。 此外,如果您不熟悉评测,可以使用手动计时来验证您的理论:

long start = System.nanotime();
process(data);
long took = System.nanotime() - start;

总结您在流程中花费的时间,并了解时间的去向。

@user656189如果时间花在流程功能上而不是数据传输上,我们需要看到的是您在流程功能中所做的事情,你不这么认为吗?你有没有考虑过在你的IDE上使用某种形式的性能测试插件,看看你的瓶颈在哪里?@Endophage-cud你有什么建议吗?JProfiler不错,但不便宜。不过,你或许可以接受为期10天的评估。。。还有一个是我一年前用过的,但不幸的是,这个名字我记不清了…我做你指定的微优化。我只创建一次stringbuilder,并在使用后将其清除为:sb.delete0,sb.length;ii数据存储在中间缓冲区中,因为一旦我们
达到它的大小并将其转换为Hadoop键值格式,然后将这些记录写入Hadoop文件系统。你能给我举个遗嘱执行人服务的例子吗?我想的遗嘱执行人服务是标准的。如果您使用的是Hadoop,那么我理解您需要使用非常大的文件,但我不确定是否需要中间缓冲区—您可以这样做:读取记录;将转换后的格式写入Hadoop;写入1GB后是否关闭当前Hadoop文件?另外,正如其他人所建议的,如果您还没有对代码进行评测,那么评测代码也很重要。优化错误的代码位是没有意义的…sb.delete对于作业来说是错误的工具,它将删除字符0..length并将剩余的字符提前,而您对此并不感兴趣。您需要的是sb.setLength0,它将忽略内容并从头开始。谢谢!这很有帮助。我可以使用什么工具来评测客户端和服务器端应用程序?试试VisualVM-