Net::LDAP vs ruby/ldap


#1

The basic premise of this test was to see how long it would take to do
the following:

1000 Basic lookups on a known attribute/value pair over an unencrypted
connection using anonymous bind for each library.

This post is for informational purposes, I knew the NET::LDAP lib
would be slower but I wanted to see by how much.
{if you are new to ruby, the reason it is slower is because its a TRUE
ruby implementation of the LDAP rfc. while on the other hand the ruby/
ldap lib is a C front end to the openldap library}

Bottom line is – I just figured i would share.
Code:

require ‘benchmark’
include Benchmark

LOOP_COUNT = 1000
require ‘ldap’
require ‘net/ldap’

HOST = ‘somehost.com
S_ATTR = ‘some attribute that exists that can be lookedup’
S_VAL = ‘a value for the attribute that iss valid’
TREE_BASE = ‘a valid base ex. o=com’

class LdapTest

def net_ldap_test
ldap = Net::LDAP.new :host => HOST, :port => 389
filter = Net::LDAP::Filter.eq( S_ATTR, S_VAL )
ldap.search( :base =>TREE_BASE, :filter => filter ) do |entry|
a=entry.dn
end
nil
end

def ldap_test
conn = LDAP::Conn.new(HOST, LDAP::LDAP_PORT)
filter = “(#{S_ATTR}=#{S_VAL})”
conn.search(TREE_BASE, LDAP::LDAP_SCOPE_SUBTREE, filter) do |entry|
a=entry.dn
end
nil
end

ldap_test=LdapTest.new

Benchmark.bm(15) do |x|
x.report(“NET::LDAP:”) { for i in 1…LOOP_COUNT;
ldap_test.net_ldap_test; end }
x.report(“ruby-ldap”) { for i in 1…LOOP_COUNT ;
ldap_test.ldap_test; end }
end
end

My results.
user system total real
NET::LDAP: 7.150000 0.580000 7.730000 ( 19.494588)
ruby-ldap 0.210000 0.120000 0.330000 ( 11.853484)

ruby/ldap : http://ruby-ldap.sourceforge.net/
net::ldap : http://rubyforge.org/projects/net-ldap/

ruby --version
ruby 1.8.6 (2007-03-13 patchlevel 0) [i686-linux]


#2

On Apr 27, 1:07 pm, dacat removed_email_address@domain.invalid wrote:

ldap lib is a C front end to the openldap library}

ldap.search( :base =>TREE_BASE, :filter => filter ) do |entry|
end
end

ruby --version
ruby 1.8.6 (2007-03-13 patchlevel 0) [i686-linux]

While it’s interesting, I’m afraid I have to stick with net-ldap. The
problem with ruby-ldap is that it segfaults in conjunction with
WEBrick, as I know all too well.

Regards,

Dan


#3

On Sat, 28 Apr 2007, Daniel B. wrote:

ruby implementation of the LDAP rfc. while on the other hand the ruby/
require ‘net/ldap’
filter = Net::LDAP::Filter.eq( S_ATTR, S_VAL )
a=entry.dn
ldap_test.ldap_test; end }
net::ldap :http://rubyforge.org/projects/net-ldap/
Dan
my good friend justin crawford works heavily with ruby and ldap for the
universtiy of colorado managing a huge federated authentication system.
they
use the pure ruby ldap lib because the c version is unstable. he’s been
using
it for several years on a system that’s serving ~ 100,000 people - so i
think
it’s fast enough.

fyi.

-a


#4

On 4/27/07, dacat removed_email_address@domain.invalid wrote:

ruby implementation of the LDAP rfc. while on the other hand the ruby/
ldap lib is a C front end to the openldap library}

I’m not entirely sure how to interpret your reported benchmark since the
system and user times are so different for the two libraries. (I don’t
know
how benchmark reports time spent inside liblber and libldap or how it
measured time spent waiting for the network.) If I may assume that the
“real” column gives the amount of elapsed wall time for the two tests,
then
I’ll say these results (a ratio of about 1.7) more or less square with
my
expectations. On a test like this, the pure-Ruby library should take
between
1.4 and 1.6 times as long to complete. (Before an extensive optimization
I
did several months ago, I would have expected three times longer or
more.) I
repeated your test and I got roughly 1.4.

I then modified your test to use Net::LDAP#open rather than
Net::LDAP#new.
Somewhat in the manner of File#open, Net::LDAP#open makes a network
connection, binds, and then performs all ldap operations within a block
on
the same connection. Doing the test this way, the pure-Ruby library took
about half as much time as before. (This squares with expectations since
I’m
using an encrypted link to the LDAP server and the network activity is
an
important part of the runtime profile.)

The performance tradeoff between pure-Ruby and compiled C code is of
course
real, and will be compelling for some applications. In general, the
reasons
to prefer the pure-Ruby are the same as ever: no installation of client
libraries, better platform independence, somewhat better conformance
with
the RFCs (for example, as regards LDIF handling), and fully-documented
handling of the network. (libldap is known for hiding the underlying
socket
descriptors and doing unexpected things with them, leading to resource
leaks
and other bizarre bugs.)

I recently completed work on a Ruby-scriptable LDAP server, built on
Net::LDAP and the EventMachine library. This project is intended for
enterprise use as a caching proxy for an A/D global catalog. So far
performance has not been a problem.

I’ve also used Net::LDAP in an identity-aggregator for a large
enterprise,
simultaneously querying and aggregating results from a large number of
LDAP
directories. In this application, performance was a problem,
especially
compared to ldapsearch (which uses libldap). Careful tuning of Net::LDAP
made the performance acceptable, but it was still noticeably less.
However
we went with the pure-Ruby version because it was easier to script, and
actually quite a bit less buggy, especially with coded binary data.


#5

On Apr 27, 10:16 pm, removed_email_address@domain.invalid wrote:

my good friend justin crawford works heavily with ruby and ldap for the
universtiy of colorado managing a huge federated authentication system. they
use the pure ruby ldap lib because the c version is unstable. he’s been using
it for several years on a system that’s serving ~ 100,000 people - so i think
it’s fast enough.

I’d be interested to discover exactly what “unstable” means here, so
that I can fix the problem.

I’d also like to see code that can reproduce the segfault in
combination with WEBRick.

Thanks,

Ian