[Dbix-class] Why is prefetch so slow?

Mark Lawrence nomad at null.net
Wed Oct 17 23:19:04 GMT 2007


On Tue Oct 16, 2007 at 05:21:27PM +0930, Jon Schutz wrote:
> On Fri, 2007-10-12 at 17:01 +0930, Jon Schutz wrote:
> > In my code I have a DBIx::Class query with prefetch that is taking about
> > 1.2 seconds to execute.  If I remove the prefetch, it takes 0.2 seconds.
> > The actual SQL query takes 0.00 seconds with or without the join.  The
> > number of records is the same with and without the prefetch/join.
...
> > 
> > Is anyone aware of this performance issue, or, even better, does anyone
> > know how to fix it???
> 
> Having spent a good part of the day with a profiler and trace
> statements, I believe I have identified the major source of the problem
> - 'use overload' in DBIx::Class::ResultSourceHandle.

This sounds similar to an issue I had with one of my XML modules.
The most likely cause of the slowdown is not the 'use overload' itself,
but some repeated test for existence or a string comparison.

For example, one often sees this kind of code:

    if ($obj) {
        # do something with $obj
    }

    # or maybe even by mistake the following:

    if ($obj eq $obj2) {
        # do something with $obj(2)
    }

The test for ($obj) (and most definately the 'eq' test) can invoke
stringification, which with a non-string-overloaded object is very quick.
Usually this takes the form Class=HASH(0x504290). However if some
expensive '""' method gets called instead then the cost of the test
naturally goes up.

I bet somewhere (either within DBIC or your own code) there is some kind
of test like this in a critical path.

I don't know for what convenience the overloading was used, but assuming
it was there for a reason the better solution is to change the test to
one of definedness:

    if (defined $obj) {
        # do something with $obj
    }

or a numeric test in the case of comparison:

    if ($obj == $obj2) {
        # do something with $obj(2)
    }

> So, what would be the implications of removing the overloaded string
> operator?  If overload is removed, the only test that fails is
> 84serialize.t.  It seems the main purpose of the overload is to tidy up
> Data::Dumper output.  It also avoids a full comparison if the
> ResultSourceHandle class by is_deeply in 84serialize.t.

Sorry, can't say anything on the implications. Either have to do some
more investigation into the reason for the overload (maybe there are
some legitmate string comparisons somewhere), or ask the person who
wrote it...

Mark.
-- 
Mark Lawrence



More information about the DBIx-Class mailing list