I'm not really much of a Perl optimization expert, but a couple things I noticed:
  1. You can get in and out of the sub a little faster by passing and returning refs instead of lists or strings. This minimizes the amount of data that needs to be copied onto the stack and then pulled back off. It would be a very minor gain per call, but, if 6000 calls in 0.25 second is normal, it may add up enough to be noticable.

  2. push can be surprisingly expensive due to the memory allocation overhead. You can mitigate this by setting the size of your array up front ($#a = $sw) and then inserting elements by index. You could also pre-size the array by initializing it with my @a = $blank x $sw.

  3. Try $chr || $blank instead of ?: - logical OR tends to be faster than doing a comparison, although they're not equivalent if $chr == 0.

  4. Another way around push would be to build the array contents directly in the join statement, presumably with map. It could get a bit convoluted in this case, since different bytes are determined by different methods, but, based on articles I've read, it sounds like this should be the fastest way to go if you can get an efficient mapping worked out.

  5. Instead of testing each attribute separately, try packing all of them into a single value, then just compare that from one iteration to the next and you'll save yourself half the dereferences/array lookups (since each structure will only need to be inspected once) and up to 80% of your comparisons (since it'll just be a single ne instead of 2 nes and 3 !=s). Something like:
    $chr = $line->[$col] || $blank; $atr = $arow->[$col]; $array_position++; $curr_attribs = $atr->[AS_BG] . $atr->[AS_FG] . $atr->[AS_U] . $atr->[ +AS_BOLD] . $atr->[AS_BLINK]; if ($curr_attribs ne $last_attribs) { $a[$array_position] = _attr($atr) . $chr; } else { $a[$array_position] = $chr; } $last_attribs = $curr_attribs;
    If it's possible to render AS_BG and AS_FG into small enough integers (i.e., if you're dealing with 16 or 256 colors instead of full-bore 24-bit color), then $curr_attribs/$last_attribs could be bitfields instead of strings, which would allow a numeric comparison and probably speed things up even more.

OK, I think I've run out of ideas... Hopefully these will improve things enough to spare you the horrors of C.


In reply to Re: Optimizing a Text Canvas: An inner loop and a cloner by dsheroh
in thread Optimizing a Text Canvas: An inner loop and a cloner by JosiahBryan

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.