From: nobu.nokada@... Date: 2002-04-03T10:16:47+09:00 Subject: Re: About efficiency Hi, At Wed, 3 Apr 2002 08:51:31 +0900, Jean-Hugues ROBERT wrote: > I have been enjoying Ruby for 2 weeks now. I am very impressed. It is > my understanding that currently the interpreter directly executes the > parse tree versus going thru some bytecode generation phase (the later > is what I did for some interpreter I wrote years ago, while at the > same time a friend of mine was going the ruby way, hence we had > opportunities to compare). Ruby VM is planned. > 1) Would using Symbol more be more efficient ? > While writing some debugging tool, I was surprised to discover that a function like Kernel.set_trace_func() would set > a proc that is given a "String" to describe what is happening. I would have guessed that a Symbol would obviously be > more efficient here (comparing two symbols is like comparing two pointers, whereas comparing two strings may involve > comparing byte per byte). Maybe it's not a big deal. But these are the deals that end up making things go faster I > think. Perhaps, for backward compatibility, and maybe to deal with Regexp. > 2) "xxx" versus 'xxx', which is more efficient ? > Equivalent according to Matz's recent comment. Well... I guess that when xxx does not include any special > construction, one of the two *has* to be faster than the other one, either at compile time (parse tree constuction > time I mean) or at runtime, right ? Which one ? I am used to using "xxx" but if 'xxx' is more efficient, I can use it > instead (when both are semantically equivalent). 'xxx' is faster a bit at parse, just an int comparison per byte. It's not significant. > 3) closure > I suspect that holding a closure means at least that the stack frame where the closure was created is referenced (and > not garbage collected until the closure disappears) (I hope that the caller stack frames aren't referenced, are they > ?). This may have big memory impacts, specially if the stack frame also holds references to large object. For sure it > does not hurt to do some xxx=nil when xxx is not usefull anymore. Proc doesn't hold each stack, Thread does. About an orphan Proc from dead Thread, the stack may be discardable. > 3) type induction > One day the "dynamic typing" versus "static typing" language war will be over. That day, you will have the ability to > switch smoothly from dynamic to static, during the optimization phase of your project. No need for C++ style templates > then. All you will have to do is give hints to the compiler/interpreter about the domain/type/range of variables so > that the compiler/interpreter can take advantage of that knowledge to optimize the code. I have seen that being > applied years ago in Turbo Prolog to some extend, with incredible results. Any plan for Ruby about that ? It's been discussed some times, but not implemented yet. > 4) String > For a String intensive language like Ruby, there is an optimization that could be worth implementing. It is an > optimization where a String is actually made of a reference to some potentially shared string representation, + > an_offset, + a_size. That means that many operations then do not need to copy the string anymore (you update > 'an_offset' and/or 'a_size' instead, still referencing the same 'string_representation'). Has such an optimization > been evaluated (it has almost no impacts on the external interface) ? I think this is a type of "Copy On Write" > optimization. Shugo Maeda had made a patch, but it's left yet due to the impact on the external interface mainly. > 5) Cache. > Reading the books about the implementation of Smalltalk gives some hints on how much efficient such caches can > be. Candidates are: caching (a_class,a_method_name)=>a_method. This cache alone doubled the speed of the smalltalk > interpreter ! Method cache is implemented already. > Another one is for (a_class,an_instance_variable_name)=>an_index. Assuming an object has a value (i.e. has some set of > instance variables) and if accessing that set directly is an option (with an index, i.e. versus sequentially or some > other less efficient method) then again this can speed things up a lot (in the most common cases, where objects have > instance variables layed out in the same order). You can add instance variables on the fly, the last assumption may not be correct. I considered it too, but had no good idea. > A less trivial cache is for inlining small methods. This is specially efficient for accessors. I think it is described > too in the books about the implementation of Smalltalk 80. Maybe, but it may prohibit/restrict forward reference, or gain compile time cost much. -- Nobu Nakada