我有一个玩具网络应用,它对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)?

我认为使用LockOSThread可能会导致创建新线程,但这并不重要:

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服务器上撤下并将其移至某些后端系统,您也可能会从中受益。考虑使用工作队列。