in reply to Inline::C hash access

For the method shown here, I doubt it would make much difference, and if it did, it'd probably be to slow it down rather than speed it up. If you're going to write things in C to speed them up, then it helps to have the data in C structures and access it there. Otherwise you might as well just use perl instead of introducing additional access layers.

Still, I could be wrong since the slowest part of perl is calling a sub. If you called your C function the hundreds of thousands of times from the C code (rather than from perl), it could possibly speed it up.

UPDATE: also, I've completed my assignment. I hope I get an A on my homework. (In all seriousness, I've never tried Inline::C before. Normally I don't write complete solutions...)

BTW, the secret to figuring this stuff out is: you can't. It's really really arcane. But these pages can help: perlxs, perlapi, perlguts, perlxstut, perlclib, and perlcall. I used perlxs, perlapi, perlguts, and some source I had written before to figure this out. It can also help to browse the source of perl itself.

#!/usr/bin/perl use strict; use Inline 'C'; use Data::Dumper; my $hash = { parent => { parent => {} } }; root($hash); print "", Dumper({initial=>$hash, result=>root($hash)}), "\n"; __END__ __C__ SV* root(SV* sv) { if( SvOK(sv) && SvTYPE(sv) == SVt_RV ) { HV* h = SvRV(sv); SV* r; int i = 0; while( hv_exists(h, "parent", 6) ) { r = *( hv_fetch(h, "parent", 6, 0) ); if( SvOK(r) && SvTYPE(r) == SVt_RV ) { h = SvRV(r); i = 1; } } if( i ) { SvREFCNT_inc(r); return r; } } else { croak("please pass hash refs to root"); } return &PL_sv_undef; }


Replies are listed 'Best First'.
Re^2: Inline::C hash access
by fireartist (Chaplain) on Sep 04, 2008 at 13:35 UTC

    Thanks for this!

    I initially tried renaming the c function to "form", which is the real name I'm using - but got an error about a previous declaration of Perl_form, so it looks like the functions are being put in a global namespace - however that's not a real problem - I just named it back to "root", then added a *form = \&root and it worked fine.

    I found while trying to run my test suite, that the if( SvOK(sv) && SvTYPE(sv) == SVt_RV ) { } check was failing sometimes - I'm not sure why, so I'll have to investigate further. However, if I comment-out that check, all tests pass ok.

    Running my usual profiling script shows the Inline::C version only runs about 2-3% faster (for total script runtime) - however, I think I'll be able to modify your code to replace a few other often-used methods - so hopefully, eventually, I'll be able to significantly speed up my program. - Thanks once again!

      if( SvOK(sv) && SvTYPE(sv) == SVt_RV )
      That's not what you want - the SvTYPE just says what the SV's body physically consists of, and says nothing about whether it currently contains a valid RV. For example, if you do  $x = "foo"; $x = \$y; then the SvTYPE of $x is actually SVt_PV. You probably want:
      if (SvROK(sv)) ...


      This does seem to be covered in the pod (Inline::C), "If you use C function names that happen to be used internally by Perl, you will get a load error at run time. There is currently no functionality to prevent this or to warn you. For now, a list of Perl's internal symbols is packaged in the Inline module distribution under the filename 'symbols.perl'. Avoid using these in your code."

      Based on that, I'd say there's no work around other than what you did.