I´m gonna keep it simple: Ruby has an excellent native debugger, that runs when you insert the -r debug parameter when calling the interpreter, such as this:


ruby -r debug [debug options] [program file] [program arguments]

Debugger commands are:

b[reak] [file:]line Set breakpoint at given line in file (default current file).
b[reak] [file:]name Set breakpoint at method in file.
b[reak] Display breakpoints and watchpoints.
wat[ch] expr Break when expression becomes true.
del[ete] [nnn] Delete breakpoint nnn (default all).
disp[lay] expr Display value of nnn every time debugger gets control.
disp[lay] Show current displays.
undisp[lay] [nnn] Remove display (default all).
c[ont] Continue execution.
s[tep] nnn=1 Execute next nnn lines, stepping into methods.
n[ext] nnn=1 Execute next nnn lines, stepping over methods.
fi[nish] Finish execution of the current function.
q[uit] Exit the debugger.
w[here] Display current stack frame.
f[rame] Synonym for where.
l[ist] [start–end] List source lines from start to end.
up nnn=1 Move up nnn levels in the stack frame.
down nnn=1 Move down nnn levels in the stack frame.
v[ar] g[lobal] Display global variables.
v[ar] l[ocal] Display local variables.
v[ar] i[stance] obj Display instance variables of obj.
v[ar] c[onst] Name Display constants in class or module name.
m[ethod] i[nstance] obj Display instance methods of obj.
m[ethod] Name Display instance methods of the class or module name.
th[read] l[ist] List all threads.
th[read] [c[ur[rent]]] Display status of current thread.
th[read] [c[ur[rent]]] nnn Make thread nnn current and stop it.
th[read] stop nnn Make thread nnn current and stop it.
th[read] resume nnn Resume thread nnn.
[p] expr Evaluate expr in the current context. expr may include assignment to variables and method invocations.
empty A null command repeats the last command.

Source: PickAxe

When searching for bottlenecks, your best bet is to use the benchmark module to check the execution of code chunks. The best thing to learn how to deal with the benchmark module is checking its documentation here.

There´s also an easy way to track your code execution: The profiler. To run it, you should just put the -r profile parameter when calling the interpreter.


ruby -r profile [program file] [program arguments]

Seems like an easy way to track down those nasty bottlenecks! Still, the best way to ensure great performance is to keep your code clean and avoid creating unnecessary crap!

Hope I remember this when running after my slow applications cemeteries!

Today i was reading the chapter 10 of my Programming Ruby book, about Ruby Exception Handling, Catch and Throw. Found some really interesting stuff, as usual, and i´m gonna write it all down here.

Exception Objects

Ruby lets you insert exception/error information into an object of class Exception (or its children). This object is passed to the preceding code, searching for a declaration that some code is capable of handling that exception. You can create your own Exception classes. To do this, all you need is to make your class children of StandardError or one of its children. It´s as simple as it gets:

class SomeVeryNastyError < StandardError
end

Error Handling

Things useful to know when dealing with error handling:

  • To cast an exception, just use the raise or Kernel.raise method. Arguments can be: raise [Exception class, [Message, [Callback array]]]
  • The code that is gonna have exception handling should be wrapped inside a begin/rescue/end block if it´s multilined or you can use rescue as a statement modifier for single-lines. The arguments to rescue clause are the exception classes it can handle (comma-separated) and an optional local variable to store a reference to the Exception object.
    begin
    # some code...
    rescue MyError, BadError, StandardError => err_reference
    #rescue stuff...
    end
    
  • Along with rescue, there are the else clause and the ensure clause:
    Code inside the else clause will execute if no exceptions happen;
    Code inside the ensure clause is always executed when the block terminates.

    begin
      # some code is executing and..
      raise SomeVeryNastyError, "Very nasty error occurred!"
    rescue SomeVeryNastyError => err_reference
      # here comes the rescue!
      puts "An error ocurred: #{err_reference.inspect}"
      # rescue code ...
    else
      puts "No error occurred!"
    ensure
      # having an error or not ...
      puts "execution ended!"
    end
    
  • There can be multiple rescue clauses within a block.
    begin
    #some code
    rescue ForcedError
    puts "Forced Error occurred!"
    rescue StandardError
    puts "Standard Error occurred!"
    end
    
  • A reference to the associated raised Exception object is placed into the global variable $!
  • Within a rescue clause, you can call the retry method, so that the code block begins its execution again.
  • You can add your own attributes and methods to your Exception classes.
    class MyError < StandardError
    attr_reader :ok_to_retry
    def initialize(retry)
    @ok_to_retry = retry
    end
    end
    begin
    #some code ...
    raise MyError(true)
    rescue MyError
    if $1.ok_to_retry
        puts "Retrying..."
        retry
      else
        puts "Not retrying!"
      end
    end
    

Catch and Throw

If you ever need to get a signal to terminate execution of some code, you will be in good hands when using catch and throw.

Firstly, you specify what to “catch”: it can be a Symbol or a String. A code block comes after and will be executed until it runs to the end or until the specified catch argument is thrown with the throw method. The throw method supports two arguments: a Symbol/String and a return value.

a = catch(:fire) do
  puts "Catching fire now!"
  throw(:fire,"fireee!")
end
puts a
# => fireee!

And that´s it for today! I´m heading towards chapter 11 of Programming Ruby tonight!
Feel free to post comments and examples in order to help me and the other fellas!

Other references: Programming RubySkorks post on exceptionsGoogle