我有一个玩具网络应用,它对CPU的占用非常大
上述功能大约需要120毫秒执行。但是当我用500个并发用户对该应用进行负载测试时(siege -t30s -i -v -c500 http:// localhost:3000 / perf)结果是
- 每个请求的平均响应时间2.51秒
- 交易速率每秒160.57笔交易
有人可以在下面回答我的问题吗?-
-
当我与100、200、500个并发用户一起运行时,我看到的不是。该应用程序刚启动时,上述应用程序使用的OS线程数从7固定为35。增加并发连接数不会更改此数字。即使有500个并发请求到达服务器,OS线程的数量仍然停留在35个OS线程中(该应用程序是使用runtime.GOMAXPROCS(runtime.NumCPU())启动的)。测试停止时,该数字仍为35。
- 有人可以向我解释这种行为吗?
- 可以吗操作系统线程的数量以某种方式增加(从OS还是从GOlang)?
- 如果没有,这会提高性能吗? OS线程数增加?
- 有人可以建议其他方法来优化此应用吗?
环境:-
OS参数-
多个goroutine可以对应一个os线程。此处描述了该设计:https://docs.google.com/document/d/1TTj4T2JO42uD5ID9e89oa0sLKhJYD0Y_kqxDv3I3XMw/edit,该文件引用了本文:http://supertech.csail.mit.edu/papers/steal.pdf。
关于问题:
Even when 500 concurrent requests arrive at the server the number of OS threads were still stuck at 35 OS threads [...] Can someone explain me this behaviour?
由于将GOMAXPROCS设置为CPU数量,因此go一次只能运行那么多goroutine。
可能令人困惑的一件事是goroutine并非总是在运行(有时它们"很忙")。例如,如果您在操作系统执行此操作时读取文件,则goroutine忙,而调度程序将选择另一个goroutine运行(假设有一个)。一旦文件读取完成,goroutine将返回"可运行" goroutines列表。
操作系统级别线程的创建由调度程序处理,并且围绕系统级别的调用存在其他复杂性。 (有时您需要一个真正的专用线程。请参阅:LockOSThread。)但是您不应该期望有大量线程。
Can the no. of OS threads be increased somehow (from OS or from GOlang)?
我认为使用
Will this improve the performance if no. of OS threads are increased?
不。从根本上说,CPU一次只能执行多少操作受到限制。 Goroutines之所以起作用,是因为事实证明大多数操作都以某种方式与IO绑定,但是如果您确实在做CPU绑定的事情,那么在该问题上抛出更多的线程将无济于事。实际上,这可能会使情况变得更糟,因为在线程之间进行切换会涉及开销。
换句话说,Go在这里做出了正确的决定。
Can someone suggest some other ways of optimizing this app?
我认为您编写此代码只是为了使CPU做很多工作?实际代码是什么样的?
您最好的选择是寻找一种优化该代码的方法,以便减少CPU时间。如果这不可能(它已经高度优化),那么您将需要添加更多计算机/ CPU。获得一台更好的计算机,或更多。
对于多台计算机,您可以在所有计算机之前放置一个负载均衡器,并且应该很容易扩展。
通过将这项工作从Web服务器上撤下并将其移至某些后端系统,您也可能会从中受益。考虑使用工作队列。