Front page | perl.dbi.dev |
Postings from April 2012
Re: Changes to make DBIS more efficient
Thread Previous
From:
Tim Bunce
Date:
April 18, 2012 04:36
Subject:
Re: Changes to make DBIS more efficient
Message ID:
20120418113546.GH588@timac.local
Perfect! Applied. Many thanks Dave.
Tim.
On Wed, Apr 18, 2012 at 11:48:31AM +0100, Dave Mitchell wrote:
> On Fri, Mar 02, 2012 at 05:04:29PM +0000, Dave Mitchell wrote:
> > On Fri, Mar 02, 2012 at 03:23:30PM +0000, Dave Mitchell wrote:
> > > I'd be happy in principle, although some guidance would be welcome
> >
> > Also in particular, what needs to continue happening across an API
> > change? Is it just that a driver, compiled and installed against an old
> > DBI, must continue to work if the DBI is upgraded?
>
> I've now attached a revised DBIS patch. The only difference is that
> the new DBI continues to store a pointer to the dbi_state struct in
> $DBI::_dbistate, so that DBD modules compiled against the old DBI can
> continue to retrieve the struct the old way. Once recompiled, they'll
> start to use the new method.
>
> IIUC, this means that there are no binary or backwards compatibility
> issues, and no API version numbers need bumping.
>
> --
> The optimist believes that he lives in the best of all possible worlds.
> As does the pessimist.
> From 0fb5fd6a7099c5fc40bd0b9d40b8b34d748533b5 Mon Sep 17 00:00:00 2001
> From: David Mitchell <davem@iabyn.com>
> Date: Fri, 10 Feb 2012 13:11:13 +0000
> Subject: [PATCH] under ithreads, make DBIS efficient for DBD::*
>
> rather than the slow looking up of $DBI::_dbistate on every use of DBIS,
> convert DBIS into a call to a C-level function that returns the address of
> the dbi_state struct.
>
> Since the C-level function is only directly callable from DBI, store its
> address in an XSUB, so that the DBD:* modules can retrieve the function's
> address and cache it in a static var.
>
> We continue to store the dbi_state struct address within $DBI::_dbistate
> too, so that DBD modules compiled against an older DBI will continue to
> work if the DBI is upgraded but the DBD not recompiled.
> ---
> DBI.pm | 4 +---
> DBI.xs | 39 +++++++++++++++++++--------------------
> DBIXS.h | 39 +++++++++++++++++++++++++++------------
> 3 files changed, 47 insertions(+), 35 deletions(-)
>
> diff --git a/DBI.pm b/DBI.pm
> index 4e02e8c..614ffae 100644
> --- a/DBI.pm
> +++ b/DBI.pm
> @@ -519,10 +519,8 @@ END {
>
>
> sub CLONE {
> - my $olddbis = $DBI::_dbistate;
> _clone_dbis() unless $DBI::PurePerl; # clone the DBIS structure
> - DBI->trace_msg(sprintf "CLONE DBI for new thread %s\n",
> - $DBI::PurePerl ? "" : sprintf("(dbis %x -> %x)",$olddbis, $DBI::_dbistate));
> + DBI->trace_msg("CLONE DBI for new thread\n");
> while ( my ($driver, $drh) = each %DBI::installed_drh) {
> no strict 'refs';
> next if defined &{"DBD::${driver}::CLONE"};
> diff --git a/DBI.xs b/DBI.xs
> index 64dc5b1..a9e9000 100644
> --- a/DBI.xs
> +++ b/DBI.xs
> @@ -127,8 +127,6 @@ char *neatsvpv _((SV *sv, STRLEN maxlen));
> SV * preparse(SV *dbh, const char *statement, IV ps_return, IV ps_accept, void *foo);
> static meth_types get_meth_type(const char * const name);
>
> -DBISTATE_DECLARE;
> -
> struct imp_drh_st { dbih_drc_t com; };
> struct imp_dbh_st { dbih_dbc_t com; };
> struct imp_sth_st { dbih_stc_t com; };
> @@ -310,13 +308,20 @@ typedef struct {
>
> START_MY_CXT
>
> -#if defined(MULTIPLICITY) || defined(PERL_OBJECT) || defined(PERL_CAPI)
> -# undef DBIS
> -# define DBIS (MY_CXT.dbi_state)
> -#endif
> +#undef DBIS
> +#define DBIS (MY_CXT.dbi_state)
>
> #define g_dbi_last_h (MY_CXT.dbi_last_h)
>
> +/* allow the 'static' dbi_state struct to be accessed from other files */
> +dbistate_t**
> +_dbi_state_lval(pTHX)
> +{
> + dMY_CXT;
> + return &(MY_CXT.dbi_state);
> +}
> +
> +
> /* --- */
>
> static void *
> @@ -521,15 +526,12 @@ dbi_bootinit(dbistate_t * parent_dbis)
> dbistate_t* DBISx;
>
> DBISx = (struct dbistate_st*)malloc_using_sv(sizeof(struct dbistate_st));
> -
> - /* publish address of dbistate so dynaloaded DBD's can find it,
> - * taking care to store the value in the same way it'll be used
> - * to avoid problems on some architectures, for example see
> - * http://rt.cpan.org/Public/Bug/Display.html?id=32309
> - */
> - sv_setiv(get_sv(DBISTATE_PERLNAME, GV_ADDMULTI), 0); /* force SvIOK */
> DBIS = DBISx;
> - DBIS_PUBLISHED_LVALUE = DBISx;
> +
> + /* make DBIS available to DBD modules the "old" (<= 1.618) way,
> + * so that unrecompiled DBD's will still work against a newer DBI */
> + sv_setiv(get_sv("DBI::_dbistate", GV_ADDMULTI),
> + PTR2IV(MY_CXT.dbi_state));
>
> /* store version and size so we can spot DBI/DBD version mismatch */
> DBIS->check_version = check_version;
> @@ -547,12 +549,6 @@ dbi_bootinit(dbistate_t * parent_dbis)
> DBIS->thr_owner = PERL_GET_THX;
> #endif
>
> - DBISTATE_INIT; /* check DBD code to set DBIS from DBISTATE_PERLNAME */
> -
> - if (DBIS_TRACE_LEVEL > 9) {
> - sv_dump(DBISTATE_ADDRSV);
> - }
> -
> /* store some function pointers so DBD's can call our functions */
> DBIS->getcom = dbih_getcom;
> DBIS->clearcom = dbih_clearcom;
> @@ -4346,6 +4342,9 @@ BOOT:
> (void)cv;
> (void)items; /* avoid 'unused variable' warning */
> dbi_bootinit(NULL);
> + /* make this sub into a fake XS so it can bee seen by DBD::* modules;
> + * never actually call it as an XS sub, or it will crash and burn! */
> + (void) newXS("DBI::_dbi_state_lval", (XSUBADDR_t)_dbi_state_lval, __FILE__);
>
>
> I32
> diff --git a/DBIXS.h b/DBIXS.h
> index 7502af8..22a18de 100644
> --- a/DBIXS.h
> +++ b/DBIXS.h
> @@ -467,8 +467,6 @@ struct dbistate_st {
> #define set_attr(h, k, v) set_attr_k(h, k, 0, v)
> #define get_attr(h, k) get_attr_k(h, k, 0)
>
> -#define DBISTATE_PERLNAME "DBI::_dbistate"
> -#define DBISTATE_ADDRSV (get_sv(DBISTATE_PERLNAME, 0x05))
> #define DBILOGFP (DBIS->logfp)
> #ifdef IN_DBI_XS
> #define DBILOGMSG (dbih_logmsg)
> @@ -476,28 +474,45 @@ struct dbistate_st {
> #define DBILOGMSG (DBIS->logmsg)
> #endif
>
> -
> /* --- perl object (ActiveState) / multiplicity hooks and hoops --- */
> /* note that USE_ITHREADS implies MULTIPLICITY */
> -#define DBIS_PUBLISHED_LVALUE (*(INT2PTR(dbistate_t**, &SvIVX(DBISTATE_ADDRSV))))
> +
> +typedef dbistate_t** (*_dbi_state_lval_t)(pTHX);
> +
> +# define _DBISTATE_DECLARE_COMMON \
> + static _dbi_state_lval_t dbi_state_lval_p = 0; \
> + static dbistate_t** dbi_get_state(pTHX) { \
> + if (!dbi_state_lval_p) { \
> + CV *cv = get_cv("DBI::_dbi_state_lval", 0); \
> + if (!cv) \
> + croak("Unable to get DBI state function. DBI not loaded."); \
> + dbi_state_lval_p = (_dbi_state_lval_t)CvXSUB(cv); \
> + } \
> + return dbi_state_lval_p(aTHX); \
> + } \
> + typedef int dummy_dbistate /* keep semicolon from feeling lonely */
> +
> #if defined(MULTIPLICITY) || defined(PERL_OBJECT) || defined(PERL_CAPI)
>
> -# define DBISTATE_DECLARE typedef int dummy_dbistate /* keep semicolon from feeling lonely */
> -# define DBISTATE_INIT_DBIS typedef int dummy_dbistate2; /* keep semicolon from feeling lonely */
> +# define DBISTATE_DECLARE _DBISTATE_DECLARE_COMMON
> +# define _DBISTATE_INIT_DBIS
> # undef DBIS
> -# define DBIS DBIS_PUBLISHED_LVALUE
> -# define dbis DBIS_PUBLISHED_LVALUE /* temp for old drivers using 'dbis' instead of 'DBIS' */
> +# define DBIS (*dbi_get_state(aTHX))
> +# define dbis DBIS /* temp for old drivers using 'dbis' instead of 'DBIS' */
>
> #else /* plain and simple non perl object / multiplicity case */
>
> -# define DBISTATE_DECLARE static dbistate_t *DBIS
> -# define DBISTATE_INIT_DBIS (DBIS = DBIS_PUBLISHED_LVALUE)
> +# define DBISTATE_DECLARE \
> + static dbistate_t *DBIS; \
> + _DBISTATE_DECLARE_COMMON
> +
> +# define _DBISTATE_INIT_DBIS DBIS = *dbi_get_state(aTHX);
> #endif
>
> # define DBISTATE_INIT { /* typically use in BOOT: of XS file */ \
> - DBISTATE_INIT_DBIS; \
> + _DBISTATE_INIT_DBIS \
> if (DBIS == NULL) \
> - croak("Unable to get DBI state from %s at %p. DBI not loaded.", DBISTATE_PERLNAME, (void*)DBISTATE_ADDRSV); \
> + croak("Unable to get DBI state. DBI not loaded."); \
> DBIS->check_version(__FILE__, DBISTATE_VERSION, sizeof(*DBIS), NEED_DBIXS_VERSION, \
> sizeof(dbih_drc_t), sizeof(dbih_dbc_t), sizeof(dbih_stc_t), sizeof(dbih_fdc_t) \
> ); \
> --
> 1.7.4.4
>
Thread Previous