|
Posted
over 18 years
ago
by
Ola Bini
I am finally back from a week of travel. Funny, it feels like much more than a week - but I guess that's because there were some interesting mishaps with some of the flights.Last Sunday I traveled to Berlin to attend RailsConf Europe. I arrived kind
... [More]
of late and was really tired and out of it during the Monday. I didn't find most of the tutorials going on that enlightening - though it was fun to see David, Aslak and Dan present on RSpec together. I liked the mind map format they used instead of regular slides. Due to general tiredness and a really bad migraine I went to bed early. But before that I managed to see Dave Thomas introductionary keynote. It was interesting and extremely well presented; the theme was art and how it can help you as a programmer to use this metaphor to understand the things we do more closely. I didn't find anything really new in the presentation and I've heard several people say that they would prefer if Dave had spent some time talking specifically about Rails instead. I tend to agree.The second day of the conference was really good. DHH delivered a keynote that basically said that there is nothing really new happening with Rails. After that it was time for sessions. I guess none of the first presentations made any real impact on me, since I don't remember what they were. After lunch I saw Nic Williams talk on meta programming; the talk was really fun. I didn't learn anything new, but I had a fun time while doing it.Charles and Tom did their JRuby presentation. And I also saw Evan Phoenix Rubinius talk. It was very interesting - if I could stand programming in such a low level language as C, I would probably spend more time helping them than I do now. I will write more about Rubinius - probably tomorrow - I haven't really said everything I need to say here.After the sessions there were more keynotes. Roy Fielding talked about REST. I gotta admit I didn't really hear much of it though, since I was spending time fixing an annoying bug. After that Craig McClanahan talked for a few minutes about Rails. It was very enlightening to know how well regarded Rails is within Sun. Some people seems to have a different view on all this though, seeing conspiracy and dirty dealings in the way Sun is working Rails. I'll need to cover that in a separate blog post too.ThoughtWorks threw a party after the days session. That was very fun and well attended.All the JRuby team attending (Charles, Nick, Tom and me) gathered together on the evening and did a JRuby Q&A BOF. Lots of people there, and a very free form of presentation made this one of the highlights for me. I had great fun and I hope the audience did too.Finally the Wednesday... Cyndi Mithell from ThoughtWorks did a very nice keynote about why Ruby and Rails may be ready to cross the chasm and get a strong hold in the enterprise.Koz and Marcel did a very good Rails Best Practices session. Down to earth, simple, totally useful advice on things to avoid in a Rails application and what to do instead.And then it was time for my presentation about JRuby in ThoughtWorks. I think it went very well, but it became a little bit too corporate for my taste. I'll need to make sure that doesn't happen the next time. Maybe some more code in the presentation? =)Most of the rest of the day was spent networking, hanging out in the exhibit hall and stuff like that. And then RailsConf was over.My flight to Sweden from Berlin that evening didn't really happen as I had expected it too. Instead I had to spend the night on a hotel in Frankfurt and take an early flight from there to Gothenburg.Overall I had a very good time at RailsConf this year. It's a worlds difference from RailsConf last year in London, which I felt was a real waste. This year the energy was high, much interesting things going on and lots of nice and smart people. Not as good as RailsConf in Portland earlier this year, but still very well worth attending. It seems that RailsConf has found a good balance in sessions. The only thing I can wish for would be more interesting choices for the tutorial day. [Less]
|
|
Posted
over 18 years
ago
by
Ola Bini
Last week I decided it was time to get Ruby-DBI working with JDBC. I resolved to get on it since it would be highly useful and probably not so hard either. But as it turned out I didn't really need to do anything. The work has already been done by
... [More]
Kristopher Schmidt. Very nice. So instead, this post will detail how to get it working with JRuby.First download the Ruby-DBI distribution from RubyForge. Secondly, unpack. The third step is to configure and install it. Execute these commands inside the Ruby-DBI directory: jruby setup.rb config --without=dbd_sqlite,dbd_sybasejruby setup.rb setupjruby setup.rb installNow you should have Ruby-DBI installed, but no DBD drivers. Verify that it's actually installed by running "jirb -rdbi". The next step is to install the JDBC driver. First create a directory called $JRUBY_HOME/lib/ruby/site_ruby/1.8/DBD/Jdbc. Download Jdbc.rb and JdbcTypeConversions.rb and put them into this directory. Also make sure that the JDBC driver you want to use is on your CLASSPATH. Now you can create a script like this:require 'dbi'DBI.connect('DBI:Jdbc:mysql://localhost/test', 'test', 'test', 'driver'=>'com.mysql.jdbc.Driver') do |dbh|p dbh.select_all('SELECT * FROM a_table')endMake sure that you include the name of the driver as done in this code. The first parameter should be the regular JDBC URI with DBI: first. In this case it's the test database on localhost I connecting to, using the test username and test password. More information about how Ruby-DBI can be used can be found by Google. [Less]
|
|
Posted
over 18 years
ago
by
Charles Oliver Nutter
Recently, the JRuby team has gone through the motions of getting a definitive JRuby book underway. We've talked through outlines, some some chapter assignments, and discussed the overall feel of a book and how it should progress. I believe one or two
... [More]
of us may have started writing. However the entire exercise has made one thing abundantly clear to me:Good authors do not have time to be good developers.Think of your favorite technical author, perhaps one of the more insightful, or the one who takes the most care in their authoring craft. Now tell me one serious, nontrivial contribution they've made in the form of real code. It's hard, isn't it?Of course I don't intend to paint with too wide a brush. There are, without a doubt, good authors that manage to keep a balance between words and code. But I'm increasingly of the opinion that it's not practical or perhaps even possible to maintain a serious dedication to both writing and coding.What brings me to this conclusion is the growing realization that working on a JRuby book would--for me--mean a good bit less time spent working on JRuby and related projects. I fully intend to make a large contribution to the eventual JRuby book, but JRuby as a passion has meant most of my waking hours are spent working on real, difficult problems (and in some cases, really difficult problems). It physically pains me to consider taking time away from that work.And I do not believe it's from a lack of interest in writing. I have long wanted to write a book, and as most of my blog posts should attest, I love putting my thoughts and ideas into a written form. I enjoy crafting English prose almost as much as I enjoy crafting excellent code. But at the end of the day, I am still a coder, and that is where my heart lies. I suspect I am not alone.When I decided to write this post, I tried to think of concrete examples. Though many came to mind, I could not think of a way to name names without seeming malicious or disrespectful. So I leave it as an exercise for the reader. Am I totally off base? Or is there a direct correlation between the quality and breadth of an author's work and a suspicious (or obvious) lack of real, concrete development? [Less]
|
|
Posted
over 18 years
ago
by
Charles Oliver Nutter
At conferences and online, Tom and I have long been talking about a mystery deployment option coming soon from the GlassFish team. It would combine the agile command-line-friendly model of Mongrel with the power and simplicity of deploying to a Java
... [More]
application server. We have shown a few quick demos, but they have only been very simple and very limited. Plus there was no public release we could give people.Until Now.Today, you can finally download the GlassFish-Rails preview release gem.So what is this tasty little morsel? Well, it's a 2.9MB Ruby gem containing the GlassFish server and the Grizzly connector for JRuby on Rails. It installs a "glassfish_rails" script in JRuby's bin directory, and you're done.Witness!~ $ gem install glassfish-gem-10.0-SNAPSHOT.gemSuccessfully installed GlassFish, version 10.0.0~ $ glassfish_rails testappSep 14, 2007 3:00:45 PM com.sun.enterprise.v3.services.impl.GrizzlyAdapter postConstructINFO: Listening on port 8080Sep 14, 2007 3:00:46 PM com.sun.enterprise.v3.services.impl.DeploymentService postConstructINFO: Supported containers : phobos,php,web,jrubySep 14, 2007 3:00:46 PM com.sun.grizzly.standalone.StaticResourcesAdapter <init>INFO: New Servicing page from: /Users/headius/testapp/public/Users/headius/NetBeansProjects/jruby/lib/ruby/gems/1.8/gems/actionmailer-1.3.3/lib/action_mailer.rb:50 warning: already initialized constant MAX_LINE_LENSep 14, 2007 3:00:53 PM com.sun.enterprise.v3.server.AppServerStartup runINFO: Glassfish v3 started in 9233 msThat's all there is to it...you've got a production-ready server. Oh, did I mention you only have to run one instance? No more managing a dozen mongrel processes, ensuring they stay running, starting and stopping them all. One command, one process.Of course this is a preview...we expect to see bug reports and find issues with it. For example, it currently deploys under a context rather than at the root of the server, so my app above would be available at http://localhost:8080/testapp instead of http://localhost:8080/. That's going to be fixed soon (and configurable) but for now you'll want to set the following in environment.rb:ActionController::AbstractRequest.relative_url_root = "/<app name>/"ActionController::CgiRequest.relative_url_root = "/<app name>/"And of course, you're going to be running JRuby, so you'll need to take that into consideration. JRuby's general Rails performance still needs more tweaking and work to surpass Mongrel Ruby, but out of the box you already get stellar static-file performance with the GlassFish gem...something like 2500req/s for the testapp index page on my system. The remaining JRuby performance is continuing to improve as well...we'll get there soon.So! Give it a try, report bugs on the GlassFish issue tracker, and let us know on the GlassFish mailing lists what you'd like to see improved.Mongrel...your days are numbered. [Less]
|
|
Posted
over 18 years
ago
by
Ola Bini
So, for various undisclosed reasons it's time to start seriously hacking XML. Now, the end artifact of this will be one of the few situations where XML is actually justified and makes this process better.Of course, Emacs is a must for this challenge.
... [More]
I wouldn't even try doing it without a real editor. Now, the undisputed king of XML in Emacs is nXML-mode. I want it everywhere. So the first step is to bring out Trang and convert all DTD's into RelaxNG. Then edit schemas.xml and we're running. Well, except for the simple fact that Emacs refuses to load anything else than xml-mode automatically. That sucks.So after lots of looking, it seems there is a new magic-mode-alist that can look at the beginning of a buffer and "magically" decide what kind of buffer we're dealing with. For some reason this behavior overrides my carefully laid out auto-mode-alist. Well. The solution for all you people is simple. Just add this snippet late in your loading process:(setq magic-mode-alist (cons '("<\\?xml " . nxml-mode) magic-mode-alist))(fset 'xml-mode 'nxml-mode) [Less]
|
|
Posted
over 18 years
ago
by
Ola Bini
Put it down to my general ignorance - I've never realized that JavaScript has send/perform, and has had it for a long, long time. Of course, it only works for methods that exists on the object. Or? Is there any way of capturing non-existent
... [More]
method-calls/property look-ups like method_missing does?Anyway, send:function SendTester() {}SendTester.prototype.foo = function() { print("Hello");};new SendTester().foo();var name = 'foo';new SendTester()[name]();Please, tell me something more cool I've been able to do in JavaScript in browsers for 5-10 years but didn't know about! [Less]
|
|
Posted
over 18 years
ago
by
Charles Oliver Nutter
Answer: Very Easy!Get the Codesvn co http://svn.codehaus.org/jruby/trunk/jrubycd jrubyantRun Your Built JRubyexport PATH=$PATH:$PWD/binjruby my_script.rbInstall Gemsgem install somegemORjruby -S gem install somegemRun the Benchmarksjruby -J-server -O
... [More]
test/bench/bench_method_dispatch.rb(-J-server uses the "server" JVM and -O disables ObjectSpace)Build and Test Your Changesant clean testLook For Bugs To Fix or Report Your OwnJRuby JIRA (bug tracker)Join the Mailing ListsJRuby Mailing ListsJoin Us on IRCChannel #jruby on FreeNode IRCWe're waiting to hear from you! [Less]
|
|
Posted
over 18 years
ago
by
Ola Bini
With all the current talk of DSLs and concurrency, what I find lacking is discussions about how to combine the two. Of course, domain specific languages are incredibly important - they create a logical separation between the implementors of the
... [More]
business logic, and the people implementing the actual implementation of the DSL. Does it seem like a strange idea to want many DSLs to be able to run parallel to each other? I would imagine that in most cases a DSL that describes business rules and business logic is sequential in the particulars, but that there are also larger concurrency possibilities. This should be totally invisible for the business rule implementor in most cases - the runtime system should be able to run everything as efficient as possible.A natural way of looking at DSLs is as declarative languages. In many cases that's the way you write them (just look at the ActiveRecord API. it looks very declarative - it just happens to be implemented using imperative primitives). Now, if the language is truly declarative it should be side effect free. In the end, that isn't a real goal, but if it would be possible to clearly understand which parts of the rules are using side effects, the rest of the implementation should be able to run totally concurrently.These kinds of things should be possible to implement in any language with sane multi threading/multi processing. That said, I wouldn't want the task of doing it with Java's concurrency primitives if I can help it. So what kind of tools would be helpful? Possibly Erlang of course, since it's already functional and that makes the identification of side effects much easier. Another possible alternative seems to be Gambit Scheme and Termite.Anyone else thinking about these issues? Is there any research going on that would shed some light on it? And further, what's the next step? Why haven't this question already been discussed? It seems to be well time for it now. [Less]
|
|
Posted
over 18 years
ago
by
Charles Oliver Nutter
A couple interesting "Bossies" were awarded by InfoWorld this week:Best Open Source Programming Language - Summary: Ruby gets mad props for a vibrant community and a diverse range of implementations (e.g. JRuby), and then they go squishy and say "and
... [More]
these other languages are great too!"Best Open Source IDE - InfoWorld heaps praise on NetBeans largely because it has *not* gone the way of an amorphous, all-encompassing "platform" and has continued to take risks to improve the overall experience of the IDE. Before the work on NetBeans 6 (don't download M10; use a daily build) I was a nay-sayer myself; having used NetBeans 6 for many months now, I can honestly say it's far better than NetBeans 5.5 and has caught up or passed Eclipse in many ways. There's more to do, but I'm extremely impressed with the progress.I try not to be too much of a Sun marketing shill, but both Bossies are pretty close to my heart. JRuby has been my passion for three years now, and NetBeans has taken a serious about face with greatly improved Java support and best-in-class Ruby support. It's good to see some recognition for hard work. [Less]
|
|
Posted
over 18 years
ago
by
Charles Oliver Nutter
Hello again friends! It's time to update you on the status of the JRuby compiler.Compiler StatusI've been working feverishly for the past several weeks to get the rest of the compiler complete. Currently, it's able to handle the majority of Ruby
... [More]
syntax. Here's a list of the remaining language features that do not compile:"rescue" blocks; exception handling in Ruby is rather complicated, and there's some particularly odd uses of rescue that will be a bit tricky to support with normal Java exception-handling."class var declaration" is not yet supported. This is when you declare a class variable (@@foo) from within the body of a class or module. This primarily affects compiling class bodies, so although it prevents AOT compilation of some scripts, it doesn't usually affect individual methods."opt n" execution. This is specifying "-n" to the Ruby runtime, and it loops the provided script as though it were surrounded by "while gets(); ... end". It's useful for line-by-line processing of stdin."post execution" blocks. Post exe blocks are when you specify an END { ... } block somewhere in your script. These blocks are saved up and executed at the end of the script execution, regardless of where they appear in the script. They're a bit like Kernel#at_exit blocks."retry". Tell me friends, do you know what "retry" actually does? Retry is used within a block/closure, and it causes the method containing the closure to be re-called anew. And as an interesting quirk, the original arguments to the method are re-evaluated, so if you call foo(bar()) and a retry is triggered within foo(), bar() will get invoked again for the retried call to foo(). Weird, eh? Update: I didn't explain this well. Here's another attempt: if you have the following code:def foo(x = bar()); 1.times {retry}; endAnd you call foo with no arguments, allowing the default argument logic to fire, retry will cause that logic to fire again and again. It's essentially re-entering the method anew with the original arguments, but causing *argument processing* to be revisited. I'm not sure why you'd want this behavior, since it could frequently result in default arguments to re-call methods that might only be valid the first time.Some non-local flow control is not yet complete. Non-local flow control happens any time you return, break, or next from within a block (when not immediately inside a normal loop construct). Much of non-local flow control is working, but I need to flush out any remaining cases that aren't running correctly.It's a pretty short list, eh? Obviously "rescue" is the biggest and trickiest item here. Without exception handling, it's hard to say the compiler is near completion. The complications I mentioned involve the ability to embed rescue processing into arbitrary expressions. Here's a good example:a = [1, 2, (begin; raise; rescue; 3; end)]When this code is compiled, it turns into a local variable assignment. The value assigned is a literal array construction with three elements: a Fixnum 1, a Fixnum 2, and a rescued block of code. The typical way to construct the array then is to follow these steps:Construct an array of the appropriate sizeDup the array referencePush a constant integer zeroPush Fixnum 1Insert Fixnum 1 at index zero in the array. This consumes the dup'ed array, the index, and the Fixnum1.Dup the array reference againPush a constant integer onePush Fixnum 2Insert Fixnum 2Dup the array reference againPush a constant integer twoNow it gets complicated; we must recurse in the compiler to handle the rescue blockThe rescue block is compiled and a "raise" is triggered in the codeThe exception raised is handled, resulting in the whole rescue leaving a Fixnum 3 on the stackInsert the Fixnum 3Construct a RubyArray object with the remaining object arrayNow that seems simple enough. However there's a sneaky complication at steps 13 and 14: catching an exception clears the operand stack, and the original created array, its duplicated reference, and the integer two disappear as a result. The value "returned" from the rescue section therefore has nowhere to go.We will likely have to solve this complication in one of two ways:We could save off the stack when entering code that might trigger exception handlingWe could put exception-handling logic in a separate method and invoke it in-place, thereby protecting our executing stack from clearage.It remains to be seen which mechanism will work out to be simplest to compile and most performant.A Nice Performance MilestoneAnd on the topic of performance, the recent compiler work has allowed us to reach a new milestone: we now exceed Ruby 1.8.6's performance on M. Edward (Ed) Borasky's MatrixBenchmark.Some months back, after the Mountain West RubyConf in Salt Lake City, Ed posted an interesting blog entry where he professed a lot of confidence in JRuby's future. We emailed a bit offline, and he pointed me to this matrix benchmark he'd been using to measure the relative performance of Ruby 1.8.6 and Ruby 1.9 (YARV). I told him I'd give it a try.Originally, we were perhaps 50% to 100% slower than Ruby 1.8.6. This was back when hardly anything was compiling, and there had been few serious efforts to optimize the JRuby runtime. Performance slowly crept up as time went on. But as recent as a week ago, JRuby performance was still roughly 20-25% slower than 1.8.6.So last week, I dug into it a bit more. I turned on JRuby's JIT logging (-J-Djruby.jit.logging=true) and verbose logging (-J-Djruby.jit.logging.verbose=true) to log compiling and non-compiling methods, respectively. As it turned out, the "inverse_from" method in matrix.rb was not yet compiling...and it was where the bulk of MatrixBenchmark's work was happening.The final sticking point in the compiler for this method was "operator element assignment" syntax, or basically anything that looks like a[0] = 5. It's a little involved to compile; you have to retrieve the element, calculate the value, call the operator method, and reassign all in one operation. For the ||= or &&= versions, you have to perform a boolean check against the element to see if you should proceed to the assignment. A good bit of compiler code, but it had to be done.So then, with "OpElementAsgn" compiling, it was time to re-run the numbers. And finally, finally, we were comfortably exceeding Ruby 1.8.6 performance:Ruby 1.8.6:Hilbert matrix of dimension 128 times its inverse = identity? true586.110000 5.710000 591.820000 (781.251569)JRuby trunk, Java 6 server, ObjectSpace disabled:Hilbert matrix of dimension 128 times its inverse = identity? true372.950000 0.000000 372.950000 (372.950000)Or should I say vastly exceeding? By my calculation this is an easy 2x performance increase, and perhaps a 70% improvement just by getting this one extra method to compile.On Beyond ZebraI believe we're pretty well on-target to have the compiler completed by RubyConf in November. I'm about to embark on a refactoring adventure to prepare for the stack-juggling I'll have to do to support rescue blocks. That will mean minimal progress on adding to the compiler until the end of the month, but ideally the refactoring will make it easy to get rescue compilation complete. The others are just a matter of spending some time.Once the JRuby compiler is complete, we will start testing in earnest against a fully pre-compiled Ruby stdlib. Along with that, we'll wire in support for pre-compiling RubyGems as they install and pre-compiling Ruby scripts as they are executed and loaded. Much of this works already in prototype form, but it waits for the completion of the compiler to go into general use.I also have plans for a "static" compiler for JRuby that enable compiling Ruby classes into normal, instantiable, callable, static Java classes. This would bring us on par with other compiled languages on the JVM, and allow you to directly instantiate and invoke JRuby/Ruby objects from within your Java code.Beyond all this work, Tom and I have been discussing a whole raft of performance improvements we could make to the underlying JRuby runtime. There's a lot more performance to be had, and it's just around the corner.Exciting times, friends. Exciting times. [Less]
|