<?xml version="1.0" encoding="utf-8"?>
<!-- If you are running a bot please visit this policy page outlining rules you must respect. https://www.livejournal.com/bots/ -->
<feed xmlns="http://www.w3.org/2005/Atom" xmlns:lj="https://www.livejournal.com">
  <id>urn:lj:livejournal.com:atom1:pphaneuf</id>
  <title>Pierre Phaneuf's Diary</title>
  <subtitle>Pierre Phaneuf</subtitle>
  <author>
    <name>Pierre Phaneuf</name>
  </author>
  <link rel="alternate" type="text/html" href="https://pphaneuf.livejournal.com/"/>
  <link rel="self" type="text/xml" href="https://pphaneuf.livejournal.com/data/atom"/>
  <updated>2008-11-14T22:05:36Z</updated>
  <lj:journal userid="4478774" username="pphaneuf" type="personal"/>
  <link rel="service.feed" type="application/x.atom+xml" href="https://pphaneuf.livejournal.com/data/atom" title="Pierre Phaneuf's Diary"/>
  <entry>
    <id>urn:lj:livejournal.com:atom1:pphaneuf:179664</id>
    <link rel="alternate" type="text/html" href="https://pphaneuf.livejournal.com/179664.html"/>
    <link rel="self" type="text/xml" href="https://pphaneuf.livejournal.com/data/atom/?itemid=179664"/>
    <title>This One's Just For You</title>
    <published>2008-11-14T22:05:36Z</published>
    <updated>2008-11-14T22:05:36Z</updated>
    <category term="syndicated"/>
    <category term="fun"/>
    <category term="work"/>
    <content type="html">Okay, so I don't post links to Youtube videos a whole lot, but &lt;a href="http://www.youtube.com/watch?v=X4dSsla-q6o&amp;amp;hl=en" target="_blank" rel="nofollow"&gt;this one is special&lt;/a&gt;. Make sure you view it on the site itself, with the US English language setting (because it &lt;em&gt;really&lt;/em&gt; is special), and make sure to catch what's in the tabs at the top of the page.</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:pphaneuf:178395</id>
    <link rel="alternate" type="text/html" href="https://pphaneuf.livejournal.com/178395.html"/>
    <link rel="self" type="text/xml" href="https://pphaneuf.livejournal.com/data/atom/?itemid=178395"/>
    <title>(Almost) Got a New Bike</title>
    <published>2008-09-25T05:38:23Z</published>
    <updated>2008-09-25T05:38:23Z</updated>
    <category term="syndicated"/>
    <category term="biking"/>
    <category term="decline of civilization"/>
    <category term="evil"/>
    <category term="montreal"/>
    <category term="fun"/>
    <category term="work"/>
    <content type="html">Today, I apparently felt very optimistic.&lt;br /&gt;&lt;br /&gt;You see, Monday I went to Cycle Technique and asked them if they had some used bikes, having in mind of &lt;a href="http://pphaneuf.livejournal.com/177971.html" target="_blank"&gt;getting a rain/winter bike&lt;/a&gt;. Turned out they did, their summer rental bikes, they were pretty nice, and (allegedly) they had a large one that would fit me. I figured I'd give it a thought, then decided it was a good idea, and went on the Tuesday. I figured I'd walk there, pick up the bike, then ride to work. Except that large was actually a medium. So I walked to work instead.&lt;br /&gt;&lt;br /&gt;Today, I figured I'd head over to Beaudry metro, check out &lt;a href="http://www.veloespresso.com/" target="_blank" rel="nofollow"&gt;Vélo Espresso&lt;/a&gt; and &lt;a href="http://www.revolutionmontreal.com/" target="_blank" rel="nofollow"&gt;Revolution Montreal&lt;/a&gt;, for sure I should be able to get a decent used ride between the two of those, right? Well, no. Well, maybe. But mainly no. I had forgotten that Revolution mainly does custom built bikes, meaning that, no, they did not have anything for sale right there. Vélo Espresso had a used bike, but while it could have done, it was &lt;em&gt;quite&lt;/em&gt; used. On their main floor, they had this rather weird bike, a &lt;a href="http://www.norco.com/bikes/city_and_path/urban_commuting/vfr_3_internal.php" target="_blank" rel="nofollow"&gt;Norco VFR 3 Internal&lt;/a&gt;. It's a fairly sporty frame, although not too aggressive, and it actually has space and lugs for fenders and racks (although I hear that it's not always the best fit ever), but it has an internal hub and a chain cover. An internal hub and a chain cover, but no fenders? I keep seeing utility bikes that have fenders, racks and lights, but no chain cover nor internal hub, and this bike has the &lt;em&gt;reverse&lt;/em&gt;? Well, uh, it so happens that this is the exact set of things that you can't &lt;em&gt;add&lt;/em&gt;, so I guess that's cool? I tried it out around a few blocks, and while it's not nearly an upright riding position, it's still surprisingly relaxed. It also &lt;em&gt;comes with clipless pedals&lt;/em&gt; and clip-on platforms like those I already have?!? What a weird bike!&lt;br /&gt;&lt;br /&gt;After that, I went to &lt;a href="http://www.abccycles.com/" target="_blank" rel="nofollow"&gt;ABC Cycles &amp; Sports&lt;/a&gt;, but it was closed (only on Wednesdays, argh!). I stopped by &lt;a href="http://brakeless.ca/" target="_blank" rel="nofollow"&gt;Brakeless&lt;/a&gt;, since it was just down from it, but they only had the one fixie, it seems more trendy than a place I'd actually want to get a bike from. I then headed over to &lt;a href="http://www.leyeti.ca/" target="_blank" rel="nofollow"&gt;Le Yéti&lt;/a&gt;, where I had a rather informative chat, and saw a ridiculously fancy German bike (I think? don't remember the make/model), which, while complying with pretty much all my requirements, and piling on disc brakes on top (because I really like brakes that work well), is also &lt;em&gt;almost three grands&lt;/em&gt;, although it's now on sale at a bit past two grands. Uh, tempting as it is, I'll have to pass.&lt;br /&gt;&lt;br /&gt;After that, &lt;a href="http://www.labicycletteriejr.com/" target="_blank" rel="nofollow"&gt;La Bicycletterie JR&lt;/a&gt;, &lt;a href="http://www.sportdepotmtl.com/" target="_blank" rel="nofollow"&gt;Sport Dépôt&lt;/a&gt;, and &lt;a href="http://www.pignonsurroues.com/" target="_blank" rel="nofollow"&gt;Pignon sur Roues&lt;/a&gt;. The latter had an interesting bike, the &lt;a href="http://www.louisgarneau.com/catalogs/catalog_product.asp?style_no=8302004" target="_blank" rel="nofollow"&gt;Louis Garneau Cityzen One&lt;/a&gt;, but is oddly missing just a chain cover (even though a blurb about the bike in Vélo Mag claims there's one?). Why is there almost no bike with chain covers?&lt;br /&gt;&lt;br /&gt;I ended up going back to Sport Dépôt, and after some pondering, getting a &lt;a href="http://www.marinbikes.com/2008/ca/bikes/specs_belvedere.php" target="_blank" rel="nofollow"&gt;Marin Belvedere&lt;/a&gt;. I had already spotted that bike from some research on the web, and while I knew they had Marin bikes there, turns out they pretty much only had this one, 20% off, so it was a happy coincidence. But... Their mechanic was off today, so they couldn't prep the bike, so I did &lt;em&gt;not&lt;/em&gt; ride to work, once more.&lt;br /&gt;&lt;br /&gt;Tomorrow, I shall ride home on my new ride! There's no stopping me! They may try, and Jeff might try to jinx me (I beat his Space Invaders high score to ward it off), but I'll be riding back tomorrow, rain or shine, and there'll be no stripe down my back if it's raining!</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:pphaneuf:177971</id>
    <link rel="alternate" type="text/html" href="https://pphaneuf.livejournal.com/177971.html"/>
    <link rel="self" type="text/xml" href="https://pphaneuf.livejournal.com/data/atom/?itemid=177971"/>
    <title>No Nick Cave and a Cycling Problem</title>
    <published>2008-09-13T17:50:33Z</published>
    <updated>2008-09-13T17:54:26Z</updated>
    <category term="syndicated"/>
    <category term="biking"/>
    <category term="music"/>
    <category term="speed"/>
    <category term="fun"/>
    <category term="show"/>
    <lj:music>Millimetrik - Sournoise Supercherie</lj:music>
    <content type="html">Damn! I wanted to see Nick Cave &amp; the Bad Seeds, coming to the Metropolis in October, but it's sold out! Oh well, I'll be trying to go to more small shows, I think. It's been too long I have been to La Sala Rossa, for example, and places like Zoobizarre merit being visited again. Oh, and going to see &lt;a href="http://www.misskittin.com/" target="_blank" rel="nofollow"&gt;Miss Kittin &amp; The Hacker&lt;/a&gt; on the 27th at SAT! Awesome!&lt;br /&gt;&lt;br /&gt;All those shows, I'd like to bike to them, but I've been finding my quest for fenders to put on &lt;a href="http://images.google.com/images?&amp;amp;q=Giant+FCR+2" target="_blank" rel="nofollow"&gt;my bike&lt;/a&gt; rather frustrating. It's a weird bike, rather easy to ride with its straight handlebars, but the rest is done in a racing style. Which means that there's basically no clearance anywhere between the tires, the frame, the fork, and the brakes, not a lug in sight for anything (well, except water bottles), and so on...&lt;br /&gt;&lt;br /&gt;I'm also pondering a winter bike, as I'd like to try (to some degree, I always have my CAM in my bag!) to ride for at least part of the winter. I'm pondering what to do, as there are many parameters...&lt;br /&gt;&lt;br /&gt;I'd like to have a city bike, that would fill in the role a car does for most people. It would have to be practical, something I'd be able to ride day in and day out. It shouldn't be a hassle to ride all the time. I do &lt;em&gt;not&lt;/em&gt; want to be hardcore. I'd like to just dress normally, as if I had a car, and arrive maybe a bit rained on at best, as if I was parked a bit far, but not drenched, and &lt;em&gt;no&lt;/em&gt; wet line along my back! It could be aluminium, to keep the weight (and the rust) down, but it wouldn't try to be super-light. I think an internal hub might be good, to minimize maintenance as much as possible. Chain cover, to protect my pants. Everything bolted on, so that locking it is easy and quick. Lights, possibly with a generator (but it shouldn't be awful like those against-the-wheel generators).&lt;br /&gt;&lt;br /&gt;One of the problems I'm having in this quest is that most bikes fulfilling these criteria (that I can find here) tend to go for a vintage look and have some of the features I listed only because most bikes in the fifties had them, not because they're sensible bikes. One bike having all those items also had things like a seat with &lt;em&gt;big&lt;/em&gt; springs (heavy if it useful, sure, but those are heavy &lt;em&gt;and&lt;/em&gt; useless!), and a back wheel cover (so that my longcoat doesn't get stuck in the spokes). Stylish, yes, but practical? I live just at the foot of the hill between René-Levesque and St-Antoine, if my first experience when I take out the bike is consistently having this feeling that I'm going to die, well, uh, I don't think that'll be encouraging!&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.batavus.ca/" target="_blank" rel="nofollow"&gt;Batavus&lt;/a&gt; seems to have some &lt;a href="http://www.batavus.ca/CA/index.aspx?menuId=1&amp;amp;page=BikePrintDetails&amp;amp;collection=1&amp;amp;bikeGroupId=776&amp;amp;frameTypeId=1497&amp;amp;colorId=1935&amp;amp;gearBoxId=1737" target="_blank" rel="nofollow"&gt;interesting models&lt;/a&gt;, and while I haven't seen much of them in Montreal, they have a Canadian site, and there are some resellers in Montreal (I've been there before, but I don't remember seeing them, I guess they can order them, in the worst case). Some details are a bit off still, like the integrated horseshoe locks, which are pretty nice, but require replacing all the inhabitants of Montreal with Danish people first, so it's a bit impractical.&lt;br /&gt;&lt;br /&gt;Another thing that's causing me some grief is the parking space. I don't think I want to give up my fast FCR for this hypothetical new bike, you see? On nice days, I don't see why I would deprive myself from the fun of zipping down Ste-Catherine at almost 40 kph! But at the moment, my spot in the basement is just big enough for one bike, maybe two if I could hang then (but it's a temporary setup, and I can't). And maybe I'll be wanting a crappier bike for the winter. And after trying out &lt;a href="http://phython.blogspot.com/" target="_blank" rel="nofollow"&gt;phython&lt;/a&gt;'s fixie, I'm still longing for one myself (soooo smooooth!). Where am I going to put all of this bikery? I have my eyes on the mezzanine at home, but it's not very practical, so it might be good to put the winter bike in the summer and vice-versa, but getting stuff up and down there is rather annoying.&lt;br /&gt;&lt;br /&gt;Ah, what to do, what to do...&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;I think I'll deal with the winter first, and get myself one of those cheap-ish Marin hybrid/commuter bikes...</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:pphaneuf:175780</id>
    <link rel="alternate" type="text/html" href="https://pphaneuf.livejournal.com/175780.html"/>
    <link rel="self" type="text/xml" href="https://pphaneuf.livejournal.com/data/atom/?itemid=175780"/>
    <title>Nothing Sucks Like A Vax!</title>
    <published>2008-06-28T03:50:43Z</published>
    <updated>2008-06-28T03:54:59Z</updated>
    <category term="syndicated"/>
    <category term="booze"/>
    <category term="tech"/>
    <category term="food"/>
    <category term="speed"/>
    <category term="photo"/>
    <category term="biking"/>
    <category term="montreal"/>
    <category term="work"/>
    <category term="fun"/>
    <content type="html">We moved into our &lt;a href="http://picasaweb.google.com/madecoste/NouveauxBureauxDeGoogleMontrAl" target="_blank" rel="nofollow"&gt;new office&lt;/a&gt; this week (photos courtesy of &lt;a href="http://www.multimad.com/" target="_blank" rel="nofollow"&gt;MAD&lt;/a&gt;, thanks!), and it's pretty damned awesome! Considering the small size of the office (in number of people), it is extremely nice, the food is great, and so is the view (we had a nice view from the 24th floor, but now we're more "in the action", I like that better). Plus, we can easily reach the wifi from the pub nearby, hehe!&lt;br /&gt;&lt;br /&gt;While the move was ongoing, we had an off-site activity on Île-Ste-Hélène that was pretty cool, involving, among other things, geo-caching, which I had never done before and is a lot of fun. It can be surprisingly difficult to find a small item, even when given the location within 10 feet! I bike there from home, and it was particularly nice, hitting 40 kph for fairly long stretches and all. On the return trip I was pretty confident that I'd get to the dinner's location first, but when I found out that the likely reason for my swift arrival was a wicked strong headwind, I wasn't so confident anymore. I did arrive first anyway, but I'm told they took a brief detour in a sketchy St-Henri bar first. Crazy people!&lt;br /&gt;&lt;br /&gt;Today, we also obtained a vacuum cleaner at home. You're probably thinking that this doesn't really sound all that exciting, and normally, I'd agree with you, but that was before I met the &lt;a href="http://www.english.dysoncanada.ca/store/product.asp?product=DC20-ALLFLOORS-CA" target="_blank" rel="nofollow"&gt;Dyson DC20&lt;/a&gt;. As far as box-opening experience goes, relatively speaking (let's face it, it's still just a vacuum cleaner), they're taking lessons from Apple, it looks like. One of the selling points is how it can fit into a small space, and when I got the box, I was a bit worried that it'd be missing, you know, maybe the whole thing?!? But no, it was all in there, and even when assembled, it packs into almost no space, and is very cleverly engineered.&lt;br /&gt;&lt;br /&gt;Tomorrow, a rather late in the making haircut.</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:pphaneuf:175428</id>
    <link rel="alternate" type="text/html" href="https://pphaneuf.livejournal.com/175428.html"/>
    <link rel="self" type="text/xml" href="https://pphaneuf.livejournal.com/data/atom/?itemid=175428"/>
    <title>Putting Thoughts Together</title>
    <published>2008-06-18T16:04:05Z</published>
    <updated>2008-07-15T02:04:48Z</updated>
    <category term="syndicated"/>
    <category term="cpp"/>
    <category term="tech"/>
    <content type="html">Something that I have said a number of times is that nowadays, there is almost no reason to pick C over C++ for a new project (one of the few reasons that I know of involve writing execute-in-place code for very small embedded systems, so no, GNOME &lt;em&gt;definitely&lt;/em&gt; doesn't qualify!). Worst case, you write exactly the same code you'd have written in C, just avoiding using the new keywords as identifiers, and you then get better warnings (remember, no templates would be involved) and stricter type checking (no more silent casting of void* to pointers to random things! No more setting enums from any random integral junk you happen to have at hand! No more forgetting a header and using a function with the wrong parameters!).&lt;br /&gt;&lt;br /&gt;But &lt;a href="http://airs.com/ian/cxx-slides.pdf" target="_blank" rel="nofollow"&gt;these slides&lt;/a&gt; really put it together, from someone who's generally thought of as neither insane or dumb. Doesn't really have much to do with GCC in particular, other than just the general fact that this is becoming so obvious that even GCC might be making the switch...&lt;br /&gt;&lt;br /&gt;Edit: This &lt;a href="http://theory.stanford.edu/~amitp/rants/c++-vs-c/" target="_blank" rel="nofollow"&gt;article&lt;/a&gt; by Amit Patel is also pretty good on this subject.</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:pphaneuf:174815</id>
    <link rel="alternate" type="text/html" href="https://pphaneuf.livejournal.com/174815.html"/>
    <link rel="self" type="text/xml" href="https://pphaneuf.livejournal.com/data/atom/?itemid=174815"/>
    <title>Moving On</title>
    <published>2008-05-28T15:29:20Z</published>
    <updated>2008-05-28T20:06:04Z</updated>
    <category term="syndicated"/>
    <category term="cpp"/>
    <category term="tech"/>
    <category term="psyche"/>
    <content type="html">&lt;a href="http://weblog.raganwald.com/" target="_blank" rel="nofollow"&gt;Reg Braithwaite&lt;/a&gt; was &lt;a href="http://weblog.raganwald.com/2008/04/why-we-are-biggest-obstacle-to-our-own.html" target="_blank" rel="nofollow"&gt;writing&lt;/a&gt; not long ago about how we can be the biggest obstacle to our own growth. It made me realize how I've dropped things that I was once a staunch supporter of.&lt;br /&gt;&lt;br /&gt;I was once a Borland Pascal programmer, and I believed that it was better than C or even C++. I believed that the flexibility of runtime typing would win over the static typing of C++ templates, as computers got faster. I belived that RPC were a great idea, and even worked on an RPC system that would work over dial-up connections (because that's what I had back then). I put in a lot of time working on object persistence and databases. I thought that exceptions were fundamentally bad. I believed that threads were bad, and that event-driven was the way to go.&lt;br /&gt;&lt;br /&gt;Now, I believe in message-passing and in letting the OS kernel manage concurrency (but I don't necessarily believe in threads, it's just what I happen to need in order to get efficient message-passing inside a concurrent application that lets the kernel do its work). I wonder when that will become wrong? And what is going to become right?&lt;br /&gt;&lt;br /&gt;I like to think I had some vision, occasionally. For example, I once worked on an email processing system for &lt;a href="http://en.wikipedia.org/wiki/FidoNet" target="_blank" rel="nofollow"&gt;FidoNet&lt;/a&gt; (thanks to &lt;a href="http://en.wikipedia.org/wiki/Tom_Jennings" target="_blank" rel="nofollow"&gt;Tom Jennings&lt;/a&gt;, a beacon of awesome!), and my friends called me a nutjob when I told them that I was designing the thing so that it was possible to send messages larger than two gigabytes. What I believed was that we'd get fantastic bandwidth someday where messages this large were feasible (we did! but that was an easy call), and that you'd be able to subscribe to television shows for some small sum, where they would send it to you by email and you'd watch it to your convenience. That's &lt;a href="http://www.apple.com/appletv/" target="_blank" rel="nofollow"&gt;never gonna happen&lt;/a&gt;, they said! Ha! HTTP (which I think is used in the iTunes Store) uses the very same chunked encoding that I put in my design back then...&lt;br /&gt;&lt;br /&gt;Note that in some cases, I was partly right, but the world changed, and what was right became wrong. For example, the 32-bit variant of Borland Pascal, Delphi, is actually a pretty nice language (ask &lt;a href="http://alumnit.ca/~apenwarr/log/" target="_blank" rel="nofollow"&gt;apenwarr&lt;/a&gt;!), and while it isn't going to beat C++ in system programming, like I believed it could, it's giving it a really hard time in Windows application programming, and that level of success &lt;em&gt;despite being an almost entirely proprietary platform&lt;/em&gt; is quite amazing. Even Microsoft is buckling under the reality that openness is good for language platforms, trying to have as many people from the outside contributing to .NET (another thing to note: C# was mainly designed by some of the Delphi designers). Imagine what could happen if Borland came to its sense and spat out a Delphi GCC front-end (and use it in their products, making it "the real one", not some afterthought)?&lt;br /&gt;&lt;br /&gt;I doubt that's going to happen, though. For application development, I think it's more likely that "scripting languages" like Ruby, Python and JavaScript are going to reach up and take this away from insanely annoying compiled languages like C++ (and maybe even Java).&lt;br /&gt;&lt;br /&gt;But hey, what do I know? I once thought RPC was going to be the future!</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:pphaneuf:174170</id>
    <link rel="alternate" type="text/html" href="https://pphaneuf.livejournal.com/174170.html"/>
    <link rel="self" type="text/xml" href="https://pphaneuf.livejournal.com/data/atom/?itemid=174170"/>
    <title>Timeouts In Blocking Socket Code</title>
    <published>2008-05-23T22:32:20Z</published>
    <updated>2008-05-23T22:32:20Z</updated>
    <category term="syndicated"/>
    <category term="tech"/>
    <content type="html">I was wondering how to handle timeouts correctly while blocked for I/O on sockets, with as few system calls as possible.&lt;br /&gt;&lt;br /&gt;Thanks to &lt;a href="http://advogato.org/person/slamb/" target="_blank" rel="nofollow"&gt;slamb&lt;/a&gt; for reminding me of &lt;tt&gt;SO_SNDTIMEO&lt;/tt&gt;/&lt;tt&gt;SO_RCVTIMEO&lt;/tt&gt;! Combined with &lt;tt&gt;recv()&lt;/tt&gt; letting me do short reads, I think I've got what I need for something completely portable.</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:pphaneuf:173835</id>
    <link rel="alternate" type="text/html" href="https://pphaneuf.livejournal.com/173835.html"/>
    <link rel="self" type="text/xml" href="https://pphaneuf.livejournal.com/data/atom/?itemid=173835"/>
    <title>Following Up On The End Of The World</title>
    <published>2008-05-19T06:50:15Z</published>
    <updated>2008-05-19T06:50:15Z</updated>
    <category term="syndicated"/>
    <category term="tech"/>
    <category term="scalability"/>
    <content type="html">Being the &lt;a href="http://pphaneuf.livejournal.com/173745.html" target="_blank"&gt;end of the world&lt;/a&gt; and all, I figure I should go into a bit more details, especially as &lt;span  class="ljuser  i-ljuser  i-ljuser-type-P     "  data-ljuser="omnifarious" lj:user="omnifarious" &gt;&lt;a href="https://omnifarious.livejournal.com/profile/"  target="_self"  class="i-ljuser-profile" &gt;&lt;img  class="i-ljuser-userhead"  src="https://l-stat.livejournal.net/img/userinfo_v8.png?v=17080&amp;v=922" /&gt;&lt;/a&gt;&lt;a href="https://omnifarious.livejournal.com/" class="i-ljuser-username"   target="_self"   &gt;&lt;b&gt;omnifarious&lt;/b&gt;&lt;/a&gt;&lt;a class="i-ljuser-badge i-ljuser-badge--pro" data-badge-type="pro" data-placement="bottom" data-pro-badge data-pro-badge-type="1" data-is-raw hidden href="#"&gt;&lt;span class="i-ljuser-badge__icon"&gt;&lt;svg class="svgicon" width="25" height="16" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 33 24"&gt;&lt;path fill-rule="evenodd" d="M19.326 11.95c0 2.01 1.47 3.45 3.48 3.45 2.02 0 3.49-1.44 3.49-3.45 0-2.01-1.47-3.45-3.49-3.45-2.01 0-3.48 1.44-3.48 3.45Zm5.51 0c0 1.24-.8 2.19-2.03 2.19-1.23 0-2.02-.95-2.02-2.19 0-1.25.79-2.19 2.02-2.19s2.03.94 2.03 2.19ZM7.92 15.28H6.5V8.61h3.12c1.45 0 2.24.98 2.24 2.15 0 1.16-.8 2.15-2.24 2.15h-1.7v2.37Zm1.51-3.62c.56 0 .98-.35.98-.9 0-.56-.42-.9-.98-.9H7.92v1.8h1.51ZM18.3802 15.28h-1.63l-1.31-2.37h-1.04v2.37h-1.42V8.61h3.12c1.39 0 2.24.91 2.24 2.15 0 1.18-.74 1.81-1.46 1.98l1.5 2.54Zm-2.49-3.62c.57 0 1-.34 1-.9s-.43-.9-1-.9h-1.49v1.8h1.49Z" clip-rule="evenodd"/&gt;&lt;path fill-rule="evenodd" d="M2 8c0-2.20914 1.79086-4 4-4h20.5c2.2091 0 4 1.79086 4 4v7.9c0 2.2091-1.7909 4-4 4H6c-2.20914 0-4-1.7909-4-4V8Zm4-2.5h20.5C27.8807 5.5 29 6.61929 29 8v7.9c0 1.3807-1.1193 2.5-2.5 2.5H6c-1.38071 0-2.5-1.1193-2.5-2.5V8c0-1.38071 1.11929-2.5 2.5-2.5Z" clip-rule="evenodd"/&gt;&lt;/svg&gt;&lt;/span&gt;&lt;/a&gt;&lt;/span&gt; went as far as &lt;a href="http://omnifarious.livejournal.com/334328.html" target="_blank"&gt;commenting&lt;/a&gt; on this life-altering situation.&lt;br /&gt;&lt;br /&gt;He's unfortunately correct about a shared-everything concurrency model being too hard for most people, mainly because the average programmer has a &lt;a href="http://iggychaos.blogspot.com/2006/02/damn-you-lizard-brain_02.html" target="_blank" rel="nofollow"&gt;lizard's brain&lt;/a&gt;. There's not much I can do about that, unfortunately. We might be having an issue of operating systems here, rather than languages, for that aspect. We can fake it in our Erlang and Newsqueak runtimes, but really, we can only pile so many schedulers up on each others and convince ourselves that we still make sense. That theme comes back later in this post...&lt;br /&gt;&lt;br /&gt;&lt;span  class="ljuser  i-ljuser  i-ljuser-type-P     "  data-ljuser="omnifarious" lj:user="omnifarious" &gt;&lt;a href="https://omnifarious.livejournal.com/profile/"  target="_self"  class="i-ljuser-profile" &gt;&lt;img  class="i-ljuser-userhead"  src="https://l-stat.livejournal.net/img/userinfo_v8.png?v=17080&amp;v=922" /&gt;&lt;/a&gt;&lt;a href="https://omnifarious.livejournal.com/" class="i-ljuser-username"   target="_self"   &gt;&lt;b&gt;omnifarious&lt;/b&gt;&lt;/a&gt;&lt;a class="i-ljuser-badge i-ljuser-badge--pro" data-badge-type="pro" data-placement="bottom" data-pro-badge data-pro-badge-type="1" data-is-raw hidden href="#"&gt;&lt;span class="i-ljuser-badge__icon"&gt;&lt;svg class="svgicon" width="25" height="16" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 33 24"&gt;&lt;path fill-rule="evenodd" d="M19.326 11.95c0 2.01 1.47 3.45 3.48 3.45 2.02 0 3.49-1.44 3.49-3.45 0-2.01-1.47-3.45-3.49-3.45-2.01 0-3.48 1.44-3.48 3.45Zm5.51 0c0 1.24-.8 2.19-2.03 2.19-1.23 0-2.02-.95-2.02-2.19 0-1.25.79-2.19 2.02-2.19s2.03.94 2.03 2.19ZM7.92 15.28H6.5V8.61h3.12c1.45 0 2.24.98 2.24 2.15 0 1.16-.8 2.15-2.24 2.15h-1.7v2.37Zm1.51-3.62c.56 0 .98-.35.98-.9 0-.56-.42-.9-.98-.9H7.92v1.8h1.51ZM18.3802 15.28h-1.63l-1.31-2.37h-1.04v2.37h-1.42V8.61h3.12c1.39 0 2.24.91 2.24 2.15 0 1.18-.74 1.81-1.46 1.98l1.5 2.54Zm-2.49-3.62c.57 0 1-.34 1-.9s-.43-.9-1-.9h-1.49v1.8h1.49Z" clip-rule="evenodd"/&gt;&lt;path fill-rule="evenodd" d="M2 8c0-2.20914 1.79086-4 4-4h20.5c2.2091 0 4 1.79086 4 4v7.9c0 2.2091-1.7909 4-4 4H6c-2.20914 0-4-1.7909-4-4V8Zm4-2.5h20.5C27.8807 5.5 29 6.61929 29 8v7.9c0 1.3807-1.1193 2.5-2.5 2.5H6c-1.38071 0-2.5-1.1193-2.5-2.5V8c0-1.38071 1.11929-2.5 2.5-2.5Z" clip-rule="evenodd"/&gt;&lt;/svg&gt;&lt;/span&gt;&lt;/a&gt;&lt;/span&gt;'s other complaint about threads is that they introduce latency, but I think he's got it backward. Communication introduces latency. Threads let the operating system reduce the overall latency by letting other runs whenever it's possible, instead of being stuck. But if you want to avoid the latency of a specific request, then you have to avoid communication, not threads. Now, that's the thing with a shared-everything model, is that it's kind of promiscuous, and not only is it tempting to poke around in memory that you shouldn't, but sometimes you even do it by accident, when multiple threads touch things that are on the same cache line (better allocators help with that, but you have to be careful still). More points in the "too hard for most people" column.&lt;br /&gt;&lt;br /&gt;His analogy of &lt;tt&gt;memcached&lt;/tt&gt; with NUMA is also to the point. While &lt;tt&gt;memcached&lt;/tt&gt; is at the cluster end of the spectrum, at the other end, there is a similar phenomenon with SMP systems that aren't all that symmetrical, multi-cores add another layer, and hyper-threading yet another. All of this should emphasize how complicated writing a scheduler that will do a good job of using this properly is, and that I'm not particularly thrilled at the idea of having to do it myself, when there's a number of rather clever people trying to do it in the kernel.&lt;br /&gt;&lt;br /&gt;What &lt;em&gt;really&lt;/em&gt; won me over to threading is the implicit I/O. I got screwed over by paging, so I fought back (wasn't going to let myself be pushed around like that!), summoning the evil powers of &lt;tt&gt;mlockall()&lt;/tt&gt;. That's where it struck me that I was forfeiting virtual memory, at this point, and figured that there had to be some way that sucked less. To use multiple cores, I was already going to have to use threads (assuming workloads that need a higher level of integration than processes), so I was already exposed to sharing and synchronization, and as I was working things out, it got clearer that this was one of those things where the worst is getting from one thread to more than one. I was already in it, why not go all the way?&lt;br /&gt;&lt;br /&gt;One of the things that didn't appeal to me in threads was getting preempted. It turns out that when you're not too greedy, you get rewarded! A single-threaded, event-driven program is very busy, because it always finds something interesting to do, and when it's really busy, it tends to exhaust its &lt;a href="http://en.wikipedia.org/wiki/Preemption_%28computing%29#Time_slice" target="_blank" rel="nofollow"&gt;time slice&lt;/a&gt;. With a blocking I/O, thread-per-request design, most servers do not overrun their time slice before running into another blocking point. So in practice, the state machine that I tried so hard to implement in user-space works itself out, if I don't eat all the virtual memory space with huge stacks. With futexes, synchronization is really only expensive in case of contention, so that on a single-processor machine, it's actually just fine too! Seems ironic, but none of it would be useful without futexes and a good scheduler, both of which we only recently got.&lt;br /&gt;&lt;br /&gt;There's still the case of CPU intensive work, which could introduce trashing between threads and reduced throughput. I haven't figured out the best way to do this yet, but it could be kept under control with something like a semaphore, perhaps? Have it set to the maximum number of CPU intensive tasks you want going, have them wait on it before doing work, post it when they're done (or when there's a good moment to yield)...&lt;br /&gt;&lt;br /&gt;&lt;span  class="ljuser  i-ljuser  i-ljuser-type-P     "  data-ljuser="omnifarious" lj:user="omnifarious" &gt;&lt;a href="https://omnifarious.livejournal.com/profile/"  target="_self"  class="i-ljuser-profile" &gt;&lt;img  class="i-ljuser-userhead"  src="https://l-stat.livejournal.net/img/userinfo_v8.png?v=17080&amp;v=922" /&gt;&lt;/a&gt;&lt;a href="https://omnifarious.livejournal.com/" class="i-ljuser-username"   target="_self"   &gt;&lt;b&gt;omnifarious&lt;/b&gt;&lt;/a&gt;&lt;a class="i-ljuser-badge i-ljuser-badge--pro" data-badge-type="pro" data-placement="bottom" data-pro-badge data-pro-badge-type="1" data-is-raw hidden href="#"&gt;&lt;span class="i-ljuser-badge__icon"&gt;&lt;svg class="svgicon" width="25" height="16" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 33 24"&gt;&lt;path fill-rule="evenodd" d="M19.326 11.95c0 2.01 1.47 3.45 3.48 3.45 2.02 0 3.49-1.44 3.49-3.45 0-2.01-1.47-3.45-3.49-3.45-2.01 0-3.48 1.44-3.48 3.45Zm5.51 0c0 1.24-.8 2.19-2.03 2.19-1.23 0-2.02-.95-2.02-2.19 0-1.25.79-2.19 2.02-2.19s2.03.94 2.03 2.19ZM7.92 15.28H6.5V8.61h3.12c1.45 0 2.24.98 2.24 2.15 0 1.16-.8 2.15-2.24 2.15h-1.7v2.37Zm1.51-3.62c.56 0 .98-.35.98-.9 0-.56-.42-.9-.98-.9H7.92v1.8h1.51ZM18.3802 15.28h-1.63l-1.31-2.37h-1.04v2.37h-1.42V8.61h3.12c1.39 0 2.24.91 2.24 2.15 0 1.18-.74 1.81-1.46 1.98l1.5 2.54Zm-2.49-3.62c.57 0 1-.34 1-.9s-.43-.9-1-.9h-1.49v1.8h1.49Z" clip-rule="evenodd"/&gt;&lt;path fill-rule="evenodd" d="M2 8c0-2.20914 1.79086-4 4-4h20.5c2.2091 0 4 1.79086 4 4v7.9c0 2.2091-1.7909 4-4 4H6c-2.20914 0-4-1.7909-4-4V8Zm4-2.5h20.5C27.8807 5.5 29 6.61929 29 8v7.9c0 1.3807-1.1193 2.5-2.5 2.5H6c-1.38071 0-2.5-1.1193-2.5-2.5V8c0-1.38071 1.11929-2.5 2.5-2.5Z" clip-rule="evenodd"/&gt;&lt;/svg&gt;&lt;/span&gt;&lt;/a&gt;&lt;/span&gt; is right about being careful about learning from what others have done. Clever use of &lt;tt&gt;shared_ptr&lt;/tt&gt; and immutable data can be used as a form of RCU, and immutable data in general tends to make good friends with being replicated (safely) in many places.&lt;br /&gt;&lt;br /&gt;One of the great ironies of this, in my opinion, is that Java got NIO almost just in time for it to it to be obsolete, while we were doing this in C and C++ since, well, almost forever. Sun has this trick for being right, yet do it wrong, it's amazing!</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:pphaneuf:173745</id>
    <link rel="alternate" type="text/html" href="https://pphaneuf.livejournal.com/173745.html"/>
    <link rel="self" type="text/xml" href="https://pphaneuf.livejournal.com/data/atom/?itemid=173745"/>
    <title>The End Of The World (As We Know It)!</title>
    <published>2008-05-16T23:44:10Z</published>
    <updated>2008-05-16T23:44:10Z</updated>
    <category term="syndicated"/>
    <category term="tech"/>
    <content type="html">Ok, here we go:&lt;br /&gt;&lt;br /&gt;&lt;big&gt;Event-driven non-blocking I/O isn't the way anymore for high-performance network servers, blocking I/O on a bunch of threads is better now.&lt;/big&gt;&lt;br /&gt;&lt;br /&gt;Wow, I can't believe I just wrote that! Here's a &lt;a href="http://paultyma.blogspot.com/2008/03/writing-java-multithreaded-servers.html" target="_blank" rel="nofollow"&gt;post&lt;/a&gt; that describes some of the reasons (this is talking more about Java, but the underlying reasons apply to C++ as well, it's not just JVMs getting wackier at optimizing locking). It depends on your platform (things don't change from being true to being false just out of the blue!), and more specifically, I have NPTL-based Linux 2.6 in mind, at the very least (NPTL is needed for better &lt;a href="http://en.wikipedia.org/wiki/Futex" target="_blank" rel="nofollow"&gt;futex&lt;/a&gt;-based synchronization, and 2.6 for the O(1) scheduler and low overhead per thread). You also want to specify the smallest stacks you can get away with, and you also want a 64-bit machine (it has a bigger address space, meaning it will explode later).&lt;br /&gt;&lt;br /&gt;The most important thing you need is to &lt;em&gt;think&lt;/em&gt; and not be an idiot, but that's not really new.&lt;br /&gt;&lt;br /&gt;And when I say "bunch of threads", &lt;em&gt;I really mean it&lt;/em&gt;! My current "ideal design" for a web server now involves not just a thread per connection, but a thread &lt;em&gt;per request&lt;/em&gt; (of which there can be multiple requests per connection)! Basically, you want one thread reading a request from the socket, then once it's read, fork it off to let it do its work, and have the writing of the reply to the socket be done on the request thread. This allows for as much pipelining as possible.&lt;br /&gt;&lt;br /&gt;Still, event-driven I/O is not completely useless, it is still handy in the case of protocols that have long-lived connections which stay quiet for a long time. Examples of that are IRC and LDAP servers, although it's possible that with connection keep-alive, one might want to do that with an HTTP server as well, using event notification to see that a request is arrived, then hand it back to a thread to actually process it.&lt;br /&gt;&lt;br /&gt;I also now realize that I was thinking too hard in my &lt;a href="http://pphaneuf.livejournal.com/158639.html" target="_blank"&gt;previous thoughts on using multiple cores&lt;/a&gt;. One could simply have a "waiting strategy" (be it &lt;tt&gt;select()&lt;/tt&gt; or &lt;tt&gt;epoll&lt;/tt&gt;), and something else to process the events (an "executor", I think some people call that?). You could then have a simple single-threaded executor that just runs the callbacks right there and then, no more fuss (think of WvStreams' &lt;tt&gt;post_select()&lt;/tt&gt;), or you could have a fancy-pants thread-poll, whatever you fancied. I was so proud of my little design, now it's all useless. Oh well, live and learn...</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:pphaneuf:172824</id>
    <link rel="alternate" type="text/html" href="https://pphaneuf.livejournal.com/172824.html"/>
    <link rel="self" type="text/xml" href="https://pphaneuf.livejournal.com/data/atom/?itemid=172824"/>
    <title>Old Fogeys</title>
    <published>2008-04-25T16:39:47Z</published>
    <updated>2008-05-07T17:01:30Z</updated>
    <category term="syndicated"/>
    <category term="quadra"/>
    <category term="decline of civilization"/>
    <category term="tech"/>
    <category term="nostalgia"/>
    <category term="biking"/>
    <category term="car"/>
    <category term="evil"/>
    <category term="fun"/>
    <content type="html">I've become a member of &lt;a href="http://communauto.com/" target="_blank" rel="nofollow"&gt;Communauto&lt;/a&gt; last week, and combined with getting my bike back, means that I'm at what is going to be my peak mobility for the next little while.&lt;br /&gt;&lt;br /&gt;Used Communauto a couple of days later to go to a &lt;a href="http://code.google.com/p/quadra/" target="_blank" rel="nofollow"&gt;Quadra&lt;/a&gt; hackfest at Rémi's, with &lt;span  class="ljuser  i-ljuser  i-ljuser-type-P     "  data-ljuser="slajoie" lj:user="slajoie" &gt;&lt;a href="https://slajoie.livejournal.com/profile/"  target="_self"  class="i-ljuser-profile" &gt;&lt;img  class="i-ljuser-userhead"  src="https://l-stat.livejournal.net/img/userinfo_v8.png?v=17080&amp;v=922" /&gt;&lt;/a&gt;&lt;a href="https://slajoie.livejournal.com/" class="i-ljuser-username"   target="_self"   &gt;&lt;b&gt;slajoie&lt;/b&gt;&lt;/a&gt;&lt;/span&gt; as well. I've had a surge of interest in Quadra, but it is a delicate thing to do: we need to release a new stable version before we can hack on the "next generation" version, and while we're getting very close now, there is definitely a momentum thing that can be lost just too easily. And now the kind of things left are packaging related, which isn't the most exciting (so help us out, &lt;span  class="ljuser  i-ljuser  i-ljuser-deleted  i-ljuser-type-P     "  data-ljuser="dgryski" lj:user="dgryski" &gt;&lt;a href="https://dgryski.livejournal.com/profile/"  target="_self"  class="i-ljuser-profile" &gt;&lt;img  class="i-ljuser-userhead"  src="https://l-stat.livejournal.net/img/userinfo_v8.png?v=17080&amp;v=922" /&gt;&lt;/a&gt;&lt;a href="https://dgryski.livejournal.com/" class="i-ljuser-username"   target="_self"   &gt;&lt;b&gt;dgryski&lt;/b&gt;&lt;/a&gt;&lt;/span&gt;!). We've got interesting ideas for future development, but we can't really do any of this for now, since it would make merging from the stable release very annoying (and it already isn't too wonderful at times)...&lt;br /&gt;&lt;br /&gt;Getting my bike back meant going to work on bike, and that is &lt;em&gt;ridiculously&lt;/em&gt; quick, on the order of six to seven minutes. That's faster than the metro, by a lot (that's only a bit more than the average waiting time, and I don't have to walk to Lionel-Groulx). In my opinion, that's not even good exercise, I hardly have time to break a sweat even if I go fast, so I might end up taking detours on good days (the Lachine Canal bike path is nearby).&lt;br /&gt;&lt;br /&gt;Related to Quadra, I've been looking at &lt;a href="http://libsdl.org/" target="_blank" rel="nofollow"&gt;SDL&lt;/a&gt; (which the next version of Quadra uses instead of its internal platform) and &lt;a href="http://www.libsdl.org/projects/SDL_net/" target="_blank" rel="nofollow"&gt;SDL_net&lt;/a&gt;. It's funny how game developers are so conservative sometimes! I don't know much about 3D games, but in 2D, people seem to develop more or less like they did on DOS more than 10 years ago, which was very limited back then, due to DOS not having much of a driver model. Because of that, since anything more than page flipping and waiting for the vertical retrace (using polling PIO, of course) is specific to every video chipset. A game wanting to use accelerated blits had to basically have its own internal driver model, and when a card was not supported, either the game would look bad (because it would use a software fallback), or would not work at all. In light of that, most games just assumed a &lt;a href="http://www.delorie.com/djgpp/doc/ug/graphics/vga.html" target="_blank" rel="nofollow"&gt;basic VGA&lt;/a&gt; card (the "Super" part is made of vendor-specific extensions), using 320x200 in 256 colors (like Doom), or 640x480 in 16 colors (ever used Windows' "safe mode"?), with maybe a few extra extensions that were extremely common and mostly the same.&lt;br /&gt;&lt;br /&gt;Then, DirectX appeared and all the fancy accelerations became available to games (window systems like X11 and Windows had their own driver model, but could afford to, being bigger projects than most games, and were pretty much the sole users of the accelerations, so they existed). What happened? Game developers kept going pretty much the same way. Some tests by Rémi back then found that using the video memory to video memory color key accelerated blits (with DirectDraw), getting &lt;em&gt;hundreds of frames per second&lt;/em&gt;, where the software equivalent could barely pull thirty frames per second on the same machine. About an &lt;em&gt;order of magnitude faster&lt;/em&gt;! You'd think game developers would be all over this, but no, they weren't. They were set in their ways, had their own libraries that did it the crappy way, and didn't bother, overall. The biggest user of 2D color keyed blitting is probably something like the Windows desktop icons.&lt;br /&gt;&lt;br /&gt;Then, 3D acceleration appeared, and they just didn't have the choice. The thing is, this hardware still isn't completely pervasive, and especially for the target audience of a game like Quadra, who like nice little games and won't have big nVidia monsters in their machines, so using the 3D hardware for that kind of game would leave them in the dust. Nowadays, DirectDraw has been obsoleted and is now a compatibility wrapper on top of Direct3D, so oddly enough, we're back to 2D games having to avoid the acceleration.&lt;br /&gt;&lt;br /&gt;Thankfully, in the meantime, the main CPUs and memory became much faster, so you can do pretty cool stuff all in software, but it's kind of a shame, I see all of this CPU being wasted. Think about it: Quadra pulls in at about 70% CPU usage on my 1.5 GHz laptop, so one could think it would "need" about 1 GHz to run adequately, right? Except it worked at just about full frame rate (its engine is bound at 100 frames per second) on my old &lt;em&gt;100 MHz&lt;/em&gt; 486DX! Something weird happened in between...&lt;br /&gt;&lt;br /&gt;Game developers seem to be used to blocking APIs and polling so much, it spills over in SDL_net, which uses its sockets in blocking mode, and where one could easily lock up a server remotely by doing something silly like hooking up a debugger to one of the client and pausing it. Maybe unplugging the Ethernet cable would do it too, for a minute or two, until the connection timed out. How awful...</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:pphaneuf:167338</id>
    <link rel="alternate" type="text/html" href="https://pphaneuf.livejournal.com/167338.html"/>
    <link rel="self" type="text/xml" href="https://pphaneuf.livejournal.com/data/atom/?itemid=167338"/>
    <title>A Few More Notes on HTTP</title>
    <published>2007-11-05T20:20:29Z</published>
    <updated>2007-11-05T20:20:29Z</updated>
    <category term="syndicated"/>
    <category term="tech"/>
    <category term="scalability"/>
    <category term="barcampmontreal"/>
    <category term="barcampmontreal3"/>
    <category term="database"/>
    <category term="montreal"/>
    <category term="barcamp"/>
    <content type="html">Saturday, I attended &lt;a href="http://barcampmontreal.org/wiki/BarCampMontreal3" target="_blank" rel="nofollow"&gt;BarCampMontreal3&lt;/a&gt;, which was quite fun. I figured that I should really practice my presentation skills, so Thursday, when I found out it was &lt;em&gt;this&lt;/em&gt; Saturday (not the next one as I has thought!), I had to find something to talk about.&lt;br /&gt;&lt;br /&gt;I figured there would be a lot of web developers in the audience, and having noticed that a lot of web application platforms tend to disable many HTTP features that helped the web scale to the level it has today, I thought I could share a few tips on how to avoid busting bandwidth caps, deliver a better user experience and overall try to avoid getting featured on &lt;a href="http://www.uncov.com/" target="_blank" rel="nofollow"&gt;uncov&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;It was well received, mostly (see the &lt;a href="http://www.slideshare.net/pphaneuf/a-few-notes-on-http/" target="_blank" rel="nofollow"&gt;slides&lt;/a&gt;), although it felt a bit like a &lt;a href="http://twitter.com/mtw/statuses/386011922" target="_blank" rel="nofollow"&gt;university lecture&lt;/a&gt; for some (maybe the blackboard Keynote theme didn't help, and I was also one of the few with a strictly educational presentation that was also technical). &lt;a href="http://macournoyer.wordpress.com/" target="_blank" rel="nofollow"&gt;Marc-André Cournoyer&lt;/a&gt; writes that just one simple trick &lt;a href="http://macournoyer.wordpress.com/2007/11/03/barcampmontreal3-report/#comment-5737" target="_blank" rel="nofollow"&gt;visibly improved his loading time&lt;/a&gt;, so it's not just for those who &lt;a href="http://twitter.com/mtw/statuses/386023372" target="_blank" rel="nofollow"&gt;get millions of visitors&lt;/a&gt;! Since at least one person thought that, I guess I should clarify or expand on a few things...&lt;br /&gt;&lt;br /&gt;When running a small web site, there are two things we are after: fast loading time, and keeping our bandwidth usage low (if you're small, you probably don't have the revenue to pay for big pipes).&lt;br /&gt;&lt;br /&gt;The best thing possible is, of course, for your server not to get a request &lt;em&gt;at all&lt;/em&gt;. This is actually quite easy to do, and is accomplished by telling the client some amount of time that it can just assume that the resource it asked will not change. This is done by having a Cache-Control header with a "max-age" directive, like this (the number is in seconds):&lt;br /&gt;&lt;pre&gt;Cache-Control: max-age=3600
&lt;/pre&gt;This used to be done with the "Expires" header in previous versions of HTTP, but as it is &lt;a href="http://www.mnot.net/blog/2007/05/15/expires_max-age" target="_blank" rel="nofollow"&gt;error-prone&lt;/a&gt;, it is best to avoid it if you are generating these headers yourself (or you can use a well-known library to do it for you).&lt;br /&gt;&lt;br /&gt;The main problem with this approach is that we live in a fast-moving world, and we want things to be as up-to-date as possible. If the home page of a news site had the Cache-Control header I just gave, the load would be greatly diminished, but so would the usefulness of the site! But there are some things that do not change all that often, CSS and JavaScript files, for example.&lt;br /&gt;&lt;br /&gt;But there is another approach that leverages caching without compromising the freshness, cache validation. Here, the idea is that the web server gives out a small bit of information that is then used by the client to validate its cache. If the client has the resource already, it can perform a "conditional GET", where the server will only return the data if it is deemed invalid. If the data cached by the client is still valid, the server replies with a "not modified" status code (304, if you need to know), and does not return any data. There is still the cost of a round-trip to the server, but this technique can help cut down on bandwidth (as well as database usage, if you do it right) quite significantly.&lt;br /&gt;&lt;br /&gt;This "small bit of information" can be either a last modification date, or an "entity tag" (ETag), which is literally a small string of your own choosing (note that both can be used at the same time, if you prefer). The last modification date is the one most people find the easiest to understand, but depending on your application, coming up with a last modification date could be difficult or less desirable. For example, a wiki application might only have a "latest version number" for a given wiki page, and would need a separate database query or an SQL join to get the modification date itself. In this case, the wiki application could use the version number as an entity tag to accomplish the same thing.&lt;br /&gt;&lt;br /&gt;This is the most difficult to implement, because it can require changing the implementation of your application. What you need to do is cut the handling of a request in two: the header part, and the content part. In the header part, you need to generate the Last-Modified or the ETag (or both), and then, you compare those with the ones sent by the client. If they match what the client sent, you can simply &lt;em&gt;skip generating the content entirely&lt;/em&gt; and return a "304 Not Modified" response status instead. If they do not match, then you keep going the normal way.&lt;br /&gt;&lt;br /&gt;I heard that Ruby on Rails now has &lt;a href="http://dev.rubyonrails.org/changeset/6158" target="_blank" rel="nofollow"&gt;automatic support for ETag&lt;/a&gt;, which it generates by doing an &lt;a href="http://en.wikipedia.org/wiki/MD5#MD5_hashes" target="_blank" rel="nofollow"&gt;MD5 digest&lt;/a&gt; of the rendered content. While this is better than nothing (it will definitely save on bandwidth), it is a bit brittle (if you have something like "generated at &amp;lt;put time here&amp;gt;" in your page, say), and it has already expended &lt;em&gt;all&lt;/em&gt; the effort of generating a page, only to &lt;em&gt;throw it away&lt;/em&gt; at the end. Ideally, generating the Last-Modified or the ETag would only require a fraction of the effort of generating the whole page. But still, even this naive implementation will save you possibly significant amounts of bandwidth!&lt;br /&gt;&lt;br /&gt;Another technique is to make your content smaller, therefore needing less bandwidth to send it. This can be done with various tricks, varying from making your CSS and JavaScript smaller (for example, using &lt;a href="http://www.crockford.com/" target="_blank" rel="nofollow"&gt;Douglas Crockford&lt;/a&gt;'s &lt;a href="http://www.crockford.com/javascript/jsmin.html" target="_blank" rel="nofollow"&gt;JSMin&lt;/a&gt;), to enabling &lt;a href="http://httpd.apache.org/docs/2.0/mod/mod_deflate.html" target="_blank" rel="nofollow"&gt;on-the-fly compression&lt;/a&gt; on your web server.&lt;br /&gt;&lt;br /&gt;A very good resource to learn more on this is on Yahoo! &lt;a href="http://developer.yahoo.com/performance/" target="_blank" rel="nofollow"&gt;Exceptional Performance&lt;/a&gt; page, which has a list of rules to follow, and even have an easy to use &lt;a href="http://developer.yahoo.com/yslow/" target="_blank" rel="nofollow"&gt;tool&lt;/a&gt; (based on the excellent &lt;a href="http://www.getfirebug.com/" target="_blank" rel="nofollow"&gt;Firebug&lt;/a&gt; to tell you how your page is doing, based on those rules (their rule about ETags is a bit incorrect, though, as it usually only applies if you have a cluster of web servers, and can be fixed in a &lt;a href="http://joshua.schachter.org/2006/11/apache-etags.html" target="_blank" rel="nofollow"&gt;better way&lt;/a&gt; than just turning them off). They in fact made a presentation similar in spirit to mine at the last &lt;a href="http://www.web2expo.com/" target="_blank" rel="nofollow"&gt;Web 2.0 Expo&lt;/a&gt;, of which they have a video on their site (&lt;a href="http://www.slideshare.net/techdude/high-performance-web-sites" target="_blank" rel="nofollow"&gt;slides&lt;/a&gt;). They even &lt;a href="http://www.oreilly.com/catalog/9780596529307/" target="_blank" rel="nofollow"&gt;wrote a book&lt;/a&gt; on this subject!&lt;a name='cutid1-end'&gt;&lt;/a&gt;</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:pphaneuf:167071</id>
    <link rel="alternate" type="text/html" href="https://pphaneuf.livejournal.com/167071.html"/>
    <link rel="self" type="text/xml" href="https://pphaneuf.livejournal.com/data/atom/?itemid=167071"/>
    <title>Three Word: Deterministic Is Good</title>
    <published>2007-11-02T01:35:30Z</published>
    <updated>2007-11-02T01:39:56Z</updated>
    <category term="syndicated"/>
    <category term="cpp"/>
    <category term="decline of civilization"/>
    <category term="tech"/>
    <category term="evil"/>
    <content type="html">&lt;a href="http://alumnit.ca/~apenwarr/log/?m=200711#01" target="_blank" rel="nofollow"&gt;apenwarr&lt;/a&gt;: No kidding. Ohh, C++ is so complicated and messy... This is so much easier... Except... Yaaaarrrrghhhhh!&lt;br /&gt;&lt;br /&gt;People, if &lt;em&gt;Perl&lt;/em&gt;, of all bloody languages/runtimes can do it in a less complicated way (pure reference counting with weak references, deterministic finalization), you're &lt;em&gt;doomed&lt;/em&gt;.&lt;br /&gt;&lt;br /&gt;Perl. Simpler. Think about &lt;em&gt;that&lt;/em&gt;.</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:pphaneuf:166738</id>
    <link rel="alternate" type="text/html" href="https://pphaneuf.livejournal.com/166738.html"/>
    <link rel="self" type="text/xml" href="https://pphaneuf.livejournal.com/data/atom/?itemid=166738"/>
    <title>A Counter-Example</title>
    <published>2007-10-15T20:34:05Z</published>
    <updated>2007-10-15T20:35:04Z</updated>
    <category term="syndicated"/>
    <category term="cpp"/>
    <category term="decline of civilization"/>
    <category term="tech"/>
    <category term="evil"/>
    <category term="database"/>
    <category term="rant"/>
    <content type="html">Related to my &lt;a href="http://pphaneuf.livejournal.com/166584.html" target="_blank"&gt;previous post&lt;/a&gt;, I would like to use MySQL++ as an counter-example: it's "result set" object does &lt;em&gt;not&lt;/em&gt; have a "no more rows" method, it simply throws an exception when it is at the end.&lt;br /&gt;&lt;br /&gt;See, this is a good example of something that is not exceptional &lt;em&gt;at all&lt;/em&gt;.</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:pphaneuf:166584</id>
    <link rel="alternate" type="text/html" href="https://pphaneuf.livejournal.com/166584.html"/>
    <link rel="self" type="text/xml" href="https://pphaneuf.livejournal.com/data/atom/?itemid=166584"/>
    <title>Assertions and Exceptions</title>
    <published>2007-10-15T11:38:57Z</published>
    <updated>2007-10-15T14:19:53Z</updated>
    <category term="syndicated"/>
    <category term="cpp"/>
    <category term="tech"/>
    <lj:music>Amon Tobin - Saboteur</lj:music>
    <content type="html">&lt;span  class="ljuser  i-ljuser  i-ljuser-type-P     "  data-ljuser="wlach" lj:user="wlach" &gt;&lt;a href="https://wlach.livejournal.com/profile/"  target="_self"  class="i-ljuser-profile" &gt;&lt;img  class="i-ljuser-userhead"  src="https://l-stat.livejournal.net/img/userinfo_v8.png?v=17080&amp;v=922" /&gt;&lt;/a&gt;&lt;a href="https://wlach.livejournal.com/" class="i-ljuser-username"   target="_self"   &gt;&lt;b&gt;wlach&lt;/b&gt;&lt;/a&gt;&lt;/span&gt; wrote an &lt;a href="http://www.advogato.org/article/949.html" target="_blank" rel="nofollow"&gt;excellent article&lt;/a&gt; recently on how to use (and &lt;em&gt;not&lt;/em&gt; use!) assertions properly, and it reminded me of some of my reflections on assertions and exceptions (warning: this is mostly written with C++ in mind, which does not have checked exceptions, no matter what you may think).&lt;br /&gt;&lt;br /&gt;I would first like to emphatically support his first point: taking out an assert or turning it into a warning is not a "fix". A good developer will do a root cause analysis and find out why the pre-condition was being violated, since &lt;em&gt;that&lt;/em&gt; is the real bug. I remember, a very long time ago, running GTK+ and GNOME programs from the command-line, seeing so-called "assertions" scroll past &lt;em&gt;by the dozen&lt;/em&gt;, and thinking "oh my goodness, we are so doomed". I don't think Qt/KDE was much better either, but it's been a long time, and that's what I used to use. Now I start things from the menu, and I'm blissfully ignorant of how close to the cliff I'm dancing...&lt;br /&gt;&lt;br /&gt;I used to despise exceptions, finding that they obscured the code path and made difficult the task of tracing through what is really happening in your code. It also forced me to litter my code with try/catch blocks, because as soon as you turn on exceptions (or rather, don't turn them off), &lt;em&gt;anything can go wrong, at any time&lt;/em&gt;. What I learned later is two-fold.&lt;br /&gt;&lt;br /&gt;First, like most tools (and C++ is very "good" at this, giving us very sharp, but &lt;em&gt;dangerous&lt;/em&gt; tools!), exceptions can be abused, and most of the early code using exceptions that I met probably suffered a bit from the novelty aspect (it was a "sexy thing" back then, I guess), and over-used them massively. The second assertion mistake &lt;span  class="ljuser  i-ljuser  i-ljuser-type-P     "  data-ljuser="wlach" lj:user="wlach" &gt;&lt;a href="https://wlach.livejournal.com/profile/"  target="_self"  class="i-ljuser-profile" &gt;&lt;img  class="i-ljuser-userhead"  src="https://l-stat.livejournal.net/img/userinfo_v8.png?v=17080&amp;v=922" /&gt;&lt;/a&gt;&lt;a href="https://wlach.livejournal.com/" class="i-ljuser-username"   target="_self"   &gt;&lt;b&gt;wlach&lt;/b&gt;&lt;/a&gt;&lt;/span&gt; talks about, using assertions for errors that may occur in the course of normal (or "non exceptional", if you will) program execution, applies to exceptions as well.&lt;br /&gt;&lt;br /&gt;My current opinion is that functions that use exceptions to signal errors should also have a non-throwing alternative, for the cases where you do expect it. One example would be a string to integer conversion. Another can be taken from Boost, where there is two ways to convert a &lt;tt&gt;weak_ptr&lt;/tt&gt; to a &lt;tt&gt;shared_ptr&lt;/tt&gt;, an implicit way that throws and an explicit way that doesn't (but could give you a "null" &lt;tt&gt;shared_ptr&lt;/tt&gt; and has to be checked for). The latter one is especially good design, since the "safer" exception throwing version is also the more implicit, "shoot from the hip" version, nicely counter-balancing each others.&lt;br /&gt;&lt;br /&gt;Second, your code has to be exception safe. What this means is that getting an exception should not leave things in a bad state. Back in the days, we used raw pointers a whole lot, because this was how it was done, so basically any time that memory was allocated on the heap, you'd have had to wrap it in a try/catch block, so that if an exception happened, you'd free the memory on the way out. This was rather tedious, to say the least, and when you look back on it today, so was using raw pointers (and having to free memory manually). Nowadays, smart pointers rule the land, and it is incredibly easy to write exception-safe code with nary a try/catch block in sight, all appropriate cleanup being stowed out of sight in destructors.&lt;br /&gt;&lt;br /&gt;So, exceptions, not so evil after all, but still should be used for exceptional conditions (big surprise!). But with the latter point, I was seeing a strong parallel with assertions, and in particular, those that I &lt;em&gt;never&lt;/em&gt; want disabled. Now, think about it for a moment about what happens with unhandled exceptions: they call &lt;tt&gt;abort()&lt;/tt&gt;, after writing a short message that tries to say what happened, &lt;em&gt;just like an assertion&lt;/em&gt;. And defining &lt;tt&gt;NDEBUG&lt;/tt&gt; doesn't touch the throws. That's exactly what I was looking for!&lt;br /&gt;&lt;br /&gt;Not only that, but I now see many things that we did in WvStreams that have similar or better equivalents. For example, we added a crash dump and a "last will" feature. The former produced a text file (in addition to a potential core dump) when crashing, with a textual stack trace. The latter was a function you could call to set a string to be put in the crash dump in case something happened, to explain what was happening at that moment. GCC's default terminate handler manages to get at the exception object, so I guess it should be possible to do the same and put the information in the crash dump (this would be platform-dependent, but getting the stack trace already is, so this is not a big deal). The "last will" could also be implemented more efficiently by using a try/catch block and giving the "last will" information only in the case of an exception (making the non-exceptional path fast and quick, only having extra work in case it is really needed), then re-throwing (this is called "exception tagging", if I'm not mistaken). &lt;b&gt;Note&lt;/b&gt;: as I mention to &lt;span  class="ljuser  i-ljuser  i-ljuser-type-P     "  data-ljuser="sfllaw" lj:user="sfllaw" &gt;&lt;a href="https://sfllaw.livejournal.com/profile/"  target="_self"  class="i-ljuser-profile" &gt;&lt;img  class="i-ljuser-userhead"  src="https://l-stat.livejournal.net/img/userinfo_v8.png?v=17080&amp;v=922" /&gt;&lt;/a&gt;&lt;a href="https://sfllaw.livejournal.com/" class="i-ljuser-username"   target="_self"   &gt;&lt;b&gt;sfllaw&lt;/b&gt;&lt;/a&gt;&lt;a class="i-ljuser-badge i-ljuser-badge--pro" data-badge-type="pro" data-placement="bottom" data-pro-badge data-pro-badge-type="1" data-is-raw hidden href="#"&gt;&lt;span class="i-ljuser-badge__icon"&gt;&lt;svg class="svgicon" width="25" height="16" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 33 24"&gt;&lt;path fill-rule="evenodd" d="M19.326 11.95c0 2.01 1.47 3.45 3.48 3.45 2.02 0 3.49-1.44 3.49-3.45 0-2.01-1.47-3.45-3.49-3.45-2.01 0-3.48 1.44-3.48 3.45Zm5.51 0c0 1.24-.8 2.19-2.03 2.19-1.23 0-2.02-.95-2.02-2.19 0-1.25.79-2.19 2.02-2.19s2.03.94 2.03 2.19ZM7.92 15.28H6.5V8.61h3.12c1.45 0 2.24.98 2.24 2.15 0 1.16-.8 2.15-2.24 2.15h-1.7v2.37Zm1.51-3.62c.56 0 .98-.35.98-.9 0-.56-.42-.9-.98-.9H7.92v1.8h1.51ZM18.3802 15.28h-1.63l-1.31-2.37h-1.04v2.37h-1.42V8.61h3.12c1.39 0 2.24.91 2.24 2.15 0 1.18-.74 1.81-1.46 1.98l1.5 2.54Zm-2.49-3.62c.57 0 1-.34 1-.9s-.43-.9-1-.9h-1.49v1.8h1.49Z" clip-rule="evenodd"/&gt;&lt;path fill-rule="evenodd" d="M2 8c0-2.20914 1.79086-4 4-4h20.5c2.2091 0 4 1.79086 4 4v7.9c0 2.2091-1.7909 4-4 4H6c-2.20914 0-4-1.7909-4-4V8Zm4-2.5h20.5C27.8807 5.5 29 6.61929 29 8v7.9c0 1.3807-1.1193 2.5-2.5 2.5H6c-1.38071 0-2.5-1.1193-2.5-2.5V8c0-1.38071 1.11929-2.5 2.5-2.5Z" clip-rule="evenodd"/&gt;&lt;/svg&gt;&lt;/span&gt;&lt;/a&gt;&lt;/span&gt; in the comments, the "last will" cannot be &lt;em&gt;replaced&lt;/em&gt; by a try/catch block, because some crashes are not through exceptions (segmentation faults, for example).&lt;br /&gt;&lt;br /&gt;Also, in the event-driven multiplexing servers that WvStreams is usually used for, it's quite possible that an exception was only fatal to a single connection, and this gives the program the possibility of choosing a middle-ground between just logging a warning or dying altogether: it can now kill off the offending connection, log that event, and keep on going.&lt;br /&gt;&lt;br /&gt;I still use &lt;tt&gt;assert()&lt;/tt&gt;, but only for the more troubling things, such as detecting stack or heap corruption, where the only sane thing to do is really to abort the whole program. This is the kind of thing that is so exceptional that if someone disables it with &lt;tt&gt;NDEBUG&lt;/tt&gt;, it wouldn't be the end of the world. I can put more expensive checks (such as canaries and magic cookies) that get disabled with &lt;tt&gt;NDEBUG&lt;/tt&gt;, and at worst, leave a few "if (...) std::terminate();"&lt;br /&gt;&lt;br /&gt;Finally, one thing that has long annoyed me were objects that have a method to know if the constructor had a problem, and where if it did, the object is invalid. Forgetting to check this state is a common source of bugs (especially in cases where the object is just instantiated on the stack), and this can often make the rest of the object's implementation more complex, having to check for validity on every method. Note that this validity check often should be an assert, IMHO.&lt;br /&gt;&lt;br /&gt;Now, why carry this extra state all the time? This is an exceptional condition, adding an extra code path over the whole lifetime of your object, based on a single boolean value which will be set to the "valid" state 99.9% of the time, thus making sure that there's only a 0.1% chance alternative code path, you can picture what will be the test coverage of &lt;em&gt;that&lt;/em&gt;! Exceptional condition, asserting on it, assertions should often be exceptions, hmm... Why not just tackle this at the source? Throw an exception in the constructor when the object would be invalid. The C++ runtime will free the memory, if it was heap-allocated. You'll have to be careful at object instantiation time, but you'd have to be anyway (checking the validity or wrapping in a try/catch block, pretty much the same overhead). If you ever forget, your program will still be correct, and will terminate, the exact same behaviour as if you didn't check the validity and called a method! Isn't that elegant or what?&lt;br /&gt;&lt;br /&gt;The net footprint of that is a simpler implementation with fewer code paths to test, and &lt;em&gt;zero real additional code for the user&lt;/em&gt; (the validity check is replaced with a try/catch)!&lt;br /&gt;&lt;br /&gt;That's what convinced me that exceptions weren't so evil, when I found this case where they reversed the trend and gave me simpler code to understand than without exceptions, and that was more robust to boot. The try/catch block was perfectly unobtrusive, and in my simple test programs where I didn't care and would have let it &lt;tt&gt;assert()&lt;/tt&gt;, it did too, but at the exact place where the object was deemed invalid (with more context to see why), instead of randomly later.&lt;a name='cutid1-end'&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;So, don't go forward and assert, but rather, go forward and throw!</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:pphaneuf:165645</id>
    <link rel="alternate" type="text/html" href="https://pphaneuf.livejournal.com/165645.html"/>
    <link rel="self" type="text/xml" href="https://pphaneuf.livejournal.com/data/atom/?itemid=165645"/>
    <title>By the way...</title>
    <published>2007-08-24T14:58:03Z</published>
    <updated>2007-08-24T15:14:07Z</updated>
    <category term="syndicated"/>
    <category term="cpp"/>
    <category term="decline of civilization"/>
    <category term="tech"/>
    <category term="evil"/>
    <content type="html">Wow, I'm quite busy these days, haven't been writing (or reading, for that matter!) much...&lt;br /&gt;&lt;br /&gt;Mostly, it's to blame on the quest for a place to live in that's going on. I'd like to buy, this time around, so this makes it a couple of notches more complicated than what I'm used to (I've never been an owner, so this is all new to me). The numbers bandied around are making me quite dizzy! Hopefully, we should come out of this with a nice place, but in the meantime, it's time for "let's save up money like crazy for the cash down", so on top of being busy with this stuff, it'll also make me less visible than I usually am (well, uh, it should still be better than the last year!).&lt;br /&gt;&lt;br /&gt;In other more geeky news, I think I am succumbing to the coding style of the C++ standard library with regard to naming. For method names, there's more than a few people who are going to think "finally!" (I used to favour a Java-style interCap, like "readUntil", now I tend to prefer "read_until"). This makes a lot of sense, since this is also more common in C and Perl code. But the more controversial part is that the standard library uses all lowercase for class names (it's "unordered_set", not "UnorderedSet"), and I'm getting a crush on those too... Perl, Ruby and Python are using FullyCapitalized style for those, and so are a number of C++ programmers I know, but I'm finding that there is something to be said for adopting the style of the language. I'm also using namespaces and exceptions (mostly in constructors and object-returning methods) more, these days.&lt;br /&gt;&lt;br /&gt;So either I'm becoming stylish, or I'm becoming senile. Oh well.&lt;br /&gt;&lt;br /&gt;Also, it would seem that the &lt;a href="http://pics.livejournal.com/pphaneuf/pic/0000rfb5/" target="_blank"&gt;giant jackhammers&lt;/a&gt; are &lt;a href="http://pphaneuf.livejournal.com/6157.html" target="_blank"&gt;following&lt;/a&gt; me.</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:pphaneuf:165395</id>
    <link rel="alternate" type="text/html" href="https://pphaneuf.livejournal.com/165395.html"/>
    <link rel="self" type="text/xml" href="https://pphaneuf.livejournal.com/data/atom/?itemid=165395"/>
    <title>I'm now jobful</title>
    <published>2007-08-02T03:18:43Z</published>
    <updated>2007-08-02T03:18:43Z</updated>
    <category term="syndicated"/>
    <category term="cpp"/>
    <category term="decline of civilization"/>
    <category term="tech"/>
    <category term="work"/>
    <content type="html">Seems like I'm now a senior something-or-other at &lt;a href="http://cypra.com/" target="_blank" rel="nofollow"&gt;Cypra Media&lt;/a&gt;, which did cause me a bit of grief. It's a "targeted marketing" company, meaning at the moment that they'll be sending out emails with ads in them to people who, weirdly enough, asked for it.&lt;br /&gt;&lt;br /&gt;I would have liked maybe a bit more "completely new and different" maybe, and while they seem open-minded, they're not quite an actual free/open source software company, merely using a lot of it. But C++ and Perl are two of my favourites at the moment (mostly for their &lt;em&gt;ratio&lt;/em&gt; of how much I can bend them to my will to how much they suck), and I think I might be in for learning some AJAXy JavaScript hackery in the process, which I've been meaning to do for a while, so that's that. They're &lt;a href="http://en.wikipedia.org/wiki/Scrum_%28development%29" target="_blank" rel="nofollow"&gt;Scrum&lt;/a&gt; fans there, which is better than being, say, &lt;a href="http://en.wikipedia.org/wiki/IBM_Rational_Unified_Process" target="_blank" rel="nofollow"&gt;RUP&lt;/a&gt;! Still, I'm more of a &lt;a href="http://en.wikipedia.org/wiki/Chaos_model" target="_blank" rel="nofollow"&gt;chaos model&lt;/a&gt; type of person, myself. We'll see, I want to try Scrum first, as it doesn't look completely nuts.&lt;br /&gt;&lt;br /&gt;So I'll be starting there as soon as tomorrow!</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:pphaneuf:165230</id>
    <link rel="alternate" type="text/html" href="https://pphaneuf.livejournal.com/165230.html"/>
    <link rel="self" type="text/xml" href="https://pphaneuf.livejournal.com/data/atom/?itemid=165230"/>
    <title>Installers</title>
    <published>2007-07-26T19:23:46Z</published>
    <updated>2007-07-26T19:23:46Z</updated>
    <category term="syndicated"/>
    <category term="tech"/>
    <content type="html">I was reading &lt;a href="http://www.codinghorror.com/blog/archives/000914.html" target="_blank" rel="nofollow"&gt;What's Wrong With Setup.exe?&lt;/a&gt;, and so was Avery, &lt;a href="http://alumnit.ca/~apenwarr/log/?m=200707#25" target="_blank" rel="nofollow"&gt;apparently&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;I pretty much agree with Avery (and commented so on Jeff's blog), but I'd like to comment on how tricky the part about the DMG files is. The problem is that Mac OS X bundles aren't a single file (that could therefore be downloaded "just like that" and would be very intuitive), but is really a directory full of files (that thus can't be fetched off a web server as a single unit).&lt;br /&gt;&lt;br /&gt;I guess Apple was focusing more on the shrink-wrap software publisher's point of view (normally shipping an actual CD-ROM), and kind of provided a virtual equivalent, but it does feel a bit weird.&lt;br /&gt;&lt;br /&gt;One solution could be to ZIP the bundle, and give the operating system the ability to run them directly. You could then just download an application, and run it, no weird installation, nothing. It'd be a challenge, for sure. For example, the fault handler in the kernel would have to be able to find the page inside of a compressed ZIP file, if you "do it right". You could cheat and decompress it silently, but that'd could make launching a big application with lots of resources very slow, which is exactly what using a bundle is supposed to help with in the first place (by demand-loading resources). I know about the "stuff the resources inside the EXE" trick, but bundles can (and often do) have multiple binaries.&lt;br /&gt;&lt;br /&gt;But they could certainly bite the bullet and find a way, I'm sure.&lt;br /&gt;&lt;br /&gt;Note that the Apple approach also follows Avery's &lt;a href="http://alumnit.ca/~apenwarr/log/?m=200707#26" target="_blank" rel="nofollow"&gt;first advice&lt;/a&gt;. Preference files are created as they are needed, while running the application. It also means that a system administrator can simply put up a read-only file share on the network with the applications used in the office, and it'll Just Work (tm).</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:pphaneuf:164334</id>
    <link rel="alternate" type="text/html" href="https://pphaneuf.livejournal.com/164334.html"/>
    <link rel="self" type="text/xml" href="https://pphaneuf.livejournal.com/data/atom/?itemid=164334"/>
    <title>I'm a B-person.</title>
    <published>2007-07-13T18:43:27Z</published>
    <updated>2007-07-13T18:51:51Z</updated>
    <category term="syndicated"/>
    <category term="society"/>
    <category term="business"/>
    <category term="work"/>
    <category term="communities"/>
    <content type="html">Denmark, which I sometimes refer to as "the place the future comes from", gave me another reason to do so: the &lt;a href="http://www.b-society.org/" target="_blank" rel="nofollow"&gt;B-society&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Having just spent a year working a more or less 9-to-6 shift (we had "flex time" inasmuch we could arrive between 8:00 and 9:30), there's no doubt about it (if there ever was!), I'm a B-person.&lt;br /&gt;&lt;br /&gt;One of the problem with being a B-person is the clash with the rest of society. Even if work lets me come in and do my hours whenever I want, there's shops, restaurants, and such. Having dinner at almost midnight can restrict choice a little bit, obviously! Social life can also be tricky. Although these is a natural clumping effect between people living similar lifestyles, they might not have as flexible work schedule. And I wouldn't even think of what things would be like with children! Ask anyone who's had to wake me up early in the morning...&lt;br /&gt;&lt;br /&gt;But it would seems they're actually trying to &lt;a href="http://news.bbc.co.uk/2/hi/programmes/from_our_own_correspondent/6749791.stm" target="_blank" rel="nofollow"&gt;tackle the issues&lt;/a&gt;, even having B-classes in school that start a few hours later. Just like the French had rules preventing abuse by employers asking employees to work later hours, they're picking up on the fact that, for some people it's asking them to &lt;em&gt;not&lt;/em&gt; work later hours that is abuse. And that's the future.&lt;br /&gt;&lt;br /&gt;P.S.: Also, in the same line of thought, &lt;a href="http://www.pickthebrain.com/blog/why-the-9-to-5-office-worker-will-become-a-thing-of-the-past/" target="_blank" rel="nofollow"&gt;why the 9 to 5 office worker will become a thing of the past&lt;/a&gt;. Not that it matters that much to me now, but I am curious to see how France will integrate that into its culture.</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:pphaneuf:161893</id>
    <link rel="alternate" type="text/html" href="https://pphaneuf.livejournal.com/161893.html"/>
    <link rel="self" type="text/xml" href="https://pphaneuf.livejournal.com/data/atom/?itemid=161893"/>
    <title>Saving what again?</title>
    <published>2007-05-21T05:41:05Z</published>
    <updated>2007-05-21T05:44:15Z</updated>
    <category term="syndicated"/>
    <category term="decline of civilization"/>
    <category term="tech"/>
    <category term="evil"/>
    <category term="dst"/>
    <category term="rant"/>
    <content type="html">As it turns out, this year's change in the implementation of daylight "savings" ended up not saving anything, and actually just causing extra annoyance. The US Congress seems completely taken by surprise by the fact that changing the time &lt;a href="http://arstechnica.com/news.ars/post/20070403-the-daylight-savings-change-no-savings-no-point.html" target="_blank" rel="nofollow"&gt;does &lt;em&gt;not&lt;/em&gt; magically create more sunlight&lt;/a&gt;. That extra hour in the evening, scientists and the Department of Energy reminds them, is actually offset by an hour &lt;em&gt;less&lt;/em&gt; in the morning! Imagine that!&lt;br /&gt;&lt;br /&gt;Seems like there is not even a &lt;a href="http://today.reuters.com/news/articlenews.aspx?type=domesticNews&amp;amp;storyID=2007-04-02T223538Z_01_N02447830_RTRUKOC_0_US-DAYLIGHT-ENERGY.xml" target="_blank" rel="nofollow"&gt;measurable energy savings&lt;/a&gt;. If anything, the biggest impact of the daylight savings change is that a bunch of computerized gadgets needed to be updated, and people with their Blackberry and Palm not being sure if the time was adjusted (some changed the time manually, only to have it change by another at the old switch-over date, for example).&lt;br /&gt;&lt;br /&gt;Down with daylight savings! End the madness!</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:pphaneuf:161071</id>
    <link rel="alternate" type="text/html" href="https://pphaneuf.livejournal.com/161071.html"/>
    <link rel="self" type="text/xml" href="https://pphaneuf.livejournal.com/data/atom/?itemid=161071"/>
    <title>Reboot</title>
    <published>2007-05-12T17:45:47Z</published>
    <updated>2007-05-12T17:45:47Z</updated>
    <category term="syndicated"/>
    <category term="cpp"/>
    <category term="tech"/>
    <category term="xplc"/>
    <category term="scalability"/>
    <category term="france"/>
    <category term="montreal"/>
    <category term="work"/>
    <lj:music>Interpol - The New</lj:music>
    <content type="html">Last weekend, I got my residency permit turned down, which, to make a long story short, means that we'll be heading back to Canada. Seems like I was misdirected by the Consulat de France in Montreal, and from what I hear, it seems to be something they've done a few times (&lt;span  class="ljuser  i-ljuser  i-ljuser-type-P     "  data-ljuser="azrhey" lj:user="azrhey" &gt;&lt;a href="https://azrhey.livejournal.com/profile/"  target="_self"  class="i-ljuser-profile" &gt;&lt;img  class="i-ljuser-userhead"  src="https://l-stat.livejournal.net/img/userinfo_v8.png?v=17080&amp;v=922" /&gt;&lt;/a&gt;&lt;a href="https://azrhey.livejournal.com/" class="i-ljuser-username"   target="_self"   &gt;&lt;b&gt;azrhey&lt;/b&gt;&lt;/a&gt;&lt;/span&gt; worked in a place here where they hire a lot of foreigners, due to language skills).&lt;br /&gt;&lt;br /&gt;So, it looks like I'm going to be looking for a job back in Montreal.&lt;br /&gt;&lt;br /&gt;My weapons of choice are C++ and Perl, but being a Unix/Linux hacker, of course, I am not limited to those, they're just the ones I'm most deadly with. I am comfortable with meta-programming (mostly, but not limited to that of C++ templates), continuations/coroutines, closures, multithreading, as well as event-driven state machines. I am quite effective at code refactoring, particularly in strongly typed languages, where I can use the typing system to my advantage.&lt;br /&gt;&lt;br /&gt;I am deeply intimate with Unix/Linux, mainly in the area of network programming (sockets, networking protocols, other forms of IPC). On Linux, I am quite familiar with a number of the high-performance APIs. I have a deep knowledge of the HTTP protocol (and some of its derivatives). I have experience writing Apache modules. I know the difference between bandwidth and latency (and wish more people did too). I have some experience with developing distributed software. I have a higher-than-average knowledge of ELF and Mach-O binary formats, particularly of how symbol resolution works. I know a good deal about component software (dynamically loading modules, for example), and ABI stability issues. While I am not a master at it, I have some Linux kernel development experience as well. I know what &lt;tt&gt;make&lt;/tt&gt; is doing, and &lt;em&gt;why&lt;/em&gt;.&lt;br /&gt;&lt;br /&gt;Finally, I also have some experience doing project and release management, where I feel I did a pretty good job, and would certainly like to do more of it. I am familiar with the free and open source software community, belonging to a number of projects, including some that were part of my work.</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:pphaneuf:159583</id>
    <link rel="alternate" type="text/html" href="https://pphaneuf.livejournal.com/159583.html"/>
    <link rel="self" type="text/xml" href="https://pphaneuf.livejournal.com/data/atom/?itemid=159583"/>
    <title>Down with the Daylight Savings!</title>
    <published>2007-03-12T15:57:38Z</published>
    <updated>2007-03-12T15:57:38Z</updated>
    <category term="syndicated"/>
    <category term="decline of civilization"/>
    <category term="evil"/>
    <category term="power management"/>
    <lj:music>Kid Koala - Roboshuffle</lj:music>
    <content type="html">Two PhD students in economics at Berkeley are &lt;a href="http://abcnews.go.com/Technology/print?id=2938715" target="_blank" rel="nofollow"&gt;studying the effect of daylight savings&lt;/a&gt; observance in Australia (which had a partially extended DST during the Olympics of 2000, thus providing useful data on the subject) and are making such shocking discoveries such as "the extra hour of light in the evening is at the cost of an extra hour of darkness in the morning"! No, &lt;em&gt;really&lt;/em&gt;? Wow!&lt;br /&gt;&lt;br /&gt;More seriously, it would seem that instead of saving anything, it could actually even have had a slight &lt;em&gt;increase&lt;/em&gt; in power use. There are also some reports of increased car usage, but I'm finding that a bit sketchy (are people really &lt;em&gt;that&lt;/em&gt; crazy? maybe I'm just too much of an optimist).&lt;br /&gt;&lt;br /&gt;In any case, at worst, it generated this &lt;a href="http://hardware.slashdot.org/comments.pl?sid=226133&amp;amp;cid=18315109" target="_blank" rel="nofollow"&gt;hilarious comment&lt;/a&gt; on good old Slashdot. Heh.</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:pphaneuf:158977</id>
    <link rel="alternate" type="text/html" href="https://pphaneuf.livejournal.com/158977.html"/>
    <link rel="self" type="text/xml" href="https://pphaneuf.livejournal.com/data/atom/?itemid=158977"/>
    <title>Message passing? Yes!</title>
    <published>2007-03-10T18:49:00Z</published>
    <updated>2008-05-16T18:47:53Z</updated>
    <category term="syndicated"/>
    <category term="tech"/>
    <category term="scalability"/>
    <content type="html">&lt;span  class="ljuser  i-ljuser  i-ljuser-type-P     "  data-ljuser="lkcl" lj:user="lkcl" &gt;&lt;a href="https://lkcl.livejournal.com/profile/"  target="_self"  class="i-ljuser-profile" &gt;&lt;img  class="i-ljuser-userhead"  src="https://l-stat.livejournal.net/img/userinfo_v8.png?v=17080&amp;v=922" /&gt;&lt;/a&gt;&lt;a href="https://lkcl.livejournal.com/" class="i-ljuser-username"   target="_self"   &gt;&lt;b&gt;lkcl&lt;/b&gt;&lt;/a&gt;&lt;/span&gt; posted a &lt;a href="http://advogato.org/person/lkcl/diary.html?start=366" target="_blank" rel="nofollow"&gt;reply&lt;/a&gt; to my &lt;a href="http://pphaneuf.livejournal.com/158639.html" target="_blank"&gt;previous post&lt;/a&gt;...&lt;br /&gt;&lt;br /&gt;Oh, lkcl, you're a bit of a pessimistic, there. &lt;tt&gt;unlink&lt;/tt&gt; is also atomic, not just &lt;tt&gt;rename&lt;/tt&gt;. ;-)&lt;br /&gt;&lt;br /&gt;But what I'm looking after right now isn't just a general message-passing operation (I already do that at a higher level, between various subsystems, using shared memory for local or sockets for remote recipients), more specifically the best way to take advantage of multiple cores as much as possible to process file descriptor events.&lt;br /&gt;&lt;br /&gt;You have to cut the libc people some slack, though, they don't have locks around &lt;em&gt;every single&lt;/em&gt; functions. I'd be amazingly appalled if &lt;tt&gt;strncmp()&lt;/tt&gt; took a lock, for example! And as I described, I already used processes and shared-memory for higher-level concurrency, this threading is only for the very lowest level, when I have no choice and I'm pushed to the edge. Note that the code is already written as a state machines, using the threads to run more than one state machine at once (there is one state machine per connection or so, more or less). I'm planning on having a lock on the state machine instance, so that a single state machine cannot be executed on more than one thread at once, so that the code inside of it can make that assumption (that still allows me to handle multiple independent connections at once).&lt;br /&gt;&lt;br /&gt;On Linux, &lt;tt&gt;epoll&lt;/tt&gt; already does that in an atomic way, for me, in its edge-triggered mode. You can just have multiple threads call &lt;tt&gt;epoll_wait()&lt;/tt&gt;, a given event will be sent to only one thread, until it is re-armed. But the specific requirement here is "compatibility layer for portability to other POSIX platforms", hence the use of crummy old &lt;tt&gt;select()&lt;/tt&gt;. Of course, if I need high-load scalability on some big iron, I'll be sure to &lt;em&gt;not&lt;/em&gt; use that layer, and go for &lt;tt&gt;epoll&lt;/tt&gt;, &lt;tt&gt;kqueue()&lt;/tt&gt; or something like that!&lt;br /&gt;&lt;br /&gt;That said, I'd like a link to that message-passing work, it sounds interesting.</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:pphaneuf:158971</id>
    <link rel="alternate" type="text/html" href="https://pphaneuf.livejournal.com/158971.html"/>
    <link rel="self" type="text/xml" href="https://pphaneuf.livejournal.com/data/atom/?itemid=158971"/>
    <title>Insight of the day</title>
    <published>2007-03-08T12:34:38Z</published>
    <updated>2007-03-08T12:38:16Z</updated>
    <category term="syndicated"/>
    <category term="tech"/>
    <category term="scalability"/>
    <lj:music>Jean Leloup - Isabelle</lj:music>
    <content type="html">I must be very silly, but I just realized that a Unix pipe is a semaphore. It's better in some aspects (is &lt;tt&gt;select()&lt;/tt&gt;able) and worse in others (SEM_VALUE_MAX is lower). Cool.&lt;br /&gt;&lt;br /&gt;In that context, the "signal handler that writes to a pipe" trick makes a new kind of sense (the semaphore equivalent, &lt;tt&gt;sem_post()&lt;/tt&gt;, is the only synchronization function that is safe to use in a signal handler).</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:pphaneuf:158639</id>
    <link rel="alternate" type="text/html" href="https://pphaneuf.livejournal.com/158639.html"/>
    <link rel="self" type="text/xml" href="https://pphaneuf.livejournal.com/data/atom/?itemid=158639"/>
    <title>select() and a thread pool</title>
    <published>2007-03-07T18:34:43Z</published>
    <updated>2007-03-08T08:44:17Z</updated>
    <category term="syndicated"/>
    <category term="tech"/>
    <category term="scalability"/>
    <content type="html">Here's the challenge: a &lt;tt&gt;select()&lt;/tt&gt;-based event dispatcher that can scale from single-threaded to multi-threaded efficiently, preferably as simple as possible and able to be effectively edge-triggered (even if &lt;tt&gt;select()&lt;/tt&gt; itself is level-triggered).&lt;br /&gt;&lt;br /&gt;Note that the point here is to run the event handlers concurrently. I've used threads in the past to work around deficiencies in &lt;tt&gt;select()&lt;/tt&gt;, putting "quiet" file descriptors on one thread that would sleep most of the time, and "busy" file descriptors on another (since &lt;tt&gt;select()&lt;/tt&gt; scales based on the number of file descriptors it watches, this made the active set more efficient), but it would still only use one thread for event handlers. It was just about sleeping more efficiently.&lt;br /&gt;&lt;br /&gt;My first idea was that all threads would be symmetrical and would thus all sleep in &lt;tt&gt;select()&lt;/tt&gt;. But that doesn't work, obviously, because as soon as one file descriptor is ready, all the threads wakes up, which is rather wasteful. Splitting the set of file descriptors between the threads isn't so good, because a scheduler would then be needed to balance the load between threads, and I prefer to leave scheduling to the kernel, as much as possible. On the other hand, this could allow better cache locality, handling the same file descriptor on the same thread (possibly bound to the processor) as often as possible, but on the third hand, let's not get ahead of ourselves.&lt;br /&gt;&lt;br /&gt;It seems that the only way is to keep all the file descriptors together, with just one thread calling &lt;tt&gt;select()&lt;/tt&gt;. When it returns, it should be examined and all the events put on a list. Then it goes into a loop of taking an event from the head of the list, posting the semaphore of the next thread (which could be itself in the single-threaded case), calling the event's handler, then waiting on the semaphore. If there was no event left, it goes back to &lt;tt&gt;select()&lt;/tt&gt; instead.&lt;br /&gt;&lt;br /&gt;There's a few good bits and a few bad bits about this design. A good bit is that the semaphores that keeps the other threads sleeping also protect the list at the same time (that's why it's posted &lt;em&gt;after&lt;/em&gt; taking the next event). A bad bit is that at the end, we would be going into the &lt;tt&gt;select()&lt;/tt&gt; before all the handlers are done, and they might want to add some file descriptors. This could be fixed by having a counter of threads busy running handlers, and the last thread that would be out of events would be the one going back into &lt;tt&gt;select()&lt;/tt&gt;, but this would also make the load more "bursty" in a busy server, where there's really work all the time, but at every round of &lt;tt&gt;select()&lt;/tt&gt;, all the threads but one would go to sleep, only to be reawakened.&lt;br /&gt;&lt;br /&gt;I think, in the end, that the usual Unix solution comes to the rescue: add a file descriptor! Having the reading end of a pipe in the &lt;tt&gt;select()&lt;/tt&gt; invocation, and adding a file descriptor from a handler would write to the writing end, waking up the &lt;tt&gt;select()&lt;/tt&gt; as needed. A bit of a shame, since it would be unnecessary in the single-threaded case, but oh well, that's how it is sometimes...&lt;a name='cutid1-end'&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Anyone has suggestions for improvements? They are most welcome!</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:pphaneuf:158346</id>
    <link rel="alternate" type="text/html" href="https://pphaneuf.livejournal.com/158346.html"/>
    <link rel="self" type="text/xml" href="https://pphaneuf.livejournal.com/data/atom/?itemid=158346"/>
    <title>Edge- Versus Level-Triggered Events</title>
    <published>2007-03-05T19:21:21Z</published>
    <updated>2008-05-16T18:44:27Z</updated>
    <category term="syndicated"/>
    <category term="tech"/>
    <category term="scalability"/>
    <content type="html">A good while ago, I declared my preference for edge-triggered events (for I/O), because in my mind, it most closely paralleled the actual workings of the hardware (IRQs being triggered when new data arrives on network interfaces or when a read/write request to disk is completed). I also figured that since it was possible to emulate level-triggered efficiently on top of edge- (that's what happens when you use close-to-the-metal "abstractions"), it probably was the more flexible choice.&lt;br /&gt;&lt;br /&gt;I then changed my mind, when I realized that what is very often needed is level-triggered, &lt;em&gt;someone&lt;/em&gt; has to remember what file descriptor still has work to do. I figured that it might as well be the kernel, since it is in the best position to do that safely, simply and efficiently. Otherwise, you end up either having to remember myself (which isn't very safe if your framework is only providing the event delivery mechanism, a buggy user could easily "get lost"), or to re-arm the file descriptor (more system calls, less efficient). On the other hand, there were also some other relatively common usage where edge-triggered was preferable (specifically, when transferring data from one file descriptor to another, where you do not want to re-arm the source until you managed to write the data to the sink first.&lt;br /&gt;&lt;br /&gt;But recently, I changed my mind again, and about a certain number of things. Many know me to be one who &lt;a href="http://ludusdesign.com/~pp/threads/" target="_blank" rel="nofollow"&gt;dislikes threads&lt;/a&gt;, but it's not exactly true, I have a dislike of how it's haphazardly used as magic pixie dust by hordes of people who are apparently utterly confused by event-driven state machines. Now that we're seeing more and more multi-core systems, I feel something has to be done about it. And it turns out that level-triggered events are a bit of a pain to handle with multiple threads: a thread going into &lt;tt&gt;epoll_wait&lt;/tt&gt; could get a notification that a file descriptor is readable while another thread is in the process of dealing with it. Adding a monitor to prevent re-entrance would just make it busy-wait instead, as it wouldn't sleep. Edge-triggered events deal with this neatly, and I think this combines with the existing cases where it was preferable to make them actually the better choice.&lt;br /&gt;&lt;br /&gt;Now, I want to have a &lt;tt&gt;select()&lt;/tt&gt;-based reference implementation, for portability, and it turns out it's kind of tricky to have multiple thread service a common set of file descriptors... I have some ideas, but that'll be for next time.&lt;a name='cutid1-end'&gt;&lt;/a&gt;</content>
  </entry>
</feed>
