howto-hpl-gpu
如果开发人员讨厌一件事,那就是看到您的代码变成了性能消耗。
可以很好地完成工作的那段代码,在进行负载测试时崩溃。
这的确使开发人员感到非常沮丧。
我的团队最近不得不经历一段写得很漂亮(不要!)的工作,浪费大量的代码,扭曲甚至变成一堆即使在大量负载下也不会汗水的东西。
幸运的是,经过几天的努力,我们能够实现这一壮举。
因此,本博客介绍了我专注于提高性能时应遵循的一些准则。
1.确定关键的性能路径
首先,在开始修复之前,您需要知道需要修复的内容。
相同的规则在这里适用。
例如,如果您的应用程序通过网络接收要存储的数据。
您正在查看通过网络进行的数据传输以及磁盘上的数据存储(可能是RDBMS)。
之后,将其他所有内容分开。
进行这种分离的几种方法可以是将应用程序的其余功能更改为定期任务,按需操作或分离应用程序本身。
当然,要做到这一点,您的架构必须是松散耦合的。
对我来说,SOA和Web服务效果最好。
![:)](https://i-blog.csdnimg.cn/blog_migrate/4081a6a1fba982b1bdc37ab46dcfe2d4.gif)
2.避免阻塞
别挡!
人们已经说过很多次了,但是您在很多地方都看到它被违反了。
处理关键性能路径时,请尽可能保持异步。
例如,如果您阻止网络呼叫,则不仅有可能占用您自己的应用程序,而且还会占用发送您数据的应用程序的风险。
在高负载率下,向您发送数据的应用程序可能会用尽连接,如果处理不当,等待传递的消息会Swift堆积在内存中。
结果可能从无害超时到灾难性的“内存不足”情况。
针对这种情况的一种简单解决方案是使用队列和线程池。
消息进入的那一刻,我们将其排队,并允许连接返回并关闭。
这将在爱护您的相邻应用程序,避免消息堆积和使数据传输顺畅的过程中发挥重要作用。
3.提取数据–内存vs磁盘vs网络
请注意这一点。
引用NodeJS的创建者Ryan Dahl的话,从内存中获取数据就像走进整个房间的同事隔间并获得记录。
通过网络获取数据将传递给您同事在世界各地的办公室并获得记录( 请查看他的演讲 )。
我喜欢这个比喻,只是因为它解释了我们许多人只是选择忽略的东西。
不必要的网络通话会带来麻烦,并且很可能是您最大的麻烦之一。
识别从磁盘(可能是RDBMS或网络)读取的数据,您将看到将要反复获取相同数据的模式。
是的,解决方案很明显。
让我们记住内存与磁盘之间的区别,让我们缓存一下。
如果您有复杂的缓存需求,或者只是使用一个简单的对象,请使用优质的库。
无论哪种方式,它都会立即将您的性能提高很多倍。
注意:就像您缓存它一样,请确保要取消缓存(使缓存无效)的实现也是可靠的。
否则,您将看到一些令人讨厌的错误,这些错误会夺走您许多晚上的睡眠。
4.上下文切换
线程非常适合异步操作。
但是,在介绍它们的那一刻,您还介绍了线程之间的上下文切换。
如果您的应用程序中运行的线程数超过1000,那么您进行上下文切换的机会可能会超过实际工作。
解决此问题的一种方法是使用“固定”线程池。
我强调固定的,因为我们很多人都习惯于使用无限制的池。
这是自找麻烦。
您的应用程序很有可能达到不可预测的状态,突然有1000个线程并崩溃。
另一个常见的错误是通过引入所谓的瓶颈线程来引入不必要的上下文切换。
例如,假设存在一个应用程序,该应用程序的队列中包含大量工作线程。
然后,创建一个“单个”线程,该线程负责从此队列中出队对象并调用工作线程来完成其工作。
我们很难控制操作系统和上下文切换策略。
因此,在高负载下,此单个双端队列线程运行的机会不足以对所有作业进行双端队列并分配了足够的工作线程,从而造成了性能瓶颈。
因此,在这种情况下,一种更好的方法可能是生成一个工作线程,该工作线程自己出队并进行适当的工作,或者在没有任何要出队的情况下死掉。
由于我们使用的是池,因此几乎不会创建成本线程。
5.永远不要放任不管
您可以使用连接池,线程池,队列和许多其他机制来获得性能。
可能在测试过程中,所有这些对您都非常有效,并且您的应用程序运行起来像黄油一样光滑。
但是,让这些不受限制地束之高阁是件麻烦事。
最佳做法是将您所有无限制的资源限制为适当的最大值,这是应对不可预测情况的良好防御措施。
我认为,任何需要高性能或至少中等性能的应用程序都应牢记以上准则。
通过遵循上面的简单准则,我的团队能够提高应用程序的性能,该应用程序在大约1000个并发情况下会发出约50个并发请求以使它们平稳运行。
PS:我可能会在本文的第二部分中跟进,以涵盖我遗漏的其他一些要点。
翻译自: https://www.javacodegeeks.com/2012/06/howto-increase-performance-in-your.html
howto-hpl-gpu