Mostrando entradas con la etiqueta ruby. Mostrar todas las entradas
Mostrando entradas con la etiqueta ruby. Mostrar todas las entradas

lunes, 23 de abril de 2012

Fastruby 0.0.21: Inline of corelib fixnum methods, restored ruby 1.8 compat

Fastruby is a gem which allows to execute ruby code much faster than normal, currently in a state of transition between a spike and a usable gem, it is released when possible with incremental improvements.

One of the main improvements on fastruby v0.0.20 v0.0.21 was the implementation of a few corelib methods (e.g. Fixnum#+) in ruby to allow inline them. The other is the restored compatibility with ruby 1.8

Install

You can clone the repository at github:
git clone git://github.com/tario/fastruby.git
git checkout v0.0.21

Or install it using gem install:
gem install fastruby


Speedup

Before (v0.0.19 and prior)







Now:








NOTE: Since issues with 1.8 compatibility, inline of corelib methods won't works on ruby 1.8, this will be fixed for v0.0.22 in future releases

Next

martes, 14 de febrero de 2012

Fastruby 0.0.19 released: improve of inline, performance bugs fixed

Fastruby is a gem which allows to execute ruby code much faster than normal, currently in a state of transition between a spike and a usable gem, it is released when possible with incremental improvements.

The main improvements on fastruby v0.0.19 are refinements on the inliner algorithm:
  • Inline of block calls (was not possible before)
  • Inline of methods with block calls (was not possible before)
And the fix of two important bugs:
  • Duplicated entries on $LOAD_PATH creates an incremental latency on require as new methods are built. Fixing this bug allows obtaining a reduction of total time of tests of %80 (150 seconds to 30 seconds on my machine). Moral: don't touch $LOAD_PATH if possible
  • Replacement of CFUNC calls using the previously implemented observer mechanism for inlining
  • Fixed case statements reduction to use deterministic names for temporal variable and allow caching of methods using case statements
No new big features...

Install

You can clone the repository at github:
git clone git://github.com/tario/fastruby.git
git checkout v0.0.19

Or install it using gem install:
gem install fastruby


martes, 1 de noviembre de 2011

Fastruby 0.0.15 released. Callcc and continuation objects!

Fastruby is a gem which allows to execute ruby code much faster than normal, currently in a state of transition between a spike and a usable gem, it is released when possible with incremental improvements.
The v0.0.15 release adds the support for continuation objects created using callcc function. To acchieve this, the implementation uses the non-lineal stack created on previous releases.
Also this release adds a few extra language support improvements such as method default arguments

Install

You can clone the repository at github:
git clone git://github.com/tario/fastruby.git
git checkout v0.0.15
Or install it using gem install:
gem install fastruby

New Features

Fixes

Examples of code being supported

Example of continuation calls, tail recursion


require "fastruby"

fastruby '
class X
def fact( n )
a = callcc { |k| [ n, 1, k ] }
n = a[0]
f = a[1]
k = a[2]
if ( n == 0 ) then return f
else
k.call n-1, n*f, k
end
end
end
'

p X.new.fact(6) # 720

Default Arguments
require "fastruby"

fastruby '
class X
def foo(a,b = a.reverse)
a + b
end
end
'

p X.new.foo("13") # 1331
p X.new.foo("xx", "yy") # xxyy

Passing proc objects as blocks
require "fastruby"

fastruby '
class X
def bar
yield(1)
yield(2)
yield(3)
end

def foo
pr = proc do |x|
p x
end

bar(&pr) # passing proc as a block
end
end
'

X.new.foo

Receiving blocks as proc objects
require "fastruby"

fastruby '
class X
def bar(&pr)
pr.call(1)
pr.call(2)
pr.call(3)
end

def foo
bar do |x|
p x
end
end
end
'

X.new.foo


domingo, 23 de octubre de 2011

Fastruby 0.0.14 released with support for method replacement

Fastruby is a gem which allows to execute ruby code much faster than normal, currently in a state of transition between a spike and a usable gem, it is released when possible with incremental improvements.
The v0.0.14 release make a internal redesign of the method hash structure to allow the store of function pointer pointers, this is what allows to reference a fixed function pointer which may change enabling method replacement while retaining most of the performance (fastruby calls now consume a extra indirection and a few extra checks)

Install

You can clone the repository at github:
git clone git://github.com/tario/fastruby.git
git checkout v0.0.14
Or install it using gem install:
gem install fastruby

New Features


Examples of code being supported

Replacement of methods

require "fastruby"

fastruby '
class X
def foo(a)
a+1
end
end
'

x = X.new
p x.foo(4) # 5

fastruby '
class X
def foo(a)
a*2
end
end
'

p x.foo(4) # 8


Remaining uncovered items on v0.0.14 release
  • Memory handling of function pointers on method hash (will be fixed for v0.0.15)
  • Fix limitation of 15 arguments when calling method defined on fastruby from normal ruby
  • Fix duplication of objects on cache when methods are replaced
  • Optimization of splat callls, currently this calls are executing using normal rb_funcall2 (will be improved for v0.2.0)
  • Optimization of calls to methods with variable number of arguments, currently are wrapped using rb_funcall (will be improved for v0.2.0)

domingo, 9 de octubre de 2011

Fastruby 0.0.13 released with support for splat arguments and method with array arguments

Fastruby is a gem which allows to execute ruby code much faster than normal, currently in a state of transition between a spike and a usable gem, it is released when possible with incremental improvements.
The v0.0.13 release of fastruby make a little internal design improvement regarding translator class and the implementation of splat arguments and methods with optional arguments (see examples below)

Install

You can clone the repository at github:
git clone git://github.com/tario/fastruby.git
git checkout v0.0.13
Or install it using gem install:
gem install fastruby

New Features



Examples of code being supported

Multiple arguments and call with splat

require "fastruby"

fastruby '
class X
def foo(*array)
array.each do |x|
p x
end
end

def bar(*args)
foo(*args)
end
end
'

x = X.new
x.foo(1,2,3) # prints 1,2 and 3
x.bar(4,5,6) # prints 4,5 and 6

Remaining uncovered items on v0.0.13 release

miércoles, 28 de septiembre de 2011

Fastruby 0.0.9 released with support for proc

Fastruby is a gem which allows to execute ruby code much faster than normal, currently in a state of transition between a spike and a usable gem, it is released when possible with incremental improvements.
Following the release of version v0.0.8 which did implement several internal improvements including a new non-linear stack structure, the new release v0.0.9 implements the support for procedure objects based in the previous implementation

Install

You can clone the repository at github:
git clone git://github.com/tario/fastruby.git
git checkout v0.0.9
Or install it using gem install:
gem install fastruby

New Features


Examples of code being supported

return method from proc

require "fastruby"

fastruby '
class X
def foo
pr = Proc.new do
return "return foo from inside proc"
end

pr.call

return "return foo"
end
end
'

x = X.new
x.foo # this returns "return foo from inside proc"

The behavior of Proc objects (those created using Proc.new) are very similar to the behavior of lambdas, but with a few little differences:
  • It is possible to do non-local return's from Proc.new of the method where the block was defined, this non-local return will fail with LocalJumpError when the method scope is closed in the moment of invoking the return (in lambdas, return only acts as next; ie, only ends the lambda function)
  • Break jumps are illegal from Proc.new blocks and always fails with LocalJumpError (in lambdas, break acts as next)

As additional note, block objects created using proc method are exact the same block objects created using lambda method, only check the the ruby 1.8 source code to see something like that:

   ...
rb_define_global_function("proc", proc_lambda, 0);
rb_define_global_function("lambda", proc_lambda, 0);
...





lunes, 19 de septiembre de 2011

Fastruby roadmap up to 0.5.0

Fastruby development (up to 1.0.0 release) will be divided into two main phases:
  • Incremental Proof of Concept. Transition from a base spike/PoC (version 0.0.1) to usable gem (version 0.1.0).
  • Usable versions. Transition from minimally usable gem (version 0.1.0) to stable API release (version 1.0.0)
This is a rough roadmap and might change in the future if new ideas or optimizations are discovered

PoC Incremental Versions


Version 0.0.8: lambdas (already released)
Version 0.0.9: proc
Version 0.0.10: Gem packaging fixes

Version 0.0.11: for, retry, redo
Version 0.0.12: Full exception support

Version 0.0.13: Methods with variable number of arguments

Version 0.0.14: Support for method replacement

Version 0.0.15: continuation objects


Etc...

Version 0.1.0: First usable release
  • Any ruby code executable by MRI can be executed by fastruby

Usable Versions (Following semantic versioning)

Zero used as mayor version number is used when API is changed every day without backward compatibility (despite the fact that will be backward compatibility when possible). Also, on 0.X.X versions the API is completely undefined.
Bugs and spec un-compliance of 0.1.0 release will be fixed on subsequent stabilization releases (0.1.1, 0.1.2, etc...)

Version 0.1.0: Execution of Ruby

Features:
  • Any executable code in ruby is executable via fastruby and gives the same results
  • Interoperation between ruby and fastruby is granted

Version 0.2.0: Fast execution of ruby, internal optimizations

Features
Version 0.3.0: Fast execution of ruby, C extension API

  • C extension points
    • API to define methods in C, by class, method name and signature allowing replacement of ruby standard lib implementation in the future.

Version 0.4.0: Fast execution of ruby, C extension API 2

  • C extension points
    • Macro methods (keeping dynamism). Examples:
      1. Fixnum#+(x:Fixnum) => INT2FIX(FIX2INT(self)+FIX2INT( x) )
      2. String#[](x:Fixnum) => rb_str_new2(RSTRING(self)->ptr[FIX2INT(x)],1)
      3. String#[]=(x:Fixnum,y:Fixnum) =>
        RSTRING(self)->ptr[FIX2INT(x)]=FIX2INT(y)

Version 0.5.0: Faster standard lib

  • Ruby standard lib re-implemented in a separated gem optimized for fastruby
  • Fastruby works with and without optimized stdlib

miércoles, 7 de septiembre de 2011

Callcc puzzle on fastruby III: Almost solved?

First of all, the plan of migrate to C++ was canceled to use ruby Garbage Collector instead to handle the resources used by the fastruby stack entities

The cost of instantiating objects on ruby

Since ruby garbage collector works only with ruby objects, I need to encapsulate as ruby objects whatever I want to have managed by the GC. The first option that comes to mind is encapsulate every local variables scope into a ruby object: bad idea, this will instantiate a ruby object for each scope and the cost of instantiating objects on ruby is of an higher order than a single memory allocation on C; the issue of this approach can be appreciated on this spike which adds a instantiation of a ruby object (using rb_objnew) for each scope to see the impact on general performance measured used benchmark scripts, the result was the increase of the execution time of the main benchmark by 3X, enough to reject the approach of one ruby object per locals scope.

Stack Chunk

To solve the issue of multiple ruby object allocations, multiple locals scopes will be grouped and encapsulated as a single ruby object, specifically those belonging the same stack. So stack chunks will grow dynamically (using C malloc) as locals scopes are allocated and all dynamic memory used by a stack chunk will be de-allocated when it is removed by ruby GC.
For the cases of lambdas, proc and continuations, StackChunk objects will be referred from a ruby local variable in the ruby scope, so, lambdas duplicating ruby stacks will make new references to stack chunks. Stack chunks will become immutable/frozen when lambdas or continuation objects are created to prevent overwriting local variables with new scopes, local variables living on immutable/frozen stack chunks may be changed but frozen chunks rejects the allocation of new scopes.

Stack Chunk properties
  • All locals variables will be placed/allocated on the current stack chunk at the moment of initialize the function frame
  • Each stack chunk is wrapped as a ruby object of type StackChunk to provide to the ruby garbage collector the interface to release stack chunks from memory (Data_Wrap_Struct) when it have no references.
  • StackChunk will be referred from the local variable scope of MRI (Matz Ruby Interpreter) to prevent this object to be removed until they stop using it (e.g. leaving the scope where the stack chunk is created); on the internal implementation of MRI, lambdas, procs and continuation objects retain references to MRI stack frames, so the issue of lambdas and continuations will be solved (in part) with this.
  • Calcc, lambdas and procs will turn the state of the current stack chunk into frozen state, this implies that new scopes can't be created in that stack chunk. When new scopes are being required, a new stack chunk will be created
Implementation

See https://github.com/tario/fastruby/commits/dynamic_locals

martes, 6 de septiembre de 2011

Callcc puzzle on fastruby II: The return of C++

In a previous post, I have explained the problem of implementing callcc while keeping the performance on fastruby; and then the focus was changed to a simpler issue: lambdas.

The approaching to the lambda issue allow us to recognize the non-linear nature of the ruby stack: while the native stack grows allocating space for local variables and decreases deallocating that space, the non-linear stack of ruby allows keeping isolated local variables scopes associated to lambda blocks (while previous scopes in the stack are deallocated) and even allows retain all the scopes of a stack for continuation objects created with callcc

The solution for lambda case is as simple as changing the place where the local variable scope lives: heap instead of stack.

Making use of dynamic memory is not a game, and if misused it may be hurt or even kill (the ruby process, after a relatively slow death with cancer)


Release of allocated memory and C++

Each allocation must have their corresponding de-allocation. It's that simple. But not so simple when programming in C, because [...]
RAII provided by C++ make more easier to code scopes of resources initialization and finalization (dynamic memory, in this case), by using the destructor of clases to release the resources. this covers function returns and C++ exceptions. It does not cover longjmp (this will be analyzed later on this post). See the wikipedia article about RAII for more info and code examples

Reference Counting

Immediately after creating a lambda object, the local variable scope is referenced twice: one reference from the lambda object itself, and the other reference from the scope living in the stack (imagine that many lambdas created in the same scope adds more references to the count). In this situation, when the execution leaves the scope of the function, it de-allocate the local variables struct, the only thing it should do is to decrement the reference count of the local variables by one unit, and the release should only occur when this count reach zero. This algorithm is called Reference Counting.

Longjmp and C++ Raii

Using of C function setjmp/longjmp for non-local GoTO's are incompatible with C++ RAII since RAII depends on the destructors of objects instantiated on the stack are called. For example, a longjmp crossing a scope allocating recurses will prevent the release of these resources.
Apparently, the solution to this issue is to replace the current use of setjmp/longjmp with c++ exceptions (the same risk is present when using setjmp/longjmp), but after a spike I realized this might not be a good idea:

test.c using longjmp and setjmp
#include "setjmp.h"

jmp_buf jmp;

void function2() {
longjmp(jmp,1);
}
void function1() {
setjmp(jmp);
}
int main() {
int i;
for (i=0;i<200000000;i++) {
function1();
}
return 0;
}

It took 2.241 seconds

test.cpp using try/catch and throw
#include "exception"

void function2() {
throw std::exception();
}
void function1() {
try {
function2();
} catch (std::exception) {
}
}
int main() {
int i;
for (i=0;i<200000000;i++) {
function1();
}
return 0;
}

It was never finished even after hours

Conclusion

C++ exceptions will always be slower than setjmp/longjmp because C++ exceptions use non-local goto's as part of their implementation and other complexities. I must look for another workaround for the longjmp detail

Links

domingo, 28 de agosto de 2011

Fastruby v0.0.6 (PoC) released

Fastruby is a gem which allows to execute ruby code faster than normal (about 20X of the MRI1.8), see this post for more info

Improved ruby support

In the first gem released version of fastruby (v0.0.1), the ruby support was very limited since that version was designed as a spike (e.g. it can't handle block calls, exceptions, break, etc...).
These ruby support improvements are based on frame structures used at runtime and some other tricks such non-local goto's to implement return, next, break; this make the generated code a bit more expensive but still 20X faster (instead of 100X of the first version)

Now (version 0.0.6) fastruby support a wide range of ruby constructions, such:
  • Exceptions (begin, rescue, ensure, end)
  • Classes and modules
  • Constants, globals
  • Flow control sentences if, unless, and case..when..end
  • Literals
  • Singleton methods (almost as slow as normal ruby)
  • Ruby built-in goto's (break, return, next)
But for now, leaves out the following:
  • Class variables (*)
  • Methods with multiple number of arguments (*)
  • Callcc (*)
* Issue created for task

Native object cache to reduce bootstrap overhead

Usually the execution of ruby code on fastruby implies parsing the code, translate to C, and build by compiling it using gcc .
Even small code snippets may take a few seconds, a lot of time comparing it with the execution of same code using MRI, which takes hundredths of a second and imagining what would happen with larger code...
The response to this issue is the implementation of the cache, transparent to the invoker. In the image, a script is executed by first time to show it takes 0,642 seconds, and when the same script is executed again, the same script takes 0,057 seconds. The script test.rb is a very simple test:
require "fastruby"

fastruby '
print "hello world\n"
'

The cache is located on $HOME/.fastruby and the cache feature can be deactivated by setting the environment variable FASTRUBY_NO_CACHE to 1 when execute a ruby script that uses fastruby.

Implementation details of cache

Each code snippet has a SHA1 sum associated and each SHA1 has a collection of native libraries including both the main object and multiple built of the methods defined in that snippet.
The diagram is only a conceptual model and does not represent any entity in fastruby source code, the sha1 association is implemented using the filesystem by saving each object collection in a directory named as the hexadecimal sha1 of the corresponding code snippet (inspired by git internals :D )




Links

Fastruby github page: https://github.com/tario/fastruby
Previous post on fastruby: http://tario-project.blogspot.com/2011/07/fastruby-v001-poc-released.html

sábado, 30 de julio de 2011

Fastruby v0.0.1 (PoC) released

Fastruby is a gem which allows to execute ruby code faster than normal (about 100X of the MRI1.8)

Fastruby IS NOT a separated ruby interpreter. Then, the design is simple

Fastruby IS NOT a DSL to generate C code using ruby or a Ruby to C translator, the goal of fastruby is to execute RUBY code

Core Concepts

Native build


All code processed by fastruby ends with a native representation, in the current version, this is acomplished using RubyParser to parse rubycode.
The ruby code is translated to C and then processed with RubyInline

Transparent multimethods (and multiblocks)

The methods processed by fastruby has multiple internal implementations depending on the type of the arguments.
Each possible signature has a version of the method and this are built in runtime when the method is called with a new signature.
The same concept will be applied to blocks (anonymous methods) in future releases

Type inference

Each version of a method is built for a specific signature, so, the builder can assume a type for the arguments and build method calls using that assumption.
Whereever the translator can asume a type for a expression involved in a method call (used as argument or as receiver), this information can be used to encode
direct calls instead of normal and expensive ruby calls.

The currently implementation only can infer types for method and block arguments, and for literals

Customization through build directives and API

To compensate for the described limitations, fastruby suport a few build directives to allow the programmer help the inference.
The syntaxis of these directives are the same as normal ruby call (see examples)
Also, fastruby will define a API to customize aspects of fastruby internals. E.g the build method to invoke the build of methods with a specific signature (see examples)

The Image

The image of this post shows a display with the execution of the current benchmarks of the test

All of them follow the pattern of executing the code with normal ruby and with fastruby. The fourth benchmark adds a few additional measures (see the benchmark source for more info)

You can locate the benchmark sources installed in the gem directory of fastruby or in the github repository and the full resolution version of the image here

Installation


The install is as simple as execute the well-known gem install:

sudo gem install fastruby

Examples

The syntax is simple since one of the main of goals of fastruby is to be transparent. The current API serves for testing and customization of this poc version of fastruby

Prebuild of methods:
 require "fastruby"

class X
fastruby '
def foo(a,b)
a+b
end
'
end

X.build([X,String,String] , :foo)

p X.new.foo("fast", "ruby") # will use the prebuilded method
p X.new.foo(["fast"], ["ruby"]) # will build foo for X,Array,Array signature and then execute it

NOTE: this is not necessary to do this, the methods will built automatically when there are called for first time

Variable "types"

Like static languages, you can define a type for a variable to help the inference and gain some performance. This can be done by using lvar_type directive

 class X
fastruby '
def foo
lvar_type(i, Fixnum)
i = 100
while (i > 0)
i = i - 1
end
nil
end
'
end


With no lvar_type, the calls to Fixnum#> and Fixnum#- will be dynamic and more expensive

Links

martes, 19 de abril de 2011

Released ImageRuby - a flexible ruby gem for image processing

ImageRuby is a flexible gem for image processing, it's designed to be easy to install and use. The core of ImageRuby is written in pure ruby and the installation is as simple as execute "gem install imageruby". The API of the library take advantage of sugar syntax constructions specific of ruby language such as method chaining and blocks. e.g, the next code loads an image from "input.bmp", crop the rectangle from 0,0 to 49,49 (50x50 pixels), replace the orange color to red color, replace the black color to orange color and finally saves the image as "output.bmp"

require "imageruby"

ImageRuby::Image.from_file("input.bmp")[0..49,0..49].
color_replace(Color.orange,Color.red).
color_replace(Color.black,Color.orange).
save("output.bmp", :bmp)

Current Status

The ImageRuby had his first release (version 0.1.0) the last week with imageruby-c (extension to override a few methods with C methods) and imageruby-bmp (support for save and load images on BMP format),

You can install the gem by doing

gem install imageruby


The current version o imageruby has no dependencies, and it's installation should be as simple as that, optionally, you can install imageruby-c to improve the performance of draw and color_replace methods and imageruby-bmp to have support for bmp images.
The extensions take effect automagically by installing the gem, there is no need to do something specific in the ruby script (e.g. when install imageruby-c the methods will be optimized)

Goals of the project

  • Become synonymous of image processing in the ruby world, displacing other options in the "market" but re-using the existent stuff (giving credit, obviously)
  • Highlight deficiencies in the ruby language when used for heavy processing (e.g. draw method implemented in ruby is very slow)
  • Spike workarounds for the Ruby language issues
  • Spike "soft" dependency model or plugin gems to avoid the problems of "static" dependencies

Competitors

There is a range of gems for image processing on ruby, most of these are based on C libraries and implies the need for a compiler in order to install them. Some have "low level" bugs such memory leaks but most of them have many possibilities through their API

  • RMagick: Ruby wrapper of the archi-famous ImageMagick library. Has reported problems with low level memory handling and is not recommended for services environment (such as a Rails application) but is good for scripting
  • ImageScience: More stable alternative to RMagick, written on top of FreeImage and RubyInline (for more optimal code in C), an issue when using this library is the RubyInline dependency which implies the need for GCC installed on the system, something that is simple on Linux but is so tricky in other environments such Windows and Heroku
  • Camellia: A C/C++ library with a Ruby interface apparently directed to photo processing, there is no gem and the installation should be using the classic command sequence ./configure; make; make install.
  • Devil: Wrapper of C library of the same name. It has a wide range of operations over an image including blur and equalize. (see documentation)
  • Ruby-Processing: Well documented library mainly oriented to interactive media including video features. Has nice pencil functions
Future

New image formats

One of the next big steps will be develop decoder and encoders for common image formats, the encoders and decoders can be released as separated gems (like imageruby-bmp) without need for change imageruby core. In fact, anyone can make their own encoder or decoder.

Competitors become allies

Re-use the existing development around image processing in the ruby world, divided in two big groups: Interfaces and Implementations

Reusing interfaces implies the creation of "mocks" or "wrappers" of ImageRuby providing the same API of other library (e.g. RMagick or ImageScience) to reduce the learning curve of ImageRuby API and provide a method to replace that library with ImageScience transparently for code developed on top of that (e.g. a rails application using ImageMagick and then the ImageMagick gem is replaced by ImageRuby, app will not need to be modified)

Reusing implementation is about build features on top of other image libraries, but without setting a "hard" o "static" dependency with the library, but by creating a optional extension for ImageRuby (something like a port between libraries). Example: imageruby-devil.

Could be installed so:
gem install imageruby-devil

And used like
# is not necessary to make a explicit require of imageruby-devil
require "imageruby"

image = ImageRuby::Image.from_file("input.bmp")

image.color_replace!(Color.black, Color.purple) # use a method of ImageRuby
image.devil.blur(1) # use a method of Devil library on the image

image.save("output.bmp", :bmp)

Feedback for Ruby improvements

One of the goals of ImageRuby is to Highlight deficiencies in the ruby language , methods such draw or color_replace process hundred of thousands of pixels per image which in the ruby language implies still much more unnecessary rubymorphic calls just to access each bit of pixel data of the processed images. This produces a very very slow result, the current workaround for this issue is override the "heavy" methods with the imageruby-c extension. This was achieved as a optional extension to avoid the unnecessary hard dependency of have a compiler in the system, ImageRuby without imageruby-c installed HAS the draw and color_replace method, but with the imageruby-c gem installed, is much much more fast (near to 100x more faster)

Links

ImageRuby rdoc reference: http://tario.github.com/imageruby/doc/
ImageRuby GitHub site: https://github.com/tario/imageruby

jueves, 17 de marzo de 2011

Shikashi - A flexible sandbox for ruby

Shikashi is an sandbox for ruby that handles all ruby method calls executed in the interpreter to allow or deny these calls depending on the receiver object, the method name, the source file from where the call was originated

Goals of the project

Provide a sandbox API to build up scripting services with granular control of privileges even at method and global variable levels

The API

The API of Shikashi expose two main services: a "eval" method and a privilege representation. The "eval" just run code in the sandbox and apply the restrictions specified in the privileges passed as parameter. Example


require "shikashi"

sandbox = Shikashi::Sandbox.new
privileges = Shikashi::Privileges.new

privileges.allow_method :"+" # mandatory to prevent SecurityError exception

result = sandbox.run "2+2", privileges
print result,"\n" # 4



Also, the API allows more effective control of the privileges by objects/method names and is not limited to methods, but also allows to control the access to global variables and constants


# ...
privileges.allow_global:$a # mandatory to prevent SecurityError exception

sandbox.run("$a = 4", privileges)

print $a, "\n"
# ...



Current Status

Currently, there are a stable version of the gem (0.3.1), but the compatibility only is guaranteed for very few environments, exluding many of the interesting like Heroku which I have verified that the gem did not work

Future

The next improvement for shikashi (for version 0.4.0) will be of course the compatibility, defining two specific objetives:
  • Making it work in Ruby 1.9
  • Making it work in Heroku (without UI or any web programming)
In addition, secondary objectives about API usability were defined for the next release, these include sugar syntax to make it easier to use like so


Sandbox.run "2+2", Privileges.allow_method("+")


Links:
https://github.com/tario/shikashi
http://tario.github.com/shikashi/doc/