Coro-Mysql
view release on metacpan or search on metacpan
Makefile.PL view on Meta::CPAN
DBD::mysql => 0, # not actually a hard dependency
},
NAME => "Coro::Mysql",
VERSION_FROM => "Mysql.pm",
INC => (cfg "--include"),
LIBS => [cfg "--libs_r"],
);
if (eval "require EV::MakeMaker; require Coro::MakeMaker; 1") {
%wm = Coro::MakeMaker::coro_args (EV::MakeMaker::ev_args (%wm));
$wm{DEFINE} .= " -DHAVE_EV=1";
} else {
print <<EOF;
**
** Especially fast with EV!
**
** This module is especially fast when used together with EV as
** the event loop - but you don't have EV installed. Too bad,
** but I work with any event loop, including EV, using my
=head2 SPEED
This module is implemented in XS, and as long as mysqld replies quickly
enough, it adds no overhead to the standard libmysql communication
routines (which are very badly written, btw.). In fact, since it has a
more efficient buffering and allows requests to run in parallel, it often
decreases the actual time to run many queries considerably.
For very fast queries ("select 0"), this module can add noticable overhead
(around 15%, 7% when EV can be used) as it tries to switch to other
coroutines when mysqld doesn't deliver the data immediately, although,
again, when running queries in parallel, they will usually execute faster.
For most types of queries, there will be no extra latency, especially on
multicore systems where your perl process can do other things while mysqld
does its stuff.
=head2 LIMITATIONS
This module only supports "standard" mysql connection handles - this
means unix domain or TCP sockets, and excludes SSL/TLS connections, named
#if PVIO
/* must be first member */
struct st_ma_pvio_methods methods;
#else
#if DESC_IS_PTR
char desc[30];
const char *old_desc;
#endif
#endif
int magic;
SV *corohandle_sv, *corohandle;
int bufofs, bufcnt;
#if HAVE_EV
ev_io rw, ww;
#endif
char buf[VIO_READ_BUFFER_SIZE];
#if PVIO
struct st_ma_pvio_methods *oldmethods;
#else
xssize_t (*old_read)(VIOPTR, uchar *, size_t);
xssize_t (*old_write)(VIOPTR, const uchar *, size_t);
our->rw.data = (void *)sv_2mortal (SvREFCNT_inc (CORO_CURRENT));
ev_io_start (EV_DEFAULT_UC, &(our->rw));
CORO_SCHEDULE;
ev_io_stop (EV_DEFAULT_UC, &(our->rw)); /* avoids races */
}
else
#endif
{
dSP;
PUSHMARK (SP);
XPUSHs (our->corohandle);
PUTBACK;
call_sv ((SV *)readable, G_VOID | G_DISCARD);
}
}
if (rd <= 0)
return rd;
our->bufcnt = rd;
our->bufofs = 0;
our->ww.data = (void *)sv_2mortal (SvREFCNT_inc (CORO_CURRENT));
ev_io_start (EV_DEFAULT_UC, &(our->ww));
CORO_SCHEDULE;
ev_io_stop (EV_DEFAULT_UC, &(our->ww)); /* avoids races */
}
else
#endif
{
dSP;
PUSHMARK (SP);
XPUSHs (our->corohandle);
PUTBACK;
call_sv ((SV *)writable, G_VOID | G_DISCARD);
}
}
else if (ptr == (char *)p)
return -1;
else
break;
}
croak ("vio.vioclose has unexpected content during unpatch - wtf?");
#if HAVE_EV
if (use_ev)
{
ev_io_stop (EV_DEFAULT_UC, &(our->rw));
ev_io_stop (EV_DEFAULT_UC, &(our->ww));
}
#endif
SvREFCNT_dec (our->corohandle);
SvREFCNT_dec (our->corohandle_sv);
#if DESC_IS_PTR
vio->desc = our->old_desc;
#endif
#if PVIO
vio->methods = our->oldmethods;
#else
VIOM (vio)->vioclose = our->old_close;
VIOM (vio)->write = our->old_write;
I_EV_API ("Coro::Mysql");
I_CORO_API ("Coro::Mysql");
use_ev = 1;
#endif
}
XPUSHs (use_ev ? &PL_sv_yes : &PL_sv_no);
}
void
_patch (IV sock, int fd, unsigned long client_version, SV *corohandle_sv, SV *corohandle)
CODE:
{
MYSQL *my = (MYSQL *)sock;
VIOPTR vio = my_to_vio (my);
ourdata *our;
/* matching versions are required but not sufficient */
if (client_version != mysql_get_client_version ())
croak ("DBD::mysql linked against different libmysqlclient library than Coro::Mysql (%lu vs. %lu).",
client_version, mysql_get_client_version ());
&& VIOM (vio)->read != vio_read_buff)
croak ("vio.read has unexpected content - library mismatch, unsupported transport or API changes?");
#endif
#if PVIO
if (vio->type != PVIO_TYPE_UNIXSOCKET && vio->type != PVIO_TYPE_SOCKET)
croak ("connection type mismatch: Coro::Mysql only supports 'unixsocket' and 'socket' types at this time");
#endif
Newz (0, our, 1, ourdata);
our->magic = CoMy_MAGIC;
our->corohandle_sv = newSVsv (corohandle_sv);
our->corohandle = newSVsv (corohandle);
#if HAVE_EV
if (use_ev)
{
ev_io_init (&(our->rw), iocb, VIOSD (vio), EV_READ);
ev_io_init (&(our->ww), iocb, VIOSD (vio), EV_WRITE);
}
#endif
#if PVIO
/* with pvio, we replace methods by our own struct,
* both becauase the original might be read-only,
SPEED
This module is implemented in XS, and as long as mysqld replies quickly
enough, it adds no overhead to the standard libmysql communication
routines (which are very badly written, btw.). In fact, since it has a
more efficient buffering and allows requests to run in parallel, it
often decreases the actual time to run many queries considerably.
For very fast queries ("select 0"), this module can add noticable
overhead (around 15%, 7% when EV can be used) as it tries to switch to
other coroutines when mysqld doesn't deliver the data immediately,
although, again, when running queries in parallel, they will usually
execute faster.
For most types of queries, there will be no extra latency, especially on
multicore systems where your perl process can do other things while
mysqld does its stuff.
LIMITATIONS
This module only supports "standard" mysql connection handles - this
means unix domain or TCP sockets, and excludes SSL/TLS connections,
( run in 0.950 second using v1.01-cache-2.11-cpan-3cd7ad12f66 )