Successfully reported this slideshow.

Method Shelters : Another Way to Resolve Class Extension Conflicts

1

Share

Loading in …3
×
1 of 54
1 of 54

More Related Content

Related Books

Free with a 14 day trial from Scribd

See all

Related Audiobooks

Free with a 14 day trial from Scribd

See all

Method Shelters : Another Way to Resolve Class Extension Conflicts

  1. 1. Method Shelters : Another Way to Resolve Class Extension Conflicts Classboxes でも Refinements でもない別のやり方 Shumpei Akai / 赤井駿平 @flexfrank
  2. 2. What I talk about today Open Class causes conflicts of methods Method Shelters resolve it!
  3. 3. % whoami  Shumpei Akai / 赤井駿平  @flexfrank  Ph.D. Student / 学生(博士課程) ◦ 東工大の千葉研 ◦ Programming Languages and Moduralization ◦ プログラミング言語とモジュール化  Today’s topic is my current research
  4. 4. Open Class  Ruby’s one of the important features  You can (re)define methods in existing classes ◦ including Object, Integer, Array, …  Frequently used in Ruby world
  5. 5. in open-uri  open-uri redefines “open” method ◦ It accepts URI open("http://penguindrum.jp/"){|f|f.read} # => Errno::ENOENT: No such file or directory require "open-uri” open("http://penguindrum.jp/"){|f|f.read} # => "<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1- transitional.dtd”…”
  6. 6. in Ruby on Rails  ActiveSupport adds various convenient methods to core classes ◦ e.g. 10.megabytes # => 10485760 1.day.ago # => Sat Jul 16 16:15:00 +0900 2011 "survival strategy".pluralize #=> "survival strategies"
  7. 7. Or Monkey Patching
  8. 8. Problem of Open Class  Methods may conflict  When One library adds a method ◦ and another library adds a method with the same name in the same class  The method defined first is vanished! ◦ depends on the order of “require” ◦ Confusing!
  9. 9. Method conflicts  I encountered about five years ago ◦ Ruby on Rails and flvtool added a method to String ◦ they used String as binary/array of int  Difficult to collaborate these two libraries ◦ I separated processes ◦ communicating via dRuby
  10. 10. Another example of conflicts  “mathn” redefines the “Integer#/” ◦ returns a Rational object ◦ Ordinary code expects “/” returns a integer  Programs get broken
  11. 11. Existing Solutions  Several module systems are proposed to resolve conflicts ◦ Selector namespaces (for Smalltalk) ◦ Classboxes (for Smalltalk and Java) ◦ Refinements (for Ruby) ◦ …
  12. 12. Refinements  Proposed by Shugo Maeda [ruby-core:33322] class Foo module MathN using MathN refine Fixnum do def foo def /(other) p1/2 quo(other) end end end end end f = Foo.new f.foo #=> (1/2) p1/2
  13. 13. Refinements (cont.)  Refinements changes behavior of methods in a lexical scope ◦ methods defined by Refinements are not enabled in indirectly called methods ◦ No local rebinding  I need local rebinding ◦ e.g. scoped monkey patching
  14. 14. Classboxes  You might have known via matz’s diary
  15. 15. Classboxes  A classbox restrict the scope of methods  A classbox can import a class in another classbox ◦ You can use an imported class ◦ You can add/redefine methods to the imported class ◦ A redefined method can be called from the imported class  Local rebinding property
  16. 16. Classboxes Cited from “Classbox/J: Controlling the Scope of Change in Java”
  17. 17. The Problem in Classboxes  Importing overwrites internally used classes ◦ Importing causes another conflict
  18. 18. The Problem in Classboxes Redefines Original Integer#div Integer Uses redefined Use original Integer#div Integer returns rational Oops! returns integer
  19. 19. I need another module system  A new module should: ◦ have local rebinding ◦ provide a way to resolve conflicts cause by importing ◦ not depends on the order of load
  20. 20. Method Shelters
  21. 21. Key concept Hide your methods Hide your imports
  22. 22. What is a method shelter  A method shelter is a module which provides a scope of methods ◦ define methods in a method shelter ◦ import other method shelters  You can call methods in the imported shelter  You can call methods in the shelter which is importing the current shelter  for local rebinding call importee call importer
  23. 23. A Code with Method Shelters shelter :MathN do class Fixnum # fixed size integer in Ruby def /(x) Rational(self,x) end end end shelter :Average do class Array def avg sum = self.inject(0){|r,i|r+i} sum / self.size end end hide import :MathN end
  24. 24. What conforms a method shelter  A method shelter is separated into tow parts ◦ An exposed chamber and a hidden chamber ◦ in order to protect internally used methods ◦ Each chamber can define methods and import - Exposed - Hidden
  25. 25. Exposed Chambers S0 - Obj#m0  for public API  Exposed methods ◦ Visible from importer ◦ Importer can call or redefine exposed S1 methods  Exposedly import ◦ Transitive importing ◦ Imported methods are S2 also visible from importer
  26. 26. Hidden chamber S0 - Obj#m1 - Obj#m0  for internally used methods  Hidden method S1 ◦ invisible in importing shelter  Hiddenly import S2 ◦ Imported methods are not exposed
  27. 27. Global Methods  Ordinal methods not in shelters ◦ Callable from any shelter ◦ Global methods can call methods in a shelter if the caller is in the shelter Global - Obj#g0 S0 obj.g0()
  28. 28. No Ambiguity  If 2+ methods are found in imported shelters S3 - C#m0 ◦ Error! S1 S2 - C#m0 S0 Error!
  29. 29. Syntax  I don’t want to edit parse.y  define methods in a block shelter :ShelterName do class Foo def hoge # <- defined in the method shelter end end end
  30. 30. Syntax: Import shelter :ShelterName do import :AnotherShelterName end
  31. 31. Syntax: hide  “hide” method switches a chamber ◦ do def or import below “hide” shelter :ShelterName do # exposed chamber hide # hidden chamber end
  32. 32. Evaluate  Evaluate within a shelter shelter_eval :ShelterName do #shelter is enabled end
  33. 33. Method Lookup Algorithm  1. look up hidden-chamber  2. look up exposed-chamber  3. look up global methods  If not found, go to superclass
  34. 34. 8 3 7 6 2 5 1 start Global 9 4
  35. 35. Found! 1 Start Global
  36. 36. Implementation  Based on Ruby 1.9.2  Add one implicit argument to method: ◦ A node of method shelter tree
  37. 37. Optimization: Method Cache  Shelter node cache ◦ Caches method entry in a node of shelter  Extend inline cache ◦ Size of an inline cache : 3 word -> 4word (per method call) ◦ Stores the found shelter node
  38. 38. Performance: empty methods  Call a empty method 10,000,000 times ◦ Less than 5% overhead when shelters are used
  39. 39. Performance: Fibonacci  fib(33) in a method shelter ◦ Up to 20% overhead
  40. 40. Performance: Ruby on Rails  Enabled in an action method ◦ Numeric#/.*bytes?/ methods are in a shelter  In the action ◦ 1. Call one method in shelter ◦ 2. One access to SQLite via ActiveRecord  on WEBRick  Rails3
  41. 41. Performance: Ruby on Rails (result)  4% overhead on production env.  50% on development ◦ Method caches are invalidated per req. production development
  42. 42. Cache hit ratio on rails  Count shelter’s cache hit
  43. 43. Performance: tDiary 3.0.1  defined String#to_a, String#each, String#method_ missing in a shelter ◦ These are used for compatibility of 1.8 & 1.9  Ran on CGI with apache  Method shelter improved performance !! ◦ Why?
  44. 44. Why shelter made tDiary fast  String#method_missing issue  “require” calls its arg’s to_path method if defined ◦ If arg’s method_missing is defined, try to call it ◦ String#method_missing slows “require”  Method shelter restrict its negative effect
  45. 45. Other Usage: protect optimized methods  In ruby, + - * / … are optimized ◦ only if they are not redefined ◦ Redefinition slows programs  Method shelters can confine effect of redefinition  Method shelter can improve performance
  46. 46. Other Usage: shelter-private accessor  Ruby has no private instance variables  A method shelter can mimic private ivars ◦ by generating unique name ◦ Accessible within the defined shelter and visible shelters
  47. 47. class Module def shelter_accessor(name) define_method name do ivname=get_unique_name(name) self.instance_variable_get(ivname) end define_method( (name.to_s+"=").to_sym) do|val| ivname= get_unique_name(name) self.instance_variable_set(ivname,val) end end end
  48. 48. Conclusion  Open class is dangerous  Method shelters resolving conflicts ◦ With hidden methods, hiddenly importing  I implemented in Ruby ◦ Not so slow (個人的な感覚)  For more details or the source code, ◦ wait for the acceptance of my paper  Deadline: 2.days.since
  49. 49. Questions?
  50. 50. 時間が余ったら
  51. 51. Global
  52. 52.  In my lookup algorithm, ◦ Shelter must have up to one parent  For simpler semantics  For efficient implementation
  53. 53. before C B A
  54. 54. after C’ C’’ B A

×