- 浏览: 4821405 次
- 性别:
- 来自: 上海
博客专栏
-
robbin谈管理
浏览量:137058
文章分类
最新评论
-
xly1981:
领导者是团队的灵魂。深入一线的过程,包括代码review,能帮 ...
robbin谈管理:改造团队的经验(2) -
jiehuangwei:
像这种总结比较性的ppt文档可以多发啊
Web并发模型粗浅探讨 -
linux1308:
看完学习到了很多东西,感谢推荐!
推荐一篇很好的RoR部署方案性能评测 -
zweite:
直接对搜索的结果进行缓存是不是会更快一点呢
漫谈应用缓存的命中率问题 -
kaogua:
现在已经是ruby2.0了, 不知道这个的效率是怎么样的, 是 ...
Ruby作为服务器端应用已经成熟了
Ruby虽然是动态脚本语言,但是和Java一样,带有VM,有自己的内存堆,创建对象的时候在堆里面分配内存,对象使用完毕由GC进行回收。但是通过我们运营Rails网站两年多的实践来看,Ruby VM的GC还是存在很大的问题。简单的来说,就是GC之后,尽管对象已经完全回收,但是物理内存释放不够充分,有泄漏的现象。通过pmap来dump ruby进程物理内存地址映射表进行分析,观察到ruby的内存堆总是在不停的扩张,GC之后回收不干净。而我对比观察Java VM,其Full GC之后,物理内存释放的非常干净。所以用Ruby做服务器长期的跑,就会发现Ruby进程没有理由的缓慢泄漏内存,内存堆缓慢增长,貌似没有上限。
由于pmap命令可以dump进程的内存映射表,因此我们可以对比RubyVM和JVM在GC前后的内存映射情况。比方说Ruby的内存状况大概是这样的:
下图是一个Ruby进程的物理内存映射表,堆内存占据的空间是我抽取出来的三行:
可以看出来Ruby的堆内存分配比较连续,分段不多。而JVM的堆内存分配段就很多了,由于堆地址段太多,我就不贴出来了,大家可以自己观察。
由于Ruby的内存分配算法和回收算法还是比较原始的,因此在进行多次回收之后,内存堆很容易出现大量的内存碎片,很多内存碎片并不能够被有效的利用,并且ruby没有好的碎片归并压缩算法,因此碎片造成的内存堆地址空间浪费就会越来越大。其结果就是Ruby进程在长期高负载运行之下,表现出缓慢的内存泄漏现象!
对比JVM的堆分配,他分配了很多的段,每个段的内存存活期不一样,根据分代算法,可以把不同存活期的对象在堆之间移动,堆内部则进行碎片归并。比方说我对一个Tomcat应用服务器的实际应用先pmap记录内存映射,然后GC,再pmap记录内存映射,两者diff一下,就可以发现某些堆在收缩,但是某些堆甚至在GC后扩张了,这便是对象在堆之间进行移动的现象。因此我不得不赞赏一下JVM的内存分配。
话说回来,由于Ruby的VM内存分配的碎片问题,导致Ruby进程几乎无可避免的内存泄漏。其结果就是你必须实时监控Ruby进程的运行情况,一旦发现内存使用超过限额,则必须果断的杀掉进程重起。比方说现在很多流行的Rails网站都是用monit去监控mongrel实例,一旦发现内存使用超过限额就杀掉重起。这种监控方式虽然可以有效的解决ruby的内存泄漏问题,但是太过简单粗暴,如果杀掉进程重起的时候,Ruby进程正好在处理请求,那么该请求是肯定会失败掉的,对于一些极端的情况,似乎很难令人接受这种现象的存在。我现在没有用monit,而是自己写shell脚本来监控(写几行shell就可以搞定的事情没必要那么麻烦搞什么monit),每天大概能出现两三次这种需要杀掉重起的情况,对比每天要处理将近100 万动态请求来说,可靠性还是达到了99.999%,还算可以。
那么将于今年年底发布的ruby 1.9.1能够解决这个问题吗? 答案是悲观的,1.9的GC并没有本质的提高,可以预见还是会出现无可避免的内存泄漏问题。但是1.9的内存泄漏会比现在的1.8要轻微一些,原因是1.9会对堆空间的内存碎片从小到大进行排序,因此对于内存碎片的利用率要高一些,再加上1.9的GC相对来说更积极主动一些,因此在一定程度上可以减轻内存碎片问题。
但不管怎么说,在可以预见的未来,Ruby的内存泄漏问题无可避免,我们还是要做好动不动杀掉ruby进程重起的准备。所以你要好好操练一下monit,或者像我一样,写个shell脚本进行监控,用crontab每隔几分钟跑一下。
我们的Rails部署方式是lighttpd+fcgi,用Unix Socket通信,监控脚本示例如下:
之前有关注过这个VM,看FAQ不能在64位系统上运行,而我们目前网站是运行在64位操作系统上。
这个VM配合mod_rails比较合适用来做虚拟主机提供rails host服务
而Rails 2.2的线程安全也应该有这方面的考虑
找个时间试试Ruby Enterprise Editio,谢谢推荐。
由于pmap命令可以dump进程的内存映射表,因此我们可以对比RubyVM和JVM在GC前后的内存映射情况。比方说Ruby的内存状况大概是这样的:
下图是一个Ruby进程的物理内存映射表,堆内存占据的空间是我抽取出来的三行:
00000000005d4000 125260K rwx-- [ anon ] 0000002a95c23000 23456K rw--- [ anon ] 0000002a99186000 50980K rw--- [ anon ]
0000000000400000 760K r-x-- /usr/local/ruby/bin/ruby 00000000005bd000 92K rw--- /usr/local/ruby/bin/ruby 00000000005d4000 125260K rwx-- [ anon ] 0000002a95556000 84K r-x-- /lib64/ld-2.3.3.so 0000002a9556b000 12K rw--- [ anon ] 0000002a9556e000 24K r--s- /usr/lib64/gconv/gconv-modules.cache 0000002a95574000 4K rw--- [ anon ] 0000002a95577000 12K rw--- [ anon ] 0000002a9557a000 204K r---- /usr/lib/locale/en_US.utf8/LC_CTYPE 0000002a9566a000 12K rw--- /lib64/ld-2.3.3.so 0000002a9566d000 8K r-x-- /lib64/libdl.so.2 0000002a9566f000 1024K ----- /lib64/libdl.so.2 0000002a9576f000 4K rw--- /lib64/libdl.so.2 ......
可以看出来Ruby的堆内存分配比较连续,分段不多。而JVM的堆内存分配段就很多了,由于堆地址段太多,我就不贴出来了,大家可以自己观察。
由于Ruby的内存分配算法和回收算法还是比较原始的,因此在进行多次回收之后,内存堆很容易出现大量的内存碎片,很多内存碎片并不能够被有效的利用,并且ruby没有好的碎片归并压缩算法,因此碎片造成的内存堆地址空间浪费就会越来越大。其结果就是Ruby进程在长期高负载运行之下,表现出缓慢的内存泄漏现象!
对比JVM的堆分配,他分配了很多的段,每个段的内存存活期不一样,根据分代算法,可以把不同存活期的对象在堆之间移动,堆内部则进行碎片归并。比方说我对一个Tomcat应用服务器的实际应用先pmap记录内存映射,然后GC,再pmap记录内存映射,两者diff一下,就可以发现某些堆在收缩,但是某些堆甚至在GC后扩张了,这便是对象在堆之间进行移动的现象。因此我不得不赞赏一下JVM的内存分配。
话说回来,由于Ruby的VM内存分配的碎片问题,导致Ruby进程几乎无可避免的内存泄漏。其结果就是你必须实时监控Ruby进程的运行情况,一旦发现内存使用超过限额,则必须果断的杀掉进程重起。比方说现在很多流行的Rails网站都是用monit去监控mongrel实例,一旦发现内存使用超过限额就杀掉重起。这种监控方式虽然可以有效的解决ruby的内存泄漏问题,但是太过简单粗暴,如果杀掉进程重起的时候,Ruby进程正好在处理请求,那么该请求是肯定会失败掉的,对于一些极端的情况,似乎很难令人接受这种现象的存在。我现在没有用monit,而是自己写shell脚本来监控(写几行shell就可以搞定的事情没必要那么麻烦搞什么monit),每天大概能出现两三次这种需要杀掉重起的情况,对比每天要处理将近100 万动态请求来说,可靠性还是达到了99.999%,还算可以。
那么将于今年年底发布的ruby 1.9.1能够解决这个问题吗? 答案是悲观的,1.9的GC并没有本质的提高,可以预见还是会出现无可避免的内存泄漏问题。但是1.9的内存泄漏会比现在的1.8要轻微一些,原因是1.9会对堆空间的内存碎片从小到大进行排序,因此对于内存碎片的利用率要高一些,再加上1.9的GC相对来说更积极主动一些,因此在一定程度上可以减轻内存碎片问题。
但不管怎么说,在可以预见的未来,Ruby的内存泄漏问题无可避免,我们还是要做好动不动杀掉ruby进程重起的准备。所以你要好好操练一下monit,或者像我一样,写个shell脚本进行监控,用crontab每隔几分钟跑一下。
我们的Rails部署方式是lighttpd+fcgi,用Unix Socket通信,监控脚本示例如下:
#!/bin/sh . /etc/profile.local RUBY_HEAP_MIN_SLOTS=600000 RUBY_HEAP_SLOTS_INCREMENT=600000 RUBY_HEAP_FREE_MIN=100000 RUBY_GC_MALLOC_LIMIT=60000000 RAILS_ENV=production export RUBY_HEAP_MIN_SLOTS RUBY_HEAP_SLOTS_INCREMENT RUBY_GC_MALLOC_LIMIT RUBY_HEAP_FREE_MIN RAILS_ENV SPAWN=/usr/local/lighttpd/bin/spawn-fcgi DISPATCH_PATH=/.../yourrailsapp/public/dispatch.fcgi SOCKET_PATH=/yourlighttpd/socket PID_PATH=/yourlighttpd/pids RSS_MAX=307200 for PSDATA in `ps -e v | grep dispatch.fcgi | awk '{print $1 ":" $8 }'` do RSS=${PSDATA#*:} PID=${PSDATA%:*} if [ $RSS -ge $RSS_MAX ]; then echo echo `date` echo "----------------------------------------" echo "PID["$PID"]: RSS="$RSS"KB is too big!" for num in 0 1 2 3 4 5 6 7 8 9 do if [ $PID -eq `cat $PID_PATH/javaeye.pid-$num` ]; then echo "PID["$PID"] using socket: "$num kill -9 $PID rm -rf $SOCKET_PATH/javaeye.socket-$num $SPAWN -f $DISPATCH_PATH -s $SOCKET_PATH/javaeye.socket-$num -P $PID_PATH/javaeye.pid-$num fi done fi done sleep 10 for num in 0 1 2 3 4 5 6 7 8 9 do if [ ! -d /proc/`cat $PID_PATH/javaeye.pid-$num` ]; then echo echo "Ruby Server using socket: "$num" had been crashed, need to be starting..." rm -rf $SOCKET_PATH/javaeye.socket-$num $SPAWN -f $DISPATCH_PATH -s $SOCKET_PATH/javaeye.socket-$num -P $PID_PATH/javaeye.pid-$num fi done
评论
11 楼
sevk
2012-01-19
JAVA开源不,把JAVA的GC移植到RUBY里来。
linux就是好,可以像组装机一样自己选择GC。
java的thread也不错,也可以鉴戒,开源就是好。
linux就是好,可以像组装机一样自己选择GC。
java的thread也不错,也可以鉴戒,开源就是好。
10 楼
liangshixing
2008-11-23
为什么不用JRuby呢?
9 楼
chengj
2008-09-09
ruby要进入企业级的应用还有很长的一段路要走。使用ROR开发的感觉确实畅快,但是现在不得不退回到java,虽然心有不甘,但是没有办法,先观望一段时间,希望ruby走好。
8 楼
t0uch
2008-09-05
按mod_rails的作者来说
改进是很明显的
但是,近来想把这个gc算法patch到ruby core搞定似乎是很困难了
改进是很明显的
引用
This has huge performance implications. The copy-on-write friendly mark table makes the garbage collector about 0%-20% slower, depending on the application and the workload. However, the non-copy-on-write friendly mark table is enabled by default, so by default there is only a 1% performance penalty. This performance penalty comes from the fact that marking an object now requires a function call which sets the mark flag, instead of setting the mark flag directly. But I think 1% is acceptable.
但是,近来想把这个gc算法patch到ruby core搞定似乎是很困难了
引用
Unfortunately the discussion stranded. Matz had some concerns about performance, which is why I made the mark table implementation pluggable. I will re-submit the patch for further evaluation when the time is right.
7 楼
leondu
2008-09-05
嗯,你说的这个就是Enterprise Ruby(很雷的名字...他们也说要选个更适合的名字),Matz说“考虑”加入到core中,但是好像没下文了。
pluskid 写道
phusion passenger (mod_rails) 的作者好像就做过改进 GC 的工作,也提交了一些补丁到 Ruby core 。不知道改进明显不明显。
6 楼
pluskid
2008-09-03
phusion passenger (mod_rails) 的作者好像就做过改进 GC 的工作,也提交了一些补丁到 Ruby core 。不知道改进明显不明显。
5 楼
QuakeWang
2008-09-03
yawl 写道
mod_rails的作者也做了个Ruby Enterprise Editio (http://www.rubyenterpriseedition.com/ ),基本上就是改进了GC.用了一阵子了一直很稳定,但我们的流量流量都没有javaeye这么大.
之前有关注过这个VM,看FAQ不能在64位系统上运行,而我们目前网站是运行在64位操作系统上。
引用
Ruby Enterprise Edition is a bit faster than standard Ruby, because of the improved memory allocator. However, this memory allocator does not work on 64-bit platforms. As a result, on 64-bit platforms, Ruby Enterprise Edition is slightly slower than standard Ruby (by a few percent). How much slower depends on the application and workload.
这个VM配合mod_rails比较合适用来做虚拟主机提供rails host服务
而Rails 2.2的线程安全也应该有这方面的考虑
4 楼
robbin
2008-09-03
yawl 写道
mod_rails的作者也做了个Ruby Enterprise Editio (http://www.rubyenterpriseedition.com/ ),基本上就是改进了GC.用了一阵子了一直很稳定,但我们的流量流量都没有javaeye这么大.
我的一个做JVM的朋友按照JVM的实现也重写过ruby gc,效果也很好.但只能限于proof of concept,没有时间和经历去雕琢.
我的一个做JVM的朋友按照JVM的实现也重写过ruby gc,效果也很好.但只能限于proof of concept,没有时间和经历去雕琢.
找个时间试试Ruby Enterprise Editio,谢谢推荐。
3 楼
yawl
2008-09-03
mod_rails的作者也做了个Ruby Enterprise Edition (http://www.rubyenterpriseedition.com/ ),基本上就是改进了GC.用了一阵子了一直很稳定,但我们的流量都没有javaeye这么大.
我的一个做JVM的朋友按照JVM的实现也重写过ruby gc,效果也很好.但只能限于proof of concept,没有时间和经历去雕琢.
我的一个做JVM的朋友按照JVM的实现也重写过ruby gc,效果也很好.但只能限于proof of concept,没有时间和经历去雕琢.
2 楼
iceskysl
2008-09-03
RSS_MAX=307200
--这个值是哪里得来的?经验?
--这个值是哪里得来的?经验?
1 楼
iceskysl
2008-09-03
简单粗暴是针对问题最直接的解决办法。
发表评论
-
《松本行弘的程序世界》推荐序
2011-07-21 13:47 15259在流行的编程语言中,ruby是一个比较另类的存在,这是因为大多 ... -
从Rails聊聊小公司的研发团队建设
2011-03-23 10:49 37212首先分享一点数据吧: JavaEye的PV到了140万了,一 ... -
Ruby作为服务器端应用已经成熟了
2009-11-17 14:55 15931JavaEye网站在过去的Ruby on rails实践当中, ... -
基于资源的HTTP Cache的实现介绍
2009-09-05 00:27 17046我们都知道浏览器会缓 ... -
请注意Rails2.3自带的memcache-client有性能问题
2009-03-23 18:05 14473Rails2.3版本发布了,这个版本内部的改动非常大,相关介绍 ... -
监视Rails进程内存泄漏的技巧
2008-12-30 21:56 10950Rails应用比较容易遇到的两类性能问题:一类是Rails执行 ... -
ruby MBARI大补丁性能评测报告
2008-12-23 12:19 5068JavaEye之前的新闻ruby内存泄漏的罪魁祸首 - 幽灵指 ... -
在top监视窗口显示Rails当前正在执行的请求URL
2008-12-01 14:15 9856这是一个从PragDave的博客上面学来的技巧,很实用,很co ... -
推荐一篇很好的RoR部署方案性能评测
2008-07-08 11:55 9633今年年初的时候,我写了一篇RoR部署方案深度剖析的文章,分析了 ... -
Ruby和Rails的缺点
2008-06-25 21:08 17400有人说,robbin你说了那么多RoR的优点,你啥时候说说Ro ... -
Skynet --- ruby的类Google Map/Reduce框架
2008-06-02 00:39 8294Skynet是一个很响亮的名 ... -
rmmseg-cpp - 简洁高效的ruby中文分词程序
2008-05-27 00:47 11234我在前一篇文章向大家 ... -
使用libmmseg实现Ruby的中文分词功能
2008-05-24 21:43 11323用Ruby on Rails开发web2.0网站的人都知道,r ... -
mod_rails尝鲜
2008-04-13 14:32 8079Passenger(俗称mod_rails)是 ... -
Lighttpd和RoR安装配置的疑难解答
2008-03-07 11:09 14841之前写过一篇在Linux平 ... -
JavaEye网站的RoR性能优化经验谈
2008-01-20 16:11 18441JavaEye网站从2006年9月11 ... -
RoR部署方案深度剖析
2008-01-14 03:10 14776RoR的部署方案可谓五花八门,有Apache/Fastcgi方 ... -
RoR网站如何利用lighttpd的X-sendfile功能提升文件下载性能
2008-01-12 17:45 10251传统的Web服务器在处理文件下载的时候,总是先读入文件内容到应 ... -
Ruby为什么会受程序员的欢迎?
2008-01-07 20:08 15751孟岩最近写了一篇博客 ... -
Ruby on Rails 2.0的新特性介绍
2007-12-10 21:32 15617万众瞩目的Ruby on Rails 2.0已经发布了,Rai ...
相关推荐
RubyVM的设计目标是提供一个可扩展且高效的平台,让开发者能够深入理解Ruby的内部工作原理,并可以根据需要对其进行定制和优化。这个“乐高玩具套装”的比喻意味着RubyVM允许开发者像拼装积木一样,自由组合和构建...
在日常开发中,`rbenv`和`ruby-build`组合提供了对Ruby版本的精细控制,使得开发者可以轻松地在不同项目之间切换,避免了版本冲突的问题。此外,它们还支持安装一些特定的patched Ruby版本,如JRuby和Truffleruby,...
Ruby Ruby Ruby Ruby Ruby Ruby
1. **YARV虚拟机优化**:Ruby 2.6.1基于YARV(Yet Another Ruby VM)虚拟机,这个版本对YARV进行了优化,提高了整体性能,尤其是对于CPU密集型的任务。 2. **编译器优化**:Ruby 2.6引入了新的编译器框架,使得语法...
8. **YARV虚拟机优化**:Ruby 2.0继续使用YARV(Yet Another Ruby VM)作为其虚拟机,但进行了多方面的优化,提高了整体性能。 压缩包内的"ruby-2.0.0-p0"可能包含了完整的Ruby解释器、标准库、开发工具以及相关的...
在性能方面,Ruby 2.2.4增强了YARV(Yet Another Ruby VM)虚拟机,提升了代码执行速度。同时,它还修复了一些已知的安全漏洞,提高了整体的系统稳定性。 Ruby 2.2.4还支持新的语法特性,如Numeric Literal Ranges...
例如,YARV(Yet Another Ruby VM)虚拟机的优化使得代码执行更高效。 2. **钻石操作符(>>>)**:Ruby 2.1引入了钻石操作符,用于解决多重继承中的方法解析顺序问题。这个符号使得类可以明确指定从哪个父类继承...
ruby DBI ruby DBI ruby DBIruby DBI ruby DBI ruby DBIruby DBI ruby DBI ruby DBIruby DBI ruby DBI ruby DBIruby DBI ruby DBI ruby DBIruby DBI ruby DBI ruby DBIruby DBI ruby DBI ruby DBIruby DBI ruby DBI ...
在Ruby的早期版本中,这个虚拟机被称为YARV(Yet Another Ruby VM),它是Ruby 1.9版本的虚拟机。书中对Ruby 2.x、1.9和1.8版本都有所覆盖,让读者可以了解到Ruby发展的不同阶段。 另一个值得探讨的部分是Ruby的...
通过USDT导出Ruby VM(MRI)堆栈和对象分配计数跟踪,以进行tracecap提取。 分析代码的设计和实现很大程度上受启发。 安装 将此行添加到您的应用程序的Gemfile中: gem 'tracecap_profiler' 然后执行: $ bundle...
这个版本对Ruby的语法进行了改进,包括更好的错误处理机制,增强了Unicode支持,以及对YARV(Yet Another Ruby VM)虚拟机的优化,使得代码执行速度有所提升。此外,1.9.3还引入了新的垃圾回收机制,提高了内存管理...
Ruby Hacking Guide是一本探讨C Ruby实现的书,这次发布的部分包括对全书的介绍和本书的第一部分。第一部分的内容包括对Ruby语言一个概要介绍和对Ruby对象模型的讲解。从我个人阅读的感觉来看,第一章对于Ruby语言的...
ruby2ruby 提供一些用来根据 RubyParser 兼容的 Sexps 轻松生成纯 Ruby 代码的方法。可在 Ruby 中轻松实现动态语言处理。 标签:ruby2ruby
本资源“ruby-v3.1.1.zip”包含了Ruby的最新版本3.1.1,这是一个重要的里程碑,因为它引入了新特性、性能优化以及对旧版本的改进。 在Ruby 3.1.1中,开发者可以期待以下关键特性: 1. **块参数解构**:Ruby 3.1...
Ruby是一种简洁而功能强大的编程语言,由日本的松本行弘(Yukihiro "Matz" Matsumoto)在1993年开发,并于...此外,由于技术不断更新,保持对最新Ruby版本的关注,以及学习相关的最佳实践和安全知识也是至关重要的。
《Ruby完全自学手册》是一本完全覆盖Ruby和Ruby on Rails的完全自学手册。《Ruby完全自学手册》的特色是由浅入深、循序渐进,注重理论和实践的结合。虽然定位为入门手册,但是依然涉及许多高级技术和应用,覆盖到的...
Ruby是一种强大的、面向对象的脚本语言,广泛用于Web开发、服务器端编程和各种应用程序。在Ruby的世界里,管理不同的Ruby实现(如MRI、JRuby、Rubinius、MagLev和MRuby)是非常重要的,这有助于开发者根据项目需求...
src-oepkgs/ruby-ruby2rubysrc-oepkgs/ruby-ruby2rubysrc-oepkgs/ruby-ruby2rubysrc-oepkgs/ruby-ruby2rubysrc-oepkgs/ruby-ruby2rubysrc-oepkgs/ruby-ruby2rubysrc-oepkgs/ruby-ruby2rubysrc-oepkgs/ruby-ruby2...