Thursday, February 28, 2013

Init.d rc Script to launchd.plist Translator


I know, why embue the heretic Apple platform with any more open-source goodness. But the reality is, there are a shit-ton of developers in the world using OS X relying heavily upon open source services. And yes, one could deploy to a VM you've spun up running CentOS or whatever, but would it not make Linux based services so much attractive to developers if open-source services were available in form native to Mac OS X?

The problem seems to be that no one has the time to understand the thoroughly different approach to agent and daemon management in OS X when adapting their Linux service to the Mac. Unfortunately it is not a simple case of wrapping existing service scripts. There is a semantic mismatch.

Init/rc style scripts implement starting and stopping whereas launchd performs this uniformly for programs as specified by a configuration file. Furthermore, launchd decides when to start, stop or re-start programs and requires that the program not actually do things that classic daemons do, like run in the background and direct standard output to /dev/null.

So unless somebody takes the time to extract the intent of service launching scripts, we get open-source services [hello JBoss!] on OS X that just don't fit well on our development machines.


References

launchd on Wikipedia

launchd source code - Apple re-released the source code under Apache license in hopes open-source crowd might adopt it as a replacement for init, rc, init.d, rc.d, inetd, xinetd, atd, and crond.

launchctl(1) - Manual page for launchctl, the user interface for launchd,

launchd.plist(5) - Manual page for the data specifying a job to be managed by launchd.

Friday, January 18, 2013

Azure for Java vs. Craigslist


The download page is competing with Craigslist real estate listings, but not much else.


Wednesday, December 12, 2012

Another micro benchmark - Formatting


Which one of these formats is faster?  The answer surprised me. 

package examples;

import java.text.MessageFormat;

import com.google.caliper.Param;
import com.google.caliper.Runner;
import com.google.caliper.SimpleBenchmark;

/**
 * Tests the performance of various StringBuilder methods.
 */
public class StringFormatBenchmark extends SimpleBenchmark {

    @Param({"1", "2", "3", "4", "5"}) private int inserts;
    public String [] s = new String [5];

    public void timeStringFormat(final int reps) {
        for (int i = 0; i < reps; ++i) {
            s[0] = String.format("asdf %s", i);
            if (inserts > 1) {
                s[1] = String.format("asdf %s asdf %s ", i, s[0]);
            }
            if (inserts > 2) {
                s[2] = String.format("asdf %s asdf %s asdf %s ", i, s[0], s[1]);
            }
            if (inserts > 3) {
                s[3] = String.format("asdf %s asdf %s asdf %s asdf %s ", i, s[0], s[1], s[2]);
            }
            if (inserts > 4) {
                s[4] = String.format("asdf %s asdf %s asdf %s asdf %s asdf %s ", i, s[0], s[1], s[2], s[3]);
            }
        }
    }

    public void timeMessageFormat(final int reps) {
        for (int i = 0; i < reps; ++i) {
            s[0] = MessageFormat.format("asdf {0}", i);
            if (inserts > 1) {
                s[1] = MessageFormat.format("asdf {0} asdf {1} ", i, s[0]);
            }
            if (inserts > 2) {
                s[2] = MessageFormat.format("asdf {0} asdf {1} asdf {2} ", i, s[0], s[1]);
            }
            if (inserts > 3) {
                s[3] = MessageFormat.format("asdf {0} asdf {1} asdf {2} asdf {3} ", i, s[0], s[1], s[2]);
            }
            if (inserts > 4) {
                s[3] = MessageFormat.format("asdf {0} asdf {1} asdf {2} asdf {3} asdf {4} ", i, s[0], s[1], s[2], s[3]);
            }
        }
    }

    public void timeStringBuilder(final int reps) {
        for (int i = 0; i < reps; ++i) {
            s[0] = new StringBuilder("asdf ").append(i).toString();
            if (inserts > 1) {
                s[1] = new StringBuilder("asdf ").append(i).append(" asdf ").append(s[0]).toString();
            }
            if (inserts > 2) {
                s[2] = new StringBuilder("asdf ").append(i).append(" asdf ").append(s[0]).append(" asdf ").append(s[1]).toString();
            }
            if (inserts > 3) {
                s[3] = new StringBuilder("asdf ").append(i).append(" asdf ").append(s[0]).append(" asdf ").append(s[1]).append(" asdf ").append(s[2]).toString();
            }
            if (inserts > 4) {
                s[4] = new StringBuilder("asdf ").append(i).append(" asdf ").append(s[0]).append(" asdf ").append(s[1]).append(" asdf ").append(s[2]).append(" asdf ").append(s[3]).toString();
            }
        }
    }

    public void timeStringConcat(final int reps) {
        for (int i = 0; i < reps; ++i) {
            s[0] = "asdf " + i;
            if (inserts > 1) {
                s[1] = "asdf " + i + " asdf " + (s[0]);
            }
            if (inserts > 2) {
                s[2] = "asdf " + i + " asdf " + (s[0]) + " asdf " + (s[1]);
            }
            if (inserts > 3) {
                s[3] = "asdf " + i + " asdf " + (s[0]) + " asdf " + (s[1]) + " asdf " + (s[2]);
            }
            if (inserts > 4) {
                s[4] = "asdf " + i + " asdf " + (s[0]) + " asdf " + (s[1]) + " asdf " + (s[2]) + " asdf " + (s[3]);
            }
        }
    }

    public static void main(final String[] args) throws Exception {
        Runner.main(StringFormatBenchmark.class, args);
    }
}

Caliper shows:  

    benchmark inserts    ns linear runtime
 StringFormat       1  2665 ==
 StringFormat       2  6686 ======
 StringFormat       3 12506 ============
 StringFormat       4 19548 ==================
 StringFormat       5 28582 ===========================
MessageFormat       1  4765 ====
MessageFormat       2  9845 =========
MessageFormat       3 15853 ===============
MessageFormat       4 23116 ======================
MessageFormat       5 31258 ==============================
StringBuilder       1   156 =
StringBuilder       2   427 =
StringBuilder       3   889 =
StringBuilder       4  1799 =
StringBuilder       5  2940 ==
 StringConcat       1   153 =
 StringConcat       2   425 =
 StringConcat       3   914 =
 StringConcat       4  1725 =
 StringConcat       5  2969 ==

Surprised?
 

Thursday, June 28, 2012

Philip "Pud" Kaplan

Why am I writing about Philip Kaplan? Pud founded AdBrite and Fucked Company.  In retrospect, Fucked Company may have been the best thing I ever experienced on the internet (perhaps except for 4chan, for which I cannot and shall not comment).  This is perhaps astounding because it was nothing like the internet of today.

FC was all text.

Regarding FC, what passes for journalists today would likely exclaim: "Fucked Company was the well-spring of tomorrow's poetry, yet also the definitive locus of the Internet's largest anarchist cesspool." It was a unique prototypical social network. I spent what seems like a lifetime reading FC during its brief existence, whose era was pre-Y2k to post 9-11.  The "Happy-Fun-Slander" board, purportedly authored by vetted employees, was a momentum trader's wet dream. I found my tribe among the free-for-all non-elite mosh-pits - a treasure-trove of unbounded raw emotion. The rumor was many comics and writers both tested and gathered material from the message boards there. When Pud finally shut it down (there were tears, lawsuits, and worse), I asked him if it'd be possible to curate a Best-Of book. I don't think anything was ever re-constituted from its ashes, though Pud did sell a book about the experience of running the joint. 


To be clear: FC was the antithesis of web properties today - anonymity was essential to its existence. As such, it was also an elaborate sock puppet theater whose sophistication has not been replicated in the transparent, post-Facebook era. The only openly verified in-real-life FC persona was Pud.



Cut to today. I just asked Pud about his newest venture, Fandalism. I told him I'm a fan and I loved the concept, but I'd like to talk about what happens after the "dates" hook up .. ya know: getting tabs, rehearsal schedules, lyrics, finding the right key signature for the singer, remembering your unique arrangement, and so on.

If something wonderful results, I'll let you know, but I feel very confident about approaching the domain defined by the intersection of "practical technology" and "musical practice".

Namaste.