I've been messing around with Berkeley DB & Ruby this evening as an experiment. I wanted to try out their replication support along with master election. This may wind up being a faster way of doing master election than the PAXOS library I wrote for ruby. Anyways, getting replication enabled in Ruby BDB on Leopard wasn't straightforward. The macports versions of Berkeley DB don't have threads enabled so the replication manager isn't there. So...
First build DB46 with threads
download db-4.6.21 from oracle
tar -zxf db-4.6.21.tar.gz
cd db-4.6.21/build_unix
../dist/configure --with-prefix=/usr/local --enable-cxx --disable-tcl --enable-pthread_api
make
sudo make install
Then build BDB
wget ftp://moulon.inra.fr/pub/ruby/bdb.tar.gz
tar -zxf bdb.tar.gz
cd bdb-0.6.2
ruby extconf.rb --with-db-dir=/usr/local/BerkeleyDB.4.6 --with-db-version=-4.6
make
sudo make install
You should now have a working Ruby/Berkely DB setup with replication working, hurray.
Showing posts with label ruby. Show all posts
Showing posts with label ruby. Show all posts
Tuesday, April 1, 2008
Friday, August 10, 2007
Why use parens in Ruby?
Here is another ruby gotcha. Ruby allows you to skip parenthesizing method calls. These two lines are equivelent:
set_table_name "users"
set_table_name("users")
In some cases this will make your code mildly more readable. In practice though this is dangerous. Consider this code:
if arr1.include? "foo" && !arr2.include? "bar" then
# do something
end
Ruby order of operations says that && will be evaluated prior to calling my_array.include?. So first you evaluate:
"foo" && !arr2.include? "bar"
Which always returns true or false. Then you evaluate;
if arr1.include? true
# do something
end
Which is clearly not what you intended. This code is correct:
if arr1.include?("foo") && !arr2.include?("bar") then
# do something
end
As a rule, you should never call a function without parenthesizing the parameters. Even if you are writing code which is not in an IF statement or is in an IF statement, but is not a part of boolean logic, you should still parenthesize it because it is possible someone else will come along and change your code not realizing this gotcha exists. Code defensively, use parens.
set_table_name "users"
set_table_name("users")
In some cases this will make your code mildly more readable. In practice though this is dangerous. Consider this code:
if arr1.include? "foo" && !arr2.include? "bar" then
# do something
end
Ruby order of operations says that && will be evaluated prior to calling my_array.include?. So first you evaluate:
"foo" && !arr2.include? "bar"
Which always returns true or false. Then you evaluate;
if arr1.include? true
# do something
end
Which is clearly not what you intended. This code is correct:
if arr1.include?("foo") && !arr2.include?("bar") then
# do something
end
As a rule, you should never call a function without parenthesizing the parameters. Even if you are writing code which is not in an IF statement or is in an IF statement, but is not a part of boolean logic, you should still parenthesize it because it is possible someone else will come along and change your code not realizing this gotcha exists. Code defensively, use parens.
Friday, July 20, 2007
Nice Ruby Reference
This site provides a references for many rdocs in one place
http://www.noobkit.com/
Covers:
ActionMailer 1.3.3
ActionPack 1.13.3
ActionWebService 1.2.3
ActiveRecord 1.15.3
ActiveSupport 1.4.2
Daemons 1.0.6
Ferret 0.11.4
Hpricot 0.6
net-ssh 1.1.2
pdf-writer 1.1.3
Rails 1.2.3
Rake 0.7.3
RedCloth 3.0.4
RFacebook 0.6.2
Rio 0.4.0
RSpec 1.0.5
Ruby 1.8.6
Syntax 1.0.0
http://www.noobkit.com/
Covers:
ActionMailer 1.3.3
ActionPack 1.13.3
ActionWebService 1.2.3
ActiveRecord 1.15.3
ActiveSupport 1.4.2
Daemons 1.0.6
Ferret 0.11.4
Hpricot 0.6
net-ssh 1.1.2
pdf-writer 1.1.3
Rails 1.2.3
Rake 0.7.3
RedCloth 3.0.4
RFacebook 0.6.2
Rio 0.4.0
RSpec 1.0.5
Ruby 1.8.6
Syntax 1.0.0
Tuesday, May 15, 2007
Rails & MySQL gotcha
Hey everyone, just so you know. Don't ever do this in MySQL:
SELECT * FROM foo WHERE id IS NULL;
MySQL has a known bug that will cause this to return the last row inserted into the DB, ie. something random, instead of what you are looking for. This is fixed in MySQL version 5.0.25 which will probably be in our next upgrade. Until then:
do this:
def find_user_by_id(user_id)
return nil if user_id == nil
@user ||= User.find_by_id(user_id )
@user
end
not this:
def find_user_by_id(user_id)
@user ||= User.find_by_id(user_id )
@user
end
For more information, see...
http://bugs.mysql.com/bug.php?id=14553
SELECT * FROM foo WHERE id IS NULL;
MySQL has a known bug that will cause this to return the last row inserted into the DB, ie. something random, instead of what you are looking for. This is fixed in MySQL version 5.0.25 which will probably be in our next upgrade. Until then:
do this:
def find_user_by_id(user_id)
return nil if user_id == nil
@user ||= User.find_by_id(user_id )
@user
end
not this:
def find_user_by_id(user_id)
@user ||= User.find_by_id(user_id )
@user
end
For more information, see...
http://bugs.mysql.com/bug.php
Wednesday, April 25, 2007
Hey guys, you may already know this but in ActionScript there is an object you can use for passing references to members functions of a class called Delegate. This is useful for associating event listeners to a method on an instance of a class rather than a static:
function hookEvent(element)
{
element.onSelectionChange = Delegate.create(this, this.on_change);
}
function on_change() // <-- note: not a static
{
// do stuff
}
Using this helps a lot with your code organization. This pattern is also available in javascript though it's slightly more arcane:
setTimeout((function() {this.sendPoll()}).bind(this), this.options.timeout);
-jay
function hookEvent(element)
{
element.onSelectionChange = Delegate.create(this, this.on_change);
}
function on_change() // <-- note: not a static
{
// do stuff
}
Using this helps a lot with your code organization. This pattern is also available in javascript though it's slightly more arcane:
setTimeout((function() {this.sendPoll()}).bind(this), this.options.timeout);
-jay
Monday, January 29, 2007
Log rotation in Ruby
I just checked in a modification to the standard log object that changes a few things to allow for nice log rotation. First, log objects you create through Log.create now use a wrapper class for the webrick log object. You can still use all the methods on the logger object like .info, .debug etc. However, the log engine now keeps track of all created logfiles & when it recieves a SIGUSR1 on linux it will reopen all the log files:
jay@foo:/var/log/call_svc$ ls
call_svc-std.log.1 call_svc-std.log.2
jay@foo:/var/log/call_svc$ ps -ef | grep ruby
jay 4435 4003 0 11:59 pts/0 00:00:02 ruby bin/ragi_server.rb
jay@foo:/var/log/call_svc$ kill -SIGUSR1 4435
jay@foo:/var/log/call_svc$ ls
call_svc-std.log call_svc-std.log.1 call_svc-std.log.2
So this means we can now create logrotate scripts that don't require restarting any services:
/var/log/call_svc/call_svc-std.log {
rotate 30
daily
postrotate
/sbin/kill -SIGUSR1 `cat /snapvine/pids/call_svc`
endscript
}
I'll try to find a moment to clean it up and post it...
-jay
jay@foo:/var/log/call_svc$ ls
call_svc-std.log.1 call_svc-std.log.2
jay@foo:/var/log/call_svc$ ps -ef | grep ruby
jay 4435 4003 0 11:59 pts/0 00:00:02 ruby bin/ragi_server.rb
jay@foo:/var/log/call_svc$ kill -SIGUSR1 4435
jay@foo:/var/log/call_svc$ ls
call_svc-std.log call_svc-std.log.1 call_svc-std.log.2
So this means we can now create logrotate scripts that don't require restarting any services:
/var/log/call_svc/call_svc-std.log {
rotate 30
daily
postrotate
/sbin/kill -SIGUSR1 `cat /snapvine/pids/call_svc`
endscript
}
I'll try to find a moment to clean it up and post it...
-jay
Sunday, December 24, 2006
Why use symbols in Ruby?
I ran a test where I did the following:
- created 100,000 random 32 character strings
- choose 1,000 of those strings randomly
- found each of the 1,000 strings in the 100,000 string array
I did this using strings, then the same exact string converted into symbols to see how the performance compares for symbol matching & string matching. Here are the results on my laptop:
Test String Time = 38.2969999313354
Test Symbol Time = 26.4219999313354
The results are independent of the ordering of the two operations and are fairly consistent. It is interesting how non-linear this is with the length of the string:
2 char/10k test set:
Test String Time = 1.84299993515015
Test Symbol Time = 1.35999989509583
8 char/10k test set:
Test String Time = 3.20300006866455
Test Symbol Time = 2.67199993133545
32 char/10k test set:
Test String Time = 3.15700006484985
Test Symbol Time = 2.73399996757507
256 char/10k test set:
Test String Time = 3.28099989891052
Test Symbol Time = 2.6560001373291
Yes, comparing 256 character strings took LESS time than comparing 32 character strings. Clearly there is some form of indexing in play here.
- created 100,000 random 32 character strings
- choose 1,000 of those strings randomly
- found each of the 1,000 strings in the 100,000 string array
I did this using strings, then the same exact string converted into symbols to see how the performance compares for symbol matching & string matching. Here are the results on my laptop:
Test String Time = 38.2969999313354
Test Symbol Time = 26.4219999313354
The results are independent of the ordering of the two operations and are fairly consistent. It is interesting how non-linear this is with the length of the string:
2 char/10k test set:
Test String Time = 1.84299993515015
Test Symbol Time = 1.35999989509583
8 char/10k test set:
Test String Time = 3.20300006866455
Test Symbol Time = 2.67199993133545
32 char/10k test set:
Test String Time = 3.15700006484985
Test Symbol Time = 2.73399996757507
256 char/10k test set:
Test String Time = 3.28099989891052
Test Symbol Time = 2.6560001373291
Yes, comparing 256 character strings took LESS time than comparing 32 character strings. Clearly there is some form of indexing in play here.
Subscribe to:
Posts (Atom)
