多线程性能

3
我正在编写一款监听UDP传入消息的应用程序。我的主线程从网络接收一个又一个的消息,然后将每个消息传递给一个新线程进行处理,使用一个执行器来处理它们。
每个处理线程对其负责的消息进行所需的处理,并将其添加到一个由所有处理线程共享的LinkedBlockingQueue中。
然后,我有一个DB工作线程,按照10000条消息的块来处理队列并将消息插入DB中。
由于消息的到达速率可能很高(每秒超过20000条消息),因此我认为使用LOAD DATA INFILE更加有效。因此,这个DB工作线程如前所述地处理队列,使用CSV格式创建一个包含所有消息的临时文件,并使用另一个执行器将创建的文件传递给另一个线程。这个新线程使用JDBC来执行LOAD DATA INFILE语句。
经过测试,我认为应用程序的性能不太好,我正在寻找提高多线程级别和DB访问级别性能的方法。
需要说明的是,我使用MySQL作为数据库管理系统。
谢谢
2个回答

3
你需要确定为什么性能较差。例如,如果你将数据按顺序写入数据库,那么很可能你不需要多个线程,因为数据库很可能是瓶颈。如果没有必要使用多个线程,则使用多个线程会增加复杂性并降低速度,因为它本身就是一种开销。我建议你尝试一下,在将数据加载到数据库之前进行所有操作,例如写文件并将其丢弃,看看性能如何。

我可以仅使用DB工作线程而不使用子线程。在这种情况下,文件将由此DB工作线程一个接一个地写入DB。但是我认为,在文件被写入(同步JDBC调用)期间,我可以利用这段时间向DB发出另一个文件。您认为这样做是否有必要? - manash
没有测量每个阶段的差异是不可能知道的。即使有12年优化Java程序的经验,通过测量系统性能而不是猜测,我仍然会惊讶于你所发现的内容。 - Peter Lawrey
你有没有一些关于如何测量多线程应用程序性能的资源可以提供给我? - manash
我会使用System.nanoTime()来计算时间,或者去除某个过程的一部分,以查看哪些部分“跟不上”。您可以使用商用CPU和内存分析器来帮助提高性能,但是除非您进行基本研究,否则您将不知道是否在优化某些实际上无关紧要的东西。 - Peter Lawrey
我已经进行了一些测试。通过删除将消息写入数据库的部分,我就没有性能问题了。当我启用数据库写入时,由于到达速率大于数据库写入速率,LinkedBlockingQueue的大小不断增长。我正在尝试提高数据库写入的性能,但我不知道该怎么做。 - manash
显示剩余3条评论

0

没有任何分析器输出很难确定,但是我的(不)专业猜测是瓶颈在于你将更改写入硬盘上的文件,然后提示数据库读取和解析此文件。存储访问始终比内存访问慢得多。因此,这很可能比仅从内存中提供查询给数据库要慢得多。

但这只是猜测。也许瓶颈在你或我从未预料到的其他地方。当您真正想知道应用程序的哪个部分占用了多少 CPU 时间时,您应该使用像 Profiler4j 这样的分析器来分析您的程序。


关于访问硬盘,我认为我没有选择。最终,我希望我的消息在数据库中,由于使用LOAD DATA INFILE更有效率,所以我必须将消息写入文件,除非还有其他可能性? - manash

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接