http://qs321.pair.com?node_id=135393


in reply to The Ovidian Transform

You might try:
SV* get_date (char* str) { char date[9]; /* the date to return */ char new_date[9]; /* this will be the date after reordering */ while ( *str++ != '|' ); strncpy( date, str, 8); new_date[0] = date[4]; new_date[1] = date[5]; new_date[2] = date[6]; new_date[3] = date[7]; new_date[4] = date[0]; new_date[5] = date[1]; new_date[6] = date[2]; new_date[7] = date[3]; return newSVpv(new_date,8); }
Might make a small difference…

–hsm

"Never try to teach a pig to sing…it wastes your time and it annoys the pig."

Replies are listed 'Best First'.
(jcwren) Re: Re: The Ovidian Transform
by jcwren (Prior) on Jan 01, 2002 at 00:05 UTC

    While the lack of error checking would certainly be foolish, you can micro-optimize this even more.

    The while() loop isn't smart enough to compile down to a 'scasb' instruction, whereas if you use 'memchr', the compiler is smart enough to play some games with it. While I haven't checked the code strncpy() uses, I know for a fact that memcpy() will reduce to either a 'rep movsb' sequence, or more likely for only 8 bytes, 2 loads and 2 stores (4 instructions). If you're on an Alpha, it'll be 2 instructions, a single load and a single store.

    strncpy() is portable and is good in that respect. memcpy() is less so, since it presumes certain things about the processor architecture.

    /me is glad to see Ovid start hacking Inline::C. It's a lot of fun. Perl is good, but not always perfect. Perl combined with Inline::C can let you do some truly scarey things.

    --Chris

    e-mail jcwren

Premature Optimization is the Root of All Evil (was Re: Ovidian Transform)
by chip (Curate) on Jan 01, 2002 at 07:34 UTC
    Why try to speed up something that you don't know is responsible for your speed problems? Even more, why try to speed up something if you don't know you HAVE speed problems?

    More computing sins are committed in the name of efficiency (without necessarily achieving it) than for any other single reason -- including blind stupidity.
        -- W. A. Wulf, "A Case Against the GOTO"

    Words to live by.

        -- Chip Salzenberg, Free-Floating Agent of Chaos

      I really have to go with chip on this one. I played around with optimization for about 1/2 an hour and found that nothing I could do affected the performance by more than 1% or so.

      I did not have as much time as I would have liked to spend on it, so I did not run profiling tools on that section, nor look at the actual code generation. I focused on that small section because I have a lot of experience with C, and frequently have to do optimizations of that nature because of the microcontrollers I work with (microcontroller compilers typically produce far worse code than GCC, since GCC benefits from a wide developer base, and most microcontroller compilers are 1 to 5 person shops).

      My other interest in speeding it up was a trade off with making it fewer lines. Those 12 or so lines just seemed nasty. If it can be reduced to fewer lines, it often becomes more maintainable. Given that, I have the following replacement:

      SV* get_date (char* str) { char new_date[9]; while (*str++ != '|'); memcpy (new_date, str+4, 4); memcpy (new_date+4, str, 4); return newSVpv(new_date,8); }

      Normally, Inline::C uses -O2 optimization, which is fairly agressive about fragments like that. It's smart enough to recognize that memcpy()s can be replaced with several instructions if the length to move reduces to a compile time constant.

      One would question if the above is actually more maintainable, since the byte copy of new_date[0] = date[4]; is more indicative of what the operation is intending to do. If one is aiming for speed and readability, the new_date[0] = date[4]; relies more on the working knowledge of the compiler.

      No matter what the case, this isn't really the area that needs work to speed this puppy up.

      --Chris

      e-mail jcwren

      Well the snap answer is “Why not?” But more to the point why write code that is less efficient than need be? In fact, you can't even get away with the canonical 'lazy' as a reason, since what I wrote takes less typing. And the declaration of an un-needed variable doesn't do a whole lot for clarity—particularly in a routine which already has the potential for confusion, i.e. the two container arrays, where the second is used for the cross-wired transfer, something that might at casual glance seem a puzzle. So since it is clearer, faster, and shorter, I'd argue a win! Re: Mr. Wulf, nice quote, but in this context it somehow reminds me of
      A foolish consistency is the hobgoblin of little minds, adored by little statesmen and philosophers and divines. With consistency a great soul has simply nothing to do. – Ralph Waldo Emerson “Self Reliance”

      –hsm

      "Never try to teach a pig to sing…unless of couse if it's New Year's Eve! Happy New Year to All!."
        I think you're arguing against a point I didn't make. (Though, in fairness, I might have been arguing against a point you didn't make.) I didn't suggest that optimization was unimportant or even undesirable; rather, that given a program almost entirely written in Perl, there's usually no point in speeding up the C bits. The key word is "usually", BTW; my main point is that optimization should only be attempted when profiling shows that the effort will be rewarded.

        UPDATE: The following complaints are wrong; please ignore them. I've left them here for hysterical raisins, and so replies don't seem confusing.

        BTW, you don't help your case when you use punctuation marks that are neither ASCII nor Latin-1; it makes your comments hard to read. Let me guess: You're using Windows, right? You ought to look at your comment from a Unix system; it has lots of question marks where they don't belong.

            -- Chip Salzenberg, Free-Floating Agent of Chaos

Re(2): The Ovidian Transform
by dmmiller2k (Chaplain) on Dec 31, 2001 at 23:32 UTC
    // ... while ( *str++ != '|' ); strncpy( date, str, 8); // ...

    Given typical current C optimizers, this is unlikely to produce a measurable improvement, although it is definitely more succinct and therefore more elegant (IMHO).

    dmm

    You can give a man a fish and feed him for a day ...
    Or, you can
    teach him to fish and feed him for a lifetime
Re: Re: The Ovidian Transform
by petral (Curate) on Jan 02, 2002 at 18:04 UTC
    If you're not counting on some sort of optimization based on alignment why do a string copy at all?
    while ( *str++ != '|' ); date[0] = str[4]; date[1] = str[5]; date[2] = str[6]; date[3] = str[7]; date[4] = str[0]; date[5] = str[1]; date[6] = str[2]; date[7] = str[3];
    Or am I not remembering C correctly?

      p

      You are correct the strncpy is superfluous. The string terminator is missing but newSVpv() has been called with an explicit length so it doesn't matter.

      All in all I would prefer jcwren's methodology.

      --
      John (wishes there was a C-monks).