21 comments

[ 3.6 ms ] story [ 51.1 ms ] thread
This has been submitted before, but it didn't get much attention.

I stumbled onto it while researching hot code reloading in ruby.

Yeah, 2.5 years old :-) But luckily HN is not time sensitive like many sites, a lot of old stuff hits the front page.

With the hot code reloading features in some JVMs now, it'd be interesting to see if there's any case for it in JRuby one day.

I found hijack on your blog:

http://www.rubyinside.com/hijack-get-a-live-irb-prompt-for-a...

This ranks higher than the github repo while searching for "ruby attach running process." hnsearch showed the same article being submitted about 2 years ago, with not much interest showed.

I was a bit surprised. I was searching for HN thread as I was expecting some useful discussion, but found none. I assumed this is the kind of topic which would interest HN crowd, but looks like that isn't the case.

HN is a funny beast. Unless it's something affecting a YC company or an obviously big story, it's pot luck as to whether something will take off or not. Often the same story or same blog post will hit it big after multiple 1 point postings.

(I did the first HN post about TechCrunch's new design, 1 point.. later one went big :-) I've even done the first post of items on the 37signals blog and Mixergy that have sat at 1. All depends who's browsing the 'new' page in that 30 minute window!)

If you're so inclined, I'd also like to hear about the hot code reloading information you've found.
I didn't find much information concerning ruby. Basically, the approach to hot code reloading is:

1. Find a way to attach to a running process. Either leave a socket open, as done in twisted manhole; or directly attach to running process.

2. Once you are connected, if you get a repl in the same address space, you can redefine methods, classes etc.

See the example in the github README where he redefines a method.

3. Redefining running code is generally considered a bad idea. The usefulness of a repl to a running process is generally the analysis - you can monitor memory usage etc without changing anything.

4. When you do change things, it's mostly small changes viz. log calls to a particular method. Dummy example:

  class Foo
    alias_method :orig_handler, :handler
    def handler
      log_request
      orig_handler
    end
  end
5. The way erlang does it is it automatically reloads if the physical file changes. It's a bit hard to implement in Python/Ruby because it isn't supported out of the box, and figuring out the module dependency isn't reliable(if file a changes, how many files were depending on it?). The general approach is to restart the server.

6. But regardless, the remote repl gives you analysis and selective reloading which is also useful.

This is pretty cool. I like seeing 'cool hack' kinds of things submitted here.

Incidentally, this is something that Erlang can do pretty much out of the box.

Remote repl can be done in Python/Ruby in hackish ways. It's the transparent hot code swap which hasn't been done yet.

I haven't investigated it much, but Armin Ronacher(flask lead developer) has said reliable code reloading when a module changes is near about impossible, because there is no reliable way to figure out the dependencies. For the flask dev server, he defaulted to a clean restart.

From what little I have investigated, same holds for Ruby.

If attaching to a running process interests you, you will find these articles interesting:

http://weblog.jamisbuck.org/2006/9/25/gdb-wrapper-for-ruby

http://weblog.jamisbuck.org/2006/9/22/inspecting-a-live-ruby...

Here is something similar that I wrote for connecting a Clojure REPL to a Clojure/Java process:

https://github.com/djpowell/liverepl

Very cool. Does it share the address space i.e redefining methods affect the running code?
Yes. Fire up multiple live-repls and they'll all be connected to the same address-space, and function redefinitions in one will instantly be visible in the others. Fun if you're playing around with Clojure's concurrency constructs.
I'm one of the developers of jark[1][2], which does something vaguely similar [maintains a persistent jvm into which clojure code can be loaded and to which a clojure repl can be connected], and we decided to go with a native client, so that you can attach to a remote jvm without having java installed.

the cost is running an nrepl server in the jvm, but if you can manage that you could probably just reuse our client (I'm in the middle of pushing all jark functionality into the server so that the client is just an nrepl client and a repl)

[1] https://github.com/icylisper/jark-server [2] https://github.com/icylisper/jark-client

I've not worked on Hijack in a while. Seeing as there is still interest for it, I'll give it some love soon (I think it needs some updates for 1.9.3).
Thanks for your hard work. Not everyone knows how to mess with gdb and ruby C api, and even when you do, it's a bit unpleasant.

As far as active dev work goes, IMO this is the kind of software which should implement the bare minimum correctly, and then shouldn't be touched again unless something breaks it(1.9.3 or any other subsequent api changes).

Two benefits I see (esp. w/ rails)

1) Quick console start. As rails developers, we spend way too much time waiting for consoles to start. This could save at least an hour out of my month.

2) Dynamically change production logging level. While their are ways to send signals to your process to control the logging level, this seems far more natural. You could easily open up an existing process change the logging level; finish your work; change it back.

Any other ideas for where the would be useful?

Can be used to diagnose memory bloat issues by inspecting ObjectSpace.
> 1) Quick console start. As rails developers, we spend way too much time waiting for consoles to start. This could save at least an hour out of my month.

Won't a better idea be to leave the console running?

What about production consoles? And even with reload, what about those classes not in your autoload path?