我在 Go 中实现了一个 HTTP 服务器。
对于每个请求,我需要为特定结构创建数百个对象,我有大约 10 个这样的结构。因此,在按照 Go 实现完成请求后,它将被垃圾收集。
因此对于每个请求,都会分配和释放这么多内存。
相反,我想实现内存池以提高分配端和 GC 端的性能
在请求开始时,我将从池中取出并在请求处理后将它们放回
从池实现端
在内存分配和释放的情况下,还有什么其他提高性能的建议吗?
最佳答案
事先说明:
很多人建议使用 sync.Pool对于 temporary 对象,这是一个快速、良好的实现。但请注意,sync.Pool 不保证保留池中的对象。引用其文档:
Any item stored in the Pool may be removed automatically at any time without notification. If the Pool holds the only reference when this happens, the item might be deallocated.
因此,如果您不希望 Pool 中的对象被垃圾收集(这取决于您的情况可能会导致更多分配),下面介绍的解决方案会更好,因为 channel 的缓冲区不会被垃圾收集。如果你的对象真的那么大,那么内存池是合理的,池 channel 的开销将被摊销。
此外,sync.Pool 不允许您限制池对象的数量,而下面提出的解决方案自然可以。
最简单的内存池“实现”是缓冲 channel 。
假设您想要一个包含一些大对象的内存池。创建一个缓冲 channel ,保存指向此类昂贵对象的值的指针,并在需要时从池( channel )中接收一个。使用完毕后,将其放回池中(在 channel 上发送)。为避免意外丢失对象(例如在紧急情况下),请在放回对象时使用 defer 语句。
让我们使用它作为我们的大对象的类型:
type BigObject struct {
Id int
Something string
}
创建一个池是:
pool := make(chan *BigObject, 10)
池的大小就是 channel 缓冲区的大小。
用昂贵对象的指针填充池(这是可选的,请参阅末尾的注释):
for i := 0; i < cap(pool); i++ {
bo := &BigObject{Id: i}
pool <- bo
}
许多 goroutine 使用池:
wg := sync.WaitGroup{}
for i := 0; i < 100; i++ {
wg.Add(1)
go func() {
defer wg.Done()
bo := <-pool
defer func() { pool <- bo }()
fmt.Println("Using", bo.Id)
fmt.Println("Releasing", bo.Id)
}()
}
wg.Wait()
在 Go Playground 上试用.
请注意,如果所有“池化”对象都在使用中,则此实现会阻塞。如果你不想这样,你可以使用 select 来强制创建新对象,如果所有对象都在使用中:
var bo *BigObject
select {
case bo = <-pool: // Try to get one from the pool
default: // All in use, create a new, temporary:
bo = &BigObject{Id:-1}
}
在这种情况下,您无需将其放回池中。或者,如果池中有空间,您可以选择尝试将所有内容放回池中,而不会阻塞,再次使用 select:
select {
case pool <- bo: // Try to put back into the pool
default: // Pool is full, will be garbage collected
}
注意事项:
事先填充池是可选的。如果您使用 select 尝试从池中获取/放回值,则池最初可能是空的。
您必须确保不会在请求之间泄露信息,例如确保您不在共享对象中使用已设置且属于其他请求的字段和值。
关于memory-management - 如何在 Golang 中实现内存池,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38505830/
出于纯粹的兴趣,我很好奇如何按顺序创建PI,而不是在过程结果之后生成数字,而是让数字在过程本身生成时显示。如果是这种情况,那么数字可以自行产生,我可以对以前看到的数字实现垃圾收集,从而创建一个无限系列。结果只是在Pi系列之后每秒生成一个数字。这是我通过互联网筛选的结果:这是流行的计算机友好算法,类机器算法:defarccot(x,unity)xpow=unity/xn=1sign=1sum=0loopdoterm=xpow/nbreakifterm==0sum+=sign*(xpow/n)xpow/=x*xn+=2sign=-signendsumenddefcalc_pi(digits
作为我的Rails应用程序的一部分,我编写了一个小导入程序,它从我们的LDAP系统中吸取数据并将其塞入一个用户表中。不幸的是,与LDAP相关的代码在遍历我们的32K用户时泄漏了大量内存,我一直无法弄清楚如何解决这个问题。这个问题似乎在某种程度上与LDAP库有关,因为当我删除对LDAP内容的调用时,内存使用情况会很好地稳定下来。此外,不断增加的对象是Net::BER::BerIdentifiedString和Net::BER::BerIdentifiedArray,它们都是LDAP库的一部分。当我运行导入时,内存使用量最终达到超过1GB的峰值。如果问题存在,我需要找到一些方法来更正我的代
我怎样才能完成http://php.net/manual/en/function.call-user-func-array.php在ruby中?所以我可以这样做:classAppdeffoo(a,b)putsa+benddefbarargs=[1,2]App.send(:foo,args)#doesn'tworkApp.send(:foo,args[0],args[1])#doeswork,butdoesnotscaleendend 最佳答案 尝试分解数组App.send(:foo,*args)
如何在buildr项目中使用Ruby?我在很多不同的项目中使用过Ruby、JRuby、Java和Clojure。我目前正在使用我的标准Ruby开发一个模拟应用程序,我想尝试使用Clojure后端(我确实喜欢功能代码)以及JRubygui和测试套件。我还可以看到在未来的不同项目中使用Scala作为后端。我想我要为我的项目尝试一下buildr(http://buildr.apache.org/),但我注意到buildr似乎没有设置为在项目中使用JRuby代码本身!这看起来有点傻,因为该工具旨在统一通用的JVM语言并且是在ruby中构建的。除了将输出的jar包含在一个独特的、仅限ruby
我正在使用的第三方API的文档状态:"[O]urAPIonlyacceptspaddedBase64encodedstrings."什么是“填充的Base64编码字符串”以及如何在Ruby中生成它们。下面的代码是我第一次尝试创建转换为Base64的JSON格式数据。xa=Base64.encode64(a.to_json) 最佳答案 他们说的padding其实就是Base64本身的一部分。它是末尾的“=”和“==”。Base64将3个字节的数据包编码为4个编码字符。所以如果你的输入数据有长度n和n%3=1=>"=="末尾用于填充n%
exe应该在我打开页面时运行。异步进程需要运行。有什么方法可以在ruby中使用两个参数异步运行exe吗?我已经尝试过ruby命令-system()、exec()但它正在等待过程完成。我需要用参数启动exe,无需等待进程完成是否有任何rubygems会支持我的问题? 最佳答案 您可以使用Process.spawn和Process.wait2:pid=Process.spawn'your.exe','--option'#Later...pid,status=Process.wait2pid您的程序将作为解释器的子进程执行。除
鉴于我有以下迁移:Sequel.migrationdoupdoalter_table:usersdoadd_column:is_admin,:default=>falseend#SequelrunsaDESCRIBEtablestatement,whenthemodelisloaded.#Atthispoint,itdoesnotknowthatusershaveais_adminflag.#Soitfails.@user=User.find(:email=>"admin@fancy-startup.example")@user.is_admin=true@user.save!ende
我正在为一个项目制作一个简单的shell,我希望像在Bash中一样解析参数字符串。foobar"helloworld"fooz应该变成:["foo","bar","helloworld","fooz"]等等。到目前为止,我一直在使用CSV::parse_line,将列分隔符设置为""和.compact输出。问题是我现在必须选择是要支持单引号还是双引号。CSV不支持超过一个分隔符。Python有一个名为shlex的模块:>>>shlex.split("Test'helloworld'foo")['Test','helloworld','foo']>>>shlex.split('Test"
我实际上是在尝试使用RVM在我的OSX10.7.5上更新ruby,并在输入以下命令后:rvminstallruby我得到了以下回复:Searchingforbinaryrubies,thismighttakesometime.Checkingrequirementsforosx.Installingrequirementsforosx.Updatingsystem.......Errorrunning'requirements_osx_brew_update_systemruby-2.0.0-p247',pleaseread/Users/username/.rvm/log/138121
这可能是个愚蠢的问题。但是,我是一个新手......你怎么能在交互式rubyshell中有多行代码?好像你只能有一条长线。按回车键运行代码。无论如何我可以在不运行代码的情况下跳到下一行吗?再次抱歉,如果这是一个愚蠢的问题。谢谢。 最佳答案 这是一个例子:2.1.2:053>a=1=>12.1.2:054>b=2=>22.1.2:055>a+b=>32.1.2:056>ifa>b#Thecode‘if..."startsthedefinitionoftheconditionalstatement.2.1.2:057?>puts"f