最近aaron发表了一篇博客:[url=http://blog.hungrymachine.com/2008/11/8/how-to-save-100m-of-ram-per-mongrel]让每个mongrel节约100M内存[/url],我觉得值得翻译一下。
---翻译开始的分割线---
我们注意到运行一个rails应用的mongrel在一启动就使用了244M内存
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
53749 some_user 15 0 337m 244m 2912 S 0 2.0 0:17.49 mongrel_rails
通过运行[url=http://blog.evanweaver.com/files/doc/fauna/bleak_house/files/README.html]Bleakhouse[/url](一个用于检测ruby内存泄漏的工具),我们发现有超过200,000个对象被创建了出来:
$ BLEAK_HOUSE=1 ruby-bleak-house ./script/runner 'puts 1'
** Bleakhouse: installed
1
** BleakHouse: working...
** BleakHouse: complete
** Bleakhouse: Run 'bleak /tmp/bleak.53749.0.dump' to analyze.
$ bleak /tmp/bleak.53749.0.dump
Displaying top 20 most common line/class pairs
2,047,025 total objects
2,047,025 filled heap slots
2,403,764 free heap slots
1779063 __null__:__null__:__node__
197423 __null__:__null__:String
16519 __null__:__null__:Array
12728 __null__:__null__:ActionController::Routing::DividerSegment
10495 __null__:__null__:Hash
5676 __null__:__null__:ActionController::Routing::StaticSegment
5436 __null__:__null__:Class
5132 __null__:__null__:Regexp
4525 __null__:__null__:ActionController::Routing::DynamicSegment
2524 __null__:__null__:ActionController::Routing::Route
1307 __null__:__null__:Gem::Version
可以看到其中有非常多的对象是ActionController::Routing,于是我使用了一个空白的routes.rb,结果:
519,307 total objects
519,307 filled heap slots
233,503 free heap slots
啊哈...有150,000个对象是因为route造成的,我知道我们的应用有很多restful/nested resource,但是没有想到它是如此的疯狂:
$ rake routes | wc -l
2516
通过进一步的观察,我发现可能是由于每个resource会生成formatted_*这样的route,其实我们的应用中很少使用这些route,于是作了个monkey patch:
ActionController::Routing::RouteSet::Mapper.class_eval do
protected
def map_unnamed_routes(map, path_without_format, options)
map.connect(path_without_format, options)
#map.connect("#{path_without_format}.:format", options)
end
def map_named_routes(map, name, path_without_format, options)
map.named_route(name, path_without_format, options)
#map.named_route("formatted_#{name}", "#{path_without_format}.:format", options)
end
end
原先应用中使用到部分的formatted_* route用手工添加,现在通过bleakhouse,发现少创建了80,000个对象:
$ bleak /tmp/bleak.56554.0.dump
1,242,796 total objects
1,242,796 filled heap slots
1,224,309 free heap slots
内存从244m 下降到了 156m
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
56554 someuser 15 0 249m 156m 2912 S 0 1.3 0:09.92 mongrel_rails
这不是一个很简洁的解决方法,但是它让每个mongrel节约了100M内存,并且启动时间减少了50%
你的Rails应用是否也有那么多的resource?是否也有内存使用过多的问题?试试看这个解决方法把。
---翻译结束的分割线---
从这篇文章我们可以学到如何用bleakhouse检查内存泄漏,以及一些试验方法,不过routes如此耗费内存倒是让我觉得非常吃惊,准备在JavaEye上也试验看看。
另外针对生成大量的route,rails的issue tracker上已经有了一个补丁,让actions和formatted变成可选项:
[url]http://rails.lighthouseapp.com/projects/8994/tickets/1215-add-actions-and-formatted-options-to-mapresources[/url]
预计将会在下一版本加入rails