Optimizing my freenode IRC

I wrote this obtuse little function to display six different IRC channels on freenode at once.

(defun irc-java ()
    (interactive)
    (delete-other-windows)
    (switch-to-buffer (get-buffer "#perl"))
    (let* (
              (p      (frame-parameters))
              (width  (cdr (assoc 'width  (frame-parameters))))
              (height (cdr (assoc 'height (frame-parameters))))
          )

        (split-window-horizontally nil)
        (split-window-vertically (/ height 3))
        (other-window 1)
        (switch-to-buffer (get-buffer "#perl6"))
        (split-window-vertically)
        (switch-to-buffer (get-buffer "#squeak"))
        (other-window 2)
        (switch-to-buffer (get-buffer "#glassfish"))
        (split-window-vertically (/ height 3))
        (other-window 1)
        (switch-to-buffer (get-buffer "#spring"))
        (split-window-vertically)
        (other-window 1)
        (switch-to-buffer (get-buffer "#java-talk"))
    )
)

Littlest uuencode

Hi, For your amusement, here's a very small uuencode program.

perl -0777 -e '$uue = pack u, <>; print "begin 0644 $ARGV\n${uue}end\n"' your-file.bin

Avoid my keys() accident

I broke $work yesterday when a change I'd made that I thought was mundane was not in fact. I'd changed some code from: if ( keys %$hash_ref ) { to if ( %$hash_ref ) { under the theory that we weren't supporting any perl less than our current production at perl-5.10.0.

What I'd completely missed was that $hash_ref might be undef and that keys %$... would auto-vivify the hash if necessary. Previously, the hash would be created as a side effect of dereferencing it. Afterward, I got an exception because the hash wasn't being automatically created just by looking at it.

The reason for this is keys() is actually an lvalue, something you can assign to. The meaning of keys( %... ) = 8 is actually fairly obscure and not what you would guess if you haven't read the documentation for keys(). Because keys() is an lvalue, the dereference %$... will auto-vivify anything necessary because I might want to modify it.

When I dropped the usage of something strictly defined as an lvalue function, the dereference stopped auto-vivifying and now I had exceptions in production. Wheee!

Ponies are the truth

Did you know you can modify perl's readonly constants for undef, true and false? Yep.

&Internals::SvREADONLY( \ !!1, 0 );
${ \ !!1 } = 'ponies!';
&Internals::SvREADONLY( \ !!1, 1 );

print !!1; # ponies!

Same thing for \ undef and \ !!0.

Benchmarking string trimming

Clever Regexps vs Multiple Simple Regexps:

In reading some code I ran across the expression s/^\s*|\s*$//g which is a trim function. It is not the optimal way to write this. The optimal way is two simpler expressions: s/^\s+//; s/\s+$//. Justification follows.

Conclusion:

  • Use of + instead of * means regexps that will would do no effective work will also fail to match. Failing to match when the work would be useless yielded some 3x to 4x improvement.

  • Use of multiple simpler patterns like s/^...//;s/...$// instead of compound patterns like s/^...|...$//g enabled boundary checking optimizations.

Testing:

String length:

long:  +80 chars
short: -80 chars

Pre/postfixes:

pre/post: "  string  "
pre:      "  string"
post:       "string  "
base:       "string"

Coding styles:

g*: s/^\s*|\s*$//g
g+: s/^\s+|\s+$//g
2*: s/^\s*//
    s/\s*$//
2+: s/^\s+//
    s/\s+$//

Calculated results:

>>  short pre 2+      1638810/s
>>  short base 2+     1622457/s
>>  short post 2+     1351812/s
>>  short pre/post 2+ 1152253/s
>>  long base 2+       564477/s
>>  long pre 2+        534890/s
    short base +g      532709/s
    short post +g      502626/s
>>  long post 2+       501015/s
    short pre +g       479683/s
    short pre/post +g  465137/s
>>  long pre/post 2+   463741/s
    short base 2*      462448/s
    short pre 2*       456719/s
    short pre/post 2*  450081/s
    short post 2*      449661/s
    short base *g      394226/s
    short pre *g       384360/s
    short post *g      367736/s
    short pre/post *g  367624/s
    long post 2*       114832/s
    long base 2*       113787/s
    long pre 2*        110305/s
    long pre/post 2*   110169/s
    long post +g       100847/s
    long base +g        99830/s
    long pre +g         98871/s
    long pre/post +g    98331/s
    long base *g        87066/s
    long post *g        86520/s
    long pre *g         84080/s
    long pre/post *g    81429/s