锁定老帖子 主题:骂一骂Ruby
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2006-08-25
charon 写道 buaawhl 写道 Python, ErLang都有VM,都有编译步骤。right? 这样,Python, ErLang都可以脱离源码,直接用中间代码部署运行。right? Python是否动态强类型?Python的编译步骤是否进行类型检查? python可以直接用中间代码执行,而且中间代码有多种类型 python是动态强类型的。但是编译期肯定不做类型检查,连变量名都不检查 这个是动态语言的短板。就是说必须把单元测试做到弱条件组合覆盖才行(比语句覆盖要强多了),才可能杜绝语法错误 比如 ... if((a>b or c>d); and f>g);: print 'aaa' else: print 'bbb' ... 这种情形下,在编译的时候并不检查a,b,c,d,e,f的存在性,更不用说类型了。而且如果a>b,则c/d的存在与否都无关紧要(因为被短路了). 这样,在单元测试的时候必须要有执行到c>d的case,否则如果里面有语法错误,那就歇菜了 而要做到语句覆盖,只要a>b,f>g,和a>b,f<g两个情况就可以了 thanks for the clarification. Python编译的中间码都是些啥? 估计是很高级的形式,里面包括了大量的 "(a>b or c>d) and f>g"这些字符串。 |
|
返回顶楼 | |
发表时间:2006-08-25
解释器的形式有两种,一种是直接遍历AST进行计算,另外一种方式是编译成VM的指令,然后由VM解释执行。VM有两种方式,一种是Stack Machine,另外一种是register machine.
理论上的研究一直说register machine效率比较高,但实现比较困难。因此绝大多数主流VM都是Stack模型,perl6的parrot VM是少见的register模型。Ruby也可以跑在parrot上(Cardinal)。 当然编译器和VM可以进行比较高级的优化,例如direct threaded code(及其变种、增强),Stack Caching,super instruction, tail optimization, last call optimization等等,还可以进行JIT。也有编译器直接在中间码中加入native code的做法,譬如erlang的HiPE就可以做到。比较特殊的语言,例如erlang还可以在虚拟机内部实现完全不同操作系统的进程调度。这些在直接遍历AST的方法不可能做到。 但是Ruby目前有很多的虚拟机移植。包括n个ruby->CLR VM,ruby->jvm,ruby ->parrot,以及原生的YARV,所以这个问题不会太大。关键是有人用,就有人搞。 但是遍历AST的方法 ,GC是没有问题,Ruby的GC是标准的Mark&Sweep,还没有做到分代。并且需要在mark的时候直接在对象的头上flags里面标记,可能会引起不好的cache因为,因此变成Bitmap形式也许更加好一点。试验中...... |
|
返回顶楼 | |
发表时间:2006-08-25
potian 写道 解释器的形式有两种,一种是直接遍历AST进行计算,另外一种方式是编译成VM的指令,然后由VM解释执行。VM有两种方式,一种是Stack Machine,另外一种是register machine.
理论上的研究一直说register machine效率比较高,但实现比较困难。因此绝大多数主流VM都是Stack模型,perl6的parrot VM是少见的register模型。Ruby也可以跑在parrot上(Cardinal)。 当然编译器和VM可以进行比较高级的优化,例如direct threaded code(及其变种、增强),Stack Caching,super instruction, tail optimization, last call optimization等等,还可以进行JIT。也有编译器直接在中间码中加入native code的做法,譬如erlang的HiPE就可以做到。比较特殊的语言,例如erlang还可以在虚拟机内部实现完全不同操作系统的进程调度。这些在直接遍历AST的方法不可能做到。 但是Ruby目前有很多的虚拟机移植。包括n个ruby->CLR VM,ruby->jvm,ruby ->parrot,以及原生的YARV,所以这个问题不会太大。关键是有人用,就有人搞。 但是遍历AST的方法 ,GC是没有问题,Ruby的GC是标准的Mark&Sweep,还没有做到分代。并且需要在mark的时候直接在对象的头上flags里面标记,可能会引起不好的cache因为,因此变成Bitmap形式也许更加好一点。试验中...... 虽然不能完全看懂,但是受益不少。 |
|
返回顶楼 | |
发表时间:2006-08-26
charon 写道
symbol确实对新接触ruby的人看上去比较古怪。习惯了就好,只是个name罢了。ruby的string每个都是单独对象(哪怕内容一样),内存利用上不经济。 buaawhl 写道 Python编译的中间码都是些啥? 估计是很高级的形式,里面包括了大量的 "(a>b or c>d) and f>g"这些字符串。 Python Byte Code Instructions |
|
返回顶楼 | |
发表时间:2006-08-26
cookoo 写道 charon 写道
symbol确实对新接触ruby的人看上去比较古怪。习惯了就好,只是个name罢了。ruby的string每个都是单独对象(哪怕内容一样),内存利用上不经济。 如果内容一样,C字符串char * 是共享的, Struct RString是字符串类String和子类的实例的结构。 330 struct RString { 331 struct RBasic basic; 332 long len; 333 char *ptr; 334 union { 335 long capa; 336 VALUE shared; 337 } aux; 338 }; 339 (ruby.h); aux.shared利用已有的字符串文本加快字符串对象的创建,当然也可以节约大量的内存空间,如果一样的话。我们可以看看下面这段Ruby代码: while true do str = "head" str.concat("tail"); end 这是一个无穷的循环。每一次都需要创建一个单独的字符串对象,它的内容是”head”,然后加上”tail”,变成”headtail“,而每个字符串对象都持有一个不同的char[]。 如果不共享的话就会有无数份拷贝,但字符串内容实际上却没有发生任何改变。 aux.shared可以使用同一字符串文本的字符串对象共享同一份char[]。如果其中某一个共享的字符串要发生变化,那么字符串首先复制到一个块不共享的内存,然后对这个新的copy进行改变。这是标准的”copy-on-write”做法。在使用一份共享的char[]时,对象结构的basic.flags中的标志ELTS_SHARED位被置上,而aux.shared就指向那个原始的对象。 |
|
返回顶楼 | |
发表时间:2006-08-26
potian你说的有道理,受教了。我另外做了如下试验:
a = [] (1..10**5);.each {|x| a << 'hello'} 内存涨了大约3M b = [] (1..10**5);.each {|x| b << 'hello'.concat(x.to_s);} 区别只是b中每个串都不同,这回内存涨了大约9M。 而通过 c = '' (1..10**5);.each {|x| c << x.to_s} 说明这么多不同部分一共也就增加1M不到,内存节约还是明显的。 |
|
返回顶楼 | |
发表时间:2006-08-26
引用 ruby的string每个都是单独对象(哪怕内容一样),内存利用上不经济 觉得cookoo中的了 |
|
返回顶楼 | |
发表时间:2006-08-28
liuyifan.com 写道 觉得cookoo中的了 什么意思?看不懂这中文啊 |
|
返回顶楼 | |
发表时间:2006-08-28
cookoo 写道 liuyifan.com 写道 觉得cookoo中的了 什么意思?看不懂这中文啊 符号扯了这么多,还是你一句中的的说。。。 |
|
返回顶楼 | |
发表时间:2006-08-29
cookoo 写道 potian你说的有道理,受教了。我另外做了如下试验:
a = [] (1..10**5);.each {|x| a << 'hello'} 内存涨了大约3M b = [] (1..10**5);.each {|x| b << 'hello'.concat(x.to_s);} 区别只是b中每个串都不同,这回内存涨了大约9M。 而通过 c = '' (1..10**5);.each {|x| c << x.to_s} 说明这么多不同部分一共也就增加1M不到,内存节约还是明显的。 irb(main);:001:0> a = b = 'hello' => "hello" irb(main);:002:0> a.object_id => -606923358 irb(main);:003:0> b.object_id => -606923358 irb(main);:004:0> c = 'hello' => "hello" irb(main);:005:0> c.object_id => -606933008 如果先把'hello'保存在一个变量里,再加到到Array里面,应该和Symbol效果相近了吧。 |
|
返回顶楼 | |