Beefy Boxes and Bandwidth Generously Provided by pair Networks
Problems? Is your data what you think it is?
 
PerlMonks  

Need for (XS) speed

by spx2 (Deacon)
on Mar 05, 2010 at 05:39 UTC ( [id://826865]=perlquestion: print w/replies, xml ) Need Help??

spx2 has asked for the wisdom of the Perl Monks concerning the following question:

Hi,

If it's known that inside an AV* array all the elements are IVs, or all the elements are UVs , can I measure the sizeof(IV) and instead of using av_fetch use normal C addressing of arrays like *(array+index) ?

If this is not possible, is there a way to just not use av_fetch, but instead use something else, for example suppose I have a SV* , I would like to make what I want of it, that is, I want to completely ignore Perl's data structure and just write in it as if it were an usual C array.

Will "corrupting" a Perl data structure in this way lead to any problems? (I wasn't able to think of any, the most important would be the refcnt , but we won't tamper with that).

Normally I wouldn't do this because I know some people thought out Perl's data structures and they should be used with the API they have written but I want to write something that will be blazing fast so I need to break some rules here, such as portability(not interested in writing portable code, just extremely fast one).

I'm sure I'm not the first one to think of this as there are so many XS modules on CPAN and there's a big chance one of them is doing this(only problem is I don't know which one).

Another idea would be to use av_fetch to first get all the pointers of the elements of an array(a AV*)and put them in a SV* array[](maybe not even this, maybe just the _SV_HEAD_UNION members of the SV structs, as I understand by reading this, that they are actually the ones containing the data) and use that array because addressing it would be faster than using av_fetch each time. This of course, all depends on many Perl implementation details.

I'm seeking general XS tips for speeding up code. Also, this is not a premature decision/thought as my code is already written, now I need to optimize it.

Thanks

Replies are listed 'Best First'.
Re: Need for (XS) speed
by BrowserUk (Patriarch) on Mar 05, 2010 at 05:55 UTC

    Why not just pack the data into a scalar and pass that to your XS?

    #! perl -slw use 5.010; use strict; use Inline C => Config => BUILD_NOISY => 1; use Inline C => <<'END_C', NAME => 'junk', CLEAN_AFTER_BUILD => 0; void test( SV *in ) { size_t len = SvCUR( in ), i; U32 *ary = (U32*)SvPVX( in ); for( i = 0; i < len / sizeof(U32); ++i ) { printf( "%d:%d\n", i, ary[ i ] ); } return; } END_C my $ary = pack 'V*', 1 .. 20; test( $ary ); __END__ C:\test>826865.pl 0:1 1:2 2:3 3:4 4:5 5:6 6:7 7:8 8:9 9:10 10:11 11:12 12:13 13:14 14:15 15:16 16:17 17:18 18:19 19:20

    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.
Re: Need for (XS) speed
by ikegami (Patriarch) on Mar 05, 2010 at 06:11 UTC

    If it's known that inside an AV* array all the elements are IVs

    The elements are never IVs (an integral type big enough to hold an int and big enough to hold a pointer). They are always scalars (SVs).

    And no, it's takes too little to convert the type of the SV body to make your plan workable. For example, just by printing the element, you can drastically change it's structure:

    use Devel::Peek; $a[0] = 123; Dump $a[0]; print "$a[0]\n"; Dump $a[0];
    SV = IV(0x238b30) at 0x238b34 REFCNT = 1 FLAGS = (IOK,pIOK) IV = 123 123 SV = PVIV(0x182005c) at 0x238b34 REFCNT = 1 FLAGS = (IOK,POK,pIOK,pPOK) IV = 123 PV = 0x23f23c "123"\0 CUR = 3 LEN = 4

    (Technically, it's the stringification for the concatenation that caused the conversion.)

    You could access the SVs in the array via some pointer then use the normal SV macros to get the IV from them. But at this point, you gotta wonder what you are doing using a Perl array. Or Perl. One subroutine call would annihilate any savings.

      yes you are right, I meant the _SV_HEAD_UNION member of SV*(corrected).let's suppose I won't ever print the element, I am just interested to use Perl's data structure for storage. btw, will pack/unpack alter it the same way print does ?(do you think I could get a relative pointer directly to the _SV_HEAD_UNION member ?)

      But at this point, you gotta wonder what you are doing using a Perl array. Or Perl.

      True, true ... but I am just decoupling the part that needs speed from the Perl part(which has different advantages such as abstraction, which I like).

        Isn't SvIVX what you're asking for? It's a version of SvIV optimised for the very condition you told us to assume.
        #define SvANY(sv) (sv)->sv_any #define SvIVX(sv) ((XPVIV*) SvANY(sv))->xiv_iv

        I am just interested to use Perl's data structure for storage.

        Then use a string as a C array like BrowserUk suggested, with the following changes:

        • You want one of pack 'j' (IV), pack 'J' (UV), pack 'i' (I32) or pack 'I' (U32). It's not constant to which of those 'V' refers.
        • Using SvPVX instead of SvPVbyte makes needless assumptions.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://826865]
Approved by planetscape
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others pondering the Monastery: (4)
As of 2024-03-29 00:51 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found