<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	xmlns:georss="http://www.georss.org/georss" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xmlns:media="http://search.yahoo.com/mrss/"
	>

<channel>
	<title>Not this...</title>
	<atom:link href="http://blog.timbunce.org/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.timbunce.org</link>
	<description>Listen. Reflect. Explore. Solve.</description>
	<lastBuildDate>Tue, 07 May 2013 08:28:03 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.com/</generator>
<cloud domain='blog.timbunce.org' port='80' path='/?rsscloud=notify' registerProcedure='' protocol='http-post' />
<image>
		<url>http://s2.wp.com/i/buttonw-com.png</url>
		<title>Not this...</title>
		<link>http://blog.timbunce.org</link>
	</image>
	<atom:link rel="search" type="application/opensearchdescription+xml" href="http://blog.timbunce.org/osd.xml" title="Not this..." />
	<atom:link rel='hub' href='http://blog.timbunce.org/?pushpress=hub'/>
		<item>
		<title>NYTProf v5 &#8211; Flaming Precision</title>
		<link>http://blog.timbunce.org/2013/04/08/nytprof-v5-flaming-precision/</link>
		<comments>http://blog.timbunce.org/2013/04/08/nytprof-v5-flaming-precision/#comments</comments>
		<pubDate>Mon, 08 Apr 2013 22:27:32 +0000</pubDate>
		<dc:creator>TimBunce</dc:creator>
				<category><![CDATA[perl]]></category>
		<category><![CDATA[nytprof]]></category>
		<category><![CDATA[performance]]></category>

		<guid isPermaLink="false">http://timbunce.wordpress.com/?p=557</guid>
		<description><![CDATA[As soon as I saw a Flame Graph visualization I knew it would make a great addition to NYTProf. So I&#8217;m delighted that the new Devel::NYTProf version 5.00, just released, has a Flame Graph as the main feature of the &#8230; <a href="http://blog.timbunce.org/2013/04/08/nytprof-v5-flaming-precision/">Continue reading <span class="meta-nav">&#8594;</span></a><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.timbunce.org&#038;blog=2562816&#038;post=557&#038;subd=timbunce&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<p>As soon as I saw a <a href="http://dtrace.org/blogs/brendan/2011/12/16/flame-graphs/">Flame Graph</a> visualization I knew it would make a great addition to NYTProf. So I&#8217;m delighted that the new <a href="https://metacpan.org/module/Devel::NYTProf">Devel::NYTProf</a> version 5.00, just released, has a Flame Graph as the main feature of the index page.</p>
<p><a href="http://timbunce.files.wordpress.com/2013/04/nytprof-v5-flamegraph.png"><img src="http://timbunce.files.wordpress.com/2013/04/nytprof-v5-flamegraph.png?w=908" alt="nytprof-v5-flamegraph.png"   class="alignnone size-full wp-image-556" /></a></p>
<p>In this post I&#8217;ll explain the Flame Graph visualization, the new &#8216;subroutine calls event stream&#8217; that makes the Flame Graph possible, and other recent changes, including improved precision in the subroutine profiler.<span id="more-557"></span><br />
<h2>Precision</h2>
<p>Let&#8217;s start with the improved precision. That work was actually released a few months ago in Devel::NYTProf 4.23 but not announced.</p>
<p>Devel::NYTProf started life as a line/statement profiler, writing a stream of events, one per statement. It&#8217;s important for speed that the stream is space efficient, so statement times were expressed as integer microseconds (a &#8216;tick&#8217;) and written in a compressed form. Values less than 128&micro;s use a single byte. This worked very well for v1. Back in early 2008 minimum statement times were typically just a few microseconds.</p>
<p>When I added the subroutine profiler I chose to use <a href="http://en.wikipedia.org/wiki/Double-precision_floating-point_format">double precision floating point</a> values to hold the subroutine call times with seconds as the units. I presume that seemed reasonable at the time as microseconds (multiples of 1e-6) can be accurately stored double precision floating point values and are significantly above the typical <a href="http://en.wikipedia.org/wiki/Machine_epsilon">machine epsilon</a> of 2.220446e-16.</p>
<p>I&#8217;d assumed the values weren&#8217;t at risk from the pernicious effect of <a href="http://en.wikipedia.org/wiki/Floating_point#Machine_precision_and_backward_error_analysis">cumulative round-off errors</a>. The situation got worse with NYTProf v2 because that switched the clock &#8216;tick&#8217; from 1&micro;s to 100ns on some systems (those with POSIX realtime clock API and OS X). And then worse again when profiling of &#8216;slowops&#8217; was added in NYTProf v3 since slowops are often far from slow.</p>
<p><code>$ perl -we '$n=10_000_000; $t=0.0; $i=3/$n; $t+=$i while $n--; print "$t\n";'<br />
2.99999999961925</code></p>
<p>The way the subroutine profiler works, calculating inclusive and exclusive times as it goes, makes it sensitive to these accumulated errors. (Sometimes a subroutine that did nothing but call a very fast subroutine many times could be reported as having taken less time than the sum of the times in the subroutine it called.)</p>
<p>The subroutine profiler still uses double precision floating point values to accumulate the times, but now accumulates integer ticks instead of fractional seconds.</p>
<p><code>$ perl -we '$n=10_000_000; $t=0.0; $i=3.0; $t+=$i while $n--; $t/=10_000_000; print "$t\n";'<br />
3</code></p>
<p>(The <code>$t=0.0</code> and <code>$i=3.0</code> ensure perl is using floating point values in that example. I checked it with <a href="https://metacpan.org/module/Devel::Peek">Devel::Peek</a>.)</p>
<h2>Subroutine Call Events</h2>
<p>There&#8217;s one thing the old and <a href="http://blog.timbunce.org/2008/07/12/devel-dprof-broken-by-the-passage-of-time/">deeply flawed</a> Devel::DProf profiler can do that NYTProf hasn&#8217;t been able to: the DProf <a href="https://metacpan.org/module/dprofpp">dprofpp</a> utility can generate a <em>subroutine call tree</em>.</p>
<p>NYTProf hasn&#8217;t been able to do that because its subroutine profiler worked entirely in memory, accumulating aggregate data about each  <em>call arc</em>, but not outputting anything until the end of the profile. So all the calls on any given arc are merged together.</p>
<p>NYTProf v5 adds a new <code>calls</code> option that enables streaming of subroutine call events as they happen. With <code>calls=2</code> subroutine call and return events are generated. With <code>calls=1</code> (the default) only subroutine return events are generated. (A curious side effect of perl internals and the way NYTProf works means it can&#8217;t <em>reliably</em> know the name of the subroutine at call entry time. So the call entry event isn&#8217;t very useful at the moment.)</p>
<p>The call return events are sufficient to recreate a call tree, albeit with some expensive massaging of the data. NYTProf does this with the new <code>nytprofcalls</code> utility which reads and processes the stream of call return events. At the moment it&#8217;s undocumented, rather hackish, and only generates the call data in a collapsed form suitable for generating a flamegraph (more below). It could be extended to produce a call tree without too much work. Then, finally, the ghost of Devel::DProf can be laid to rest.</p>
<h2>Flame Graph</h2>
<p><a href="http://twitter.com/brendangregg">Brendan Gregg</a> developed the Flame Graph as a way to visualize very large volumes of stack traces sampled by <a href="http://dtrace.org/blogs/about/">DTrace</a>.</p>
<p>It&#8217;s a wonderfully compact and information-rich way to visualize the where a program is spending its time. It&#8217;s also unusual and potentially confusing, so a little explanation is required. Keep in mind that it&#8217;s a visualization of <em>distinct call stacks</em> and that the colors are not meaningful.</p>
<p>The y-axis represents stack depth. Each box represents the spent time in a particular subroutine <em>when called by the subroutine below it</em>. So a particular subroutine will appear in multiple places if called via different call stacks.</p>
<p>The x-axis spans the time the profiler was running. It does not show the passing of time from left to right, as most graphs do. The left to right ordering has no meaning (it&rsquo;s sorted alphabetically).</p>
<p>The width of the box shows the inclusive time the subroutine was running, or part of the ancestry of subroutines that were running (the boxes above it). Wider box functions may be slower than narrow box functions, <em>or</em> they may simply be called more often. The call count is not shown.</p>
<p>Brendan&#8217;s original flamegraph script generated an SVG that wasn&#8217;t well suited to embedding in an application like NYTProf. He&#8217;s kindly accepted a series of <a href="https://github.com/brendangregg/FlameGraph/pulls/timbunce?direction=desc&amp;page=1&amp;sort=created&amp;state=closed">pull requests</a> to add the key features I was looking for. The most important being the ability to make the boxes clickable: click on a box and you&#8217;ll be taken to the report for that subroutine!</p>
<p>Let&#8217;s take a closer look at a simple example using a recursive Fibonacci function:</p>
<blockquote><pre>sub fib {
    my $n = shift;
    return $n if $n &lt; 2;
    fib($n-1) + fib($n-2);
}
sub foo { fib(8) }
sub bar { fib(8) }
foo();
bar();</pre>
</blockquote>
<p>That gives us a Flame Graph like this:</p>
<p><a href="http://timbunce.files.wordpress.com/2013/04/nytprof-v5-flamegraph-fib2.png"><img src="http://timbunce.files.wordpress.com/2013/04/nytprof-v5-flamegraph-fib2.png?w=908" alt="nytprof-v5-flamegraph-fib"   class="alignnone size-full wp-image-565" /></a></p>
<p>The line at the bottom that spans the full width represents the entire profile run. In this case it was 778&micro;s. (Hover over any block to see the time &#8211; you can see one in the image, along with the bold and bordered box it relates to).</p>
<p>The first line above that shows the calls to <code>foo</code> and <code>bar</code>. The line for those is shorter than the total line because the total includes the time perl spent compiling the script. It shows up clearly here because this script is so fast.</p>
<p>Then, above the blocks for both <code>foo</code> and <code>bar</code>, you can see the recursive calls to <code>fib</code> rising like flames (okay, with a little imagination). Two things to note here. Firstly <code>bar</code> is shown to the left of <code>foo</code> simply because the names at each level are in lexicographic order. There&#8217;s no deeper meaning in the ordering.</p>
<p>Secondly, you can easily see that <code>bar</code> was faster (narrower) than <code>foo</code>, even though they contain the same code. Why&#8217;s that? When <code>foo</code> ran first it would have paid the price for growing the stacks and warming the memory pages. Then when <code>bar</code> was called it gained from <code>foo</code>&#8216;s work.</p>
<h2>Flame Graph Generator</h2>
<p>Behind the scenes <code>nytprofhtml</code> runs <code>nytprofcalls</code> to generate a file in the report directory called <code>all_stacks_by_time.calls</code>. It then calls <code>flamegraph.pl</code> to read that file and generate the <code>all_stacks_by_time.svg</code> that&#8217;s shown in the report.</p>
<p>The <code>all_stacks_by_time.calls</code> has a very simple format. One line per distinct call stack, with subroutine names separated by semicolons, followed by a number (which is either in 1&micro;s or 100ns units depending on the platform). Here&#8217;s an example running the code above but calling <code>fib(2)</code> instead of <code>fib(8)</code> to keep it small:</p>
<pre><code>main::bar 37
main::bar;main::fib 45
main::bar;main::fib;main::fib 19
main::foo 416
main::foo;main::fib 222
main::foo;main::fib;main::fib 61
</code></pre>
<p>This simple format is perfect for grep&#8217;ing! You can effectively zoom-in on any subset of the call stacks by generating a flamegraph of just the stacks that contain the functions you&#8217;re interested in. For example, running this command on the profile of <a href="https://metacpan.org/module/Perl::Critic">perlcritic</a> shown at the top:</p>
<p><code>grep -w Perl::Critic::Policy::new nytprof/all_stacks_by_time.calls | flamegraph.pl &gt; tmp.svg &amp;&amp; open tmp.svg</code></p>
<p>gives you this Flame Graph:</p>
<p><a href="http://timbunce.files.wordpress.com/2013/04/nytprof-v5-flamegraph-grep.png"><img src="http://timbunce.files.wordpress.com/2013/04/nytprof-v5-flamegraph-grep.png?w=908" alt="nytprof-v5-flamegraph-grep"   class="alignnone size-full wp-image-573" /></a></p>
<p>You can see that a lot of time is being spent gathering stack traces for exceptions (this is with perlcritic 1.118 on perl v5.14.2).</p>
<p>It would be nice to have a Flame Graph generated for each of the top-N files/modules, showing just the subset of call stacks that involve any of the subroutines defined in that file. I didn&#8217;t get around to that for v5.00. Feel free to <a href="https://github.com/timbunce/devel-nytprof">fork the code</a>, add that in, and send me a pull request!</p>
<h2>Minor Changes</h2>
<p>The very old and very limited <code>nytprofcsv</code> utility has been deprecated. Let me know if you use it, otherwise it would be around much longer.</p>
<p>The <code>blocks</code> option is no longer on by default &#8211; it seems that few people used the ability to view statement times rolled up at the block level. You can always enable it with <code>blocks=1</code> in the options.</p>
<h2>What Next?</h2>
<p>For NYTProf? I don&#8217;t know.</p>
<p>Next up on <em>my</em> to-do list is giving <a href="http://blog.timbunce.org/2012/10/05/introducing-develsizeme-visualizing-perl-memory-use/">Devel::SizeMe</a> the love it needs. There&#8217;s some deep work I&#8217;d really like to get done before <a href="http://www.yapcna.org">YAPC::NA</a> in June.</p>
<p>Maybe I&#8217;ll see you there.</p>
<br />Filed under: <a href='http://blog.timbunce.org/category/tech/software/perl/'>perl</a> Tagged: <a href='http://blog.timbunce.org/tag/nytprof/'>nytprof</a>, <a href='http://blog.timbunce.org/tag/performance/'>performance</a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.timbunce.org&#038;blog=2562816&#038;post=557&#038;subd=timbunce&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://blog.timbunce.org/2013/04/08/nytprof-v5-flaming-precision/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/1cf82705f5ab43c73273ab5d690866b3?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">TimBunce</media:title>
		</media:content>

		<media:content url="http://timbunce.files.wordpress.com/2013/04/nytprof-v5-flamegraph.png" medium="image">
			<media:title type="html">nytprof-v5-flamegraph.png</media:title>
		</media:content>

		<media:content url="http://timbunce.files.wordpress.com/2013/04/nytprof-v5-flamegraph-fib2.png" medium="image">
			<media:title type="html">nytprof-v5-flamegraph-fib</media:title>
		</media:content>

		<media:content url="http://timbunce.files.wordpress.com/2013/04/nytprof-v5-flamegraph-grep.png" medium="image">
			<media:title type="html">nytprof-v5-flamegraph-grep</media:title>
		</media:content>
	</item>
		<item>
		<title>Suggested Alternatives as a MetaCPAN feature</title>
		<link>http://blog.timbunce.org/2013/03/10/suggested-alternatives-as-a-metacpan-feature/</link>
		<comments>http://blog.timbunce.org/2013/03/10/suggested-alternatives-as-a-metacpan-feature/#comments</comments>
		<pubDate>Sun, 10 Mar 2013 22:16:06 +0000</pubDate>
		<dc:creator>TimBunce</dc:creator>
				<category><![CDATA[perl]]></category>
		<category><![CDATA[cpan]]></category>
		<category><![CDATA[metacpan]]></category>

		<guid isPermaLink="false">http://timbunce.wordpress.com/?p=549</guid>
		<description><![CDATA[I expressed this idea recently in a tweet and then started writing it up in more detail as a comment to Brendan Byrd&#8217;s The Four Major Problems with CPAN blog post. It grew in detail until I figured I should &#8230; <a href="http://blog.timbunce.org/2013/03/10/suggested-alternatives-as-a-metacpan-feature/">Continue reading <span class="meta-nav">&#8594;</span></a><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.timbunce.org&#038;blog=2562816&#038;post=549&#038;subd=timbunce&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<p>I expressed this idea recently in <a href="https://twitter.com/timbunce/status/310385898971869186">a tweet</a> and then started writing it up in more detail as a comment to Brendan Byrd&#8217;s <a href="http://blogs.perl.org/users/brendan_byrd/2013/03/the-four-major-problems-with-cpan.html">The Four Major Problems with CPAN</a> blog post. It grew in detail until I figured I should just write it up as a blog post of my own.<span id="more-549"></span>(I fell out of the way of blogging over the two years or so of focus and distraction that our major <a href="http://blog.timbunce.org/2011/06/29/building-a-different-kind-of-extension/">house extension</a> took to go from conception to reality. I&#8217;ve been meaning to start blogging again more regularly anyway. I&#8217;ve a few blog posts brewing in the back of my mind, so we&#8217;ll see how it goes.)</p>
<p>In Brendan&#8217;s <a href="http://blogs.perl.org/users/brendan_byrd/2013/03/the-four-major-problems-with-cpan.html">post</a> he describes four problems with CPAN:</p>
<ol>
<li>Too many modules are unmaintained; abandoned but not marked as such.</li>
<li>There is not enough data on what modules are mature; which ones are the &#8220;right ones&#8221; to use.</li>
<li>Many modules are only used for semi-private needs.</li>
<li>Modules cannot be renamed or deleted, even with a long-term deprecation process.</li>
</ol>
<p>I&#8217;d like to propose a feature that doesn&#8217;t seem to address these issues directly but would, I believe, greatly reduce the significance of all of them. </p>
<p>Olaf Alders responded to Brendan&#8217;s post with <a href="http://blogs.perl.org/users/olaf_alders/2013/03/sifting-through-the-cpan.html">Sifting Through the CPAN</a> and pointed out the need for better search tools and specifically suggests tagging. While tagging might be helpful in general I think we need a way to explicitly guide users from one module to another.</p>
<h2>Suggested Alternatives</h2>
<p>I&#8217;ve long thought that CPAN would benefit from a mechanism to track &#8220;suggested alternative modules&#8221;. (And/or perhaps &#8220;suggested alternative <em>distributions</em>&#8220;, but I&#8217;ll just talk about modules for now.)</p>
<p>I envisage a &#8220;Suggested Alternatives&#8221; section in the right sidebar on every module page. It would show the top-N suggestions, with a [++] icon beside each, ordered by the number of people who have made the suggestion or agreed to it by pressing the [++] icon. And naturally it would have a text field to enter an existing module name, with type-ahead suggestions. Finally, the Suggested Alternatives heading would be a link to a details page.</p>
<p>The details page would show, for that module, every instance of a suggestion being made or up-voted, with the user and the date. That would let people see who made the suggestion and when. Users would be able to remove their own suggestions.</p>
<p>For modules that are the suggested alternative for some other module, their page could show something like &#8220;Suggested as the alternative to X other modules by Y people&#8221; with a link to a page that would show the corresponding details.</p>
<p>With something like this in place &#8220;unmaintained, abandoned&#8221; modules would gather suggested alternatives. Mature &#8216;good&#8217; modules would tend to accumulate suggestions pointing towards them, while mature &#8216;poor&#8217; modules would tend to accumulate suggestions pointing away. Experiments and obscure &#8220;private needs&#8221; modules wouldn&#8217;t gather suggestions and that, combined with the higher ranking of modules with votes and inward pointing suggestions, means they&#8217;d languish in obscurity doing little harm.</p>
<h2>The Alternatives Graph</h2>
<p>This &#8220;alternatives&#8221; data creates a <em>graph of relationships</em> among similar modules in a powerful and directly useful way.</p>
<p>For search results it would be useful not only for ranking but also for widening the search. Modules that are the suggested alternatives for modules in the &#8216;natural&#8217; results could be included. That&#8217;s potentially a big win.</p>
<p>Of course it would be perfectly reasonable for a pair of modules to have suggestions pointing to each other. Or for there to be loops of suggestions. That&#8217;s fine and simply expresses the conflicting views of the users making the suggestions.</p>
<h2>Similar Modules (a digression)</h2>
<p>I also had the idea that there may be value in having a &#8216;similar modules&#8217; link that shows the list of modules produced by traversing the graph of suggestions for some number of hops in both directions, and ranked by some combination of votes and placement in the graph.</p>
<p>But then I wondered if that would be better implemented an explicit way to suggest a &#8216;similar module&#8217;. In other words, generalize the idea of a &#8220;suggested alternative&#8221; into a &#8220;related module&#8221; relationship plus attributes like a &#8220;weight&#8221;. Where a positive weight denotes a &#8220;suggested alternative&#8221; and a zero weight is simply a &#8220;similar module&#8221; or a &#8220;see also&#8221;. Perhaps there&#8217;s also value in having a &#8220;complementary module&#8221; relationship.</p>
<p>This is all a bit vague. It suggests to me that any code to support a &#8220;module relationship&#8221; mechanism should be kept generic to allow for other kinds of relationships in future.</p>
<h2>The Whys and Wherefores</h2>
<p>The primary data of the graph is a link from one module to another with a count of the number of people who agreed with that suggestion.</p>
<p>That surface data is built from a deeper layer that records, for each link, which users that made the suggestion and when.</p>
<p>A helpful extra feature would be to let users optionally give a short reason for <em>why</em> <em>they</em> are suggesting <em>this</em> particular alternative. Perhaps because they feel it&#8217;s unmaintained, or lacks specific features that their suggested alternative has.</p>
<p>Suggestions without the whys would be very useful, and I&#8217;d suggest that that much is implemented first. But suggestions without explanations are also very limited. Knowing what motivated someone to suggest a particular alternative would be <em>very</em> helpful to others trying to pick a module for a task. For example, people might make multiple alternative suggestions recommending Bar instead of Foo if you want a certain feature, and Baz instead of Foo if they want another. </p>
<p>I don&#8217;t think there&#8217;s much risk of this becoming a comment battlefield because on any given page all the comments share the same direction &#8216;away&#8217; from the module. Someone with an opposing viewpoint would add a separate suggestion with their own comments on the &#8216;opposite&#8217; module.</p>
<p>I&#8217;d suggest the comment field be kept <em>very</em> short, say 50 characters, and provide a separate url to encourage referencing supporting material such as a blog post or mailing list archive.</p>
<p>Other approaches might be to have a few checkboxes with typical reasons (very limited), or perhaps tags, or link in with <a href="http://cpanratings.perl.org">cpanratings</a> in some way (possibly complex).</p>
<h2>Alternative Distributions</h2>
<p>The best way to build and present Alternative Distributions data is probably to simply derive it from the Alternative Modules data.</p>
<p>It would simply be a read-only view that collapses the module level graph data down to links between the corresponding distributions.</p>
<h2>Yanick Steps Up</h2>
<p>After writing a draft of this post I saw a <a href="https://twitter.com/yenzie/status/310839547250499586">tweet</a> from <a href="https://twitter.com/yenzie">Yanick</a> with a link to <a href="http://babyl.dyndns.org/techblog/entry/metacpan-recommendations">a specific proposal on his blog</a>. I skimmed it, realised it was similar to mine and replied saying to I&#8217;d reference it here. I decided I&#8217;d finish my post before reading it properly.</p>
<p>So here are my thoughts on Yanick&#8217;s suggestions:</p>
<p>Distributions vs Modules: Modules are the fundamental unit of use and the natural focus of attention and reviews. It&#8217;s relatively easy to derive distribution suggestions from module suggestions, but not the other way around. Using modules as the focus also means the suggestions will still be valid if a module moves from one distribution to another.</p>
<p>Adding notes: I agree that comments are best avoided for the <em>initial</em> system. I also feel strongly that their value outweighs their risks if implemented and presented carefully, so they should at least be taken into account in the initial design work.</p>
<p>User interface for recommending an alternative: Having a button beside the existing high-profile vote button doesn&#8217;t feel right to me. The vote button is a positive action and encouraging low-friction drive-by voting makes sense. Suggesting an alternative is a more negative action, and one to be considered more carefully. Using the sidebar seems more appropriate.</p>
<p>User interface for viewing suggestion alternatives: I&#8217;d rather not include any user names on the module page. It complicates the code and confuses the user experience (&#8220;which names are shown and why?&#8221; etc). The full details are available on the detail page if anyone wants to take the extra step to see them.</p>
<p>Volunteering to <em>do something</em>: Awesome!</p>
<p>Thanks Yanick.</p>
<p>Update: Implementation is being discussed on <a href="https://github.com/CPAN-API/cpan-api/issues/253">this cpan-api ticket</a>.</p>
<br />Filed under: <a href='http://blog.timbunce.org/category/tech/software/perl/'>perl</a> Tagged: <a href='http://blog.timbunce.org/tag/cpan/'>cpan</a>, <a href='http://blog.timbunce.org/tag/metacpan/'>metacpan</a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.timbunce.org&#038;blog=2562816&#038;post=549&#038;subd=timbunce&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://blog.timbunce.org/2013/03/10/suggested-alternatives-as-a-metacpan-feature/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/1cf82705f5ab43c73273ab5d690866b3?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">TimBunce</media:title>
		</media:content>
	</item>
		<item>
		<title>Introducing Devel::SizeMe &#8211; Visualizing Perl Memory Use</title>
		<link>http://blog.timbunce.org/2012/10/05/introducing-develsizeme-visualizing-perl-memory-use/</link>
		<comments>http://blog.timbunce.org/2012/10/05/introducing-develsizeme-visualizing-perl-memory-use/#comments</comments>
		<pubDate>Fri, 05 Oct 2012 11:49:03 +0000</pubDate>
		<dc:creator>TimBunce</dc:creator>
				<category><![CDATA[perl]]></category>
		<category><![CDATA[memory]]></category>
		<category><![CDATA[performance]]></category>
		<category><![CDATA[sizeme]]></category>

		<guid isPermaLink="false">http://timbunce.wordpress.com/?p=540</guid>
		<description><![CDATA[For a long time I&#8217;ve wanted to create a module that would shed light on how perl uses memory. This year I decided to do something about it. My research and development didn&#8217;t yield much fruit in time for OSCON &#8230; <a href="http://blog.timbunce.org/2012/10/05/introducing-develsizeme-visualizing-perl-memory-use/">Continue reading <span class="meta-nav">&#8594;</span></a><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.timbunce.org&#038;blog=2562816&#038;post=540&#038;subd=timbunce&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<p>For a long time I&#8217;ve wanted to create a module that would shed light on how perl uses memory. This year I decided to do something about it.</p>
<p>My research and development didn&#8217;t yield much fruit in time for OSCON in July, where <a href="http://www.slideshare.net/Tim.Bunce/perl-memory-use-201207">my talk</a> ended up being about my research and plans. (I also tried to explain that RSS isn&#8217;t a useful measurement for this, and that malloc buffering means even total process size isn&#8217;t a very useful measurement.) I was invited to speak at <a href="http://yapcasia.org/2012/">YAPC::Asia</a> in Tokyo in September and <em>really</em> wanted to have something worthwhile to demonstrate there.</p>
<p>I&#8217;m delighted to say that some frantic hacking (aka Conference Driven Development) yielded a working demo just in time and, after a little more polish, I&#8217;ve now uploaded <a href="http://search.cpan.org/perldoc?Devel%3A%3ASizeMe">Devel::SizeMe</a> to CPAN.</p>
<p>In this post I want to introduce you to Devel::SizeMe, show some screenshots, a <a href="http://blip.tv/timbunce/perl-memory-use-and-devel-sizeme-at-yapc-asia-2012-6381282">screencast of the talk and demo</a>, and outline current issues and plans for future development.<span id="more-540"></span></p>
<p>For a while I thought <a href="http://blog.timbunce.org/tag/nytprof/">Devel::NYTProf</a> might be a useful framework for building some kind of &#8220;memory profiler&#8221;. Something that would measure changes in memory use over time between lines and subroutines. Nicholas Clark even created a clever experimental hack to demo the concept. Sadly the data just didn&#8217;t seem to be very useful. It turns out that knowing where memory is <em>allocated</em> and <em>freed</em> isn&#8217;t nearly as important as knowing where memory is being <em>held</em>.</p>
<h2>The Plan</h2>
<p>It was clear that some kind of &#8216;snapshot&#8217; mechanism was needed. Something that would:
<ol>
<li>crawl <em>all</em> the data structures within a perl interpreter</li>
<li>have some way of <em>naming</em> the path to each data structure</li>
<li>stream the data out for external storage and processing</li>
<li>be fast enough that snapshots could be taken frequently</li>
<li>visualize the vast amount of data</li>
<li>compare different snapshots</li>
</ol>
<p>Luckily the hardest part, step 1, was already covered by <a href="https://metacpan.org/module/Devel::Size">Devel::Size</a>. Originally written by Dan Sugalski in 2005, then maintained by Tels and BrowserUK, it had been picked up and polished by Nicholas Clark to stay in sync with the many internal optimizations he and others were adding to the perl core. It&#8217;s not without problems, and I&#8217;ll outline those below, but it was a great base for me.</p>
<p>I added a callback mechanism, so my code and others could &#8220;hitch a ride&#8221; on the back of Devel::Size as it crawled the data structures, and came up with a very lightweight way to track and output the &#8220;name path&#8221;.</p>
<h2>Textual Output</h2>
<p>My initial code just wrote a tree-like textual representation to prove the concept:</p>
<pre style="line-height:normal;">$ SIZEME='' perl -MDevel::SizeMe=total_size -e 'total_size([ 1, "hi", [] ])'
SV(PVAV) fill=2/2		[#1 @0] 
:   +24 sv_head =24
:   +40 sv_body =64
:   +24 av_max =88
:   ~note av_len 2
:   AVelem-&gt;		[#2 @1] 
:   :   SV(RV)		[#3 @2] 
:   :   :   +24 sv_head =112
:   :   :   RV-&gt;		[#4 @3] 
:   :   :   :   SV(PVAV) fill=-1/-1		[#5 @4] 
:   :   :   :   :   +24 sv_head =136
:   :   :   :   :   +40 sv_body =176
:   :   ~note i 2
:   AVelem-&gt;		[#6 @1] 
:   :   SV(PV)		[#7 @2] 
:   :   :   +24 sv_head =200
:   :   :   +16 sv_body =216
:   :   :   +16 SvLEN =232
:   :   ~note i 1
:   AVelem-&gt;		[#8 @1] 
:   :   SV(IV)		[#9 @2] 
:   :   :   +24 sv_head =256
:   :   ~note i 0
</pre>
<p>There you can see the array (PVAV) &#8216;node&#8217; with &#8216;leaf&#8217; sizes for the sv_head (24 bytes), sv_body (40 bytes), and the array of element pointers (av_max, 24 bytes). Below that you can see a &#8216;link&#8217; called AVelem pointing to a reference (RV) to an array with no elements. The &#8220;~note&#8221; lines are &#8216;attributes&#8217; that can be used to provide extra information about nodes. The &#8216;<code>=<em>NNN</em></code>&#8216; gives a running total of the accumulated size.</p>
<p>The terminology here (sv_head, sv_body, av_max etc.) might not be familiar to you unless you&#8217;ve spent time <a href="http://cpansearch.perl.org/src/RURBAN/illguts-0.42/index.html">delving into perl guts</a>. Hopefully, though, it&#8217;s clear that Devel::SizeMe gives access to <em>immense detail</em>.</p>
<h2>Graph Visualization</h2>
<p>That detail can quickly become overwhelming for non-trivial data structures. Some kind of visualization was needed. So I added a more compact &#8216;raw&#8217; output format and a script (sizeme_store.pl) to process it. The script &#8216;decorates&#8217; the nodes with the leaf and attribute data, gives the links better names, and adds extra details like the total size of the children.</p>
<pre>$ SIZEME='|sizeme_store.pl --dot=sizeme.dot' perl -MDevel::SizeMe=total_size -e 'total_size([ 1, "hi", [] ])'</pre>
<p>The SIZEME env var gives the name of the file to write the raw data to, or in this case the name of a program to pipe the data into. Here I&#8217;m asking sizeme_store.pl to write a <a href="http://www.graphviz.org/content/dot-language">dot format</a> file which, when rendered by <a href="http://www.graphviz.org">Graphviz</a>, produces a graph like this:</p>
<p><img style="display:block;margin-left:auto;margin-right:auto;" src="http://timbunce.files.wordpress.com/2012/10/screen-shot-2012-10-04-at-22-55-181.png?w=400&#038;h=228" alt="Screen Shot 2012-10-04 at 22.55.18.png" border="0" width="400" height="228" /></p>
<p>You can see the links have been labeled with the index attribute, and the nodes show how the size is calculated (self+children=total) and the sizes accumulate up the graph.</p>
<p>That&#8217;s lovely, and works well for modestly sized data structures. It doesn&#8217;t scale well though. You quickly find yourself looking at diagrams like this:</p>
<p><img style="display:block;margin-left:auto;margin-right:auto;" src="http://timbunce.files.wordpress.com/2012/10/screen-shot-2012-10-04-at-22-31-09.png?w=600&#038;h=193" border="0" width="600" height="193" /></p>
<h2>Treemap Visualization</h2>
<p>The graph visualization is rather more impressive than it is practical. A more useful visualization for this kind of data is an interactive <a href="http://en.wikipedia.org/wiki/Treemapping">treemap</a>. Where the size of the boxes represents the memory use and you can drill-down into the data structures. To do that, and have it work on massive data dumps, I needed some kind of database and tree map code that supported on-demand loading. I opted for <a href="http://sqlite.org">SQLite</a> as the data store, the <a href="http://thejit.org">JavaScript InfoVis Toolkit</a> for the tree map code, and <a href="https://metacpan.org/module/Mojolicious::Lite">Mojolicious::Lite</a> as the web app framework.</p>
<pre>$ SIZEME='|sizeme_store.pl --db=sizeme.db' perl -MDevel::SizeMe=total_size -e 'total_size([ 1, "hi", [] ])'</pre>
<p>That&#8217;s asking sizeme_store.pl to produce a sizeme.db file. Then, to visualize the data you can run sizeme_graph.pl to launch the web app:</p>
<pre>$ sizeme_graph.pl --db=sizeme.db daemon</pre>
<p>then visit <a href="http://127.0.0.1:3000/" rel="nofollow">http://127.0.0.1:3000/</a> to see the result:</p>
<p><img style="display:block;margin-left:auto;margin-right:auto;" src="http://timbunce.files.wordpress.com/2012/10/screen-shot-2012-10-04-at-22-58-18.png?w=600&#038;h=364" alt="Screen Shot 2012 10 04 at 22 58 18" border="0" width="600" height="364" /></p>
<p>The overall grey area, which has a title bar labeled &#8220;SV(PVAV)&#8221;, represents the total memory used by the structure. The area is divided into three parts for the three elements of the array. The smallest, labeled &#8220;[0]-&gt; SV(IV)&#8221;, is the integer. The next larger one, labeled &#8220;[1]-&gt; SV(PV)&#8221;, is the string. The largest area is the array reference. Because the referenced array was empty the logic in sizeme_graph.pl has &#8216;collapsed&#8217; the array into the parent node to simplify the tree map. This is reflected in the label &#8220;[2]-&gt; SV(RV) RV-&gt; SV(AV)&#8221;.</p>
<p>The darker box is a tooltip that moves with the pointer and displays extra detail about whatever node the pointer hovers over. In this case it&#8217;s showing that the total memory use is 88 bytes (the head and the body size of the RV and the AV have been summed up). The rest of the content is mostly debugging information. They&#8217;ll be more useful info here in future.</p>
<h2>The Whole Picture</h2>
<p>The total_size($ref) function dumps the contents of a particular data structure. But it&#8217;s not enough to get the whole picture. For that I wanted to be able to dump <em>everything</em> in a perl interpreter. Executing total_size(\%main::) gets closer to everything, but it&#8217;s still a long way off.</p>
<p>So I added a <code>perl_size()</code> function. That starts by dumping the stashes (<code>\%main::</code>, or in internals speak PL_defstash) but then goes on to dump many more items you might never have realized existed. PL_stashcache, PL_regex_padav, PL_encoding, PL_modglobal, and PL_parser to name but a few. It then records the amount of unused space in perl&#8217;s arenas.</p>
<p>Finally then scans the arenas looking for any values that haven&#8217;t been seen yet. Currently this finds quite a lot because the <code>perl_size()</code> code isn&#8217;t complete yet. (Many thanks to <a href="https://metacpan.org/author/FLORA">rafl</a> for helping improve the coverage here.) Once it&#8217;s complete, any unseen values found in the arenas will be leaks. So Devel::SizeMe may turn into a useful leak detection tool.</p>
<p>Taking this idea further, there&#8217;s also a <code>heap_size()</code> function. The goal here is to try to account for everything in the heap. (See <a href="http://www.slideshare.net/Tim.Bunce/perl-memory-use-yapcasia2012">my slides</a> if you&#8217;re not familiar with that term.) The one key item here is asking malloc for information about how much memory it&#8217;s using and, especially, how much &#8216;free&#8217; memory it&#8217;s holding on to, for malloc&#8217;s which support that.</p>
<h2>See It In Action</h2>
<p>This explanation is rather dry. To get a real sense of what Devel::SizeMe can do you need to see it in action with some non-trivial data. Here&#8217;s a screencast of my Perl Memory Use talk at YAPC::Asia (also available as a raw mov <a href="http://blip.tv/file/get/Timbunce-PerlMemoryUseAndDevelSizeMeAtYAPCAsia2012311.mov">here</a> and <a href="http://a20.video4.blip.tv/3990001922812/Timbunce-PerlMemoryUseAndDevelSizeMeAtYAPCAsia2012311.mov">here</a>, mv4 <a href="http://blip.tv/file/get/Timbunce-PerlMemoryUseAndDevelSizeMeAtYAPCAsia2012447.m4v">here</a> and <a href="http://a1.video2.blip.tv/13610011292959/Timbunce-PerlMemoryUseAndDevelSizeMeAtYAPCAsia2012447.m4v">here</a>, and mp4 <a href="http://blip.tv/file/get/Timbunce-PerlMemoryUseAndDevelSizeMeAtYAPCAsia2012614.mp4">here</a> and <a href="http://a11.video2.blip.tv/9620011293108/Timbunce-PerlMemoryUseAndDevelSizeMeAtYAPCAsia2012614.mp4">here</a>). The demonstration starts at 13:00.</p>
<embed src="http://blip.tv/play/AYOFvkYA?p=1" type="application/x-shockwave-flash" width="960" height="606" allowscriptaccess="never" allowfullscreen="true"></embed>
<h2>Simple Usage</h2>
<p>Just four steps:</p>
<ol>
<li>cpanm Devel::SizeMe # install the module</li>
<li>perl -d:SizeMe &#8230;your.script.here&#8230;</li>
<li>sizeme_graph.pl daemon</li>
<li>open <a href="http://127.0.0.1:3000/" rel="nofollow">http://127.0.0.1:3000/</a></li>
</ol>
<p>Devel::SizeMe notices that it&#8217;s been run as <code>perl -d:SizeMe</code> and arranges to automatically call <code>perl_size()</code> in an <code>END</code> block. Simple.</p>
<h2>Current Issues</h2>
<p>There are two weakness with the current Devel::Size logic that affect Devel::SizeMe.</p>
<p>The first is that it uses a simple depth-first search. That&#8217;s fine when just calculating a total, but for Devel::SizeMe it means that chasing references held by one named item, like a subroutine, can lead to all sorts of other items, including entire stashes, appearing to be &#8220;within&#8221; the item that held the reference. The second is that Devel::Size doesn&#8217;t have well defined sense of when to stop chasing references because it doesn&#8217;t consider reference counts.</p>
<p>So I plan to add a multi-phase search mechanism. References with a count of 1 will be followed immediately. References with a count greater than one will be queued, along with a count of how many times the reference has been seen so far. In this way all the &#8216;named&#8217; data reachable from <code>%main::</code> will be found first and identified with their natural names before the queued items are crawled. This should greatly improve the output.</p>
<p>More coverage is needed in perl_size() to reduce the number of &#8216;unseen&#8217; items that show up in the arenas, as seen in the screencast.</p>
<h2>Future Plans</h2>
<p>A priority is to get my changes to the core of Devel::Size integrated back in. It would be crazy to have two modules duplicating this sometimes complex and perl-version-specific logic. My goal is to have a single C file that&#8217;s used by both modules. Each would compile it with different macros to enable the required behavior. This should enable Devel::Size to suffer no performance loss for the extra logic that Devel::SizeMe has added.</p>
<p>I&#8217;ve already started adding some support for &#8220;named&#8221; runs. The idea is to enable the size functions to be called multiple times within a single process, and to store the data in separate tables within the database. This is an important step towards being able to compare multiple runs to see how the memory use has changed.</p>
<p>Lots of refactoring is needed to turn my conference-driven-dash-for-the-finish-line hacking into more robust and reusable code. In particular I&#8217;d like to get a reasonable stable and useful database schema so other people can write module to process the data generated by Devel::SizeMe.</p>
<p>Further in the future I can imagine having an option to record the existence of pointers to data that&#8217;s already been seen. That information is currently discarded but would add a great deal of detail to the output. Reference loops would be much easier to see for example. It would turn the output &#8216;tree&#8217; into a <a href="http://en.wikipedia.org/wiki/Directed_graph">directed graph</a> and enable much richer visualizations.</p>
<p>We&#8217;re just at the start.</p>
<p>Enjoy.</p>
<br />Filed under: <a href='http://blog.timbunce.org/category/tech/software/perl/'>perl</a> Tagged: <a href='http://blog.timbunce.org/tag/memory/'>memory</a>, <a href='http://blog.timbunce.org/tag/performance/'>performance</a>, <a href='http://blog.timbunce.org/tag/perl/'>perl</a>, <a href='http://blog.timbunce.org/tag/sizeme/'>sizeme</a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.timbunce.org&#038;blog=2562816&#038;post=540&#038;subd=timbunce&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://blog.timbunce.org/2012/10/05/introducing-develsizeme-visualizing-perl-memory-use/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
<enclosure url="http://blip.tv/file/get/Timbunce-PerlMemoryUseAndDevelSizeMeAtYAPCAsia2012311.mov" length="0" type="video/quicktime" />
<enclosure url="http://blip.tv/file/get/Timbunce-PerlMemoryUseAndDevelSizeMeAtYAPCAsia2012311.mov" length="0" type="video/quicktime" />
<enclosure url="http://blip.tv/file/get/Timbunce-PerlMemoryUseAndDevelSizeMeAtYAPCAsia2012447.m4v" length="44043750" type="video/mp4" />
<enclosure url="http://blip.tv/file/get/Timbunce-PerlMemoryUseAndDevelSizeMeAtYAPCAsia2012447.m4v" length="44043750" type="video/mp4" />
<enclosure url="http://blip.tv/file/get/Timbunce-PerlMemoryUseAndDevelSizeMeAtYAPCAsia2012614.mp4" length="39601412" type="video/mp4" />
<enclosure url="http://blip.tv/file/get/Timbunce-PerlMemoryUseAndDevelSizeMeAtYAPCAsia2012614.mp4" length="39601412" type="video/mp4" />
<enclosure url="http://blip.tv/file/get/Timbunce-PerlMemoryUseAndDevelSizeMeAtYAPCAsia2012614.mp4" length="39601412" type="video/mp4" />
<enclosure url="http://blip.tv/file/get/Timbunce-PerlMemoryUseAndDevelSizeMeAtYAPCAsia2012614.mp4" length="39601412" type="video/mp4" />
<enclosure url="http://a20.video4.blip.tv/3990001922812/Timbunce-PerlMemoryUseAndDevelSizeMeAtYAPCAsia2012311.mov" length="124493455" type="video/quicktime" />
<enclosure url="http://a20.video4.blip.tv/3990001922812/Timbunce-PerlMemoryUseAndDevelSizeMeAtYAPCAsia2012311.mov" length="124493455" type="video/quicktime" />
<enclosure url="http://a20.video4.blip.tv/3990001922812/Timbunce-PerlMemoryUseAndDevelSizeMeAtYAPCAsia2012311.mov" length="124493455" type="video/quicktime" />
<enclosure url="http://a20.video4.blip.tv/3990001922812/Timbunce-PerlMemoryUseAndDevelSizeMeAtYAPCAsia2012311.mov" length="124493455" type="video/quicktime" />
<enclosure url="http://a20.video4.blip.tv/3990001922812/Timbunce-PerlMemoryUseAndDevelSizeMeAtYAPCAsia2012311.mov" length="124493455" type="video/quicktime" />
<enclosure url="http://a1.video2.blip.tv/13610011292959/Timbunce-PerlMemoryUseAndDevelSizeMeAtYAPCAsia2012447.m4v" length="44043750" type="video/mp4" />
<enclosure url="http://a1.video2.blip.tv/13610011292959/Timbunce-PerlMemoryUseAndDevelSizeMeAtYAPCAsia2012447.m4v" length="44043750" type="video/mp4" />
<enclosure url="http://a1.video2.blip.tv/13610011292959/Timbunce-PerlMemoryUseAndDevelSizeMeAtYAPCAsia2012447.m4v" length="44043750" type="video/mp4" />
<enclosure url="http://a1.video2.blip.tv/13610011292959/Timbunce-PerlMemoryUseAndDevelSizeMeAtYAPCAsia2012447.m4v" length="44043750" type="video/mp4" />
<enclosure url="http://a1.video2.blip.tv/13610011292959/Timbunce-PerlMemoryUseAndDevelSizeMeAtYAPCAsia2012447.m4v" length="44043750" type="video/mp4" />
<enclosure url="http://a1.video2.blip.tv/13610011292959/Timbunce-PerlMemoryUseAndDevelSizeMeAtYAPCAsia2012447.m4v" length="44043750" type="video/mp4" />
<enclosure url="http://a1.video2.blip.tv/13610011292959/Timbunce-PerlMemoryUseAndDevelSizeMeAtYAPCAsia2012447.m4v" length="44043750" type="video/mp4" />
<enclosure url="http://a1.video2.blip.tv/13610011292959/Timbunce-PerlMemoryUseAndDevelSizeMeAtYAPCAsia2012447.m4v" length="44043750" type="video/mp4" />
<enclosure url="http://a1.video2.blip.tv/13610011292959/Timbunce-PerlMemoryUseAndDevelSizeMeAtYAPCAsia2012447.m4v" length="44043750" type="video/mp4" />
<enclosure url="http://a1.video2.blip.tv/13610011292959/Timbunce-PerlMemoryUseAndDevelSizeMeAtYAPCAsia2012447.m4v" length="44043750" type="video/mp4" />
<enclosure url="http://a11.video2.blip.tv/9620011293108/Timbunce-PerlMemoryUseAndDevelSizeMeAtYAPCAsia2012614.mp4" length="39601412" type="video/mp4" />
<enclosure url="http://a11.video2.blip.tv/9620011293108/Timbunce-PerlMemoryUseAndDevelSizeMeAtYAPCAsia2012614.mp4" length="39601412" type="video/mp4" />
<enclosure url="http://a11.video2.blip.tv/9620011293108/Timbunce-PerlMemoryUseAndDevelSizeMeAtYAPCAsia2012614.mp4" length="39601412" type="video/mp4" />
<enclosure url="http://a11.video2.blip.tv/9620011293108/Timbunce-PerlMemoryUseAndDevelSizeMeAtYAPCAsia2012614.mp4" length="39601412" type="video/mp4" />
<enclosure url="http://a11.video2.blip.tv/9620011293108/Timbunce-PerlMemoryUseAndDevelSizeMeAtYAPCAsia2012614.mp4" length="39601412" type="video/mp4" />
<enclosure url="http://a11.video2.blip.tv/9620011293108/Timbunce-PerlMemoryUseAndDevelSizeMeAtYAPCAsia2012614.mp4" length="39601412" type="video/mp4" />
<enclosure url="http://a11.video2.blip.tv/9620011293108/Timbunce-PerlMemoryUseAndDevelSizeMeAtYAPCAsia2012614.mp4" length="39601412" type="video/mp4" />
<enclosure url="http://a11.video2.blip.tv/9620011293108/Timbunce-PerlMemoryUseAndDevelSizeMeAtYAPCAsia2012614.mp4" length="39601412" type="video/mp4" />
<enclosure url="http://a11.video2.blip.tv/9620011293108/Timbunce-PerlMemoryUseAndDevelSizeMeAtYAPCAsia2012614.mp4" length="39601412" type="video/mp4" />
<enclosure url="http://a11.video2.blip.tv/9620011293108/Timbunce-PerlMemoryUseAndDevelSizeMeAtYAPCAsia2012614.mp4" length="39601412" type="video/mp4" />
	
		<media:content url="http://1.gravatar.com/avatar/1cf82705f5ab43c73273ab5d690866b3?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">TimBunce</media:title>
		</media:content>

		<media:content url="http://timbunce.files.wordpress.com/2012/10/screen-shot-2012-10-04-at-22-55-181.png" medium="image">
			<media:title type="html">Screen Shot 2012-10-04 at 22.55.18.png</media:title>
		</media:content>

		<media:content url="http://timbunce.files.wordpress.com/2012/10/screen-shot-2012-10-04-at-22-31-09.png" medium="image" />

		<media:content url="http://timbunce.files.wordpress.com/2012/10/screen-shot-2012-10-04-at-22-58-18.png" medium="image">
			<media:title type="html">Screen Shot 2012 10 04 at 22 58 18</media:title>
		</media:content>
	</item>
		<item>
		<title>A Space For Thought</title>
		<link>http://blog.timbunce.org/2012/04/08/a-space-for-thought/</link>
		<comments>http://blog.timbunce.org/2012/04/08/a-space-for-thought/#comments</comments>
		<pubDate>Sun, 08 Apr 2012 18:15:33 +0000</pubDate>
		<dc:creator>TimBunce</dc:creator>
				<category><![CDATA[health]]></category>
		<category><![CDATA[life]]></category>
		<category><![CDATA[oscon]]></category>
		<category><![CDATA[toastmasters]]></category>

		<guid isPermaLink="false">http://timbunce.wordpress.com/?p=511</guid>
		<description><![CDATA[This is the text of a speech I originally wrote for the International Speech Competition at my Toastmasters club in April 2012. (I won the club competition and came second in the area competition a week or so later.) In &#8230; <a href="http://blog.timbunce.org/2012/04/08/a-space-for-thought/">Continue reading <span class="meta-nav">&#8594;</span></a><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.timbunce.org&#038;blog=2562816&#038;post=511&#038;subd=timbunce&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<p>This is the text of a speech I originally wrote for the International Speech Competition at my <a href="http://www.toastmasters.org/" target="_blank">Toastmasters</a> club in April 2012. (I won the club competition and came second in the area competition a week or so later.)</p>
<p>In July I gave a slightly modified version, reproduced here, as a 5 minute Lightning Talk at OSCON in Portland OR.<span id="more-511"></span>I wrote early drafts in the first person, which I prefer to do for material rooted in personal experience, then changed it be mostly second person as that seemed to be more effective in this case. In written form you&#8217;ll miss the gestures and delivery but hopefully the text is clear enough.</p>
<p>It&#8217;s written to spoken quite slowly, with pauses, so please read it that way when you&#8217;ve some time to spare. </p>
<h2>A SPACE FOR THOUGHT</h2>
<p>What is the difference between thought, and the quiet awareness in the space between thoughts?</p>
<p>~pause~</p>
<p>I want to share with you the single most important thing I&#8217;ve learned in my life.</p>
<p>It&#8217;s a shift in how I relate to myself and the world around me.<br />
A change in perspective that has revealed answers to many mysteries;<br />
so much more of the world makes sense to me now.</p>
<p>I really want to share this with you, but I have a problem.</p>
<p>The key idea is so simple that, if you&#8217;re not familiar with it, you probably won&#8217;t believe me.</p>
<p>Or if you are, you may dismiss it as obvious and of no value. Missing the depth and implications of it.</p>
<p>To persuade you I could quote countless great examples from literature, science, art, and everyday life.<br />
Showing you how they fit together and make sense when viewed in this light.</p>
<p>But I don&#8217;t have time.</p>
<p>I only have time to give you a starting point, to plant a seed,<br />
and some suggestions for how to nurture it, in the hope that it can grow and blossom for you too.</p>
<p>Before I share you this simple insight, before I plant this seed,<br />
I need <em>your</em> help to prepare the ground.<br />
I need <em>you</em> to <em>experience</em> something for yourself.</p>
<p>So please join me in a simple exercise in awareness. In paying attention.</p>
<p>Start paying attention now, to the feeling of your left foot.<br />
Just experience your left foot for a while, <em>without thinking about it</em>.</p>
<p>~pause~</p>
<p>What you&#8217;re paying attention <em>to</em> is your foot.<br />
What you&#8217;re paying attention <em>with</em> is in your head.</p>
<p>~pause~</p>
<p>We&#8217;ll do that again now but this time I&#8217;ll say something to prompt some thought.<br />
I want you to notice what happens to your attention when you start thinking.</p>
<p>Return your attention to your foot now.</p>
<p>~pause~</p>
<p>Nine plus seven.</p>
<p>~pause~</p>
<p>Did you notice your attention move away from your foot when you started thinking?<br />
The focus of your awareness moved from your foot into your mind.</p>
<p>Your full attention can&#8217;t be on a thought and something else at the same time.<br />
You need to be <em>aware</em> of the thought, just as you need to be aware of the feeling.</p>
<p>Awareness is primary. Thinking and feeling are secondary.</p>
<p>~pause~</p>
<p>So here&#8217;s the seed I want to plant:</p>
<p><em>You</em> are not your thoughts, just as you are not your feelings.<br />
You, the essence of who you really are, <em>is</em> the awareness.<br />
The conscious awareness within which your thoughts and feelings arise.</p>
<p>~pause~</p>
<p>That&#8217;s it.</p>
<p>It&#8217;s so simple, and yet so delicate.</p>
<p>Easily crushed by the weight of your own thoughts, that are constantly seeking to define you.</p>
<p>~pause~</p>
<p>Having planted the seed, I want to give you three tips for nurturing it, that I have found very helpful.</p>
<p>1st &#8211; Give your thoughts and opinions some space.</p>
<p>View them from a little distance.<br />
Note their contents but <em>don&#8217;t judge them</em>.<br />
Judging involves the thinking mind and you won&#8217;t break free.<br />
Simply note their contents and let them go.</p>
<p>Treat your thoughts as suggestions from a <em>much loved friend</em>.<br />
But a friend who you know is vain, insecure, and untrustworthy.</p>
<p>Noticing how this friend reacts to situations in your life<br />
is a <em>fascinating and rewarding</em> pastime.</p>
<p>You don&#8217;t need to watch a soap opera on TV<br />
when you can watch the one going on in your thinking mind!</p>
<p>2nd &#8211; Practice taking your attention away from thoughts<br />
whenever they&#8217;re unhappy, unproductive or unhelpful.<br />
Which, let&#8217;s face it, can be much of the time.</p>
<p>Simply bring your attention to your breathing, your foot,<br />
or anything else in the present moment.</p>
<p>3rd &#8211; Slow the momentum of the mind by bringing moments of stillness into your life regularly.</p>
<p>The phone rings &mdash; take a conscious breath with an empty mind before answering.<br />
Get in the car &mdash; take a few breaths before starting the engine.<br />
Look at nature, birds, trees, flowers, people, without labeling, judging, or other mental activity.</p>
<p>~pause~</p>
<p>The more often <em>I</em> remember to do these simple things,<br />
the more my sense of self shifts,<br />
from the noise and turmoil of the thinking mind,<br />
to being rooted in the peace beyond it.</p>
<p>So what is the difference between thought, and the quiet awareness in the space between thoughts?<br />
That&#8217;s for you to discover in your own way, if you want to,<br />
<em>but you won&#8217;t find out by thinking about it</em>.</p>
<br />Filed under: <a href='http://blog.timbunce.org/category/life/health/'>health</a>, <a href='http://blog.timbunce.org/category/life/'>life</a> Tagged: <a href='http://blog.timbunce.org/tag/oscon/'>oscon</a>, <a href='http://blog.timbunce.org/tag/toastmasters/'>toastmasters</a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.timbunce.org&#038;blog=2562816&#038;post=511&#038;subd=timbunce&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://blog.timbunce.org/2012/04/08/a-space-for-thought/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/1cf82705f5ab43c73273ab5d690866b3?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">TimBunce</media:title>
		</media:content>
	</item>
		<item>
		<title>What&#8217;s actually installed in that perl library?</title>
		<link>http://blog.timbunce.org/2011/11/16/whats-actually-installed-in-that-perl-library/</link>
		<comments>http://blog.timbunce.org/2011/11/16/whats-actually-installed-in-that-perl-library/#comments</comments>
		<pubDate>Wed, 16 Nov 2011 21:52:01 +0000</pubDate>
		<dc:creator>TimBunce</dc:creator>
				<category><![CDATA[perl]]></category>
		<category><![CDATA[conference]]></category>
		<category><![CDATA[cpan]]></category>
		<category><![CDATA[metacpan]]></category>
		<category><![CDATA[presentation]]></category>

		<guid isPermaLink="false">http://timbunce.wordpress.com/?p=502</guid>
		<description><![CDATA[A key part of my plan for Upgrading from Perl 5.8 is the ability to take a perl library installed for one version of perl, and reinstall it for a different version of perl. To do that you have to &#8230; <a href="http://blog.timbunce.org/2011/11/16/whats-actually-installed-in-that-perl-library/">Continue reading <span class="meta-nav">&#8594;</span></a><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.timbunce.org&#038;blog=2562816&#038;post=502&#038;subd=timbunce&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<p>A key part of my plan for <a href="http://blog.timbunce.org/2011/07/21/upgrading-from-perl-5-8/">Upgrading from Perl 5.8</a> is the ability to take a perl library installed for one version of perl, and reinstall it for a different version of perl.</p>
<p>To do that you have to know exactly what distributions were installed in the original library.  And not just which distributions, but which versions of those distributions.</p>
<p>I&#8217;ve a solution for that now. It turned out to be rather harder to solve than I&#8217;d thought&#8230; <span id="more-502"></span>As I mentioned <a href="http://blog.timbunce.org/2011/07/21/upgrading-from-perl-5-8/">previously</a>, I had developed a &#8220;distinctly hackish solution&#8221; that seemed to be working well. Sadly it didn&#8217;t withstand battle testing.</p>
<p>We have a library with almost 5000 modules installed from CPAN over many years. I ran that hackish script and it duly listed the distributions it thought were installed. Using that list I reinstalled them into a new library and ran <code>diff -r</code> to compare the two. That found a bunch of differences that led me into a vortex of hacking and rerunning. Eventually I had to admit that the whole approach wasn&#8217;t robust enough and I started to explore other ideas.</p>
<p>Some searching turned up <a href="http://search.cpan.org/perldoc?BackPAN::Version::Discover">BackPAN::Version::Discover</a> which is meant to &#8220;Figure out exactly which dist versions you have installed&#8221;. Perfect. Sadly it simply didn&#8217;t work well for me. Probably because it&#8217;s using a similarly flawed approach to my own.</p>
<p>I knew brian d foy&#8217;s <a href="http://blogs.perl.org/users/brian_d_foy/2011/03/recreating-a-perl-installation-with-mycpan.html">MyCPAN</a> project was working towards a similar goal. His approach required us to either run a large BackPAN indexing process or paying to license the data to offset his costs for doing so. That didn&#8217;t seem attractive.</p>
<p>I wondered about using <a href="https://github.com/gitpan">GitPAN</a> and the github API to match git blob hashes of local modules with files in the gitpan repos. Sadly GitPAN has fallen out of date and isn&#8217;t being maintained at the moment. With hindsight I&#8217;m thankful of that because it lead me to a better solution.</p>
<h2>MetaCPAN</h2>
<p><a href="http://metacpan.org/about">MetaCPAN</a> is full of awesome. On the surface it looks like another kind of search.cpan.org site. Don&#8217;t be fooled. Underneath is a vast repository of CPAN metadata powered by an <a href="http://www.elasticsearch.org/">ElasticSearch</a> distributed database (based on Lucene). How vast? Every file in every distribution on CPAN (<em>and</em>, critically for me, the BackPAN archive) has been indexed in great detail. Including details like the file size and which spans of lines are code and which are pod.</p>
<p>The cherry on the cake is the <a href="https://github.com/CPAN-API/cpan-api/wiki/Beta-API-docs">RESTful API</a> that provides full access to <a href="http://www.elasticsearch.org/guide/reference/query-dsl/">ElasticSearch query expressions</a>.</p>
<p>The key &#8220;lightbulb over head&#8221; moment came when I realized I could ask MetaCPAN to &#8220;<a href="http://explorer.metacpan.org/?url=%2Ffile&amp;content=%7B%22query%22%3A%7B%22filtered%22%3A%7B%22query%22%3A%7B%22match_all%22%3A%7B%7D%7D%2C%22filter%22%3A%7B%22and%22%3A%5B%7B%22term%22%3A%7B%22file.module.name%22%3A%22DBI%3A%3AProfile%22%7D%7D%2C%7B%22term%22%3A%7B%22file.module.version%22%3A%222.014123%22%7D%7D%5D%7D%7D%7D%2C%22fields%22%3A%5B%22release%22%5D%7D">find all releases that contain a particular version of a module</a>&#8220;. Bingo!</p>
<h2>The Method</h2>
<p>The next step was how to work out which of those candidates was the one actually installed. The key realization here was that I could use MetaCPAN to get version and file size info for all the modules in each candidate release and see how well they matched what was currently installed.</p>
<p>The whole process falls into several distinct phases&#8230;</p>
<p>The first phase finds the name, version, and file size of all the modules in the library being surveyed. (Taking care to handle an archlib nested within the main lib.)</p>
<p>Then, for every module it asks MetaCPAN for all the distribution releases that included that that module version. For rarely changed modules in frequently released distributions there might be many candidates, so it tries to limit the number of candidates by also matching the file size. This is especially helpful for modules that don&#8217;t have a version number.</p>
<p>Then, for every candidate distribution release, MetaCPAN is queried to get the modules in the release, along with their version numbers and file sizes. These are compared to the data it gathered about the locally installed modules to yield a &#8220;fraction installed&#8221; figure between 0 and 1. The candidates that share the highest fraction installed are returned.</p>
<p>Typically there&#8217;s just one candidate that has fraction installed of 1. A perfect match. Sometimes the fraction is less than 1 for various obscure but valid reasons. Sometimes life isn&#8217;t so simple. There may be multiple candidates that have the same highest fraction installed value. So the next phase attempts to narrow the choice from among the &#8220;best candidates&#8221; for each module. The results are gathered into a two level hash of distributions and candidate releases.</p>
<p>The final phase is the first to work in terms of distributions instead of modules. For each distribution it tries to choose among the candidate releases.</p>
<h2>The Results</h2>
<p>The method seems to work well. It identifies files with local changes. It deals gracefully with &#8216;remnant&#8217; modules that were included in an old release but not in later ones. And it copes with distributions that have been split into separate distributions.</p>
<p>It reports progress and anything unusual to stderr and writes the list of distributions to stdout. You should investigate anything that&#8217;s reported to ensure that the chosen distribution is the right one.</p>
<p>I checked the results by creating a new library (see below) and running <code>diff -r <em>old_lib new_lib</em></code>. I didn&#8217;t see any differences that I couldn&#8217;t account for.</p>
<p>The survey process is not fast. It can take a couple of hours on the first run for a large library. Most of that time is spent making MetaCPAN calls (<em>lots and lots</em> of MetaCPAN calls) so you&#8217;re dependent on network and MetaCPAN performance. Most of the calls are cached in an external file so later runs are much faster.</p>
<h2>Using The Results</h2>
<p>Using a list of distributions to recreate a library isn&#8217;t as straight-forward as it might seem. You can&#8217;t just give the list to <a href="http://search.cpan.org/perldoc?cpanm">cpanm</a> because it would try to install the <em>latest</em> version of any prerequisites. I looked at using &#8211;scandeps or topological sorting to reorder the list to put the prerequisites first. It didn&#8217;t work out. I also looked at using <a href="http://search.cpan.org/perldoc?mcpani">CPAN::Mini::Inject</a> (and <a href="http://search.cpan.org/dist/OrePAN/" target="_blank">OrePAN</a> and <a href="http://search.cpan.org/perldoc?Pinto" target="_blank">Pinto</a>) to create a local MiniCPAN for cpanm to fetch from. They didn&#8217;t work out either, for various reasons.</p>
<p>In the end I added a <code>--makecpan <em>dir</em></code> option so that the surveyor script itself would fetch the distributions and create a MiniCPAN for cpanm to use.</p>
<p>So now a typical initial run looks like this:</p>
<p><code>    dist_surveyor --makecpan my_cpan /some/perl/lib/dir &gt; installed_dists.txt</code></p>
<p>followed by building a new library from the results:</p>
<p><code>    cpanm --mirror file:$PWD/my_cpan --mirror-only -l new_lib &lt; installed_dists.txt</code></p>
<p>If you need to rebuild the library, perhaps due to test failures, then it&#8217;s <em>much</em> faster to use a list of modules to drive cpanm. Fortunately dist_surveyor writes one for you:</p>
<p><code>    cpanm --mirror file:$PWD/my_cpan --mirror-only -l new_lib &lt; my_cpan/dist_surveyor/token_packages.txt</code></p>
<h2>Testing Bonus</h2>
<p>Speaking of test failures, I was surprised to see how often tests failed due to problems with prerequisites even though the distribution and its prerequisites had passed their tests when originally installed. For example, imagine distribution A v1, and its prerequisite B v1 are installed. Later, distribution B gets upgraded to v2 but the tests for distribution A don&#8217;t get rerun.</p>
<p>Reinstalling all the distributions forces all distributions to be tested with the prerequisites that are actually being used.</p>
<h2>Presentation Slides</h2>
<p>I gave a lightning talk on Dist::Surveyor at the <a href="http://conferences.yapceurope.org/lpw2011/">2011 London Perl Workshop</a> (always a great event) and uploaded the <a href="http://www.slideshare.net/Tim.Bunce/perl-distsurveyor-2011">slides</a>.</p>
<h2>Source Code</h2>
<p>The <a href="https://github.com/timbunce/Dist-Surveyor">repository</a> is on github and I&#8217;ve made a <a href="http://search.cpan.org/dist/Dist-Surveyor/">release</a> to CPAN.</p>
<br />Filed under: <a href='http://blog.timbunce.org/category/tech/software/perl/'>perl</a> Tagged: <a href='http://blog.timbunce.org/tag/conference/'>conference</a>, <a href='http://blog.timbunce.org/tag/cpan/'>cpan</a>, <a href='http://blog.timbunce.org/tag/metacpan/'>metacpan</a>, <a href='http://blog.timbunce.org/tag/perl/'>perl</a>, <a href='http://blog.timbunce.org/tag/presentation/'>presentation</a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.timbunce.org&#038;blog=2562816&#038;post=502&#038;subd=timbunce&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://blog.timbunce.org/2011/11/16/whats-actually-installed-in-that-perl-library/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/1cf82705f5ab43c73273ab5d690866b3?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">TimBunce</media:title>
		</media:content>
	</item>
		<item>
		<title>Upgrading from Perl 5.8</title>
		<link>http://blog.timbunce.org/2011/07/21/upgrading-from-perl-5-8/</link>
		<comments>http://blog.timbunce.org/2011/07/21/upgrading-from-perl-5-8/#comments</comments>
		<pubDate>Thu, 21 Jul 2011 14:50:26 +0000</pubDate>
		<dc:creator>TimBunce</dc:creator>
				<category><![CDATA[perl]]></category>
		<category><![CDATA[cpan]]></category>
		<category><![CDATA[testing]]></category>

		<guid isPermaLink="false">http://timbunce.wordpress.com/?p=499</guid>
		<description><![CDATA[Imagine&#8230; You have a production system, with many different kinds of application services running on many servers, all using the perl 5.8.8 supplied by the system. You want to upgrade to use perl 5.14.1 You don&#8217;t want to change the &#8230; <a href="http://blog.timbunce.org/2011/07/21/upgrading-from-perl-5-8/">Continue reading <span class="meta-nav">&#8594;</span></a><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.timbunce.org&#038;blog=2562816&#038;post=499&#038;subd=timbunce&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<p>Imagine&#8230;</p>
<ol>
<li>You have a production system, with many different kinds of application services running on many servers, all using the perl 5.8.8 supplied by the system.
</li>
<li>You want to upgrade to use perl 5.14.1
</li>
<li>You don&#8217;t want to change the system perl.
</li>
<li>You&#8217;re using CPAN modules that are slightly out of date but you can&#8217;t upgrade them because newer versions have dependencies that require perl 5.10.
</li>
<li>The perl application codebase is large and has poor test coverage.
</li>
<li>You want developers to be able to easily test their code with different versions of perl.
</li>
<li>You don&#8217;t want a risky all-at-once &#8220;<a href="http://en.wikipedia.org/wiki/Big_bang_adoption">big bang</a>&#8221; upgrade. Individual production installations should be able to use different perl versions, even if only for a few days, and to switch back and forth easily.
</li>
<li>You want to simplify future perl upgrades.
</li>
</ol>
<p>I imagine there are lots of people in similar situations.</p>
<p>In this post I want to explore how I&#8217;m tackling a similar problem, both for my own benefit and in the hope it&#8217;ll be useful to others.<span id="more-499"></span><br />
<h2>Incremental Upgrades</h2>
<p>Perl now has an explicit <a href="http://metacpan.org/module/perlpolicy#BACKWARD-COMPATIBILITY-AND-DEPRECATION">deprecation policy</a> that requires a mandatory warning for at least one major perl version before a feature is removed. So a feature that&#8217;s removed in perl 5.14 will generate a mandatory warning, at compile time if possible, in perl 5.12.</p>
<p>This means we should <em>not</em> jump straight from perl 5.8.8 to 5.14.1. It&#8217;s important to test our code with the latest 5.10.x and 5.12.x releases along the way. That way if we do hit a problem it&#8217;ll be easier to determine the cause.</p>
<p>This also fits in with our desire to simplify future upgrades. Effectively we&#8217;re not doing one perl version upgrade but three, although we may only do one or two actual upgrades on production machines.</p>
<h2>Multiple Perls</h2>
<p>We want the developers to be able to able to easily test their code with different versions of perl, so we need to allow multiple versions to be installed at the same time. Fortunately <a href="http://metacpan.org/module/perlbrew">perlbrew</a> makes that easy. </p>
<p>We&#8217;ll probably have the systems team install ready-built and read-only perlbrew perls on all the machines via scp. We&#8217;ll use perlbrew as a way to get a set of perls installed but the actual selecting of a perl via PATH etc. we&#8217;ll handle ourselves.</p>
<h2>Multiple CPAN Install Trees</h2>
<p>Major versions of perl aren&#8217;t binary compatible with each other. This means extension modules, like DBI, which were installed for one major version of perl can&#8217;t be reused with another.</p>
<p>We keep all the code installed from CPAN in a repository, separate from the perl installation. Perl finds them using PERL5LIB env var and installers install there using the PERL_MB_OPT and PERL_MM_OPT env vars to set it as the &#8216;install_base&#8217;.</p>
<p>Since we want developers to switch easily between perl versions, this means we need multiple CPAN installation directories, one per <em>major</em> perl version. We&#8217;ll rebuild and reinstall the extension modules into each immediately after building and installing the corresponding perl version.</p>
<p>If we have to rebuild and reinstall the extension modules then we can easily rebuild and reinstall <em>all</em> our CPAN modules. That way we get to rerun all their test suites against each version of perl plus the specific versions of their prerequisite modules that we&#8217;re using.</p>
<h2>Reinstalling CPAN Distributions</h2>
<p>This is where it gets tricky. </p>
<p>Identifying what CPAN distributions we have installed is fairly easy. You can use tools like CPAN.pm or <a href="https://github.com/bingos/throwaway/blob/master/whatdists.pl">whatdists.pl</a> to generate a list. But there&#8217;s a catch. They&#8217;ll only tell you what <em>current distributions</em> you need to install to get the same set of modules. That&#8217;s not what we need.</p>
<p>We need a list of the <em>specific distribution versions</em> that are currently installed. It turns out that that information isn&#8217;t recorded in the installation and it&#8217;s amazingly difficult to recreate <em>reliably</em>. (The perllocal.pod file ought to have this information but isn&#8217;t updated by the Module::Build installer and doesn&#8217;t record the actual distribution name.)</p>
<p>In an extension of his MyCPAN work, brian d foy is trying to tackle this problem by creating MD5 hashes for the <em>millions</em> of files on BackPAN (the CPAN archive) but there&#8217;s <a href="http://blogs.perl.org/users/brian_d_foy/2011/03/recreating-a-perl-installation-with-mycpan.html">still much hard work ahead</a>.</p>
<p>Why do we need the specific versions, why not simply upgrade everything to the latest version first as a separate project? Two reasons.</p>
<p>First, we&#8217;re caught by the fact that some latest distributions, either directly or indirectly, require a later version of perl. (David Cantrel&#8217;s <a href="http://cpxxxan.barnyard.co.uk/">cpxxxan</a> project offers an interesting approach to this problem. E.g., use <a href="http://cp5.8.8an.barnyard.co.uk/" rel="nofollow">http://cp5.8.8an.barnyard.co.uk/</a> as the CPAN mirror to get a &#8220;latest that works on 5.8.8&#8243; view. [Thanks to ribasushi++ for the reminder.])</p>
<p>Second, having a complete list of <em>exactly</em> what we have installed also gives us easy reproducibility. Future installs will always yield exactly the same set of files, without risk of silent changes due to new releases on CPAN. The cpxxxan indices for older perls are much less likely to change, but still may. Also, if we upgraded everything to the latest using cp5.8.8an we&#8217;d need an extra testing cycle to check for problems with that upgrade before we even start on the perl upgrade.</p>
<p>After contemplating the large, ambitious, and incomplete MyCPAN project, I decided I&#8217;d try a distinctly hackish solution to this problem by extending the whatdists.pl script with a perllocal.pod parser and some heuristics. It <em>seems</em> to have worked out well. I&#8217;m going to check it by installing the distributions into a different directory and diff&#8217;ing that against the original. </p>
<p>If that works out I&#8217;ll release the code and write up a blog post about it.</p>
<h2>Installing Only Specific CPAN Distributions</h2>
<p>Normally when you install a distribution from CPAN you&#8217;re happy for the installer to fetch and install the latest version of any prerequisite modules it might need. In our situation we want to install only a specific version of each.</p>
<p>In theory we could arrange that by ordering the list such that the prerequisite modules are installed first. The <a href="http://metacpan.org/module/CPANDB">CPANDB</a> module combined with a topological sort of the requires, test_requires, and build_requires dependencies via the <a href="http://metacpan.org/module/Graph#Topological-Sort">Graph module</a> should do the trick. [Hat tip to ribasushi++ for the CPANDB suggestion.] But there&#8217;s a simpler approach&#8230;</p>
<p>I&#8217;ll probably simply duck that issue by using <a href="http://metacpan.org/module/CPAN::Mini::Inject">CPAN::Mini::Inject</a> to create a miniature CPAN that contains <em>only</em> the specific versions of the specific distributions we&#8217;re using. Then we can use the <a href="http://metacpan.org/module/cpanm">cpanm</a> &#8211;mirror and &#8211;mirror-only options to install from that mini CPAN.</p>
<h2>Extending Test Coverage</h2>
<p>All the above will give developers the ability to switch perl versions with ease, while keeping exactly the same set of CPAN modules. So now we can turn our attention to testing.</p>
<p>Our test coverage could charitably be described as spotty. Getting it up to a good level across all our code is simply not viable in the short term.</p>
<p>So for now I&#8217;m setting a <em>very</em> low goal: simply get <em>all</em> the perl modules and scripts compiled. You could say I&#8217;m aiming for 100% &#8220;compilation coverage&#8221; :-)</p>
<p>This will get all the developers aware of the basic mechanics of testing, like <a href="http://metacpan.org/module/Test::Most">Test::Most</a> and <a href="http://metacpan.org/module/prove">prove</a> and it gives us a good baseline to increase coverage from. More importantly in the short term it let&#8217;s us detect any compile-time deprecation warnings as we test with perl 5.10 and 5.12.</p>
<p>To ensure 100% (compilation) coverage I&#8217;ll use <a href="http://metacpan.org/module/Devel::Cover">Devel::Cover</a> to do coverage analysis and write a utility, probably using <a href="http://metacpan.org/module/Devel::CoverX::Covered">Devel::Cover::Covered</a>, to find <em>all</em> our perl scripts and modules and check that they have all at least been compiled.</p>
<h2>Summary</h2>
<ul>
<li>Multiple perl versions, via perlbrew.
</li>
<li>Multiple identical CPAN install trees, one per major perl version.
</li>
<li>Proven 100% compilation coverage as a minimum.
</li>
</ul>
<p>So, that&#8217;s the plan.</p>
<br />Filed under: <a href='http://blog.timbunce.org/category/tech/software/perl/'>perl</a> Tagged: <a href='http://blog.timbunce.org/tag/cpan/'>cpan</a>, <a href='http://blog.timbunce.org/tag/testing/'>testing</a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.timbunce.org&#038;blog=2562816&#038;post=499&#038;subd=timbunce&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://blog.timbunce.org/2011/07/21/upgrading-from-perl-5-8/feed/</wfw:commentRss>
		<slash:comments>10</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/1cf82705f5ab43c73273ab5d690866b3?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">TimBunce</media:title>
		</media:content>
	</item>
		<item>
		<title>Building a different kind of extension</title>
		<link>http://blog.timbunce.org/2011/06/29/building-a-different-kind-of-extension/</link>
		<comments>http://blog.timbunce.org/2011/06/29/building-a-different-kind-of-extension/#comments</comments>
		<pubDate>Wed, 29 Jun 2011 21:44:29 +0000</pubDate>
		<dc:creator>TimBunce</dc:creator>
				<category><![CDATA[local]]></category>

		<guid isPermaLink="false">http://timbunce.wordpress.com/?p=496</guid>
		<description><![CDATA[For the past year I&#8217;ve been rather distracted, with little time to devote to Open Source projects. I&#8217;ve been working on a different kind of project, adding an extension to our home. It&#8217;s been quite a journey. After much planning &#8230; <a href="http://blog.timbunce.org/2011/06/29/building-a-different-kind-of-extension/">Continue reading <span class="meta-nav">&#8594;</span></a><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.timbunce.org&#038;blog=2562816&#038;post=496&#038;subd=timbunce&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<p>For the past year I&#8217;ve been rather distracted, with little time to devote to Open Source projects. I&#8217;ve been working on a different kind of project, adding an extension to our home. It&#8217;s been quite a journey.</p>
<p>After much planning (the plumbing Statement of Works, for example, covers four pages), and our fair share of trials and tribulations, the builders broke ground two weeks ago. Now, after days of digging and rock-breaking, the foundations trenches are all dug out and the concrete will be poured tomorrow morning. Finally, we&#8217;ll be &#8220;out of the ground&#8221;.</p>
<p><img style="display:block;margin-left:auto;margin-right:auto;" src="http://timbunce.files.wordpress.com/2011/06/img_0404.jpg?w=600&#038;h=450" alt="Digging foundations" border="0" width="600" height="450" /></p>
<p>Naturally I want to be around to handle issues as they arise, so this year I won&#8217;t be going to OSCON or YAPC::EU. If all goes well we should be completed in time for me to attend the <a href="http://lanyrd.com/2011/london-perl-workshop/">London Perl Workshop</a> in November.</p>
<p>Meanwhile I hope to find a little time for catching up on outstanding issues with DBI and NYTProf and perhaps a little more blogging.</p>
<br />Filed under: <a href='http://blog.timbunce.org/category/life/ireland/local/'>local</a>  <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.timbunce.org&#038;blog=2562816&#038;post=496&#038;subd=timbunce&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://blog.timbunce.org/2011/06/29/building-a-different-kind-of-extension/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/1cf82705f5ab43c73273ab5d690866b3?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">TimBunce</media:title>
		</media:content>

		<media:content url="http://timbunce.files.wordpress.com/2011/06/img_0404.jpg" medium="image">
			<media:title type="html">Digging foundations</media:title>
		</media:content>
	</item>
		<item>
		<title>Looking for a Senior Developer job? TigerLead is Hiring again in West LA</title>
		<link>http://blog.timbunce.org/2011/04/14/looking-for-a-senior-developer-job-tigerlead-is-hiring-again-in-west-la/</link>
		<comments>http://blog.timbunce.org/2011/04/14/looking-for-a-senior-developer-job-tigerlead-is-hiring-again-in-west-la/#comments</comments>
		<pubDate>Thu, 14 Apr 2011 17:50:58 +0000</pubDate>
		<dc:creator>TimBunce</dc:creator>
				<category><![CDATA[perl]]></category>
		<category><![CDATA[software]]></category>
		<category><![CDATA[jobs]]></category>
		<category><![CDATA[postgresql]]></category>

		<guid isPermaLink="false">http://timbunce.wordpress.com/?p=486</guid>
		<description><![CDATA[The company I work for, TigerLead.com, has another job opening in West LA: As a Senior Developer, you will be playing a central role in the design, development, and delivery of cutting-edge web applications for one of the most heavily-trafficked &#8230; <a href="http://blog.timbunce.org/2011/04/14/looking-for-a-senior-developer-job-tigerlead-is-hiring-again-in-west-la/">Continue reading <span class="meta-nav">&#8594;</span></a><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.timbunce.org&#038;blog=2562816&#038;post=486&#038;subd=timbunce&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<p>The company I work for, <a href="http://www.tigerlead.com/">TigerLead.com</a>, has another job  opening in West LA: </p>
<blockquote><p>As a Senior Developer, you will be playing a central role in the design, development, and delivery of cutting-edge web applications for one of the most heavily-trafficked network of real estate sites on the web. You will work in a small, collaborative environment with other seasoned pros and with the direct support of the company&rsquo;s owners and senior management. Your canvas and raw materials include rich data sets totaling several million property listings replenished daily by hundreds of external data feeds. This valuable data and our powerful end-user tools to access it are deployed across several thousand real estate search sites used by more than a million home-buyer leads and growing by 50K+ users each month. The 1M+ leads using our search tools are in turn tracked and cultivated by the several thousand real estate professionals using our management software. This is an outstanding opportunity to see your creations immediately embraced by a large community of users as you work within a creative and supportive environment that is both professional and non-bureaucratic at the same time, offering the positives of a start-up culture without the drama and instability. </p></blockquote>
<p>If that sounds like interesting work to you then take a look at the <a href="http://www.tigerlead.com/jobs/senior-web-developer.html">full job posting</a>.</p>
<p>TigerLead is a lovely company to work for and this is a great opportunity. Highly recommended.</p>
<br />Filed under: <a href='http://blog.timbunce.org/category/tech/software/perl/'>perl</a>, <a href='http://blog.timbunce.org/category/tech/software/'>software</a> Tagged: <a href='http://blog.timbunce.org/tag/jobs/'>jobs</a>, <a href='http://blog.timbunce.org/tag/perl/'>perl</a>, <a href='http://blog.timbunce.org/tag/postgresql/'>postgresql</a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.timbunce.org&#038;blog=2562816&#038;post=486&#038;subd=timbunce&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://blog.timbunce.org/2011/04/14/looking-for-a-senior-developer-job-tigerlead-is-hiring-again-in-west-la/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/1cf82705f5ab43c73273ab5d690866b3?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">TimBunce</media:title>
		</media:content>
	</item>
		<item>
		<title>java2perl6api &#8211; Java to Perl 6 API translation &#8211; What, Why, and Whereto</title>
		<link>http://blog.timbunce.org/2010/07/16/java2perl6api-java-to-perl-6-api-tranalation-what-why-and-whereto/</link>
		<comments>http://blog.timbunce.org/2010/07/16/java2perl6api-java-to-perl-6-api-tranalation-what-why-and-whereto/#comments</comments>
		<pubDate>Fri, 16 Jul 2010 17:12:59 +0000</pubDate>
		<dc:creator>TimBunce</dc:creator>
				<category><![CDATA[perl]]></category>
		<category><![CDATA[software]]></category>
		<category><![CDATA[dbdi]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[perl6]]></category>

		<guid isPermaLink="false">http://timbunce.wordpress.com/?p=460</guid>
		<description><![CDATA[In this post I&#8217;m going to talk about the java2perl6api project. What its goals are, why I think it&#8217;s important, how it relates to a Perl 6 DBI, what exists now, what&#8217;s needs doing, and how you can help. Firstly &#8230; <a href="http://blog.timbunce.org/2010/07/16/java2perl6api-java-to-perl-6-api-tranalation-what-why-and-whereto/">Continue reading <span class="meta-nav">&#8594;</span></a><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.timbunce.org&#038;blog=2562816&#038;post=460&#038;subd=timbunce&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<p>In this post I&#8217;m going to talk about the java2perl6api project. What its goals are, why I think it&#8217;s important, how it relates to a Perl 6 DBI, what exists now, what&#8217;s needs doing, and how you can help.<br />
<span id="more-460"></span></p>
<p>Firstly I&#8217;d like to point out that, funnily enough, I&#8217;m not very familiar with Java or Perl6. It&#8217;s entirely possible that I&#8217;ll make all sorts of errors in the following details. If you spot any do please let me know.</p>
<h2>Background</h2>
<p>The Java language ecosystem is big and mature after years of heavy investment of time and money.</p>
<p>It doesn&#8217;t have a central repository of Open Source modules like CPAN (though <a href="http://en.wikipedia.org/wiki/Apache_Maven">Maven</a> repositories <a href="http://download.java.net/maven/1/">like</a> <a href="http://repo1.maven.org/maven2/">these</a> are similar I guess). It does, however, have a number of mature high quality class libraries, and a very large number of developers familiar with those libraries (more on that below).</p>
<h2>Goals</h2>
<p>The primary goal of the java2perl6api project is to make it easy to create Perl 6 class libraries that <em>mirror</em> Java equivalents. By <em>mirror</em> I mean share the same method names and semantics at a high level (though not at a low-level, more on that below).</p>
<p>Secondary goals are to do that well enough that:</p>
<ul>
<li>the documentation for Java classes can serve as primary the documentation for the corresponding Perl 6 classes. The Perl 6 classes need only document the differences in behavior, which these should be minimal and &#8216;natural&#8217;. The same applies to books describing the Java classes.
</li>
<li>Java developers familiar with the Java classes should feel comfortable working with the corresponding Perl 6 classes.
</li>
<li>and, hopefully, some way can be found to convert test suites for the Java classes into Perl 6 code that&#8217;ll test the corresponding Perl 6 classes. (I appreciate that this is a non-trivial proposition, but there are viable approaches available, like <a href="http://www.xmlvm.org/overview/">xmlvm</a>.) Even if that can&#8217;t be done, extracting and translating tests manually is less work, and more effective, than creating them from scratch for a new API.
</li>
</ul>
<h2>Why?</h2>
<p>Firstly, creating good APIs is hard. Java APIs like <a href="http://download.oracle.com/docs/cd/E17409_01/javase/6/docs/technotes/guides/jdbc/">JDBC 3.0</a> and <a href="http://java.sun.com/developer/technicalArticles/javase/nio/">NIO.2</a> are the result of years of professional effort and demanding commercial experience. Why not build on that experience?</p>
<p>I appreciate that Java APIs are often limited by the constraints of the language, such as the lack of closures, and that Perl 6 can probably express any given set of semantics more effectively than Java. My point here is that some Java APIs embody, however inelegantly, years of hard won experience that we can benefit from. I&#8217;d rather make new mistakes than repeat old ones.</p>
<p>Secondly, there are many more Java developers than Perl developers. Many <em>many</em> more if job vacancies are any indication:</p>
<p><img src="http://www.indeed.com/trendgraph/jobgraph.png?q=%22perl+developer%22%2C%22java+developer%22" alt="job vacancy trends for perl developer and java developer" height="300" width="540" /></p>
<p>I think we&#8217;d be foolish not to try to smooth the path for any Java developers who might be interested in Perl 6. The java2perl6api project is just one small aspect of that.</p>
<p>I really hope someone starts writing a &#8220;Perl 6 for Java Developers&#8221; tutorial. Perl 6 has the potential to become a very popular language<sup><a href="#1">1</a></sup>. Getting just a tiny percentage of Java developers (and Computer Science majors and their teachers) interested in it could be a big help.</p>
<p>Thirdly, any future DBI for Perl 6 and Parrot needs a much better foundation than the very limited and poorly defined one that <a href="http://search.cpan.org/~timb/DBI-1.611/lib/DBI/DBD.pm">underlies the Perl 5 DBI</a>. I plan to adopt the JDBC 3.0 API <em>and test suite</em> for that <em>internal</em> role. (You could call this a &#8220;Test Suite Driven Strategy&#8221;.) I&#8217;ll talk more about that in a future blog post.</p>
<h2>The History java2perl6api</h2>
<p>I&#8217;ve been kicking around various ideas for integrating Java and Perl6/Parrot for years. I think I first decided to use JDBC as the inspiration for the DBI-to-driver API in 2006.</p>
<p>You may remember back in 2004, around the 10th anniversary of the DBI, the <a href="http://www.perlfoundation.org/">Perl Foundation</a> setup a &#8220;DBI Development Fund&#8221; that people could <a href="http://dbi.perl.org/donate/">donate</a> to. I&#8217;ve never drawn any money from that fund. I want to use it to oil other peoples wheels.</p>
<p>In 2007 <a href="http://news.perlfoundation.org/2007/03/best-practical-sponsors-perl-6.html">Best Practical sponsored Perl 6 Microgrants</a> through the Perl Foundation. I asked if I could piggyback my idea for a Java to Perl 6 API translator onto their microgrant management process but using money from the DBI Development Fund. TPF and Best Practical kindly agreed. I posted a description of the task and Phil Crow volunteered and was <a href="http://news.perlfoundation.org/2007/04/phil-crow-to-create-jdbc-api-f.html">awarded the microgrant</a> in April 2007.</p>
<p>At OSCON in July 2007 I gave lightning talk called &#8220;<a href="http://www.slideshare.net/Tim.Bunce/dbi-for-parrot-and-perl-6-lightning-talk-2007">Database interfaces for open source languages suck</a>&#8221; which explained the rationale for using JDBC as a foundation for the DBI-to-driver API and mentioned Phil&#8217;s java2perl6 project.</p>
<p>Development ground to a halt around the end of 2007 for various reasons. It picked up again for a few months after OSCON 2009 (where I gave a short lightning talk asking for help) then stalled again in October. Partly because we seemed to have hit a limitation with Rakudo and partly because I was focussed on Devel::NYTProf <a href="http://blog.timbunce.org/2009/12/24/nytprof-v3-worth-the-wait/">version 3</a> and then <a href="http://blog.timbunce.org/2010/06/09/nytprof-v4-now-with-string-eval-x-ray-vision/">version 4</a>, which took <em>way</em> more time than I expected.</p>
<p>There&#8217;s life in the project again now. We&#8217;ve dodged the earlier problem, put the <a href="http://github.com/timbunce/java2perl6">code on github</a>, brought it into sync with current <a href="http://rakudo.org/">Rakudo</a> Perl 6 syntax, and generally instilled some momentum.</p>
<h2>The Current java2perl6api</h2>
<p>Let&#8217;s take a look at a simple example.</p>
<p>To generate a perl6 file that mirrors the API of the java.sql.Savepoint class you&#8217;d just execute java2perl6api like this:</p>
<pre style="background-color:#ddd;margin:2em;padding:1em;">$ java2perl6api java.sql.Savepoint
loading java.sql.Savepoint
wrote java/sql/Savepoint.pm6 - interface java.sql.Savepoint
checking java/sql/Savepoint.pm6 - interface java.sql.Savepoint
</pre>
<p>That&#8217;s loaded and parsed the description of the java.sql.Savepoint class (from the <a href="http://download.oracle.com/docs/cd/E17476_01/javase/1.5.0/docs/tooldocs/windows/javap.html">javap</a> command), generated a corresponding perl6 module, and run perl6 to validate it.</p>
<p>The generated module (with some whitespace and cruft removed) looks like this:</p>
<pre style="background-color:#ddd;margin:1em;padding:1em;">use v6;
role java::sql::Savepoint {
    method getSavepointId (
    --&gt; Int   #  int
    ) { ... }
    method getSavepointName (
    --&gt; Str   #  java.lang.String
    ) { ... }
};
=begin pod
=head1 Java
  Compiled from "Savepoint.java"
  public interface java.sql.Savepoint{
      public abstract int getSavepointId() throws java.sql.SQLException;
      public abstract java.lang.String getSavepointName() throws java.sql.SQLException;
  }
=end pod
</pre>
<p>The pod section shows the description of the class that javap returned. The java2perl6api utility parsed that <a href="http://download.oracle.com/docs/cd/E17409_01/javase/tutorial/java/concepts/interface.html">Java interface</a> and generated the corresponding <a href="http://perlcabal.org/syn/S14.html#Roles">Perl6 role</a>. The &#8216;java.sql.Savepoint&#8217; has been mapped to &#8216;java::sql::Savepoint&#8217;. The generated methods are stubs using <code>...</code> (the &#8220;yada, yada, yada&#8221; operator). The types int and java.lang.String have been mapped to Int and Str. Because the only types used were built-ins, no type declarations were added.</p>
<p>Currently java2perl6api handles the above plus overloaded methods (which generate <a href="http://perlcabal.org/syn/S12.html#Multisubs_and_Multimethods">multi methods</a>), multiple implements clauses (which generate multiple <a href="http://perlcabal.org/syn/S14.html#Compile-time_Composition">does</a> clauses). There&#8217;s also partial support for class/interface constants (which currently generate exported methods).</p>
<p>The default behavior is to recursively process any Java types referenced by the class which aren&#8217;t mapped to Perl 6 types. So executing <code>java2perl6api java.sql.Connection</code>, for example, will generate 48 Perl 6 modules! (Because <code>java.sql.Connection</code> refers to many types, including <code>java.sql.Array</code> which refers to many types including <code>java.sql.ResultSet</code> which refers to <code>java.net.URL</code> which refers to <code>java.net.Proxy</code> etc. etc.) The <code>--norecurse</code> options disables this behavior.</p>
<p>Normally you&#8217;ll want to use the recursion but instead of letting it drill <em>all</em> the way into the Java types, you would supply your own &#8216;typemap&#8217; specification via an option. That tells java2perl6api which Java types you want to map to which Perl 6 types. So instead of recursing into the <code>java.net.URL</code> type to generate a <code>java/net/URL.pm6</code> file, for example, you can tell java2perl6api to use a specific Perl 6 type. Perhaps just <code>Str</code> for now.</p>
<h2>How this relates to JDBC / DBDI / DBI v2</h2>
<p>I want to start applying java2perl6api to the <a href="http://download.oracle.com/docs/cd/E17409_01/javase/6/docs/technotes/guides/jdbc">JDBC</a> classes now to create a &#8220;Database Driver Interface&#8221; or &#8220;DBDI&#8221; for Perl 6.</p>
<p>Starting with the <a href="http://download-llnw.oracle.com/docs/cd/E17409_01/javase/6/docs/api/java/sql/DriverManager.html">DriverManager</a> class and the <a href="http://download-llnw.oracle.com/docs/cd/E17409_01/javase/6/docs/api/java/sql/Connection.html">Connection</a>  interface I&#8217;ll use java2perl6api to generate corresponding Perl 6 roles with <em>heavy</em> stubbing out of types. Basically anything I don&#8217;t need to think about right now will be mapped to the <code>Any</code> type.</p>
<p>I&#8217;ll start fleshing out some basic implementation logic for each in a Perl 6 class that <a href="http://perlcabal.org/syn/S14.html#Compile-time_Composition">does</a> the corresponding role. I&#8217;ll probably use PostgreSQL as the first driver and the guts of <a href="http://github.com/mberends/MiniDBI/blob/master/lib/MiniDBD/Pg.pm6">MiniDBD::Pg</a> as inspiration.</p>
<p>The first minor milestones will be creating connections, then execute non-selects, then selects then prepared statements. Somewhere along the way I expect they&#8217;ll be a Perl 6 DBDI driver implemented for the <a href="http://blogs.perl.org/users/martin_berends/2010/06/rakudo-perl-6-gets-into-databases.html">Perl 6 MiniDBI project</a>. The next key step would be to start refactoring the code heavily so anyone wanting to implement a new driver should only have to implement the driver specific parts. (There are some JDBC driver toolkits that can provide useful ideas for that.)</p>
<h2>What needs doing</h2>
<p>There&#8217;s a <a href="http://github.com/timbunce/java2perl6/blob/master/TODO">TODO file in the repository</a> that lists the current items that need working on.</p>
<p>One fairly simple item is to add a <code>--prefix</code> option to specify an extra leading name for the generated role. So <code>java.sql.Savepoint</code> with a prefix of <code>DBDI</code> would generate a <code>DBDI::java::sql::Savepoint</code> role.</p>
<p>Another item, less simple but more important, is to automatically discover the values of constants and embed them into the generated file. Probably the best way to do that is to extend <a href="http://github.com/timbunce/java2perl6/blob/master/lib/Java/Javap/javap.grammar">the parser</a> (which uses <a href="http://search.cpan.org/perldoc?Parse::RecDescent">Parse::RecDescent</a>) to parse the verbose-mode output of javap, which includes those details.</p>
<p>There are <a href="http://github.com/timbunce/java2perl6/blob/master/TODO">plenty of others</a>.</p>
<h2>How you can get involved</h2>
<p>Firstly, come and say &#8220;Hi!&#8221; in the <a href="irc://chat.freenode.net/#dbdi">#dbdi</a> IRC channel on irc.freenode.net.</p>
<p>The code is on <a href="http://github.com/timbunce/java2perl6">github</a>. You can get commit access by asking on the <a href="irc://chat.freenode.net/#perl6">#perl6</a> channel.</p>
<p>There&#8217;s also a mailing list at <a href="mailto:dbdi-dev@perl.org">dbdi-dev@perl.org</a> which you can <a href="mailto:dbdi-dev-subscribe@perl.org">subscribe</a> to.</p>
<p>I look forward to hearing from you!</p>
<hr />
<ol>
<li><a name="1"></a><br />
When I say &#8220;Perl 6 has the potential to become a very popular language&#8221; I do so with typical British <a href="http://en.wikipedia.org/wiki/Understatement">Understatement</a>.
</li>
</ol>
<br />Filed under: <a href='http://blog.timbunce.org/category/tech/software/perl/'>perl</a>, <a href='http://blog.timbunce.org/category/tech/software/'>software</a> Tagged: <a href='http://blog.timbunce.org/tag/dbdi/'>dbdi</a>, <a href='http://blog.timbunce.org/tag/java/'>java</a>, <a href='http://blog.timbunce.org/tag/perl/'>perl</a>, <a href='http://blog.timbunce.org/tag/perl6/'>perl6</a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.timbunce.org&#038;blog=2562816&#038;post=460&#038;subd=timbunce&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://blog.timbunce.org/2010/07/16/java2perl6api-java-to-perl-6-api-tranalation-what-why-and-whereto/feed/</wfw:commentRss>
		<slash:comments>10</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/1cf82705f5ab43c73273ab5d690866b3?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">TimBunce</media:title>
		</media:content>

		<media:content url="http://www.indeed.com/trendgraph/jobgraph.png?q=%22perl+developer%22%2C%22java+developer%22" medium="image">
			<media:title type="html">job vacancy trends for perl developer and java developer</media:title>
		</media:content>
	</item>
		<item>
		<title>NYTProf 4.04 &#8211; Came, Saw Ampersand, and Conquered</title>
		<link>http://blog.timbunce.org/2010/07/09/nytprof-4-04-came-saw-ampersand-and-conquered/</link>
		<comments>http://blog.timbunce.org/2010/07/09/nytprof-4-04-came-saw-ampersand-and-conquered/#comments</comments>
		<pubDate>Fri, 09 Jul 2010 21:06:24 +0000</pubDate>
		<dc:creator>TimBunce</dc:creator>
				<category><![CDATA[perl]]></category>
		<category><![CDATA[nytprof]]></category>

		<guid isPermaLink="false">http://timbunce.wordpress.com/?p=457</guid>
		<description><![CDATA[Please forgive the title! Perl has three regular expression match variables ( $&#38; $&#8216; $&#8217; ) which hold the string that the last regular expression matched, the string before the match, and the string after the match, respectively. As you&#8217;re &#8230; <a href="http://blog.timbunce.org/2010/07/09/nytprof-4-04-came-saw-ampersand-and-conquered/">Continue reading <span class="meta-nav">&#8594;</span></a><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.timbunce.org&#038;blog=2562816&#038;post=457&#038;subd=timbunce&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<p><em>Please forgive the title!</em></p>
<p>Perl has three regular expression match variables ( <code>$&amp; $&lsquo; $&rsquo;</code> ) which hold the string that the last regular expression matched, the string before the match, and the string after the match, respectively.</p>
<p>As you&#8217;re probably aware, the mere presence of <em>any</em> of these variables, <em>anywhere</em> in the code, even if never accessed, will slow down <em>all</em> regular expression matches in the <em>entire</em> program. (See the WARNING at the end of the <a href="http://perldoc.perl.org/perlre.html#Capture-buffers">Capture Buffers section of the perlre documentation</a> for more information.)</p>
<p>Clearly this is not good.<br />
<span id="more-457"></span></p>
<p>I&#8217;ve long planned to add detection and reporting of this to <a href="http://search.cpan.org/dist/Devel-NYTProf/">Devel::NYTProf</a>, along with things like method cache invalidation, but it&#8217;s never risen to the top of the list. In fact, now I look, I see it never even got entered into the ever-growing collection of ideas recorded in the <a href="http://cpansearch.perl.org/src/TIMB/Devel-NYTProf-4.04/HACKING">HACKING</a> file.</p>
<p>After the 4.00 release, plus few minor releases, I&#8217;d put NYTProf on hold and was starting to focus on my java2perl6 API translation project (more news on that soon).</p>
<p>Then I saw a recent <a href="http://www.effectiveperlprogramming.com/blog/140">blog post by Josh McAdams</a>, one of the authors of <a href="http://www.amazon.com/exec/obidos/ASIN/0321496949/theeffeperl-20">Effective Perl Programming</a> (along with Joseph N. Hall and brian d foy) about detecting these variables using the <a href="http://search.cpan.org/perldoc?Devel::SawAmpersand">Devel::SawAmpersand</a> and <a href="http://search.cpan.org/perldoc?Devel::FindAmpersand">Devel::FindAmpersand</a> modules. Firstly it reminded me of the issue, and then it struck me that few people would bother using those tools because they simply <em>wouldn&#8217;t know they had the problem</em> in the first place.</p>
<p>Someone with a performance problem is likely to use a profiler like NYTProf to see where time is being spent in their code. That might point out that significant time is being spent in regular expressions, but even then they might not make the leap to consider these special match variables as a possible cause. <em>The profiler should point it out to them!</em></p>
<p>NYTProf version 4.03 didn&#8217;t. Clearly that was not good. So NYTProf version 4.04 now does!</p>
<p>In the list of files on the index page it highlights the file and adds a comment:</p>
<p><img src="http://timbunce.files.wordpress.com/2010/07/nytprof-highlighted-file-on-index-page.png?w=815&#038;h=157" alt="highlighted file on index page" border="0" width="815" height="157" /></p>
<p>On the report page for the file itself it adds an unmissable, and hopefully self-explanatory, note to the top of the page:</p>
<p><img src="http://timbunce.files.wordpress.com/2010/07/nytprof-note-on-report-page.png?w=670&#038;h=186" alt="note on report page" border="0" width="670" height="186" /></p>
<p>I&#8217;d be very interested to hear from anyone who now discovers these problem variable lurking in their application code or any CPAN modules.</p>
<p>Go take a look!</p>
<br />Filed under: <a href='http://blog.timbunce.org/category/tech/software/perl/'>perl</a> Tagged: <a href='http://blog.timbunce.org/tag/nytprof/'>nytprof</a>, <a href='http://blog.timbunce.org/tag/perl/'>perl</a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.timbunce.org&#038;blog=2562816&#038;post=457&#038;subd=timbunce&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://blog.timbunce.org/2010/07/09/nytprof-4-04-came-saw-ampersand-and-conquered/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/1cf82705f5ab43c73273ab5d690866b3?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">TimBunce</media:title>
		</media:content>

		<media:content url="http://timbunce.files.wordpress.com/2010/07/nytprof-highlighted-file-on-index-page.png" medium="image">
			<media:title type="html">highlighted file on index page</media:title>
		</media:content>

		<media:content url="http://timbunce.files.wordpress.com/2010/07/nytprof-note-on-report-page.png" medium="image">
			<media:title type="html">note on report page</media:title>
		</media:content>
	</item>
		<item>
		<title>Reflections on Perl and DBI from an Early Contributor</title>
		<link>http://blog.timbunce.org/2010/07/08/reflections-on-perl-and-dbi-from-an-early-contributor/</link>
		<comments>http://blog.timbunce.org/2010/07/08/reflections-on-perl-and-dbi-from-an-early-contributor/#comments</comments>
		<pubDate>Thu, 08 Jul 2010 12:48:27 +0000</pubDate>
		<dc:creator>TimBunce</dc:creator>
				<category><![CDATA[perl]]></category>
		<category><![CDATA[cpan]]></category>
		<category><![CDATA[dbi]]></category>
		<category><![CDATA[perl4]]></category>

		<guid isPermaLink="false">http://timbunce.wordpress.com/?p=449</guid>
		<description><![CDATA[The name Buzz Moschetti probably isn&#8217;t familiar to you. Buzz was the author of the Perl 4 database for Interbase known as Interperl. Back in those days Perl 5 was barely a twinkle in Larry&#8217;s eye and database interfaces for &#8230; <a href="http://blog.timbunce.org/2010/07/08/reflections-on-perl-and-dbi-from-an-early-contributor/">Continue reading <span class="meta-nav">&#8594;</span></a><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.timbunce.org&#038;blog=2562816&#038;post=449&#038;subd=timbunce&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<p>The name Buzz Moschetti probably isn&#8217;t familiar to you. Buzz was the author of the Perl 4 database for <a href="http://en.wikipedia.org/wiki/InterBase#History">Interbase</a> known as <a href="http://cpan.perl.org/modules/dbperl/perl4/interperl/README">Interperl</a>.</p>
<p>Back in those days Perl 5 was barely a twinkle in Larry&#8217;s eye and <a href="http://cpan.perl.org/modules/dbperl/perl4/">database interfaces for Perl 4</a> required building a custom perl binary.</p>
<p>Buzz was one of the four people to get the email on September 29th 1992 from Ted Lemon that started the <a href="http://cpan.perl.org/modules/dbperl/DBI/perldb-interest/">perldb-interest</a> project which defined a <a href="http://cpan.perl.org/modules/dbperl/DBI/dbispec.v04">specification</a> that ultimately lead to the DBI. (The other people were Kurt Andersen re informix, Kevin Stock re <a href="http://cpan.perl.org/modules/dbperl/perl4/oraperl/">oraperl</a>, and Michael Peppler re <a href="http://cpan.perl.org/modules/dbperl/perl4/sybperl/">sybperl</a>. I joined a few days later.)</p>
<p><strong>Update</strong>: It turns out that it was actually Buzz who sent that original email, Ted just forwarded it on to others, including me. So Buzz can be said to have started the process that led to the DBI!</p>
<p>I hadn&#8217;t heard from Buzz for <em>many</em> years until he sent me an email recently.</p>
<p>This is his story:<span id="more-449"></span><br />
<hr />
Thought I&#8217;d share a quick story with you.</p>
<p>Recently, I was frustrated with a development team&#8217;s efforts in putting<br />
together some DB-oriented reconciliations.  The candidate solution was a<br />
blend of precompiled SQL in COBOL code, file dumps and ftps, programs to<br />
read files, more programs to read other DBs, etc. etc.   Not only was<br />
the process orchestration a project in its own right, the end-to-end<br />
logic required to accurately perform the reconciliation was distributed<br />
across several programs and platforms, diluting the knowledge base.  I<br />
knew a perl program using multiple DBD drivers to different DB engines<br />
could do it in a much cleaner way, but over the years my job has changed<br />
and although I still use perl regularly, I don&#8217;t do much in the way of<br />
DBD/DBI.   To make matters worse, one of the targets was mainframe DB2<br />
and very little work had been done here with DBD::DB2.   Also, the<br />
Sybperl module continues to be heavily used in addition to DBD::Sybase,<br />
so local DBD/DBI expertise in general is thin.  I decided to get it<br />
working on my own.</p>
<p>The infrastructure team spun up for me a Linux virtual machine with a<br />
modern build environment on it.  This had the latest gcc compilers and a<br />
firm-approved build of perl 5.8.5 right out of the box.  It took a few<br />
days of low-priority requests to get the appropriate 32bit Linux<br />
client-side SDKs for the DB2 and Sybase products but soon enough I had<br />
an environment set up with headers and shared libs.  I was ready to<br />
build some perl modules, something I haven&#8217;t done in years.</p>
<p>I went to CPAN and downloaded DBD::DB2, untar&#8217;d it, and ran perl<br />
Makefile.PL and make.  Everything worked perfectly and the whole<br />
exercise took minutes.  &#8216;make test&#8217; sets PERL_DL_NONLAZY and warned of<br />
some unused symbols not being found, but that was OK.  The rest of the<br />
tests that I expected to work with my level of permissions worked fine.<br />
&#8216;make install&#8217; worked perfectly.  Buoyed by this success, I wrote a<br />
4-liner test program just to connect and fetch some data from a table I<br />
knew about.  Outside of the test environment, however, the shared libs<br />
for DB2 were not found so I cheated and relinked and reinstalled DB2.so<br />
with the -Wl,-rpath option to &#8220;cement in&#8221; the location of those libs so<br />
I wouldn&#8217;t have to fuss with LD_LIBRARY_PATH.   My test program now<br />
worked fine.  Newly comfortable with the process, I downloaded<br />
DBD::Sybase and built and installed the module in scarcely more time than<br />
it took for the compiler to run.  In my excitement I skipped over the<br />
DBD::Sybase 4-liner test program and went straight to a slightly bigger<br />
script that used both modules and grabbed data from both DBs.  It<br />
quietly and quickly executed.  </p>
<p>Total time from initial download with almost no clues to a running<br />
example: about 40 minutes.  Later, for grin&#8217;s sake, I threw in<br />
DBD::Oracle for good measure.  That went even faster &#8212; about 5 minutes<br />
&#8211; from CPAN download to printing &#8220;Oracle connected!&#8221; because I was more<br />
familiar with the connection string syntax that is bespoke for each<br />
engine.</p>
<p>As I watched the program run, it made me reflect on how far we&#8217;ve come<br />
and how easy yet sophisticated the perl module ecosystem has become.<br />
There is no question that this multi-DBD perl program is easier to<br />
understand and support than a solution involving a set of disconnected<br />
programs, platforms, and files.  But I think it is the organization and<br />
design of the resources as a whole &#8212; DBI, DBD, CPAN, MakeMaker, pod,<br />
binary and non-binary library locations, etc. &#8212; that makes the whole<br />
environment so clear, symmetric, and easy to use with confidence.  I<br />
think back to the build environment that I used to create <a href="http://cpan.perl.org/modules/dbperl/perl4/interperl/README">interperl</a>, and<br />
the progress that has been made in terms of both breadth of module<br />
functionality and depth of framework for module build portability is<br />
simply amazing.  Perl has grown far beyond just being another language.<br />
It has a value proposition as an able integrator of widely disparate<br />
functionality.  </p>
<p>I exited the Perl mainstream some time ago but I am watching from the<br />
side and I applaud the work you&#8217;ve done in this space.</p>
<p>Take care.</p>
<hr />
<p>Thanks Buzz!</p>
<br />Filed under: <a href='http://blog.timbunce.org/category/tech/software/perl/'>perl</a> Tagged: <a href='http://blog.timbunce.org/tag/cpan/'>cpan</a>, <a href='http://blog.timbunce.org/tag/dbi/'>dbi</a>, <a href='http://blog.timbunce.org/tag/perl/'>perl</a>, <a href='http://blog.timbunce.org/tag/perl4/'>perl4</a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.timbunce.org&#038;blog=2562816&#038;post=449&#038;subd=timbunce&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://blog.timbunce.org/2010/07/08/reflections-on-perl-and-dbi-from-an-early-contributor/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/1cf82705f5ab43c73273ab5d690866b3?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">TimBunce</media:title>
		</media:content>
	</item>
		<item>
		<title>Looking for a new job? TigerLead is also Hiring in Ann Arbor MI</title>
		<link>http://blog.timbunce.org/2010/07/02/looking-for-a-new-job-tigerlead-is-also-hiring-in-ann-arbor-mi/</link>
		<comments>http://blog.timbunce.org/2010/07/02/looking-for-a-new-job-tigerlead-is-also-hiring-in-ann-arbor-mi/#comments</comments>
		<pubDate>Fri, 02 Jul 2010 19:41:27 +0000</pubDate>
		<dc:creator>TimBunce</dc:creator>
				<category><![CDATA[software]]></category>
		<category><![CDATA[jobs]]></category>
		<category><![CDATA[perl]]></category>
		<category><![CDATA[postgresql]]></category>
		<category><![CDATA[ruby]]></category>

		<guid isPermaLink="false">http://timbunce.wordpress.com/?p=443</guid>
		<description><![CDATA[In addition to the job vacancy in West LA, the company I work for, TigerLead.com, has an opening for a &#8220;skilled developer&#8221; in Ann Arbor, Michigan: Our work involves manipulating and warehousing external data feeds and developing web interfaces to &#8230; <a href="http://blog.timbunce.org/2010/07/02/looking-for-a-new-job-tigerlead-is-also-hiring-in-ann-arbor-mi/">Continue reading <span class="meta-nav">&#8594;</span></a><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.timbunce.org&#038;blog=2562816&#038;post=443&#038;subd=timbunce&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<p>In addition to the <a href="http://blog.timbunce.org/2010/07/02/looking-for-a-new-job-tigerlead-is-hiring-in-west-la/">job vacancy in West LA</a>, the company I work for, <a href="http://www.tigerlead.com/">TigerLead.com</a>, has an opening for a &#8220;skilled developer&#8221; in Ann Arbor, Michigan:</p>
<blockquote><p> Our work involves manipulating and warehousing external data feeds and developing web interfaces to create home search tools for prospective buyers and lead management tools for real estate agents. We&#8217;re looking for a skilled coder to join our small team of talented engineers in Ann Arbor. We hope to find an experienced programmer who is a good fit with our team, well-versed in multiple languages, able to learn quickly and work independently. We work in a Linux environment, and tools and languages we use include Perl, Ruby on Rails, PostgreSQL, and GIT. Perl experience is a significant plus, but your current comfort level with any of these specific tools is less important than overall technical aptitude and ability to learn quickly and fit in well with the current team.</p></blockquote>
<p>That&#8217;s a little thin on details partly because the work is varied. If you think you might be interested, take a look at the <a href="http://annarbor.craigslist.org/eng/1804836163.html">full job posting</a>.</p>
<p>TigerLead is a lovely company to work for and this is a great opportunity. Highly recommended.</p>
<br />Filed under: <a href='http://blog.timbunce.org/category/tech/software/'>software</a> Tagged: <a href='http://blog.timbunce.org/tag/jobs/'>jobs</a>, <a href='http://blog.timbunce.org/tag/perl/'>perl</a>, <a href='http://blog.timbunce.org/tag/postgresql/'>postgresql</a>, <a href='http://blog.timbunce.org/tag/ruby/'>ruby</a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.timbunce.org&#038;blog=2562816&#038;post=443&#038;subd=timbunce&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://blog.timbunce.org/2010/07/02/looking-for-a-new-job-tigerlead-is-also-hiring-in-ann-arbor-mi/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/1cf82705f5ab43c73273ab5d690866b3?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">TimBunce</media:title>
		</media:content>
	</item>
		<item>
		<title>Looking for a new job? TigerLead is Hiring in West LA</title>
		<link>http://blog.timbunce.org/2010/07/02/looking-for-a-new-job-tigerlead-is-hiring-in-west-la/</link>
		<comments>http://blog.timbunce.org/2010/07/02/looking-for-a-new-job-tigerlead-is-hiring-in-west-la/#comments</comments>
		<pubDate>Fri, 02 Jul 2010 17:37:22 +0000</pubDate>
		<dc:creator>TimBunce</dc:creator>
				<category><![CDATA[software]]></category>
		<category><![CDATA[jobs]]></category>
		<category><![CDATA[perl]]></category>
		<category><![CDATA[postgresql]]></category>
		<category><![CDATA[ruby]]></category>

		<guid isPermaLink="false">http://timbunce.wordpress.com/?p=439</guid>
		<description><![CDATA[The company I work for, TigerLead.com, has an opening for a &#8220;skilled coder / database wrangler&#8221;. We&#8217;re looking for a skilled coder / database wrangler to play a key role within our Operations and Engineering teams. The various responsibilities of &#8230; <a href="http://blog.timbunce.org/2010/07/02/looking-for-a-new-job-tigerlead-is-hiring-in-west-la/">Continue reading <span class="meta-nav">&#8594;</span></a><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.timbunce.org&#038;blog=2562816&#038;post=439&#038;subd=timbunce&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<p>The company I work for, <a href="http://www.tigerlead.com/">TigerLead.com</a>, has an opening for a &#8220;skilled coder / database wrangler&#8221;. </p>
<blockquote><p>We&#8217;re looking for a skilled coder / database wrangler to play a key role within our Operations and Engineering teams. The various responsibilities of the job include working with the large databases underlying our real estate search tools, setting up services for new clients, communicating with clients to evaluate bug reports, troubleshooting technical issues escalated by our client services team, and interfacing with the engineering team on systems maintenance and development. The scope of work that we do involves managing hundreds of external data feeds that feed into in-house databases totaling several million property listings. These listing databases power hundreds of real estate search sites used by more than a million home-buyer leads, who are tracked and cultivated by the thousands of Realtors using our management software. This position is critical to the robustness of these systems.</p></blockquote>
<p>If that sounds like interesting work to you then take a look at the <a href="http://losangeles.craigslist.org/wst/eng/1821042952.html">full job posting</a>.</p>
<p>TigerLead is a lovely company to work for and this is a great opportunity. Highly recommended.</p>
<br />Filed under: <a href='http://blog.timbunce.org/category/tech/software/'>software</a> Tagged: <a href='http://blog.timbunce.org/tag/jobs/'>jobs</a>, <a href='http://blog.timbunce.org/tag/perl/'>perl</a>, <a href='http://blog.timbunce.org/tag/postgresql/'>postgresql</a>, <a href='http://blog.timbunce.org/tag/ruby/'>ruby</a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.timbunce.org&#038;blog=2562816&#038;post=439&#038;subd=timbunce&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://blog.timbunce.org/2010/07/02/looking-for-a-new-job-tigerlead-is-hiring-in-west-la/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/1cf82705f5ab43c73273ab5d690866b3?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">TimBunce</media:title>
		</media:content>
	</item>
		<item>
		<title>New lease of life for Yahoo::Search</title>
		<link>http://blog.timbunce.org/2010/06/11/new-lease-of-life-for-yahoosearch/</link>
		<comments>http://blog.timbunce.org/2010/06/11/new-lease-of-life-for-yahoosearch/#comments</comments>
		<pubDate>Fri, 11 Jun 2010 14:01:58 +0000</pubDate>
		<dc:creator>TimBunce</dc:creator>
				<category><![CDATA[perl]]></category>
		<category><![CDATA[geo]]></category>
		<category><![CDATA[xml]]></category>
		<category><![CDATA[yahoo]]></category>

		<guid isPermaLink="false">http://timbunce.wordpress.com/?p=405</guid>
		<description><![CDATA[I&#8217;ve recently started looking into geocoding in perl. We&#8217;re currently using some old hand-coded logic to query the Yahoo Search API. I wanted to switch to Geo::Coder::Yahoo but I noticed that that depended on Yahoo::Search which hadn&#8217;t been updated since &#8230; <a href="http://blog.timbunce.org/2010/06/11/new-lease-of-life-for-yahoosearch/">Continue reading <span class="meta-nav">&#8594;</span></a><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.timbunce.org&#038;blog=2562816&#038;post=405&#038;subd=timbunce&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<p>I&#8217;ve recently started looking into <a href="http://blog.timbunce.org/2010/06/09/high-quality-multi-source-geocoding-in-perl/">geocoding in perl</a>. We&#8217;re currently using some old hand-coded logic to query the Yahoo Search API. I wanted to switch to <a href="http://search.cpan.org/perldoc?Geo::Coder::Yahoo">Geo::Coder::Yahoo</a> but I noticed that that depended on <a href="http://search.cpan.org/perldoc?Yahoo::Search">Yahoo::Search</a> which hadn&#8217;t been updated since March 2007 and had accumulated <a href="https://rt.cpan.org/Dist/Display.html?Name=Yahoo-Search">a number of bug reports</a> (which may well be closed by the time you read this).</p>
<p>Several related to the fact that Yahoo::Search didn&#8217;t handle Unicode properly when using its default internal XML parser (instead of the optional XML::Simple which does the right thing, but slowly).</p>
<p>What happened next makes a nice little example of getting things done in the Open Source world&#8230;<span id="more-405"></span><br />
I emailed Jeffrey Friedl, the author of Yahoo::Search, to enquire about the status of the module and saying I might be willing to help out with maintenance. He replied promptly saying he&#8217;d be delighted if someone could take it over.</p>
<p>So I created a <a href="http://github.com/timbunce/Yahoo-Search">new repository on github</a> (with the release history from the <a href="http://github.com/gitpan/Yahoo-Search">repository</a> maintained by the amazingly useful <a href="http://github.com/schwern/gitpan/blob/master/README">gitPAN project</a>).</p>
<p>Then I <a href="http://github.com/timbunce/Yahoo-Search/commits/master/">started hacking</a>, mostly adding tests and applying patches and straight-forward fixes for the open tickets. The Unicode fix turned out to be <a href="http://github.com/timbunce/Yahoo-Search/commit/677f719030b86eee0c2b22682290e58317870cd9#diff-3">reasonably small and simple</a>.</p>
<p>I also changed the distribution from using a traditional Makefile.PL over to the awesome <a href="http://dzil.org/">dzil</a> tool to reduce friction and simplify future releases.</p>
<p>Then I changed the permissions on <a href="http://pause.perl.org">PAUSE</a> to enable me to make releases and eventually, when that propagates to <a href="https://rt.cpan.org/">RT</a>, be able to maintain the bug tracker and close the tickets.</p>
<p>And finally for today, I&#8217;ve uploaded a development release to CPAN for <a href="http://www.cpantesters.org/">cpantesters</a> to smoke test. I&#8217;ll close the RT tickets in due course.</p>
<p>Once I&#8217;ve made a final release in a few days I&#8217;ll have shaved my Yahoo::Search <a href="http://en.wiktionary.org/wiki/yak_shaving">yak</a>. After that I&#8217;ve no real interest in maintaining it on an ongoing basis.</p>
<p>Could you be interested looking after a freshly shaven and sweet smelling Yahoo::Search? Available free of charge to a good home!</p>
<br />Filed under: <a href='http://blog.timbunce.org/category/tech/software/perl/'>perl</a> Tagged: <a href='http://blog.timbunce.org/tag/geo/'>geo</a>, <a href='http://blog.timbunce.org/tag/perl/'>perl</a>, <a href='http://blog.timbunce.org/tag/xml/'>xml</a>, <a href='http://blog.timbunce.org/tag/yahoo/'>yahoo</a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.timbunce.org&#038;blog=2562816&#038;post=405&#038;subd=timbunce&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://blog.timbunce.org/2010/06/11/new-lease-of-life-for-yahoosearch/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/1cf82705f5ab43c73273ab5d690866b3?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">TimBunce</media:title>
		</media:content>
	</item>
		<item>
		<title>High Quality Multi-Source Geocoding in Perl</title>
		<link>http://blog.timbunce.org/2010/06/09/high-quality-multi-source-geocoding-in-perl/</link>
		<comments>http://blog.timbunce.org/2010/06/09/high-quality-multi-source-geocoding-in-perl/#comments</comments>
		<pubDate>Wed, 09 Jun 2010 21:24:40 +0000</pubDate>
		<dc:creator>TimBunce</dc:creator>
				<category><![CDATA[perl]]></category>
		<category><![CDATA[geo]]></category>

		<guid isPermaLink="false">http://timbunce.wordpress.com/?p=399</guid>
		<description><![CDATA[Where I&#8217;m working at the moment we&#8217;re using the Yahoo Geocoding API but aren&#8217;t very happy with it. I&#8217;ve been asked to look into how we can improve our geo coding. Geo coding services vary greatly in accuracy, precision, availability, &#8230; <a href="http://blog.timbunce.org/2010/06/09/high-quality-multi-source-geocoding-in-perl/">Continue reading <span class="meta-nav">&#8594;</span></a><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.timbunce.org&#038;blog=2562816&#038;post=399&#038;subd=timbunce&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<p>Where I&#8217;m working at the moment we&#8217;re using the Yahoo Geocoding API but aren&#8217;t very happy with it. I&#8217;ve been asked to look into how we can improve our geo coding.</p>
<p><span id="more-399"></span>Geo coding services vary greatly in accuracy, precision, availability, throughput capping, and other attributes. So it can help to try multiple services until you get <em>sufficient confidence</em> in the result.</p>
<p>It seems there are <a href="http://search.cpan.org/search?query=geocode&amp;mode=all">plenty of modules on CPAN for geocoding</a> from a single source, including Yahoo, Google, Mapquest, Multimap, Cloudmade and Bing. The only one that I could find that handles multiple services was <a href="http://search.cpan.org/perldoc?Geo::Coder::Multiple">Geo::Coder::Multiple</a>.</p>
<p>I&#8217;m writing this blog post for two reasons&#8230;</p>
<p>Firstly I&#8217;m interested in your experiences with geocoding services. Which you&#8217;ve tried, and which you&#8217;d recommend (for geocoding for US addresses). What problems you&#8217;ve encountered and any advice you&#8217;d like to pass on.</p>
<p>Secondly I&#8217;m interested in your thoughts on working with multiple services.</p>
<p><a href="http://search.cpan.org/perldoc?Geo::Coder::Multiple">Geo::Coder::Multiple</a> looks interesting but quite limited. For example, it&#8217;ll accept the first valid response even if it&#8217;s of low precision. There&#8217;s also no provision for checking multiple results to derive some measure of confidence, for &#8220;knowing when to stop&#8221;.</p>
<p>Some feature ideas:</p>
<ul>
<li>Ordered list of geocoders
</li>
<li>Auto rate limit by detecting over-limit response and disabling for a period, perhaps with exponential back-off.
</li>
<li>Result-filter callback to discard uninteresting responses, e.g., precision too low to be useful.
</li>
<li>Result-picking callback to pick best result from those collected so far. It could tell if there were more to try and return undef to mean &#8220;keep going&#8221;.
</li>
<li>Some pre-defined result-picking callbacks for common use cases.
</li>
</ul>
<p>Any thoughts on those?</p>
<p>What kind of features would you like to see?</p>
<p>Want to help build this?</p>
<br />Filed under: <a href='http://blog.timbunce.org/category/tech/software/perl/'>perl</a> Tagged: <a href='http://blog.timbunce.org/tag/geo/'>geo</a>, <a href='http://blog.timbunce.org/tag/perl/'>perl</a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.timbunce.org&#038;blog=2562816&#038;post=399&#038;subd=timbunce&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://blog.timbunce.org/2010/06/09/high-quality-multi-source-geocoding-in-perl/feed/</wfw:commentRss>
		<slash:comments>11</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/1cf82705f5ab43c73273ab5d690866b3?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">TimBunce</media:title>
		</media:content>
	</item>
		<item>
		<title>NYTProf v4 &#8211; Now with string-eval x-ray vision!</title>
		<link>http://blog.timbunce.org/2010/06/09/nytprof-v4-now-with-string-eval-x-ray-vision/</link>
		<comments>http://blog.timbunce.org/2010/06/09/nytprof-v4-now-with-string-eval-x-ray-vision/#comments</comments>
		<pubDate>Wed, 09 Jun 2010 19:26:17 +0000</pubDate>
		<dc:creator>TimBunce</dc:creator>
				<category><![CDATA[perl]]></category>
		<category><![CDATA[nytprof]]></category>
		<category><![CDATA[performance]]></category>
		<category><![CDATA[postgresql]]></category>

		<guid isPermaLink="false">http://timbunce.wordpress.com/?p=393</guid>
		<description><![CDATA[I released Devel::NYTProf v3 on Christmas Eve 2009. Over the next couple of months a few more features were added. The v3 work had involved a complete rewrite of the subroutine profiler and heavy work on much else besides. At &#8230; <a href="http://blog.timbunce.org/2010/06/09/nytprof-v4-now-with-string-eval-x-ray-vision/">Continue reading <span class="meta-nav">&#8594;</span></a><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.timbunce.org&#038;blog=2562816&#038;post=393&#038;subd=timbunce&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<p>I released Devel::NYTProf <a href="http://blog.timbunce.org/2009/12/24/nytprof-v3-worth-the-wait/">v3 on Christmas Eve</a> 2009. Over the next couple of months a <a href="http://blog.timbunce.org/2010/03/18/polishing-nytprof/">few more features</a> were added. The v3 work had involved a complete rewrite of the subroutine profiler and heavy work on much else besides. At that point I felt I&#8217;d done enough with NYTProf for now and it was time to focus on other more pressing projects.
</p>
<p>Over those months I&#8217;d also started working on <a href="http://blog.timbunce.org/2009/10/05/wishlist-of-plperl-enhancements-for-postgresql-8-5/">enhancements for PostgreSQL PL/Perl</a>. That project turned into something of an <em>epic adventure</em> with more than its fair share of highs and lows and twists and turns. The dust is only just settling now. I would have blogged about it but security issues arose that led the PostgreSQL team to consider removing the plperl language entirely. Fortunately I was able to help avoid that by removing Safe.pm entirely! At some point I hope to write a blog post worthy of the journey. Meanwhile, if you&#8217;re using PostgreSQL, you really do want to upgrade to the latest point-release.
</p>
<p>One of the my goals in enhancing PostgreSQL PL/Perl was improve the integration with NYTProf. I wanted to be able to profile PL/Perl code embedded in the database server. With PostgreSQL 8.4 I could get the profiler to run, with some <a href="http://github.com/timbunce/posgtresql-plperl-injector/blob/master/lib/PostgreSQL/PLPerl/Injector.pm">hackery</a>, but in the report the subroutines were all __ANON__ and you couldn&#8217;t see the source code, so there were no statement timings. <em>It was useless</em>.
</p>
<p>The key problem was that Devel::NYTProf couldn&#8217;t see into string evals properly. To fix that I <em>had</em> to go back spelunking deep in the NYTProf guts again; mostly in the data model and report generation code. With NYTProf v4, string evals are now treated as files, mostly, and a whole new level of insight is opened up!
</p>
<p>In the rest of this post I&#8217;ll be describing this and other new features.</p>
<p><span id="more-393"></span></p>
<h2>Seeing Into String Evals</h2>
<p>Let&#8217;s start by taking a look at a small example:</p>
<blockquote><p><code>perl -d:NYTProf -e 'eval("sub { $_ }")-&gt;() for 1,2,2'</code>
</p></blockquote>
<p>That executes three string evals, each of which defines an anonymous subroutine which is then executed. Two of the three evals have identical source code.</p>
<p>With NYTProf 3.11 the report for the &#8220;<code>-e</code> file&#8221; looked like this:</p>
<p><img src="http://timbunce.files.wordpress.com/2010/06/nytprof-eval-sub-example1-3111.png?w=765&#038;h=260" alt="NYTProf eval-sub example1 311.png" border="0" width="765" height="260" /></p>
<p>Two key things to note: Firstly, there&#8217;s no link to drill-down to see the actual source code executed by the eval. (In this example we can <em>see</em> the source, but that&#8217;s rare in practice.) Secondly, the three anonymous subroutines have been merged. You can&#8217;t see individual details like call counts, callers, or timings.</p>
<p>(In case you&#8217;re wondering, the main::BEGIN subroutine is defined as a side effect of loading NYTProf, and the main::RUNTIME subroutine is a dummy created by NYTProf to act as the &#8216;root caller&#8217;. You&#8217;ll see it appear as the caller of the anonymous subs in a later screenshot.)</p>
<p>With NYTProf 4.00 the same report looks like this:</p>
<p><img src="http://timbunce.files.wordpress.com/2010/06/screen-shot-2010-06-08-at-00-11-03.png?w=766&#038;h=291" alt="NYTProf eval-sub example1 400.png" border="0" width="766" height="291" /></p>
<p>Now you can see much more detail right there. The two evals with identical source code have been merged, as have the identical anonymous subroutines defined by them. The eval and anonymous sub with different source code have been kept separate. What you can&#8217;t easily see from the image is that the &#8220;<code>string eval</code>&#8221; texts in the grey annotation are links. This is where it&#8217;s gets more interesting&#8230;</p>
<p>Clicking on the &#8220;<code>2 string evals (merged)</code>&#8221; link takes us to a typical NYTProf report page showing the performance-annotated source code executed by the eval:</p>
<p><img src="http://timbunce.files.wordpress.com/2010/06/nytprof-eval-sub-example1-eval1.png?w=849&#038;h=359" alt="NYTProf eval-sub example1 eval.png" border="0" width="849" height="359" /></p>
<p>What you&#8217;re looking at here is source code <em>that never existed as a file</em>. (That second line containing a semicolon was added by perl as part of the implementation of <code>eval</code>.)</p>
<p>In the table at the top, you&#8217;ll see &#8220;Eval Invoked At&#8221; with a link that&#8217;ll take you to the eval statement that executed this source code. You&#8217;ll also see a &#8220;Sibling evals&#8221; row. That&#8217;s added in cases where an eval was executed multiple times and not all were merged into a single report. Finally, because this particular eval includes data merged from others, the report includes a clear banner alerting you to how many evals were merged to produce this report page.</p>
<p><em><strong>Update</strong>: You&#8217;ll need a recent version of perl (5.8.9+, 5.10.1+, or 5.12+) to see the eval source code.<br />
</em></p>
<p>So why does NYTProf go to all the effort of merging evals and anonymous subs? Here&#8217;s a real-world example using <a href="https://www.me.com/ix/tim.bunce/Public/perl/nytprof/nytprof-perlcritic-demo/PPI-Node-pm-56-line.html#645">a profile of perlcritic</a>:</p>
<p><img src="http://timbunce.files.wordpress.com/2010/06/nytprof-eval-sub-perlcritic1.png?w=795&#038;h=154" alt="NYTProf eval-sub perlcritic1.png" border="0" width="795" height="154" /></p>
<p>Without merging, those 4196 evals would have produced 4196 report pages! Their sheer volume making them almost useless. Now it&#8217;s clear from the report that only a few distinct source code strings are used and <a href="https://www.me.com/ix/tim.bunce/Public/perl/nytprof/nytprof-perlcritic-demo/(eval%20189)[-usr-local-perl512-dev-lib-site_perl-5-12-0-PPI-Node-pm-654]-516-line.html">the reports</a> for each are <em>far</em> more useful.</p>
<p>In that example perlcritic is compiling lots of tiny snippets of code. Many applications use string eval to compile large quantities of code. The <a href="http://search.cpan.org/perldoc?ORLite">ORLite module</a> is one example. It dynamically generates and compiles a large chunk of code with many subroutines that implement a customized interface for a specific <a href="http://www.sqlite.org/">SQLite</a> database file.</p>
<p>With NYTProf 3.11 you couldn&#8217;t <em>see</em> the hundreds of lines of source code, <em>or</em> the per-caller subroutine performance, <em>or</em> the individual statement performance. All you could see was a list of subs calls and the overall time spent in each:</p>
<p><img src="http://timbunce.files.wordpress.com/2010/06/nytprof-eval-sub-cpangraph-311.png?w=905&#038;h=249" alt="NYTProf eval-sub cpangraph 311.png" border="0" width="905" height="249" /> </p>
<p>That was better than nothing, but now, with NYTProf v4, <a href="https://www.me.com/ix/tim.bunce/Public/perl/nytprof/nytprof-cpangraph-demo/(eval%20957)[-usr-local-perl512-dev-lib-site_perl-5-12-0-ORLite-pm-586]-1097-line.html">you can see everything</a>!</p>
<div style="background-color:#eeeeee;padding:10px;">
Aside&hellip;</p>
<h2>I see a SQLite in the Distance</h2>
<p>Getting all this working correctly, especially the data model manipulations required for merging evals and anonymous subroutines, was far more painful than I&#8217;d anticipated. I both blessed and cursed the test suite on numerous occasions!</p>
<p>I think it would be wise for NYTProf reporting and data model code to read the data from, and manipulate the data in, an SQLite database. That would yield simpler more maintainable code. It would also be enable nytprofhtml to be used for presenting performance data from other sources, including perl6.</p>
<p>If you&#8217;re interested in working on this, starting with a utility to load an nytprof.out file into a SQLite database, please <a href="http://groups.google.com/group/develnytprof-dev">contact the mailing list</a>.
</div>
<p></p>
<h2>String Eval Timings</h2>
<p>There&#8217;s a slight caveat worth noting about the timings shown for string evals <em>that define subroutines</em>.</p>
<p>Timings for string evals are taken from the statement profiler (the subroutine profiler doesn&#8217;t pay attention to evals). So the &#8220;time spent executing the eval&#8221; is the sum of the time spent executing <em>any statements within the eval</em>.</p>
<p>That&#8217;s fine for evals that don&#8217;t define subroutines. For those that do, the time for the eval includes not only the time spent executing the eval itself but also time spent executing statements in subroutines defined within the eval but called later from outside it.</p>
<p>Hence the careful wording you can see in the example from perlcritic shown previously:</p>
<blockquote><pre># spent  2.65s executing statements in 1369 string evals (merged)
# includes 1.83s spent executing 122015 calls to 1 sub defined therein.</pre>
</blockquote>
<p>I could have automatically subtracted the subroutine time from the eval time but I was wary about doing that (for some reason that currently escapes me). Maybe that&#8217;ll change in the near future. Further out, a future version of NYTProf might use the subroutine profiler logic to time evals. That&#8217;s a deeper change that would give a more natural view of the timings.</p>
<h2>Other Changes in v4</h2>
<ul>
<li>Subroutines that couldn&#8217;t be associated with a perl source file, such as xsubs in packages with no perl source, used to not appear in reports at all. So associated caller and timing information couldn&#8217;t be seen. <a href="https://www.me.com/ix/tim.bunce/Public/perl/nytprof/nytprof-cpangraph-demo/usr-local-perl512-dev-bin-cpangraph-1-line.html#163">Now it can</a>.
</li>
<li>Similarly, subroutine calls that couldn&#8217;t be associated with a specific <em>line</em>, such as calls made by perl to END blocks, are now shown in reports. They appear as <a href="https://www.me.com/ix/tim.bunce/Public/perl/nytprof/nytprof-cpangraph-demo/usr-local-perl512-dev-bin-cpangraph-1-line.html#0">as calls from line 0</a>.
</li>
<li>NYTProf v3 added renaming of <code>BEGIN</code> subs, so a BEGIN (or <code>use</code>) on line 3 would be called <code>BEGIN@3</code> and so kept distinct from others in the same package. NYTProf v4 takes that further by detecting the rare cases where the modified name isn&#8217;t unique and adding a sequence number to it, like <a href="https://www.me.com/ix/tim.bunce/Public/perl/nytprof/nytprof-cpangraph-demo/(eval%20957)[-usr-local-perl512-dev-lib-site_perl-5-12-0-ORLite-pm-586]-1097-line.html#3"><code>BEGIN@3.59</code></a>.
</li>
<li>NYTProf v2 added the savesrc option to enable storing a copy of the profiled perl source code into the profile data file itself. This makes report generation immune from later changes to the source files. NYTProf v4 now enables that option by default.
</li>
<li>The report generator used to only generate report lines up to the maximum number of source lines present. If there was no source code available, for whatever reason, you&#8217;d get an empty report for that file, even though there was useful information to report. Now the report generates enough lines to ensure all available profile information gets included. This is especially useful for old perl versions where source code is more likely to be unavailable. Also, the report generator now collapses groups of three or more blank lines.
</li>
<li>Nicholas Clark contributed changes to refine the timing of the beginning and end of profiling. Now END blocks defined at runtime are included in the profile and compilation-only checks (e.g., <code>perl -c</code>) can also be profiled.
</li>
<li>You may be aware that the <code>POSIX::_exit</code> function exits the process immediately, without flushing stdio buffers and without giving perl a chance to clean up. That means NYTProf didn&#8217;t get a chance to finish and the profile wasn&#8217;t usable. NYTProf v4 now intercepts calls to <code>POSIX::_exit</code> and cleans up properly.
</li>
<li>Finally, tired of waiting for nytprofhtml to produce a report from a long profile run? The new <code>--minimal</code> (-m) option makes nytprofhtml skip building reports for the rarely used &#8216;blocks&#8217; and &#8216;subs&#8217; levels of detail and skips generating the graphviz .dot files. That saves a lot of time.
</li>
</ul>
<p>Enjoy!</p>
<hr />
Translations: <a href="http://www.designcontest.com/show/nytprof-v4-now-with-string-eval-x-ray-vision-be">Belorussian translation</a> thanks to Bohdan Zograf.</p>
<hr />
<br />Filed under: <a href='http://blog.timbunce.org/category/tech/software/perl/'>perl</a> Tagged: <a href='http://blog.timbunce.org/tag/nytprof/'>nytprof</a>, <a href='http://blog.timbunce.org/tag/performance/'>performance</a>, <a href='http://blog.timbunce.org/tag/postgresql/'>postgresql</a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.timbunce.org&#038;blog=2562816&#038;post=393&#038;subd=timbunce&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://blog.timbunce.org/2010/06/09/nytprof-v4-now-with-string-eval-x-ray-vision/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/1cf82705f5ab43c73273ab5d690866b3?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">TimBunce</media:title>
		</media:content>

		<media:content url="http://timbunce.files.wordpress.com/2010/06/nytprof-eval-sub-example1-3111.png" medium="image">
			<media:title type="html">NYTProf eval-sub example1 311.png</media:title>
		</media:content>

		<media:content url="http://timbunce.files.wordpress.com/2010/06/screen-shot-2010-06-08-at-00-11-03.png" medium="image">
			<media:title type="html">NYTProf eval-sub example1 400.png</media:title>
		</media:content>

		<media:content url="http://timbunce.files.wordpress.com/2010/06/nytprof-eval-sub-example1-eval1.png" medium="image">
			<media:title type="html">NYTProf eval-sub example1 eval.png</media:title>
		</media:content>

		<media:content url="http://timbunce.files.wordpress.com/2010/06/nytprof-eval-sub-perlcritic1.png" medium="image">
			<media:title type="html">NYTProf eval-sub perlcritic1.png</media:title>
		</media:content>

		<media:content url="http://timbunce.files.wordpress.com/2010/06/nytprof-eval-sub-cpangraph-311.png" medium="image">
			<media:title type="html">NYTProf eval-sub cpangraph 311.png</media:title>
		</media:content>
	</item>
		<item>
		<title>Relaxed Perl Myths in Ann Arbor</title>
		<link>http://blog.timbunce.org/2010/05/31/relaxed-perl-myths-in-ann-arbor/</link>
		<comments>http://blog.timbunce.org/2010/05/31/relaxed-perl-myths-in-ann-arbor/#comments</comments>
		<pubDate>Mon, 31 May 2010 12:25:34 +0000</pubDate>
		<dc:creator>TimBunce</dc:creator>
				<category><![CDATA[perl]]></category>
		<category><![CDATA[modern perl]]></category>
		<category><![CDATA[myths]]></category>

		<guid isPermaLink="false">http://timbunce.wordpress.com/?p=383</guid>
		<description><![CDATA[Speaking of belated screencasts, I also haven&#8217;t blogged about my visit to the Ann Arbor Perl Mongers in Michigan. The Ann Arbor Perl Mongers group was being restarted (after a 10 year gap) by the TigerLead tech team. I&#8217;m working &#8230; <a href="http://blog.timbunce.org/2010/05/31/relaxed-perl-myths-in-ann-arbor/">Continue reading <span class="meta-nav">&#8594;</span></a><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.timbunce.org&#038;blog=2562816&#038;post=383&#038;subd=timbunce&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<p>Speaking of <a href="http://blog.timbunce.org/2010/05/31/screencasts-from-the-italian-perl-workshop-2009/">belated screencasts</a>, I also haven&#8217;t blogged about my visit to the <a href="http://annarbor.pm.org/">Ann Arbor Perl Mongers</a> in Michigan.
</p>
<p>The Ann Arbor Perl Mongers group was being restarted (after a 10 year gap) by the <a href="http://www.tigerlead.com/">TigerLead</a> tech team. I&#8217;m working for TigerLead and was going to be in Ann Arbor for a meeting so they asked me to give a couple of talks: Devel::NYTProf and Perl Myths.
</p>
<p>I like giving talks at events like these because there&#8217;s no set time limit and the audience is more relaxed (the free pizza probably helped).
</p>
<p>I&#8217;ve uploaded a <a href="http://blip.tv/file/3303623">screencast of the Perl Myths talk</a>. As usual it covers the Perl jobs market, CPAN, best practices, power tools, community and perl6. At almost 1 hour 20 minutes it&#8217;s significantly longer than my usual, more rushed, 40 minute version given at conferences and includes 15 minutes of Q &amp; A at the end.</p>
<br />Filed under: <a href='http://blog.timbunce.org/category/tech/software/perl/'>perl</a> Tagged: <a href='http://blog.timbunce.org/tag/modern-perl/'>modern perl</a>, <a href='http://blog.timbunce.org/tag/myths/'>myths</a>, <a href='http://blog.timbunce.org/tag/perl/'>perl</a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.timbunce.org&#038;blog=2562816&#038;post=383&#038;subd=timbunce&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://blog.timbunce.org/2010/05/31/relaxed-perl-myths-in-ann-arbor/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/1cf82705f5ab43c73273ab5d690866b3?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">TimBunce</media:title>
		</media:content>
	</item>
		<item>
		<title>Screencasts from the Italian Perl Workshop 2009</title>
		<link>http://blog.timbunce.org/2010/05/31/screencasts-from-the-italian-perl-workshop-2009/</link>
		<comments>http://blog.timbunce.org/2010/05/31/screencasts-from-the-italian-perl-workshop-2009/#comments</comments>
		<pubDate>Mon, 31 May 2010 12:09:49 +0000</pubDate>
		<dc:creator>TimBunce</dc:creator>
				<category><![CDATA[perl]]></category>
		<category><![CDATA[ipw09]]></category>
		<category><![CDATA[presentation]]></category>
		<category><![CDATA[yapc]]></category>

		<guid isPermaLink="false">http://timbunce.wordpress.com/?p=381</guid>
		<description><![CDATA[I&#8217;ve just been updating the page where I keep links to my presentations and noticed that, not only had I not updated the section for the 2009 Italian Perl Workshop, but I hadn&#8217;t even uploaded the screencasts I&#8217;d made. So, &#8230; <a href="http://blog.timbunce.org/2010/05/31/screencasts-from-the-italian-perl-workshop-2009/">Continue reading <span class="meta-nav">&#8594;</span></a><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.timbunce.org&#038;blog=2562816&#038;post=381&#038;subd=timbunce&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<p>I&#8217;ve just been updating the page where I keep links to <a href="http://blog.timbunce.org/my-presentations/">my presentations</a> and noticed that, not only had I not updated the section for the 2009 Italian Perl Workshop, but I hadn&#8217;t even uploaded the screencasts I&#8217;d made.
</p>
<p>So, with apologies for the delay, here&#8217;s my entry for IPW09, with the links to the uploaded screencasts:
</p>
<blockquote><p>I&nbsp;<a href="http://blog.timbunce.org/2008/09/24/the-italian-perl-workshop/">had a great time</a> at IPW08 and was delighted to be invited back for IPW09, which was another great success. My contributions were two talks. The first was called &ldquo;<a href="http://conferences.yapceurope.org/ipw2009/talk/2366">DBI Oddmenti</a>&rdquo; and covered DBD::Gofer (16 minute&nbsp;<a href="http://blip.tv/file/3693768">screencast</a>), DBI::Profiler (7 minute&nbsp;<a href="http://blip.tv/file/3199117">screencast</a>), and DBDI a key component of a future DBI for Perl 6 (5 minute&nbsp;<a href="http://blip.tv/file/3693636">screencast</a>). The second was &ldquo;<a href="http://conferences.yapceurope.org/ipw2009/talk/2355">State-of-the-art Profiling with Devel::NYTProf</a>&rdquo; (40 minute&nbsp;<a href="http://blip.tv/file/2840795">screencast</a>).&#65279;</p>
<p>With 30 talks from 20 speakers on 2 tracks, IPW09 was another success for the <a href="http://www.perl.it/associazione/index.html">Italian Perl Association</a>, which was formally incorporated at the event. I&rsquo;m confident that <a href="http://conferences.yapceurope.org/ye2010/">YAPC::EU 2010</a> is in safe hands.
</p></blockquote>
<p>I&#8217;m really looking forward to YAPC::EU. We&#8217;re combining the conference with our family summer holiday. We&#8217;ll be staying in a cottage in the <a href="http://maps.google.co.uk/maps?f=q&amp;source=s_q&amp;hl=en&amp;geocode=&amp;q=calci&amp;sll=53.800651,-4.064941&amp;sspn=16.889907,46.318359&amp;ie=UTF8&amp;hq=&amp;hnear=Calci+Pisa,+Tuscany,+Italy&amp;ll=43.723227,10.484734&amp;spn=0.161026,0.361862&amp;t=h&amp;z=12">village of Calci</a> a few miles outside Pisa.</p>
<br />Filed under: <a href='http://blog.timbunce.org/category/tech/software/perl/'>perl</a> Tagged: <a href='http://blog.timbunce.org/tag/ipw09/'>ipw09</a>, <a href='http://blog.timbunce.org/tag/presentation/'>presentation</a>, <a href='http://blog.timbunce.org/tag/yapc/'>yapc</a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.timbunce.org&#038;blog=2562816&#038;post=381&#038;subd=timbunce&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://blog.timbunce.org/2010/05/31/screencasts-from-the-italian-perl-workshop-2009/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/1cf82705f5ab43c73273ab5d690866b3?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">TimBunce</media:title>
		</media:content>
	</item>
		<item>
		<title>Polishing NYTProf</title>
		<link>http://blog.timbunce.org/2010/03/18/polishing-nytprof/</link>
		<comments>http://blog.timbunce.org/2010/03/18/polishing-nytprof/#comments</comments>
		<pubDate>Thu, 18 Mar 2010 10:30:03 +0000</pubDate>
		<dc:creator>TimBunce</dc:creator>
				<category><![CDATA[perl]]></category>
		<category><![CDATA[nytprof]]></category>
		<category><![CDATA[performance]]></category>
		<category><![CDATA[postgresql]]></category>

		<guid isPermaLink="false">http://timbunce.wordpress.com/?p=376</guid>
		<description><![CDATA[I released Devel::NYTProf 3.0 almost three months ago, on Christmas Eve. Since then a few point releases have accumulated some changes and features worth mentioning: Jan Dubois contributed portability fixes for Windows and 64bit configurations. NYTProf should now run well &#8230; <a href="http://blog.timbunce.org/2010/03/18/polishing-nytprof/">Continue reading <span class="meta-nav">&#8594;</span></a><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.timbunce.org&#038;blog=2562816&#038;post=376&#038;subd=timbunce&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<p>I released <a href="http://search.cpan.org/dist/Devel-NYTProf">Devel::NYTProf</a> 3.0 almost three months ago, <a href="http://blog.timbunce.org/2009/12/24/nytprof-v3-worth-the-wait/">on Christmas Eve</a>.</p>
<p>Since then a few point releases have accumulated some changes and features worth mentioning:</p>
<p><span id="more-376"></span>
<ul>
<li> Jan Dubois contributed portability fixes for Windows and 64bit configurations. NYTProf should now run well on most, if not all, Windows configurations with recent versions of perl.
</li>
<li> Markus Peter contributed a sub-microsecond timer for Mac OS X. It yields the same 100ns resolution used on systems with POSIX realtime clocks.
</li>
<li> Nicholas Clark has contributed a huge amount of work recently, including many optimizations and a <em>major</em> refactoring of I/O.
</li>
<li> Nicholas&#8217;s <code>nytprofmerge</code> utility is now significantly faster as a result of those changes. He&#8217;s also fixed a bunch of edge cases. If you&#8217;re generating multiple profile data files and would like to merge them into a single report, <code>nytprofmerge</code> is now a very effective tool.
</li>
<li>I fixed the <code>usecputime=1</code> option as it was broken in several ways. It&#8217;s still of limited value and the docs now explain that more clearly.
</li>
<li>I&#8217;ve also added a section to the docs to explain how to make NYTProf faster. For those rare cases where the performance impact of profiling is a problem.
</li>
<li>Assorted crashing bugs and odd behaviors in edge cases (like <code>goto &amp;sub</code> out of an <code>AUTOLOAD</code> being called for a <code>DESTROY</code> in perl &lt;5.8.8) have been fixed. NYTProf now also behaves more sanely with multiplicity and threads (although it still can&#039;t actually profile multiple threads or interpreters).
</li>
<li>The <code>Devel::NYTProf::PgPLPerl</code> module has been removed and the code moved to a separate <a href="http://search.cpan.org/perldoc?PostgreSQL::PLPerl::NYTProf"><code>PostgreSQL::PLPerl::NYTProf</code></a> distribution.
</li>
<li>One little UI tweak worth noting is that sortable tables now show a little arrow in the heading of the sorted column. If you didn&#8217;t know that you could click most column headings to sort by that column, hopefully the arrow will act as a visual reminder.
</li>
</ul>
<p>The only thing I&#8217;m likely to work on soon is the handling is string evals. They&#8217;re mostly hidden in the reports now. I need to improve that to make <code>PostgreSQL::PLPerl::NYTProf</code> actually <em>useful</em>. So that&#8217;s pretty much bound to happen sometime between now and my speaking at <a href="http://www.pgcon.org/2010/">PGcon</a> in May.</p>
<p>Meanwhile, if you&#8217;re not using Devel::NYTProf 3.11, <a href="http://search.cpan.org/dist/Devel-NYTProf/">upgrade</a>!</p>
<br />Filed under: <a href='http://blog.timbunce.org/category/tech/software/perl/'>perl</a> Tagged: <a href='http://blog.timbunce.org/tag/nytprof/'>nytprof</a>, <a href='http://blog.timbunce.org/tag/performance/'>performance</a>, <a href='http://blog.timbunce.org/tag/perl/'>perl</a>, <a href='http://blog.timbunce.org/tag/postgresql/'>postgresql</a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.timbunce.org&#038;blog=2562816&#038;post=376&#038;subd=timbunce&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://blog.timbunce.org/2010/03/18/polishing-nytprof/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/1cf82705f5ab43c73273ab5d690866b3?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">TimBunce</media:title>
		</media:content>
	</item>
		<item>
		<title>NYTProf v3 &#8211; Worth the wait!</title>
		<link>http://blog.timbunce.org/2009/12/24/nytprof-v3-worth-the-wait/</link>
		<comments>http://blog.timbunce.org/2009/12/24/nytprof-v3-worth-the-wait/#comments</comments>
		<pubDate>Thu, 24 Dec 2009 23:08:54 +0000</pubDate>
		<dc:creator>TimBunce</dc:creator>
				<category><![CDATA[perl]]></category>
		<category><![CDATA[nytprof]]></category>

		<guid isPermaLink="false">http://timbunce.wordpress.com/?p=362</guid>
		<description><![CDATA[After more than six months, and more than a few technical hurdles, NYTProf v3 has been released at last. In this post I&#8217;ll review the major changes and significant new features. What&#8217;s new in Devel::NYTProf v3? Treemap The first big &#8230; <a href="http://blog.timbunce.org/2009/12/24/nytprof-v3-worth-the-wait/">Continue reading <span class="meta-nav">&#8594;</span></a><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.timbunce.org&#038;blog=2562816&#038;post=362&#038;subd=timbunce&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<p>After more than six months, and more than a few technical hurdles, NYTProf v3 has been released at last.</p>
<p>In this post I&#8217;ll review the major changes and significant new features.<span id="more-362"></span><br />
<h1>What&#8217;s new in Devel::NYTProf v3?<br />
</h1>
<h2>Treemap</h2>
<p>The first big feature is a visualization of the exclusive time spent in subroutines represented as a <a href="http://en.wikipedia.org/wiki/Treemap">treemap</a>:</p>
<p><img src="http://timbunce.files.wordpress.com/2009/07/filename.png?w=770" alt="filename.png" border="0" width="770" height="550	" /></p>
<p>That&#8217;s a treemap of a profile of perlcritic 1.088. The colors don&#8217;t mean anything. They&#8217;re just used to visually group subroutines in the same package. (I&#8217;m not very happy with the colors but the <a href="http://thejit.org/">JIT toolkit</a> I&#8217;m using doesn&#8217;t make it easy to use an attractive colour range. It interpolates a value in RGB color space. It would be much better to interpolate the value in HSV color space.)</p>
<p>The treemap is interactive! If you click on a square then the treemap is redrawn &#8220;zoomed in&#8221; one package level &#8216;closer&#8217; to the package of the subroutine you clicked on.</p>
<h2>Subroutine Caller Tracking</h2>
<p>The subroutine profiler has been almost completely rewritten, yielding another major new feature. It now finds and records the name of the <em>calling</em> subroutine. (You might have assumed that NYTProf always did that. In fact it <em>guessed</em> based on the calling file and line number, and so was easily confused by nested subroutines and closures.) By properly tracking the calling subroutine NYTProf can now generate a more accurate call graph.</p>
<p>One immediate beneficiary is the nytprofcg utility (contributed by <a href="http://search.cpan.org/~clkao/">Chia-liang Kao</a>). nytprofcg reads NYTProf profile data and generates callgrind data for viewing via <a href="http://kcachegrind.sourceforge.net/html/Home.html">Kcachegrind</a>. The previous guessing behaviour limited the usefulness of nytprofcg. Now it works well, as you can see here: </p>
<p><img src="http://timbunce.files.wordpress.com/2009/07/zz4f06129a.png?w=799&#038;h=562" alt="ZZ4F06129A.png" border="0" width="799" height="562" /></p>
<p>I&#8217;ve not played with it much yet. If you do, <a href="http://groups.google.com/group/develnytprof-dev">let us know</a> how it works out for you!</p>
<p>The subroutine called <code>main::RUNTIME</code> in the image above is the fake name that NYTProf gives to &#8216;caller&#8217; of the main script code. Code run at compile time will have a top-level caller of <code>main::BEGIN</code>.</p>
<h2>BEGIN</h2>
<p>Speaking of <code>BEGIN</code>s, they&#8217;ve always been a problem because there can be many of them in a single package. Each <code>use</code> statement, for example, generates a <code>BEGIN</code> sub that&#8217;s immediately executed then discarded. Previously the data for all those <code>BEGIN</code>s was mashed together and so almost useless.</p>
<p>The NYTProf subroutine profiler now renames <code>BEGIN</code>s by appending <code>@<em>linenumber</em></code> to make them unique. A whole new level of detail is opened up by this change. (This, along with a few other new features, requires perl 5.10.1+ or 5.8.9+.)</p>
<h2>Goto</h2>
<p>NYTProf now handles <code>goto &amp;sub;</code> properly. That tail-call construct is commonly found at the end of <code>AUTOLOAD</code> subroutines&mdash;so it&#8217;s more common than you might think.</p>
<p>The calling and called subroutine call counts and timings are updated correctly. For the call graph, the destination subroutine appears to have been called by the subroutine that called the subroutine that executed the goto. In other words, if A calls B and B does a goto &amp;C, that call to C will show A as the caller. That fits the way goto &amp;sub works, and ensures inclusive and exclusive times make sense.</p>
<h2>Slow Opcode Profiling</h2>
<p>This is another major new feature. NYTProf can now profile the time spent executing certain opcodes (the lowest-level units of execution in the perl interpreter).</p>
<p>I originally envisaged adding the mechanism for opcodes that corresponded to system calls (read, write, mkdir, chdir etc.) and called the feature &#8216;sys ops&#8217;. Then I realised there were other perl opcodes that would be worth profiling. The main two being <code>match</code> (<code>m/.../</code>) and <code>subst</code> (<code>s/.../.../</code>). So now the NYTProf subroutine profiler can now profile time spent in regular expressions!</p>
<p>Here&#8217;s an example:</p>
<p><img src="http://timbunce.files.wordpress.com/2009/08/zz1f7ce510.png?w=755&#038;h=235" alt="ZZ1F7CE510.png" border="0" width="755" height="235" /></p>
<p>The opcodes are given pseudo-subroutine names <em>in the package that invoked the opcode</em> with &#8220;<code>CORE:</code>&#8221; prepended to the opcode name. In the example above you can see  two instances of <code>CORE:match</code>. One accounting for matches performed in the <code>main::</code> package, and another accounting for matches performed in the <code>File::Find::</code> package. (They&#8217;re marked &#8216;xsub&#8217; above but I&#8217;ve changed that to &#8216;opcode&#8217; now.)</p>
<p>Profiling of &#8216;slowops&#8217;, as I&#8217;ve called them, is controlled by the <code>slowops=N</code> option. A value of 0 turns off slowop profiling. A value of 2 (the default) gives the behaviour shown above, with opcodes called in different packages being accounted for separately. A value of 1 will put all the slowops into a single package named &#8220;<code>CORE::</code>&#8220;.</p>
<h2>GraphViz</h2>
<p>Another spin-off from the work on call graphs: NYTProf now also outputs representations of the subroutine call graph as GraphViz <a href="http://en.wikipedia.org/wiki/DOT_language">dot language</a> files. These can be rendered by<br />
<a href="http://www.graphviz.org/">a variety of viewers</a>. I use <a href="http://www.pixelglow.com/graphviz/">GraphViz by pixelglow</a>.</p>
<p>Here&#8217;s a simple example showing the calling relationship between packages in a little demo script I use for testing:</p>
<p><img src="http://timbunce.files.wordpress.com/2009/08/subs-callgraph.png?w=514&#038;h=282" alt="subs-callgraph.png" border="0" width="514" height="282" /></p>
<p>The dot file for that inter-package view is available as a link on the top-level index page of the report.</p>
<p>On the individual report pages for each source file there&#8217;s a link to another dot file. This one shows the calls into, out of, and between the subroutines in package(s) in that source file. For example, here&#8217;s the call graph for the subs in the File::Find module:</p>
<p><img src="http://timbunce.files.wordpress.com/2009/08/call-graphviz-file-find-pm.png?w=682&#038;h=365" alt="call-graphviz-File-Find-pm.png" border="0" width="682" height="365" /></p>
<p>There are many things that could be improved with that graph, such as adding call counts. Overall though, I&#8217;m pretty happy with it.</p>
<h2>Report Format Changes</h2>
<p>There have been some changes to the main report columns:</p>
<p><img src="http://timbunce.files.wordpress.com/2009/08/zz5dc6382a.png?w=908" alt="ZZ5DC6382A.png" border="0"/></p>
<p>There are two new columns, &#8220;Calls&#8221; and &#8220;Time in Subs&#8221;. They show the number of subroutine calls executed on that line, and the total time spent in those subroutines due to those calls. Both are color coded, <em>relative to the other values in the same columns</em>, using the same <a href="http://en.wikipedia.org/wiki/Median_absolute_deviation">Median Average Deviation</a> that&#8217;s used elsewhere.</p>
<p>To make room for the new columns, the column showing the average statement execution time has been removed (it wasn&#8217;t much use anyway) and the column headings tightened up. The average value, if you&#8217;re interested, is available as a tool-tip, as shown above.</p>
<h2>New Options</h2>
<p>A few new options have been added, including:</p>
<ul>
<li><code>sigexit=<em>S</em> </code> Some signals will abort a process leaving a corrupt profile data file. The <code>sigexit</code> option can be used to tell NYTProf to catch those signals and close the profile cleanly before exiting.
</li>
<li><code>forkdepth=<em>N</em> </code>When a process being profiled is forked the child process is also profiled. The <code>forkdepth=N</code> option can be used to limit the number of generations that are profiled. The default is -1 (all generations). A value of 0 effectively disables profiling of child processes.
</li>
<li><code>log=<em>F</em> </code>If you enable NYTProf trace output, via the <code>trace=<em>N</em></code> option, it&#8217;s normally written to stderr. The <code>log=<em>F</em> </code> can be used to write the log to a specific file instead.
</li>
</ul>
<h2>nytprofmerge</h2>
<p>As I mentioned above, when a profiled process forks, the child is also profiled, with the profile being written to a new file. So processes which have many children, like mod_perl, end up with many profile data files. Naturally many people have expressed a wish for NYTProf to be able to merge multiple profiles into a single report. Sadly no one has stepped up actually do the work, till now.</p>
<p><a href="http://www.ccl4.org/~nick/">Nicholas Clark</a>, who contributed the great <a href="http://blog.timbunce.org/2008/10/03/nytprof-204-gives-you-90-smaller-data-files/">zip compression</a> for v2.04 (and a major contributor to the perl core and pumpkin for the 5.8.2+ releases) has come up trumps again. NYTProf v3 includes a new nytprofmerge utility that&#8217;ll read multiple profiles and write out a new, merged, profile. It&#8217;s very new, and somewhat experimental, but answers a very real need. Give it a whirl and <a href="http://groups.google.com/group/develnytprof-dev">let us know</a> how it goes. </p>
<h2>Screencast</h2>
<p>I gave a talk on Devel::NYTProf at the (excellent) <a href="http://conferences.yapceurope.org/ipw2009">Italian Perl Workshop</a> in October. I covered both the features in version 3 and the phased approach I take to optimizing perl code. You can <a href="http://blip.tv/file/2840795">watch the screencast</a>.</p>
<h2>And finally</h2>
<p>For more information on the changes in Devel::NYTProf v3 you can <a href="http://search.cpan.org/~timb/Devel-NYTProf-3.00/Changes">read the Changes file</a>.</p>
<p>It&#8217;s <a href="http://en.wikipedia.org/wiki/Christmas_Eve">Christmas Eve</a> here in Ireland. After days, and nights, of hard frost the countryside is spectacularly encased in tiny ice crystals sparking in the bright sunshine. I&#8217;m delighted to have stumbled into working on NYTProf. It&#8217;s a great project at the intersection of two of my professional passions: performance and visualization. And I&#8217;m delighted to give you NYTProf v3 in time for <em>this</em> Christmas.</p>
<p>Enjoy!</p>
<p>Tim.</p>
<br />Posted in perl Tagged: nytprof <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.timbunce.org&#038;blog=2562816&#038;post=362&#038;subd=timbunce&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://blog.timbunce.org/2009/12/24/nytprof-v3-worth-the-wait/feed/</wfw:commentRss>
		<slash:comments>13</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/1cf82705f5ab43c73273ab5d690866b3?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">TimBunce</media:title>
		</media:content>

		<media:content url="http://timbunce.files.wordpress.com/2009/07/filename.png" medium="image">
			<media:title type="html">filename.png</media:title>
		</media:content>

		<media:content url="http://timbunce.files.wordpress.com/2009/07/zz4f06129a.png" medium="image">
			<media:title type="html">ZZ4F06129A.png</media:title>
		</media:content>

		<media:content url="http://timbunce.files.wordpress.com/2009/08/zz1f7ce510.png" medium="image">
			<media:title type="html">ZZ1F7CE510.png</media:title>
		</media:content>

		<media:content url="http://timbunce.files.wordpress.com/2009/08/subs-callgraph.png" medium="image">
			<media:title type="html">subs-callgraph.png</media:title>
		</media:content>

		<media:content url="http://timbunce.files.wordpress.com/2009/08/call-graphviz-file-find-pm.png" medium="image">
			<media:title type="html">call-graphviz-File-Find-pm.png</media:title>
		</media:content>

		<media:content url="http://timbunce.files.wordpress.com/2009/08/zz5dc6382a.png" medium="image">
			<media:title type="html">ZZ5DC6382A.png</media:title>
		</media:content>
	</item>
	</channel>
</rss>
