Facilitating the Spread of Knowledge and Innovation in Professional Software Development

Write for InfoQ


Choose your language

InfoQ Homepage News Gemstone OODB to support JRuby, Rubinius

Gemstone OODB to support JRuby, Rubinius

This item in japanese

Gemstone, producer of products like Object Databases (OODB) such as the Smalltalk-based Gemstone/S or Java-based Facets, is working on Ruby support for their products. In short: JRuby will get support for Facets and Rubinius will be used for non-JRuby users with features resembling Gemstone/S.
An OODB, in short, allows to persist object graphs transparently. This is in contrast  to using a Relational Database (RDBMS), where object data must be stored in tables, which involves Object Relational Mapping (ORM). ORM happens either manually, i.e the developer stores the data in the tables, or with the aid of tools or libraries such as Ruby's ActiveRecord or, to mention just one, Hibernate for Java.

We talked to Alan McKean from Gemstone to get some more details on these recent developments concerning Gemstone and Ruby.

Alan explains how these efforts fit into the product range:
GemStone has two object database products: one built for Java (Facets) and one for Smalltalk (GemStone/S). We are looking at applying Facets to JRuby and GemStone/S to Rubinius. Since the JRuby project is already in a 1.0 release, we are doing our first proof-of-concept on that platform. So far, it looks good. It requires downloading our JVM (the JVM is licensed from Sun and we have tweaked the byte codes to allow for transparent persistence of Java objects). The JVM is slightly slower (about 5% in my tests) than the current Sun JVM because of the additional work going on with the persistence.

Alan is working with the JRuby team to handle some issues that arose from current implementation details in the JRuby runtime:
There has been one problem to solve in the JRuby implementation and I have submitted a fix to the JRuby team. JRuby currently does not support serialization (or our style of persistence) because every Ruby object has direct references to the JRuby runtime (threads, dynamic methods, and other internal objects). When the objects are serialized (or persisted) they drag along the entire runtime system. So I found a way to detach the objects from this runtime system and enable both serialization and transparent persistence. Once that was done, our persistence engine just worked.

To get a impression of how using JRuby with Gemstone will look, here some sample code making use of persistent objects:
# to persist an object in one VM  declare a
# persistent 'root' that allows access to objects with the
# 'name' of the object
persistent :people => :name

# begin a transaction, put a Ruby object and all objects that are
# connected to it into the persistent root, and commit it
p ='Alan')
p.children <<'Jimmy')
p.children <<'Janie')
people << p

# in another VM
persistent :people => :name
p = people['Alan']
p.children.each do { |child| puts }

Alan explains the API design and how this can be used from Rails:
We are in the process of designing an API for this transparent persistence. In Rails, you won't use 'transact' and 'commit'. You will just declare the persistent roots and put objects into them. The transaction boundaries will be created when the request comes in and the commit will happen just before the response goes out.

The benefits become clearer when the OODB way of doing things is compared to ActiveRecord:
Since much of ActiveRecord is there because of the impedance mismatch between objects and relational databases, a lot of ActiveRecord will be unnecessary. For example, belongs_to, has_many, etc. are there to support associations (foreign keys in the db, etc) and they are unnecessary. Likewise with acts_as_list, etc. I find it interesting that ActiveRecord requires so many duplicate constructs in violation of the DRY Principle. Declaring associations in your Ruby classes and setting up the foreign keys in the schema. It would all go away.

But we do want to support filters, validations, etc. Whether it will look exactly like ActiveRecord is doubtful because, unlike ActiveRecord, the Ruby objects do not have to be subclassed off of a particular class. The other problem with ActiveRecord that transparent persistence solves is subclassing. There is no good solution to representing a hierarchy of classes in a relational database (sparse tables or table joins). With our persistence, it is automatically supported. Subclass to you heart's content, mixin any modules into your domain classes. It just works.
Continuing with technical details, Alan explains how Gemstone's custom JVM makes persistence possible:
We persist the Java representations of the Ruby objects. The JRuby objects are simple Java objects with a Map of instance variables. It is not image-based. Although the fix I sent to the JRuby team does allow serialization, we don't use serialization. Our persistence is based on page caching. Small (8K) pages of memory are flushed to the database on a commit and pages are faulted in from the persistent store as the application uses the object references. Since objects tend to aggregate onto the same page, there is little paging going on once a page is brought in.

Ruby objects don't have a well-defined structure. One instance of a Ruby class might have a different structure than another instance of the same class. This is because instance variables are dynamically added by the methods that are invoked upon the instances. So the structure (and the ivars) that an instance has depends on what messages it has been sent during its lifetime. This is very different from both Java and Smalltalk where the are places in the classes where all of the instance variables are declared statically. So migration of Ruby objects is not as large an issue. There are some requirements that would make sense to support (e.g.e, removing an instance variable and its associated value when the method that caused it to exist has been removed from the class definition, but we see that as an administrative task that is supported by tools.

The other branch of Gemstone's Ruby support will work with the Rubinius, a Ruby VM written in (mostly) Ruby using concepts gleaned from Smalltalk VMs. (InfoQ recently featured interviews with Rubinius' Evan Phoenix: a look into Rubinius VM Internals and more Rubinius Internals like ObjectSpace and Threading). Alan explains how Gemstone will make use of Rubinius:
By the way, stay tuned for progress on the Rubinius VM. That will not run in JRuby and will not require using our JVM. We are working with Evan Phoenix to ensure that the VM will support our requirements out of the box. Then it will probably just be a gem that you install to use our persistence. Our intention is to provide a product for free (limited ot a 4G data repository on one server) as we are doing with Seaside. Once you need more than 4G of data or you want to scale to multiple servers, it requires purchase and licensing.
Gemstone has been busy supporting new web frameworks and tools. Next to the new Ruby support, Seaside will be supported as well.
We are applying our persistence to the Smalltalk Seaside framework. It will be released this Fall. The approach in Seaside will be very similar to what we are looking at doing for Ruby and Rails.
Initial announcements call this GLASS, which stands for Gemstone/Linux/Apache/Smalltalk/Seaside.

Rate this Article