Archive for the 'visual studio integration' Category

Ruby debuggers

Monday, April 24th, 2006

I’ve now got the basic debugger more or less sorted. The next step in to build an ‘expression evaluator’ so that the watch window will work. It doesn’t look too bad, but it’s another half dozen or so COM interfaces to implement. The problem with this stuff is that it’s so low level. But to be honest, I can’t figure out a way Microsoft could have done it and yet retain the flexibility required to cover almost any situation.

For example, breakpoints aren’t just a simple ‘stop here’ sort of thing. You can have many breakpoints coming off one ‘pending’ breakpoint – breakpoints that only fire when a particular condition occurs, say. The these can either be ‘bound’ or in ‘error’. For a simple debugger like my current one, this is overkill, but you still have to abide by the Visual Studio model.

While doing the debugger, I did some research on existing Ruby debuggers. The results were quite interesting. The standard Ruby debugger, debug.rb, apparently executes around 100 times slower than running Ruby code without the debugger. Now that’s simply horrible. I wouldn’t want to debug any serious program with that. Active State have improved on this with their debugger to around 50 times. Better, but still unusable for a large program, I would think. Both of these debuggers use the tracing mechanism built into the Ruby interpreter to get a hook into the evaluator event source. However, it’s a pretty unsatisfactory way to go about things.

The last one I looked at was Arachno Ruby. This seems to have a 50 percent slowdown. That’s more like it! The problem is that Arachno has had to patch the Ruby interpreter to get this to work and patched interpreters are bad news. Not only are they non-standard, but you have to maintain them as well. Arachno currently doesn’t support 1.8.4 for example.

However, I’ve figured out a better way of running the Ruby interpreter in a fast debug mode without patching it. The trouble is, it isn’t at all easy to implement. The current Steel debugger (beta 0.6, not yet released) is just using the original slow debug.rb. The fast debugger will have to wait for the commercial version of Steel.

I had a good look at Arachno. Nice ideas there but there’s something slightly amiss. Say you want to write an IDE for Ruby, Perl, PHP and Python. Ok, ambitious – but doable: Active State have something there along those lines; probably taken them well over 20 man-years at a guess. Now let’s add in the fact that you want to be able to run it on Windows, Linux and Mac OS. Hmm, that’s challenging: making things portable is hard – just look at the work that’s gone into Ruby. So what do you chose to write it in: GNU Eiffel and some open source graphics package?? Now, that’s the heroic school of programming. The result (I’m guessing really) seems to have been that Arachno has spent a fair bit of time getting these wonderful open source things to work properly. That’s great if you have the time, money and inclination (personally I don’t). Still, I wish Arachno well.

Building an IDE of any sort is a big job (far more than one person can reasonably undertake). That’s why I’ve decided to stick firmly to Visual Studio – and that’s difficult enough. It does limit the scope to Ruby on Windows, but I’m happy with that for two reasons. First, I think it’s doable by two people in a reasonable timeframe. And secondly, there doesn’t seem to be any money in Linux products. Over and over again, I’ve seen companies produce stuff for Linux (Borland with Kylix is a notable example) only to withdraw after a short while. It’s true that a number of people have made money out of support for open source products. But I don’t know of many that have made money out of the raw product itself.

Debug bootstrap

Tuesday, April 11th, 2006

It’s taken me a good five days to get my head round the Visual Studio Debugger. For my first attempt, I tried to trap the Set Breakpoint command and go from there. Nope. Not even close. The debugger is a lot more complicated than that. It’s not made any easier by having documentation that’s aimed at a C++ implementation rather than a C# one. After a fruitless day spent trying to hack it in C#, I worked through the TextInterpreter example (which doesn’t work properly in the beta VSIP SDK I’m currently using). Even though it’s in C++, I got the general idea and was able to build a managed version reasonably easily - I’d definitely start with the C++ tutorial if I was doing it again.

The main problem with the debugger is that to build a simple (let alone one that lets you ‘edit and run’, say) you have to implement about ten COM interfaces. Then you have to build some sort of state machine on it’s own thread - plus any worker threads to handle the input and output to the Ruby interpreter itself. Each of the COM interface names starts with ‘IDebug’ so there’s IDebugProcess, IDebugProgram, IDebugProgramNode - and so on. Damned confusing. Then each interface has about ten methods and while they don’t all need coding, they need to be considered. It’s not a small job - and that’s before you get to any Ruby stuff.

One thing that struck me as I was doing the C# bits after the C++ tutorial, was how much faster it is to code in C#. Even with the ATL wizard, it still takes a lot longer than implementing the same interfaces with C#. I have to say that I’m coming round to the idea that Microsoft has done a reasonable job with COM and C#.

In passing, I found a tricky problem with the basic  IDE. The Steel splash icon had vanished (this appears on the Visual Studio startup splash screen along with C#, VB, etc.). The thing was, it had been visible in the past - but no longer! It turns out that the splash icons and menu commands are installed when you do a ‘devenv /setup’ command. But setup works differently from when you just run the IDE. In particular, the DTE automation isn’t initialised. The IDE setup sequence calls the package ‘Initialize’ command before the splash icon is loaded. If you try to access automation in the package Initialise, an exception is thrown and the icon loading is never called! Worse, nothing tells you this interesting fact. You have to turn logging on and look in the log file. The solution is to test for a null DTE in Initialize: if you are running setup, this is null, otherwise it’s set to something sensible.

I’m a big fan of VSIP, but it sure isn’t simple. There’s just a lot of stuff to learn.