在 nodejs 中,主要批评者基于其单线程事件循环模型。
nodejs 最大的缺点是无法在应用程序中执行 CPU 密集型任务。为了演示目的,让我们以 while 循环为例(这可能类似于一个返回十万条记录的 db 函数,然后在 nodejs 中处理这些记录。)
while(1){
x++
}
此类代码将阻塞主堆栈,因此事件队列中等待的所有其他任务将永远没有机会执行。 (而在 web 应用程序中,新用户将无法连接到该应用程序)。
但是,可以使用像cluster 这样的模块来利用多核系统并部分解决上述问题。 Cluster 模块允许创建一个由独立进程组成的小型网络,这些进程可以共享服务器端口,这使 Node.js 应用程序可以访问服务器的全部功能。 (但是,使用 Cluster 的最大缺点之一是无法在应用程序代码中维护状态)。
但是,如果服务器负载过大,我们很有可能再次陷入同样的情况(如上所述)。
当我开始学习 Go 语言并了解它的架构和 goroutine 时,我认为它可能会解决由于 nodejs 的单线程事件循环模型而出现的问题。并且它可能会避免上述 CPU 密集型任务的场景,直到我遇到这段有趣的代码,它阻塞了所有 GO 应用程序并且什么也没有发生,很像 nodejs 中的 while 循环。
func main() {
var x int
threads := runtime.GOMAXPROCS(0)
for i := 0; i < threads; i++ {
go func() {
for { x++ }
}()
}
time.Sleep(time.Second)
fmt.Println("x =", x)
}
//or perhaps even if we use some number that is just greater than the threads.
所以,问题是,如果我有一个负载密集型应用程序,并且还会有很多 CPU 密集型任务,我可能会陷入上述情况。 (其中 db 返回大量行,然后应用程序需要处理和修改这些行中的某些内容)。传入的用户不会被阻止,所有其他任务也会被阻止吗?
那么,如何解决上述问题呢?
附言
或许,我提到的用例没有多大意义? :)
最佳答案
目前(Go 1.11 及更早版本)你所谓的 紧密循环确实会阻塞代码。 发生这种情况仅仅是因为当前 Go 编译器 插入执行“抢占检查”的代码(«我应该放弃吗? 到调度程序,以便它运行另一个 goroutine?») 仅在 它编译的函数的序言(几乎,但我们不要离题)。 如果您的循环不调用任何函数,则不会进行抢占检查 将被制作。
Go 开发者很清楚这一点 和 are working on eventually alleviating this issue .
仍然请注意,您所谓的问题在 最真实的场景:执行很长时间的代码 在不调用任何函数的情况下运行 CPU 密集型工作 很少见,而且介于两者之间。
在某些情况下,您确实拥有这样的代码并且您拥有 检测到它真的让其他 goroutines 饿死 (让我强调一下:你已经通过分析发现了这一点——作为 反对只是想出“它一定很慢”),你可以 应用几种技术来处理这个问题:
runtime.Gosched() 的调用在某些关键点
长时间运行的 CPU 密集型代码。
这将强制放弃对另一个 goroutine 的控制
而实际上并没有挂起调用者 goroutine(所以它会
一旦再次安排就运行)。N 个“worker goroutines”;N 明显小于 runtime.GOMAXPROCS
或提高后者,这样您就有了 N 个额外的线程。关于node.js - Nodejs EventLoop(带集群模块)和Golang Scheduler的比较,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51375902/
假设我做了一个模块如下:m=Module.newdoclassCendend三个问题:除了对m的引用之外,还有什么方法可以访问C和m中的其他内容?我可以在创建匿名模块后为其命名吗(就像我输入“module...”一样)?如何在使用完匿名模块后将其删除,使其定义的常量不再存在? 最佳答案 三个答案:是的,使用ObjectSpace.此代码使c引用你的类(class)C不引用m:c=nilObjectSpace.each_object{|obj|c=objif(Class===objandobj.name=~/::C$/)}当然这取决于
作为我的Rails应用程序的一部分,我编写了一个小导入程序,它从我们的LDAP系统中吸取数据并将其塞入一个用户表中。不幸的是,与LDAP相关的代码在遍历我们的32K用户时泄漏了大量内存,我一直无法弄清楚如何解决这个问题。这个问题似乎在某种程度上与LDAP库有关,因为当我删除对LDAP内容的调用时,内存使用情况会很好地稳定下来。此外,不断增加的对象是Net::BER::BerIdentifiedString和Net::BER::BerIdentifiedArray,它们都是LDAP库的一部分。当我运行导入时,内存使用量最终达到超过1GB的峰值。如果问题存在,我需要找到一些方法来更正我的代
我有一个包含模块的模型。我想在模块中覆盖模型的访问器方法。例如:classBlah这显然行不通。有什么想法可以实现吗? 最佳答案 您的代码看起来是正确的。我们正在毫无困难地使用这个确切的模式。如果我没记错的话,Rails使用#method_missing作为属性setter,因此您的模块将优先,阻止ActiveRecord的setter。如果您正在使用ActiveSupport::Concern(参见thisblogpost),那么您的实例方法需要进入一个特殊的模块:classBlah
我有一个围绕一些对象的包装类,我想将这些对象用作散列中的键。包装对象和解包装对象应映射到相同的键。一个简单的例子是这样的:classAattr_reader:xdefinitialize(inner)@inner=innerenddefx;@inner.x;enddef==(other)@inner.x==other.xendenda=A.new(o)#oisjustanyobjectthatallowso.xb=A.new(o)h={a=>5}ph[a]#5ph[b]#nil,shouldbe5ph[o]#nil,shouldbe5我试过==、===、eq?并散列所有无济于事。
我刚刚被困在这个问题上一段时间了。以这个基地为例:moduleTopclassTestendmoduleFooendend稍后,我可以通过这样做在Foo中定义扩展Test的类:moduleTopmoduleFooclassSomeTest但是,如果我尝试通过使用::指定模块来最小化缩进:moduleTop::FooclassFailure这失败了:NameError:uninitializedconstantTop::Foo::Test这是一个错误,还是仅仅是Ruby解析变量名的方式的逻辑结果? 最佳答案 Isthisabug,or
我想获取模块中定义的所有常量的值:moduleLettersA='apple'.freezeB='boy'.freezeendconstants给了我常量的名字:Letters.constants(false)#=>[:A,:B]如何获取它们的值的数组,即["apple","boy"]? 最佳答案 为了做到这一点,请使用mapLetters.constants(false).map&Letters.method(:const_get)这将返回["a","b"]第二种方式:Letters.constants(false).map{|c
我的假设是moduleAmoduleBendend和moduleA::Bend是一样的。我能够从thisblog找到解决方案,thisSOthread和andthisSOthread.为什么以及什么时候应该更喜欢紧凑语法A::B而不是另一个,因为它显然有一个缺点?我有一种直觉,它可能与性能有关,因为在更多命名空间中查找常量需要更多计算。但是我无法通过对普通类进行基准测试来验证这一点。 最佳答案 这两种写作方法经常被混淆。首先要说的是,据我所知,没有可衡量的性能差异。(在下面的书面示例中不断查找)最明显的区别,可能也是最著名的,是你的
我一直致力于让我们的Rails2.3.8应用程序在JRuby下正确运行。一切正常,直到我启用config.threadsafe!以实现JRuby提供的并发性。这导致lib/中的模块和类不再自动加载。使用config.threadsafe!启用:$rubyscript/runner-eproduction'pSim::Sim200Provisioner'/Users/amchale/.rvm/gems/jruby-1.5.1@web-services/gems/activesupport-2.3.8/lib/active_support/dependencies.rb:105:in`co
我有一个Controller,我想为这个Controller创建一个助手,我可以在不包含它的情况下使用它。我尝试像这样创建一个与Controller同名的助手classCars::EnginesController我创建的助手是moduleCars::EnginesHelperdefcheck_fuellogger.debug("chekingfuel")endend我得到的错误是undefinedlocalvariableormethod`check_fuel'for#有没有我遗漏的约定? 最佳答案 如果你真的想在Controll
我有一个模块stat存在于目录结构中:lib/stat_creator/stat/在lib/stat_creator/stat.rb中,我在lib/stat_creator/stat/目录中有我需要的文件,以及:moduleStatCreatormoduleStatendend当我使用该模块时,我将这些类称为StatCreator::Stat::Foo.new现在我想要一个存在于应用程序中的根Stat类。我在app/models中制作了我的Stat类,并在routes.rb中进行了设置。但是,如果我转到Rails控制台并尝试在应用程序/模型中使用Stat类,例如:Stat.by_use