1
Concrete Partial Evaluation in Ruby Andrew Keep Arun Chauhan Deptartment of Computer Science Indiana University {akeep,achauhan}@cs.indiana.edu Introduction Modern scientific research is a collaborative process, with researchers from many disciplines and institutions working toward a common goal. Dynamic languages, like Ruby, provide a platform for quickly developing simulation and analysis tools, freeing researchers to fo- cus on research instead of developing infrastructure. Ruby fits this role well, allowing: Incorporation of existing C libraries Simple Domain Specific Language creation Support for REST and SOAP web APIs Distributed programming, through a simplified Java RMI style library Why Ruby? Ruby is already finding a place in the scientific commu- nity and industry: MPI extension [3, 1] for quick prototyping New libraries [6, 5] support MapReduce [2] The popular Ruby on Rails framework supports REST- ful development Ruby was originally developed by Yukihiro Matsumoto (Matz), based on his favorite languages [4]. The Ruby language: Is purely object-oriented and dynamically-typed Provides open classes, allowing meta-programming Supports closures and functional programming Provides simple iterators through Ruby blocks The Challenge The power of Ruby comes at a price. The current C- based interpreter, the Matz Ruby Interpreter (MRI), suf- fers poor performance since the abstract syntax tree (AST) is used directly by the interpreter. The flexibility of Ruby complicates compilation because context affects the meaning of expressions, as illustrated below. class Fixnum def fact if self == 0 1 else self * ( self - 1). fact end end end 5. fact = > 120 # expected result class Fixnum def * other self + other end end 5. fact = > 16 # new * , new result Ruby MRI presents another challenge by implementing the core Ruby library in C, for performance reasons. The C implementation buries much of the semantic informa- tion about the core library (see figure 1). Ruby Core Library Interpreter Ruby Libraries C Libraries Written in Ruby Written in C Figure 1: Ruby: Matz Ruby Interpreter 1.8.x Our Approach Despite these challenges, Ruby MRI provides a full eval- uation environment and access to the AST, allowing a partial evaluator to evaluate source at compile time, as the following figure illustrates. Ruby Source Program Compiled Ruby Source Program Source to Source Compiler Running Ruby Session (Performs Partial Evaluation) Core Library "Safety" Rules (Decides when Partial Evaluation is Safe) Figure 2: The partial evaluator In order to use this environment, the core library must be analyzed to determine the safety of each method. C Source Files Find accessed globals and called functions Identify and Extract External Functions Flag safe and unsafe C Standard Library Create final function safety list by combining external and defined functions and running fixed-point analysis Figure 3: C analyzer process Safe methods are those that do not perform I/O and do not rely on global variables. A tool to perform the analy- sis of the C code was developed, both to speed the analy- sis process, and insulate against changes in Ruby. Figure 3 illustrates how C source files are analyzed. The Algorithm Our algorithm first analyzes, then uses the results to par- tially evaluate Ruby source, producing a new Ruby file. Currently, the partial evaluator targets whole programs due to Ruby’s dynamic nature, though we are confident it can be extended to handle libraries. Analysis proceeds top-down from the beginning of a program, following a traditional data-flow approach. Handle Next Expression Already Marked Safe ? Last Expression ? Stop Simple Expression ? Mark Safe Analyze Method Load or Require ? Inline File At Top-level Ignore Instance Variable Assignment Add to Known Unsafe List Safe ? Unsafe ? Initializer ? No Loop or Branch ? Data-flow Fixed Point or Meet No No No No No No Evaluate known sub-expressions No Yes Yes Yes Yes Yes Yes Yes Yes Figure 4: Ruby analyzer process Method Analysis Method call analysis is the crux of the algorithm. This analysis provides: A list of called methods with their contexts for further analysis A list of accessed global, class, and instance variables A list of parameters and variables captured in any pro- vided block, which have been modified A list of files loaded or required by the method For methods implemented in C, we rely on the previ- ously performed C analysis step. Method Call Safety Safe method calls do not access shared state, have safe blocks, and only call safe methods, though we relax the shared state requirement by taking an “all-or-nothing” approach, marking methods safe, only if all methods ac- cessing a shared variable are safe. Analysis runs itera- tively, until a fixed point is reached, ensuring informa- tion about shared state is as complete as possible. Special Cases Object Initialization The special method new first allo- cates space, then calls the initialize method for newly created objects. The partial evaluator must ensure initialize calls only safe methods. Loading Modules Ruby loads supporting modules through the load and require methods, loading files into the top-level environment, unless a module is spec- ified. The partial evaluator must mimic this behavior, analyzing loaded source code as if it were part of the original program. Future Work Once the partial evaluator is complete for whole pro- grams, we hope to use the insights gained during de- velopment to: Partially evaluate modules, inserting runtime checks to ensure correctness Analyze C extensions to Ruby, exposing their semantic properties to the partial evaluator Perform further specialization, such as method- inlining References [1] C. C. Aycock. MPI Ruby with Remote Memory Access. In Pro- ceedings of the 13th IEEE International Symposium on High Perfor- mance Distributed Computing (HPDC), pages 280–281, 2004. [2] J. Dean and S. Ghemawat. MapReduce: Simplified Data Pro- cessing on Large Clusters. In Proceedings of the 6th Symposium on Operating Systems Design and Implementation, pages 137–150, 2004. [3] E. Ong. MPI Ruby: Scripting in a Parallel Environment. Comput- ing in Science and Engineering, 4(4):78–82, 2002. [4] About Ruby. On the web. http://www.ruby-lang.org/en/ about/. [5] Skynet: A Ruby MapReduce Framework. On the web. http: //skynet.rubyforge.org/. [6] Starfish - Ridiculously Easy Distributed Programming with Ruby. On the web. http://rufy.com/starfish/doc/.

Concrete Partial Evaluation in RubyThe popular Ruby on Rails framework supports REST-ful development Ruby was originally developed by Yukihiro Matsumoto (Matz), based on his favorite

  • Upload
    others

  • View
    0

  • Download
    0

Embed Size (px)

Citation preview

Page 1: Concrete Partial Evaluation in RubyThe popular Ruby on Rails framework supports REST-ful development Ruby was originally developed by Yukihiro Matsumoto (Matz), based on his favorite

Concrete Partial Evaluation in RubyAndrew Keep Arun Chauhan

Deptartment of Computer ScienceIndiana University

{akeep,achauhan}@cs.indiana.edu

Introduction

Modern scientific research is a collaborative process,with researchers from many disciplines and institutionsworking toward a common goal. Dynamic languages,like Ruby, provide a platform for quickly developingsimulation and analysis tools, freeing researchers to fo-cus on research instead of developing infrastructure.Ruby fits this role well, allowing:• Incorporation of existing C libraries• Simple Domain Specific Language creation• Support for REST and SOAP web APIs•Distributed programming, through a simplified Java

RMI style library

Why Ruby?

Ruby is already finding a place in the scientific commu-nity and industry:•MPI extension [3, 1] for quick prototyping•New libraries [6, 5] support MapReduce [2]•The popular Ruby on Rails framework supports REST-

ful developmentRuby was originally developed by Yukihiro Matsumoto(Matz), based on his favorite languages [4]. The Rubylanguage:• Is purely object-oriented and dynamically-typed•Provides open classes, allowing meta-programming• Supports closures and functional programming•Provides simple iterators through Ruby blocks

The Challenge

The power of Ruby comes at a price. The current C-based interpreter, the Matz Ruby Interpreter (MRI), suf-fers poor performance since the abstract syntax tree(AST) is used directly by the interpreter. The flexibilityof Ruby complicates compilation because context affectsthe meaning of expressions, as illustrated below.c l a s s Fixnum

def f a c ti f s e l f == 0

1e l s e

s e l f ∗ ( s e l f − 1 ) . f a c tend

endend

5 . f a c t => 120 # expected r e s u l t

c l a s s Fixnumdef ∗ other

s e l f + otherend

end

5 . f a c t => 16 # new ∗ , new r e s u l t

Ruby MRI presents another challenge by implementingthe core Ruby library in C, for performance reasons. TheC implementation buries much of the semantic informa-tion about the core library (see figure 1).

Ruby

Core Library

Interpreter

Ruby Libraries

C Libraries

Written in Ruby

Written in C

Figure 1: Ruby: Matz Ruby Interpreter 1.8.x

Our Approach

Despite these challenges, Ruby MRI provides a full eval-uation environment and access to the AST, allowing apartial evaluator to evaluate source at compile time, asthe following figure illustrates.

Ruby Source Program

Compiled Ruby Source Program

Source to Source Compiler

Running Ruby Session

(Performs Partial Evaluation)

Core Library "Safety" Rules

(Decides when Partial

Evaluation is Safe)

Figure 2: The partial evaluator

In order to use this environment, the core library mustbe analyzed to determine the safety of each method.

C Source Files

Find accessed globals and called functions

Identify and Extract External Functions

Flag safe and unsafe C Standard Library

Create final function safety list by combining external and defined functions and running fixed-point analysis

Figure 3: C analyzer process

Safe methods are those that do not perform I/O and donot rely on global variables. A tool to perform the analy-sis of the C code was developed, both to speed the analy-sis process, and insulate against changes in Ruby. Figure3 illustrates how C source files are analyzed.

The AlgorithmOur algorithm first analyzes, then uses the results to par-tially evaluate Ruby source, producing a new Ruby file.Currently, the partial evaluator targets whole programsdue to Ruby’s dynamic nature, though we are confidentit can be extended to handle libraries. Analysis proceedstop-down from the beginning of a program, following atraditional data-flow approach.

Handle NextExpression

AlreadyMarked

Safe?

Last Expression

?

Stop

SimpleExpression

?

Mark Safe

AnalyzeMethod

Loador

Require?

Inline FileAt Top-level

Ignore InstanceVariable Assignment

Add to KnownUnsafe List

Safe?

Unsafe?

Initializer?

No Loopor

Branch?

Data-flow FixedPoint or Meet

No

No

No

No

No

No

Evaluate knownsub-expressions

No

Yes

Yes

Yes

Yes

Yes

Yes

Yes

Yes

Figure 4: Ruby analyzer process

Method Analysis

Method call analysis is the crux of the algorithm. Thisanalysis provides:•A list of called methods with their contexts for further

analysis•A list of accessed global, class, and instance variables•A list of parameters and variables captured in any pro-

vided block, which have been modified•A list of files loaded or required by the method

For methods implemented in C, we rely on the previ-ously performed C analysis step.

Method Call Safety

Safe method calls do not access shared state, have safeblocks, and only call safe methods, though we relax theshared state requirement by taking an “all-or-nothing”approach, marking methods safe, only if all methods ac-cessing a shared variable are safe. Analysis runs itera-tively, until a fixed point is reached, ensuring informa-tion about shared state is as complete as possible.

Special CasesObject Initialization The special method new first allo-cates space, then calls the initialize method fornewly created objects. The partial evaluator must ensureinitialize calls only safe methods.

Loading Modules Ruby loads supporting modulesthrough the load and require methods, loading filesinto the top-level environment, unless a module is spec-ified. The partial evaluator must mimic this behavior,analyzing loaded source code as if it were part of theoriginal program.

Future Work

Once the partial evaluator is complete for whole pro-grams, we hope to use the insights gained during de-velopment to:

•Partially evaluate modules, inserting runtime checksto ensure correctness

•Analyze C extensions to Ruby, exposing their semanticproperties to the partial evaluator

•Perform further specialization, such as method-inlining

References

[1] C. C. Aycock. MPI Ruby with Remote Memory Access. In Pro-ceedings of the 13th IEEE International Symposium on High Perfor-mance Distributed Computing (HPDC), pages 280–281, 2004.

[2] J. Dean and S. Ghemawat. MapReduce: Simplified Data Pro-cessing on Large Clusters. In Proceedings of the 6th Symposiumon Operating Systems Design and Implementation, pages 137–150,2004.

[3] E. Ong. MPI Ruby: Scripting in a Parallel Environment. Comput-ing in Science and Engineering, 4(4):78–82, 2002.

[4] About Ruby. On the web. http://www.ruby-lang.org/en/about/.

[5] Skynet: A Ruby MapReduce Framework. On the web. http://skynet.rubyforge.org/.

[6] Starfish - Ridiculously Easy Distributed Programming withRuby. On the web. http://rufy.com/starfish/doc/.