From: Mike S. <msc...@ao...> - 2003-01-22 02:10:01
|
jc...@di... wrote: > Mike, > > do you want to carry this conversation over to log4perl-devel ? > if so, cc them in, and Ill follow it over. Sure ... everybody, please see below ... > > >> >> Ah, now I understand. I like the idea of being able to manipulate >> logging behaviour at this very granular level. However, the >> performance impact is overwhelming: >> >> Every log statement, no matter if it's actually active or not, will >> cause a call to caller() and get_logger(). This way, it doesn't >> really matter if you enable or disable logging, the load on the >> system will always like if you enabled DEBUG logging all over the >> place. That's something log4j has been designed to avoid. Is there a >> way of getting around this? >> > > Ive taken a 2nd swing at getting around the everytime AUTOLOAD, caller > problem. > > attached is a generic explanation which I put to perlmonks today, and > will put to perl-porters later, > after another round of nearest-neighbor reality checks. > > I also posted an earlier version of this to perlmonks.org, if youve > ever ben there > >------------------------------------------------------------------------ > >#!/usr/local/bin/perl -w >use strict; >no strict 'refs'; > >=for request for assistance > >im trying to work out an auto-categorization feature for >Log::Log4perl::AutoCategorize, a notional extension to its namesake. > >My exploratory version used AUTOLOAD on every Logger->invoke, and used >caller() to dynamically extract caller context, which is then used for >logging decisions. > >This works nicely, except for speed; it would be great to capture this >info once, either at compile phase, or on 1st invocation of an >autoload-vivified subroutine. > >=head GOAL > >use Log::Log4perl::AutoCategorize ( alias_as => 'Logger' ); > ># want simple invocation >Logger->debug(@_); > ># to invoke a late-vivified, custom-named function >Logger->debug_<$callerpkg,$caller_sub,$caller_ln>(@_); > ># which will be mapped at 1st use according to the config ># sub {return undef} is CONSTANT; > >=head1 PROBLEM > >I mentally file this as a function-name munging problem cuz I hope it >happens at compile time. That said, Im trying to solve it with >1st-time AUTOLOAD handling, cuz thats what I know. So, with these >blinders applied; > >Munging: > changing the subroutine-ref added to %__PACKAGE_:: > > >Inner: > producing munged name from user context. > lexical context should be available. > A::AUTOLOAD adds new sub to symbol table, either munged or unmunged > >Outer (heres where my problems are): > > wo munging, symtab entry is call-once to AUTOLOAD > w munging, munged name is not available on 2nd try > > getting Logger->debug() to invoke AUTOLOAD repeatedly. > w munging, this is given, as lookup fails > > in sub cooperative_dynamic_name_invoke() below, Im doing the munge > externally, > > > >=head1 Hunch > >I think optimizer.pm, B::Generate are probably the tools, but Ive got >insufficient fu of B::* to understand where to start (I have read, and >will reread. I hope that this might be an 'intersting app' of >optimizer.pm; with sufficient merit to garner porter interest. > > 1. when to 'require optimizer extend ...' > whats it mean to do so in INIT{} or CHECK {} blocks ? > or do it directly in AUTOLOAD {} ? > > 2. how to recognize (particularly at compile time) whether AUTOLOAD > would eventually be called, or how to get the lexical scope > during compilation. a compile-time analogue to caller() would be > cool. > >=cut > >package A; >use Data::Dumper; >use vars qw($AUTOLOAD); >use Carp 'cluck'; > >sub AUTOLOAD { > # compile and goto& munged method-name > # > (my $meth = $AUTOLOAD) =~ s/.*:://; > return if $meth eq 'DESTROY'; > my ($package, $filename, $line, $subroutine) = caller(0); > > my $buf = "<$meth>: $package, $filename, $line, $subroutine\n"; > $buf =~ s|[\./]||g; > print "creating: $buf"; > > *{'A::'.$meth} = sub { > print "invoked: $buf"; # force string interpolation, no closure (dont need) > # print "\twith ", Dumper (\@_); > }; > goto &{'A::'.$meth}; >} > >package main; >A::auto("string{}"); >cooperative_dynamic_name_invoke(); >print "done\n"; > >sub cooperative_dynamic_name_invoke { > > # macro-like invoke of auto-names > # invoker help needed; by creating custom sub-name > # for each lexical invocation > > foreach (1..2) { > > # autoload compiles sub on 1st iteration > # (and vivifies name in symbol table) > # 2nd time, new asub called directly > > my $munge = "dyn_name_000"; # wo reinit, would just make 3,4 > $munge++; # this doesnt give string++, but irrelevant to test > $munge = undef; > A->$munge("1st try"); > > $munge++; > A->$munge("2nd try\n"); > > $munge++; > A->$munge("3rd try\n"); > > } >} > >__END__ > > > >=cut > >use optimizer extend => sub { > print "dump ", Dumper \@_ > if 0 > #or $_[0]->name() eq "goto" > #or ref $_[0] =~ /CV/i > ; > # =~ /__ANON__/; >}; > >sub loop { > foreach (1..2) { > # if hashref were CONSTANT, and not rebuilt for each invocation, > # it could preserve the > A::fancy({arb=>1},1); > A::fancy({ok=>2},2); > A::auto({}); > A::auto({}); > } > use Data::Dumper; > print Dumper (\%A::); >} > > > >__END__ > > > -- -- Mike Mike Schilli log...@pe... |