Category Archives: General

Adding NDEBUG to the Xcode Release target

Programmers often want to put behavior in programs that only happens for debug builds, like logging or other diagnostics. A common convention in C is to surround your debug-only behavior with “#ifndef NDEBUG … #endif”. The double-negative is ugly, but it’s a widely used convention nonetheless.

Xcode doesn’t use this convention by default, so you need to add “-DNDEBUG” to your Release compiles to turn off the debugging behavior. To do this, Get Info on your project, go to the “Build” tab, select the “Release” target and edit the Preprocessor Macros line like in the following screenshot.

Screenshot showing Xcode project configuration dialog

(Credit: Greg Parker)

Firefox crashes

Firefox has lots of hidden “about:*” pages. “about:config” and “about:plugins” are two of the more well known pages. I just learned about the “about:crashes” page, which lists the occasions when the crash reporter was invoked. My historical counts:

  • 2008: 23 (17 in the first three months)
  • 2009: 2
  • 2010: 2

That’s a nice improvement. Two crashes per year is a pretty good mean time between failure for a heavily used, complex application that executes arbitrary third-party code.

Alternative blogging

To subscribers to this site: Most of my commentary of late has been on Perl, so I’ve been posting on my use.perl.org journal. That is the dominant site for journalling for Perl authors, so I’ve found that I get more eyeballs when posting there. I’ll continue to post here sporadically on non-Perl topics.

iTunes Music Store contest

Apple is currently having a contest counting down to 500,000,000 iTunes songs sold. To publicize the contest, they exposed an XML representation of the current count of songs sold. Just out of curiosity, I wrote a Perl program that uses that count information to extrapolate the next winning times. Not too hard considering the simple XML structure:

<?xml version="1.0" encoding="utf-8"?>
<root>
<count name="curCount" timestamp="Thu, 07 Jul 2005 23:16:00 GMT">485066974</count>
<count name="preCount" timestamp="Thu, 07 Jul 2005 23:11:00 GMT">485060489</count>
</root>

The problem is made easier by a few CPAN libraries.

  • LWP::Simple – retrieves files via HTTP
  • CAM::XML – an XML parser and DOM representation
  • DateTime::Format::Strptime – a date/time parser

So, here are my extrapolations followed by the source code. It looks like there will be a winner about once an hour. Of course, that assumes that the purchase rate is typical right now (a Thursday evening).

Retrieving http://www.apple.com/itunes/external_counter.xml...
Rate: 23.19 songs/sec
Predicted count right now: 485173522 (Thu Jul  7 19:35:14 2005 CDT)
485,200,000   Thu Jul  7 19:54:15 2005 CDT
485,300,000   Thu Jul  7 21:06:07 2005 CDT
485,400,000   Thu Jul  7 22:17:58 2005 CDT
485,500,000   Thu Jul  7 23:29:50 2005 CDT
485,600,000   Fri Jul  8 00:41:41 2005 CDT
485,700,000   Fri Jul  8 01:53:33 2005 CDT
485,800,000   Fri Jul  8 03:05:25 2005 CDT
485,900,000   Fri Jul  8 04:17:16 2005 CDT
486,000,000   Fri Jul  8 05:29:08 2005 CDT
486,100,000   Fri Jul  8 06:40:59 2005 CDT
486,200,000   Fri Jul  8 07:52:51 2005 CDT
486,300,000   Fri Jul  8 09:04:43 2005 CDT
486,400,000   Fri Jul  8 10:16:34 2005 CDT
486,500,000   Fri Jul  8 11:28:26 2005 CDT
486,600,000   Fri Jul  8 12:40:17 2005 CDT
486,700,000   Fri Jul  8 13:52:09 2005 CDT
486,800,000   Fri Jul  8 15:04:00 2005 CDT
486,900,000   Fri Jul  8 16:15:52 2005 CDT
487,000,000   Fri Jul  8 17:27:44 2005 CDT
487,100,000   Fri Jul  8 18:39:35 2005 CDT
487,200,000   Fri Jul  8 19:51:27 2005 CDT
487,300,000   Fri Jul  8 21:03:18 2005 CDT
487,400,000   Fri Jul  8 22:15:10 2005 CDT
487,500,000   Fri Jul  8 23:27:02 2005 CDT
487,600,000   Sat Jul  9 00:38:53 2005 CDT
487,700,000   Sat Jul  9 01:50:45 2005 CDT
487,800,000   Sat Jul  9 03:02:36 2005 CDT
487,900,000   Sat Jul  9 04:14:28 2005 CDT
488,000,000   Sat Jul  9 05:26:19 2005 CDT
488,100,000   Sat Jul  9 06:38:11 2005 CDT
488,200,000   Sat Jul  9 07:50:03 2005 CDT
488,300,000   Sat Jul  9 09:01:54 2005 CDT
488,400,000   Sat Jul  9 10:13:46 2005 CDT
488,500,000   Sat Jul  9 11:25:37 2005 CDT
488,600,000   Sat Jul  9 12:37:29 2005 CDT
488,700,000   Sat Jul  9 13:49:21 2005 CDT
488,800,000   Sat Jul  9 15:01:12 2005 CDT
488,900,000   Sat Jul  9 16:13:04 2005 CDT
489,000,000   Sat Jul  9 17:24:55 2005 CDT
489,100,000   Sat Jul  9 18:36:47 2005 CDT
489,200,000   Sat Jul  9 19:48:38 2005 CDT
489,300,000   Sat Jul  9 21:00:30 2005 CDT
489,400,000   Sat Jul  9 22:12:22 2005 CDT
489,500,000   Sat Jul  9 23:24:13 2005 CDT
489,600,000   Sun Jul 10 00:36:05 2005 CDT
489,700,000   Sun Jul 10 01:47:56 2005 CDT
489,800,000   Sun Jul 10 02:59:48 2005 CDT
489,900,000   Sun Jul 10 04:11:40 2005 CDT
490,000,000   Sun Jul 10 05:23:31 2005 CDT
490,100,000   Sun Jul 10 06:35:23 2005 CDT
490,200,000   Sun Jul 10 07:47:14 2005 CDT
490,300,000   Sun Jul 10 08:59:06 2005 CDT
490,400,000   Sun Jul 10 10:10:57 2005 CDT
490,500,000   Sun Jul 10 11:22:49 2005 CDT
490,600,000   Sun Jul 10 12:34:41 2005 CDT
490,700,000   Sun Jul 10 13:46:32 2005 CDT
490,800,000   Sun Jul 10 14:58:24 2005 CDT
490,900,000   Sun Jul 10 16:10:15 2005 CDT
491,000,000   Sun Jul 10 17:22:07 2005 CDT
491,100,000   Sun Jul 10 18:33:59 2005 CDT
491,200,000   Sun Jul 10 19:45:50 2005 CDT
491,300,000   Sun Jul 10 20:57:42 2005 CDT
491,400,000   Sun Jul 10 22:09:33 2005 CDT
491,500,000   Sun Jul 10 23:21:25 2005 CDT
491,600,000   Mon Jul 11 00:33:16 2005 CDT
491,700,000   Mon Jul 11 01:45:08 2005 CDT
491,800,000   Mon Jul 11 02:57:00 2005 CDT
491,900,000   Mon Jul 11 04:08:51 2005 CDT
492,000,000   Mon Jul 11 05:20:43 2005 CDT
492,100,000   Mon Jul 11 06:32:34 2005 CDT
492,200,000   Mon Jul 11 07:44:26 2005 CDT
492,300,000   Mon Jul 11 08:56:18 2005 CDT
492,400,000   Mon Jul 11 10:08:09 2005 CDT
492,500,000   Mon Jul 11 11:20:01 2005 CDT
492,600,000   Mon Jul 11 12:31:52 2005 CDT
492,700,000   Mon Jul 11 13:43:44 2005 CDT
492,800,000   Mon Jul 11 14:55:35 2005 CDT
492,900,000   Mon Jul 11 16:07:27 2005 CDT
493,000,000   Mon Jul 11 17:19:19 2005 CDT
493,100,000   Mon Jul 11 18:31:10 2005 CDT
493,200,000   Mon Jul 11 19:43:02 2005 CDT
493,300,000   Mon Jul 11 20:54:53 2005 CDT
493,400,000   Mon Jul 11 22:06:45 2005 CDT
493,500,000   Mon Jul 11 23:18:37 2005 CDT
493,600,000   Tue Jul 12 00:30:28 2005 CDT
493,700,000   Tue Jul 12 01:42:20 2005 CDT
493,800,000   Tue Jul 12 02:54:11 2005 CDT
493,900,000   Tue Jul 12 04:06:03 2005 CDT
494,000,000   Tue Jul 12 05:17:54 2005 CDT
494,100,000   Tue Jul 12 06:29:46 2005 CDT
494,200,000   Tue Jul 12 07:41:38 2005 CDT
494,300,000   Tue Jul 12 08:53:29 2005 CDT
494,400,000   Tue Jul 12 10:05:21 2005 CDT
494,500,000   Tue Jul 12 11:17:12 2005 CDT
494,600,000   Tue Jul 12 12:29:04 2005 CDT
494,700,000   Tue Jul 12 13:40:56 2005 CDT
494,800,000   Tue Jul 12 14:52:47 2005 CDT
494,900,000   Tue Jul 12 16:04:39 2005 CDT
495,000,000   Tue Jul 12 17:16:30 2005 CDT
495,100,000   Tue Jul 12 18:28:22 2005 CDT
495,200,000   Tue Jul 12 19:40:13 2005 CDT
495,300,000   Tue Jul 12 20:52:05 2005 CDT
495,400,000   Tue Jul 12 22:03:57 2005 CDT
495,500,000   Tue Jul 12 23:15:48 2005 CDT
495,600,000   Wed Jul 13 00:27:40 2005 CDT
495,700,000   Wed Jul 13 01:39:31 2005 CDT
495,800,000   Wed Jul 13 02:51:23 2005 CDT
495,900,000   Wed Jul 13 04:03:15 2005 CDT
496,000,000   Wed Jul 13 05:15:06 2005 CDT
496,100,000   Wed Jul 13 06:26:58 2005 CDT
496,200,000   Wed Jul 13 07:38:49 2005 CDT
496,300,000   Wed Jul 13 08:50:41 2005 CDT
496,400,000   Wed Jul 13 10:02:32 2005 CDT
496,500,000   Wed Jul 13 11:14:24 2005 CDT
496,600,000   Wed Jul 13 12:26:16 2005 CDT
496,700,000   Wed Jul 13 13:38:07 2005 CDT
496,800,000   Wed Jul 13 14:49:59 2005 CDT
496,900,000   Wed Jul 13 16:01:50 2005 CDT
497,000,000   Wed Jul 13 17:13:42 2005 CDT
497,100,000   Wed Jul 13 18:25:34 2005 CDT
497,200,000   Wed Jul 13 19:37:25 2005 CDT
497,300,000   Wed Jul 13 20:49:17 2005 CDT
497,400,000   Wed Jul 13 22:01:08 2005 CDT
497,500,000   Wed Jul 13 23:13:00 2005 CDT
497,600,000   Thu Jul 14 00:24:51 2005 CDT
497,700,000   Thu Jul 14 01:36:43 2005 CDT
497,800,000   Thu Jul 14 02:48:35 2005 CDT
497,900,000   Thu Jul 14 04:00:26 2005 CDT
498,000,000   Thu Jul 14 05:12:18 2005 CDT
498,100,000   Thu Jul 14 06:24:09 2005 CDT
498,200,000   Thu Jul 14 07:36:01 2005 CDT
498,300,000   Thu Jul 14 08:47:53 2005 CDT
498,400,000   Thu Jul 14 09:59:44 2005 CDT
498,500,000   Thu Jul 14 11:11:36 2005 CDT
498,600,000   Thu Jul 14 12:23:27 2005 CDT
498,700,000   Thu Jul 14 13:35:19 2005 CDT
498,800,000   Thu Jul 14 14:47:10 2005 CDT
498,900,000   Thu Jul 14 15:59:02 2005 CDT
499,000,000   Thu Jul 14 17:10:54 2005 CDT
499,100,000   Thu Jul 14 18:22:45 2005 CDT
499,200,000   Thu Jul 14 19:34:37 2005 CDT
499,300,000   Thu Jul 14 20:46:28 2005 CDT
499,400,000   Thu Jul 14 21:58:20 2005 CDT
499,500,000   Thu Jul 14 23:10:12 2005 CDT
499,600,000   Fri Jul 15 00:22:03 2005 CDT
499,700,000   Fri Jul 15 01:33:55 2005 CDT
499,800,000   Fri Jul 15 02:45:46 2005 CDT
499,900,000   Fri Jul 15 03:57:38 2005 CDT
500,000,000   Fri Jul 15 05:09:29 2005 CDT

And the source:

#!/usr/bin/perl -w

use strict;
use LWP::Simple qw(get);
use CAM::XML;
use DateTime::Format::Strptime;

# Constants
my $url = "http://www.apple.com/itunes/external_counter.xml";

# Fetch, parse and extract tags from the XML
print "Retrieving $url...\n";
my $xmlstr = get($url) || die "Failed to retrive the XML";
my $xml = CAM::XML->parse(-string => $xmlstr) || die "Failed to parse the XML";
my @nodes = $xml->getNodes(-tag => "count");
die "Not enough data in the XML\n" unless (@nodes >= 2);

# Parse the times and counts out of the XML data
my $parser = DateTime::Format::Strptime->new(pattern => '%a, %d %b %Y %H:%M:%S %Z');
my ($count1, $count2, $time1, $time2);
foreach my $node (@nodes)
{
   my $timestr = $node->getAttribute("timestamp");
   my $timestamp = $parser->parse_datetime($timestr)->epoch;
   my $count = $node->getInnerText();
   if ($node->getAttribute("name") =~ /cur/)
   {
      $time2 = $timestamp;
      $count2 = $count;
   }
   else
   {
      $time1 = $timestamp;
      $count1 = $count;
   }
}
die "Failed to understand the XML\n" unless ($count1 && $count2 && $time1 && $time2);

# Compute the songs per second
my $rate = ($count2-$count1)/($time2-$time1);
printf "    Rate: %.2f songs/sec\n", $rate;

# Extrapolate to now
my $now = int($rate * (time()-$time2) + $count2);
print "    Predicted count right now: $now (".localtime()." CDT)\n";

# Extrapolate to other prize times
for (my $c=485000000; $c<=500000000; $c+=100000)
{
   next if ($c < $count2); # these have already passed...
   my $t = ($c-$count2)/$rate + $time2;
   # Insert commas
   my $cstr = $c;
   1 while ($cstr =~ s/(\d)(\d{3}(?:,.*|))$/$1,$2/);
   print "    $cstr   ".localtime($t)." CDT\n";
}