<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-1234953837283832282</id><updated>2012-01-11T04:00:26.806-08:00</updated><category term='queer'/><category term='yahoo'/><category term='minimed'/><category term='javascript'/><category term='opcode'/><category term='pump'/><category term='death'/><category term='eval'/><category term='lookback'/><category term='pecl'/><category term='creative commons'/><category term='conference'/><category term='http'/><category term='pdo'/><category term='what is wrong with men?'/><category term='coincidence'/><category term='audio'/><category term='favorite'/><category term='compiled variables'/><category term='slashdotted'/><category term='unicode'/><category term='misogyny'/><category term='code'/><category term='strings'/><category term='lexer'/><category term='work'/><category term='zval'/><category term='diabetes'/><category term='apache'/><category term='facebook'/><category term='oss'/><category term='php'/><category term='DYG'/><category term='win'/><category term='prank'/><category term='oop'/><category term='catholicism wow'/><category term='cats'/><category term='CV'/><category term='book'/><category term='reddit'/><category term='hawaii'/><category term='ucb'/><category term='photo'/><category term='sql'/><category term='csii'/><category term='europe'/><category term='search'/><category term='tsrmls_cc'/><category term='epic'/><category term='tsrmls'/><category term='fail'/><category term='zend'/><category term='re2c'/><category term='schadenfreude'/><category term='compiler'/><title type='text'>Still trying to get it all out</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://blog.golemon.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1234953837283832282/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://blog.golemon.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Sara Golemon</name><uri>http://www.blogger.com/profile/14557640555210645219</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>30</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-1234953837283832282.post-2012613328090586970</id><published>2009-06-11T14:34:00.000-07:00</published><updated>2010-05-13T16:40:54.164-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='http'/><category scheme='http://www.blogger.com/atom/ns#' term='reddit'/><category scheme='http://www.blogger.com/atom/ns#' term='fail'/><category scheme='http://www.blogger.com/atom/ns#' term='apache'/><category scheme='http://www.blogger.com/atom/ns#' term='slashdotted'/><title type='text'>Slashdotted; Post-mortem</title><content type='html'>&lt;p&gt;About a day and a half ago, &lt;a href="http://reddit.com/"&gt;Reddit&lt;/a&gt; user &lt;a href="http://www.reddit.com/user/stderr"&gt;stderr&lt;/a&gt; posted a link to &lt;a href="http://www.php.net/manual/en/control-structures.goto.php"&gt;the PHP documentation&lt;/a&gt; showing that GOTO will be a part of the language as of version 5.3.  Somewhere in the &lt;a href="http://www.reddit.com/r/programming/comments/8r3dz/cmon_php_at_this_point_youre_almost_a_parody_of/"&gt;reddit comments for this post&lt;/a&gt;, a link was pasted to an entry on this blog where I announced the feature being added years earlier. This naturally brought out the usual flame wars that circle around something like GOTO and drove some new traffic to my blog. No big deal, my server is pretty low-traffic, it can handle a few extra hits.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Within a few hours, &lt;a href="http://www.reddit.com/user/burghler"&gt;burghler&lt;/a&gt; had browsed through other entries on my blog, finding what was at the time, the most recent entry about &lt;a href="http://saragolemon.blogspot.com/2009/06/wait-did-you-seriously-just-say-that.html"&gt;my friend's experience burying her mother&lt;/a&gt;&lt;a&gt;.  Just like the first reddit post, which had made the front page, this one also had a &lt;/a&gt;&lt;a href="http://www.reddit.com/r/atheism/comments/8rc1s/evil_christians_ruin_a_funeral_because_daughter/"&gt;somewhat incendiary title&lt;/a&gt;.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Okay, more than a little incendiary, but I'll get to that in a moment...&lt;/p&gt; &lt;h3&gt;The lesson&lt;/h3&gt; &lt;p&gt;You would think, given that I'm the Architect for Yahoo WebSearch Front-end Engineering, that I would know something about configuring a server to not fall over under load. And in fact, I spend a good portion of my time on making sure that unexpected traffic spikes aren't enough to make a server get overloaded and trigger a chain-reaction of front-ends falling over. I really have &lt;b&gt;no excuse&lt;/b&gt; for not preparing my server for what happened.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;When I woke up Wed morning, I found that my server just didn't seem to respond to SSH or HTTP attempts. A reboot request didn't help, and the colo folks insisted that the server was simply running slow, but it was running. So I left my ssh connection attempt running and eventually I did get a login prompt. Several pained minutes later I managed to get an iptables rule in place to block off the flood of traffic (quicker than trying to stop the webserver). Suddenly, the CPU load was gone! Turns out I had my MaxClients setting much too high, and after a certain degree of concurrency, enough web-server children had spawned off to use up the available memory, which triggered disk swap, and made the CPU load 10x worse. Again, I know this effect exists, I really should have set up this server better.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;A few tweaks to the config later and I got my server running smoothly. I also took the time to re-run my access log statistics. Of the aproximately 3 years of stats I've got, a full &lt;b&gt;2%&lt;/b&gt; of my hits were logged yesterday.  Impressive reddit.... you win this round...&lt;/p&gt;&lt;p&gt;Bright squares indicate heavy traffic, dark squares indicate low traffic&lt;/p&gt;&lt;br /&gt;&lt;h4&gt;Prior to yesterday's traffic&lt;/h4&gt;&lt;table border="0" cellpadding="0" cellspacing="0"&gt; &lt;tbody&gt; &lt;tr&gt; &lt;td class="valueentry"&gt;Jan&lt;/td&gt; &lt;td style="background-color: rgb(60, 66, 90);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(71, 78, 107);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(68, 75, 103);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(70, 77, 105);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(81, 89, 122);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(72, 79, 108);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(70, 77, 105);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(70, 77, 106);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(78, 86, 117);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(69, 76, 104);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(67, 74, 101);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(63, 69, 95);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(62, 69, 94);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(39, 43, 59);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(37, 41, 56);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(69, 76, 103);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(63, 70, 95);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(64, 70, 96);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(64, 70, 96);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(66, 72, 99);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(68, 75, 103);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(71, 79, 107);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(67, 74, 101);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(69, 76, 104);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(58, 64, 87);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(71, 78, 106);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(83, 91, 124);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(74, 81, 111);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(92, 102, 139);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(79, 87, 119);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(78, 86, 117);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td class="valueentry"&gt;Feb&lt;/td&gt; &lt;td style="background-color: rgb(77, 85, 116);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(67, 73, 100);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(63, 69, 95);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(67, 74, 101);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(75, 83, 113);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(73, 80, 109);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(80, 88, 120);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(74, 82, 112);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(66, 72, 99);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(72, 79, 108);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(71, 78, 107);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(76, 83, 114);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(75, 82, 112);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(76, 84, 115);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(69, 76, 104);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(70, 77, 105);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(74, 81, 111);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(73, 80, 109);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(70, 77, 106);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(65, 72, 98);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(74, 81, 111);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(71, 78, 106);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(69, 76, 104);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(71, 78, 107);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(91, 100, 137);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(123, 135, 184);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(80, 88, 120);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(82, 90, 123);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(29, 32, 43);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(0, 0, 0);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(0, 0, 0);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td class="valueentry"&gt;Mar&lt;/td&gt; &lt;td style="background-color: rgb(98, 108, 148);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(85, 94, 128);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(77, 85, 115);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(79, 87, 118);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(78, 86, 118);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(76, 84, 114);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(78, 86, 118);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(99, 109, 149);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(71, 78, 107);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(83, 91, 125);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(74, 82, 111);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(78, 86, 118);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(73, 80, 109);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(67, 74, 101);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(67, 74, 101);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(66, 73, 99);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(72, 79, 108);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(74, 81, 111);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(84, 92, 126);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(71, 79, 107);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(83, 91, 125);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(78, 86, 117);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(76, 84, 115);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(89, 98, 133);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(89, 98, 134);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(88, 97, 132);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(84, 92, 126);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(70, 77, 105);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(75, 82, 112);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(84, 93, 127);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(76, 84, 115);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td class="valueentry"&gt;Apr&lt;/td&gt; &lt;td style="background-color: rgb(95, 105, 143);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(116, 127, 174);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(139, 153, 209);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(95, 105, 143);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(85, 93, 128);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(74, 81, 111);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(76, 84, 115);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(83, 92, 125);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(99, 109, 149);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(98, 108, 148);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(95, 104, 142);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(87, 95, 130);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(81, 89, 121);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(96, 105, 144);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(96, 106, 145);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(94, 103, 141);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(86, 94, 129);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(89, 98, 134);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(100, 110, 150);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(86, 94, 129);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(93, 102, 140);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(89, 98, 134);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(99, 109, 148);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(106, 117, 159);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(103, 113, 155);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(116, 128, 175);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(135, 148, 202);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(116, 128, 175);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(95, 105, 143);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(93, 103, 140);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(0, 0, 0);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td class="valueentry"&gt;May&lt;/td&gt; &lt;td style="background-color: rgb(105, 116, 158);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(95, 105, 143);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(96, 105, 144);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(138, 152, 208);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(98, 108, 147);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(95, 104, 142);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(93, 103, 140);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(101, 111, 152);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(144, 158, 216);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(85, 94, 128);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(89, 98, 133);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(104, 115, 156);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(92, 101, 138);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(86, 94, 129);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(83, 91, 124);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(89, 98, 134);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(70, 77, 106);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(80, 88, 121);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(102, 113, 154);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(99, 109, 149);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(95, 105, 143);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(110, 121, 165);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(93, 102, 139);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(92, 101, 138);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(99, 109, 148);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(93, 102, 139);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(87, 96, 131);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(93, 102, 139);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(95, 104, 142);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(97, 106, 145);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(88, 96, 132);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td class="valueentry"&gt;Jun&lt;/td&gt; &lt;td style="background-color: rgb(97, 107, 146);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(104, 114, 156);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(89, 98, 134);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(95, 104, 143);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(103, 113, 154);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(102, 112, 153);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(99, 109, 149);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(135, 148, 202);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(170, 187, 255);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(71, 79, 107);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(82, 90, 123);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(76, 83, 114);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(69, 76, 104);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(66, 73, 100);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(68, 75, 102);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(71, 79, 107);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(98, 108, 148);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(87, 96, 131);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(105, 116, 158);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(95, 104, 142);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(82, 90, 123);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(79, 87, 119);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(78, 85, 117);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(78, 86, 117);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(72, 80, 109);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(81, 90, 122);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(82, 90, 123);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(84, 93, 127);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(80, 89, 121);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(82, 90, 123);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(0, 0, 0);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td class="valueentry"&gt;Jul&lt;/td&gt; &lt;td style="background-color: rgb(72, 79, 109);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(74, 81, 111);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(136, 150, 204);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(103, 114, 155);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(99, 109, 149);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(76, 83, 114);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(75, 83, 113);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(69, 76, 104);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(74, 81, 111);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(80, 88, 120);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(94, 103, 141);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(75, 82, 112);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(77, 84, 115);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(76, 84, 115);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(64, 71, 96);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(36, 39, 54);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(55, 60, 82);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(73, 80, 109);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(70, 78, 106);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(66, 72, 99);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(66, 73, 100);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(65, 72, 98);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(68, 75, 102);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(86, 95, 130);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(122, 135, 184);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(90, 99, 135);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(86, 95, 129);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(75, 83, 113);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(68, 75, 102);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(89, 98, 134);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(79, 87, 119);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td class="valueentry"&gt;Aug&lt;/td&gt; &lt;td style="background-color: rgb(80, 88, 120);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(74, 82, 112);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(70, 77, 105);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(62, 68, 93);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(68, 75, 103);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(62, 68, 93);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(69, 76, 104);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(73, 81, 110);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(75, 83, 113);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(75, 82, 112);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(81, 89, 122);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(67, 74, 101);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(61, 67, 91);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(60, 66, 91);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(77, 84, 115);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(80, 88, 120);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(76, 83, 114);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(76, 84, 114);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(62, 68, 93);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(70, 77, 105);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(80, 89, 121);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(73, 80, 110);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(61, 67, 92);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(60, 66, 90);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(68, 75, 102);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(92, 102, 139);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(85, 93, 127);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(81, 89, 122);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(64, 71, 97);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(38, 42, 58);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(65, 72, 98);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td class="valueentry"&gt;Sep&lt;/td&gt; &lt;td style="background-color: rgb(69, 75, 103);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(63, 70, 95);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(69, 76, 103);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(70, 77, 105);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(69, 75, 103);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(56, 62, 84);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(55, 60, 82);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(64, 71, 96);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(60, 66, 90);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(60, 66, 90);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(64, 71, 96);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(67, 74, 101);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(110, 121, 165);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(79, 87, 118);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(90, 99, 135);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(91, 100, 136);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(84, 92, 126);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(76, 83, 114);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(74, 81, 111);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(67, 74, 101);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(65, 71, 97);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(51, 56, 77);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(56, 61, 84);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(82, 90, 123);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(82, 90, 124);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(87, 96, 130);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(68, 75, 102);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(63, 69, 95);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(66, 73, 100);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(64, 70, 96);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(0, 0, 0);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;/tr&gt;&lt;tr&gt; &lt;td class="valueentry"&gt;Oct&lt;/td&gt; &lt;td style="background-color: rgb(65, 72, 98);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(77, 85, 116);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(68, 75, 102);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(69, 76, 103);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(60, 66, 90);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(66, 73, 100);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(61, 67, 92);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(65, 71, 97);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(70, 77, 105);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(76, 84, 114);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(68, 75, 102);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(79, 87, 119);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(60, 66, 90);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(60, 66, 91);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(67, 74, 101);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(67, 74, 101);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(70, 77, 105);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(132, 146, 199);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(75, 82, 112);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(77, 85, 116);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(69, 76, 104);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(80, 88, 120);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(69, 76, 103);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(67, 74, 101);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(64, 70, 96);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(68, 75, 103);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(56, 62, 84);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(69, 76, 104);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(69, 76, 104);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(76, 83, 114);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(74, 81, 111);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td class="valueentry"&gt;Nov&lt;/td&gt; &lt;td style="background-color: rgb(73, 80, 109);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(73, 80, 109);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(70, 78, 106);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(65, 71, 97);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(76, 84, 115);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(123, 136, 185);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(76, 84, 114);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(68, 74, 102);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(59, 65, 89);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(68, 75, 102);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(68, 74, 102);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(69, 76, 104);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(80, 89, 121);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(71, 78, 106);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(65, 72, 98);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(69, 76, 104);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(70, 77, 105);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(60, 66, 91);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(67, 74, 101);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(69, 76, 104);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(66, 73, 100);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(64, 70, 96);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(60, 66, 91);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(61, 67, 91);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(55, 61, 83);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(62, 68, 93);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(69, 76, 103);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(60, 66, 90);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(63, 69, 94);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(60, 66, 90);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(0, 0, 0);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td class="valueentry"&gt;Dec&lt;/td&gt; &lt;td style="background-color: rgb(61, 67, 91);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(65, 71, 97);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(66, 73, 99);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(78, 86, 117);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(63, 70, 95);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(66, 73, 99);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(70, 77, 105);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(60, 66, 90);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(62, 69, 94);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(64, 71, 97);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(72, 79, 108);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(69, 76, 104);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(73, 80, 110);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(128, 141, 193);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(76, 83, 114);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(64, 70, 96);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(65, 72, 98);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(69, 76, 104);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(68, 75, 103);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(65, 71, 97);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(58, 64, 87);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(55, 60, 82);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(63, 69, 94);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(64, 70, 96);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(59, 65, 89);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(53, 58, 79);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(59, 65, 89);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(62, 68, 93);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(73, 81, 110);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(56, 62, 85);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(54, 60, 82);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;br /&gt;&lt;/td&gt; &lt;td class="keyentry"&gt;01&lt;/td&gt; &lt;td class="keyentry"&gt;02&lt;/td&gt; &lt;td class="keyentry"&gt;03&lt;/td&gt; &lt;td class="keyentry"&gt;04&lt;/td&gt; &lt;td class="keyentry"&gt;05&lt;/td&gt; &lt;td class="keyentry"&gt;06&lt;/td&gt; &lt;td class="keyentry"&gt;07&lt;/td&gt; &lt;td class="keyentry"&gt;08&lt;/td&gt; &lt;td class="keyentry"&gt;09&lt;/td&gt; &lt;td class="keyentry"&gt;10&lt;/td&gt; &lt;td class="keyentry"&gt;11&lt;/td&gt; &lt;td class="keyentry"&gt;12&lt;/td&gt; &lt;td class="keyentry"&gt;13&lt;/td&gt; &lt;td class="keyentry"&gt;14&lt;/td&gt; &lt;td class="keyentry"&gt;15&lt;/td&gt; &lt;td class="keyentry"&gt;16&lt;/td&gt; &lt;td class="keyentry"&gt;17&lt;/td&gt; &lt;td class="keyentry"&gt;18&lt;/td&gt; &lt;td class="keyentry"&gt;19&lt;/td&gt; &lt;td class="keyentry"&gt;20&lt;/td&gt; &lt;td class="keyentry"&gt;21&lt;/td&gt; &lt;td class="keyentry"&gt;22&lt;/td&gt; &lt;td class="keyentry"&gt;23&lt;/td&gt; &lt;td class="keyentry"&gt;24&lt;/td&gt; &lt;td class="keyentry"&gt;25&lt;/td&gt; &lt;td class="keyentry"&gt;26&lt;/td&gt; &lt;td class="keyentry"&gt;27&lt;/td&gt; &lt;td class="keyentry"&gt;28&lt;/td&gt; &lt;td class="keyentry"&gt;29&lt;/td&gt; &lt;td class="keyentry"&gt;30&lt;/td&gt; &lt;td class="keyentry"&gt;31&lt;/td&gt; &lt;/tr&gt; &lt;/tbody&gt; &lt;/table&gt;&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Current stats&lt;/h4&gt;&lt;table border="0" cellpadding="0" cellspacing="0"&gt; &lt;tbody&gt; &lt;tr&gt; &lt;td class="valueentry"&gt;Jan&lt;/td&gt; &lt;td style="background-color: rgb(16, 17, 24);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(19, 20, 28);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(18, 20, 27);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(18, 20, 28);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(21, 23, 32);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(19, 21, 28);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(18, 20, 27);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(18, 20, 28);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(20, 22, 31);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(18, 20, 27);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(17, 19, 26);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(16, 18, 25);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(16, 18, 25);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(10, 11, 15);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(10, 11, 15);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(18, 20, 27);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(16, 18, 25);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(17, 18, 25);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(17, 18, 25);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(17, 19, 26);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(18, 20, 27);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(19, 20, 28);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(17, 19, 26);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(18, 20, 27);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(15, 17, 23);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(18, 20, 28);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(22, 24, 33);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(19, 21, 29);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(24, 27, 36);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(21, 23, 31);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(20, 22, 31);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td class="valueentry"&gt;Feb&lt;/td&gt; &lt;td style="background-color: rgb(20, 22, 30);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(17, 19, 26);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(16, 18, 25);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(17, 19, 26);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(20, 22, 30);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(19, 21, 29);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(21, 23, 32);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(19, 21, 29);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(17, 19, 26);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(19, 21, 28);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(19, 20, 28);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(20, 22, 30);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(19, 21, 29);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(20, 22, 30);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(18, 20, 27);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(18, 20, 27);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(19, 21, 29);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(19, 21, 29);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(18, 20, 28);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(17, 19, 26);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(19, 21, 29);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(18, 20, 28);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(18, 20, 27);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(18, 20, 28);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(24, 26, 36);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(32, 35, 49);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(21, 23, 31);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(21, 24, 32);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(7, 8, 11);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(0, 0, 0);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(0, 0, 0);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td class="valueentry"&gt;Mar&lt;/td&gt; &lt;td style="background-color: rgb(26, 28, 39);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(22, 25, 34);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(20, 22, 30);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(21, 23, 31);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(20, 22, 31);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(20, 22, 30);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(20, 22, 31);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(26, 29, 39);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(18, 20, 28);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(22, 24, 33);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(19, 21, 29);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(20, 22, 31);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(19, 21, 29);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(18, 19, 27);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(17, 19, 26);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(17, 19, 26);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(19, 21, 28);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(19, 21, 29);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(22, 24, 33);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(19, 20, 28);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(22, 24, 33);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(20, 22, 31);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(20, 22, 30);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(23, 26, 35);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(23, 26, 35);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(23, 25, 35);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(22, 24, 33);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(18, 20, 27);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(19, 21, 29);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(22, 24, 33);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(20, 22, 30);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td class="valueentry"&gt;Apr&lt;/td&gt; &lt;td style="background-color: rgb(25, 27, 38);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(30, 33, 46);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(36, 40, 55);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(25, 27, 37);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(22, 24, 33);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(19, 21, 29);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(20, 22, 30);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(22, 24, 33);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(26, 29, 39);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(26, 28, 39);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(25, 27, 37);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(23, 25, 34);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(21, 23, 32);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(25, 28, 38);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(25, 28, 38);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(25, 27, 37);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(22, 25, 34);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(23, 26, 35);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(26, 29, 39);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(22, 25, 34);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(24, 27, 37);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(23, 26, 35);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(26, 28, 39);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(28, 31, 42);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(27, 30, 41);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(30, 34, 46);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(35, 39, 53);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(30, 34, 46);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(25, 27, 38);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(24, 27, 37);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(0, 0, 0);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td class="valueentry"&gt;May&lt;/td&gt; &lt;td style="background-color: rgb(28, 30, 42);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(25, 28, 38);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(25, 28, 38);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(36, 40, 55);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(26, 28, 39);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(25, 27, 37);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(24, 27, 37);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(26, 29, 40);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(38, 42, 57);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(22, 24, 34);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(23, 26, 35);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(27, 30, 41);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(24, 27, 36);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(22, 25, 34);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(22, 24, 33);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(23, 26, 35);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(18, 20, 28);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(21, 23, 32);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(27, 29, 40);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(26, 29, 39);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(25, 27, 38);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(29, 32, 44);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(24, 27, 37);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(24, 26, 36);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(26, 28, 39);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(24, 27, 37);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(23, 25, 34);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(24, 27, 37);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(25, 27, 37);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(25, 28, 38);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(23, 25, 35);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td class="valueentry"&gt;Jun&lt;/td&gt; &lt;td style="background-color: rgb(25, 28, 38);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(27, 30, 41);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(23, 26, 35);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(25, 27, 37);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(27, 30, 41);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(27, 29, 40);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(26, 29, 39);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(35, 39, 53);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(45, 49, 67);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(170, 187, 255);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(63, 69, 95);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(20, 22, 30);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(18, 20, 27);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(17, 19, 26);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(18, 19, 27);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(19, 20, 28);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(26, 28, 39);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(23, 25, 34);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(28, 30, 42);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(25, 27, 37);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(21, 23, 32);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(21, 23, 31);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(20, 22, 31);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(20, 22, 31);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(19, 21, 29);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(21, 23, 32);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(21, 23, 32);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(22, 24, 33);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(21, 23, 32);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(21, 23, 32);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(0, 0, 0);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td class="valueentry"&gt;Jul&lt;/td&gt; &lt;td style="background-color: rgb(19, 21, 28);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(19, 21, 29);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(36, 39, 54);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(27, 30, 41);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(26, 29, 39);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(20, 22, 30);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(20, 22, 30);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(18, 20, 27);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(19, 21, 29);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(21, 23, 32);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(25, 27, 37);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(19, 21, 29);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(20, 22, 30);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(20, 22, 30);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(17, 18, 25);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(9, 10, 14);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(14, 16, 21);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(19, 21, 29);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(18, 20, 28);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(17, 19, 26);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(17, 19, 26);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(17, 19, 26);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(18, 19, 27);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(22, 25, 34);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(32, 35, 48);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(23, 26, 35);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(22, 25, 34);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(20, 22, 30);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(18, 19, 27);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(23, 26, 35);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(21, 23, 31);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td class="valueentry"&gt;Aug&lt;/td&gt; &lt;td style="background-color: rgb(21, 23, 31);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(19, 21, 29);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(18, 20, 28);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(16, 18, 24);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(18, 20, 27);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(16, 18, 24);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(18, 20, 27);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(19, 21, 29);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(20, 22, 30);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(19, 21, 29);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(21, 23, 32);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(17, 19, 26);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(16, 17, 24);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(16, 17, 24);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(20, 22, 30);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(21, 23, 31);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(20, 22, 30);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(20, 22, 30);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(16, 18, 24);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(18, 20, 28);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(21, 23, 32);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(19, 21, 29);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(16, 17, 24);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(15, 17, 23);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(18, 19, 27);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(24, 27, 36);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(22, 24, 33);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(21, 23, 32);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(17, 18, 25);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(10, 11, 15);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(17, 19, 26);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td class="valueentry"&gt;Sep&lt;/td&gt; &lt;td style="background-color: rgb(18, 20, 27);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(16, 18, 25);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(18, 20, 27);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(18, 20, 27);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(18, 20, 27);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(14, 16, 22);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(14, 16, 21);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(17, 18, 25);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(16, 17, 24);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(15, 17, 23);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(17, 18, 25);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(17, 19, 26);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(29, 32, 44);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(20, 23, 31);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(23, 26, 35);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(24, 26, 36);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(22, 24, 33);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(20, 22, 30);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(19, 21, 29);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(18, 19, 27);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(17, 18, 25);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(13, 15, 20);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(14, 16, 22);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(21, 23, 32);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(21, 24, 32);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(23, 25, 34);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(18, 19, 27);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(16, 18, 25);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(17, 19, 26);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(17, 18, 25);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(0, 0, 0);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td class="valueentry"&gt;Oct&lt;/td&gt; &lt;td style="background-color: rgb(17, 19, 26);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(20, 22, 31);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(18, 19, 27);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(18, 20, 27);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(15, 17, 23);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(17, 19, 26);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(16, 18, 24);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(17, 18, 25);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(18, 20, 28);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(20, 22, 30);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(18, 19, 27);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(21, 23, 31);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(16, 17, 24);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(16, 17, 24);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(17, 19, 26);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(18, 19, 27);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(18, 20, 27);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(35, 38, 52);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(19, 21, 29);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(20, 22, 30);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(18, 20, 27);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(21, 23, 31);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(18, 20, 27);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(17, 19, 26);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(17, 18, 25);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(18, 20, 27);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(14, 16, 22);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(18, 20, 27);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(18, 20, 27);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(20, 22, 30);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(19, 21, 29);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td class="valueentry"&gt;Nov&lt;/td&gt; &lt;td style="background-color: rgb(19, 21, 29);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(19, 21, 29);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(18, 20, 28);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(17, 19, 25);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(20, 22, 30);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(32, 36, 49);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(20, 22, 30);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(18, 19, 27);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(15, 17, 23);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(18, 19, 27);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(18, 19, 27);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(18, 20, 27);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(21, 23, 32);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(18, 20, 28);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(17, 19, 26);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(18, 20, 27);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(18, 20, 28);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(16, 17, 24);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(17, 19, 26);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(18, 20, 27);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(17, 19, 26);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(17, 18, 25);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(16, 17, 24);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(16, 17, 24);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(14, 16, 22);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(16, 18, 24);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(18, 20, 27);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(16, 17, 24);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(16, 18, 25);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(16, 17, 24);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(0, 0, 0);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td class="valueentry"&gt;Dec&lt;/td&gt; &lt;td style="background-color: rgb(16, 17, 24);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(17, 19, 25);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(17, 19, 26);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(20, 22, 31);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(16, 18, 25);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(17, 19, 26);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(18, 20, 27);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(16, 17, 24);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(16, 18, 25);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(17, 18, 25);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(19, 21, 28);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(18, 20, 27);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(19, 21, 29);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(34, 37, 51);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(20, 22, 30);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(16, 18, 25);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(17, 19, 26);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(18, 20, 27);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(18, 20, 27);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(17, 18, 25);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(15, 17, 23);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(14, 16, 21);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(16, 18, 25);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(17, 18, 25);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(15, 17, 23);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(14, 15, 21);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(15, 17, 23);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(16, 18, 24);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(19, 21, 29);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(15, 16, 22);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;td style="background-color: rgb(14, 16, 21);"&gt;&lt;br /&gt;&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;br /&gt;&lt;/td&gt; &lt;td class="keyentry"&gt;01&lt;/td&gt; &lt;td class="keyentry"&gt;02&lt;/td&gt; &lt;td class="keyentry"&gt;03&lt;/td&gt; &lt;td class="keyentry"&gt;04&lt;/td&gt; &lt;td class="keyentry"&gt;05&lt;/td&gt; &lt;td class="keyentry"&gt;06&lt;/td&gt; &lt;td class="keyentry"&gt;07&lt;/td&gt; &lt;td class="keyentry"&gt;08&lt;/td&gt; &lt;td class="keyentry"&gt;09&lt;/td&gt; &lt;td class="keyentry"&gt;10&lt;/td&gt; &lt;td class="keyentry"&gt;11&lt;/td&gt; &lt;td class="keyentry"&gt;12&lt;/td&gt; &lt;td class="keyentry"&gt;13&lt;/td&gt; &lt;td class="keyentry"&gt;14&lt;/td&gt; &lt;td class="keyentry"&gt;15&lt;/td&gt; &lt;td class="keyentry"&gt;16&lt;/td&gt; &lt;td class="keyentry"&gt;17&lt;/td&gt; &lt;td class="keyentry"&gt;18&lt;/td&gt; &lt;td class="keyentry"&gt;19&lt;/td&gt; &lt;td class="keyentry"&gt;20&lt;/td&gt; &lt;td class="keyentry"&gt;21&lt;/td&gt; &lt;td class="keyentry"&gt;22&lt;/td&gt; &lt;td class="keyentry"&gt;23&lt;/td&gt; &lt;td class="keyentry"&gt;24&lt;/td&gt; &lt;td class="keyentry"&gt;25&lt;/td&gt; &lt;td class="keyentry"&gt;26&lt;/td&gt; &lt;td class="keyentry"&gt;27&lt;/td&gt; &lt;td class="keyentry"&gt;28&lt;/td&gt; &lt;td class="keyentry"&gt;29&lt;/td&gt; &lt;td class="keyentry"&gt;30&lt;/td&gt; &lt;td class="keyentry"&gt;31&lt;/td&gt; &lt;/tr&gt; &lt;/tbody&gt; &lt;/table&gt;&lt;br /&gt;&lt;h4&gt;My flickr views...&lt;/h4&gt;&lt;br /&gt;&lt;img src="http://3.bp.blogspot.com/_GiRlhVCzImE/S-yLymDCzMI/AAAAAAAAAAM/z2eVl2oHzKs/s640/flickr-stats.png" /&gt;&lt;br /&gt;&lt;h3&gt;Clarifications&lt;/h3&gt; &lt;p&gt;Despite the title of the reddit entry, I have nothing against Christians. Further, I count myself as one. So if you really want to take a piss at people who are calling Christians evil, don't aim at me. Thanks.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Moreover, I don't think those people were evil, or even horrible (though I did use that word in the heat of the moment). A loved one had just died, and &lt;i&gt;everyone&lt;/i&gt; was in pain.  Death &lt;b&gt;SUCKS&lt;/b&gt;, and it was a bad situation no matter how you slice it. I don't hate those people for trying to erase my friend though, I pity them. I pity the fact that they turned down the chance to mourn the passing of their loved one by crying on another loved one's shoulder. I pity the fact that they didn't get nearly the closure that my friend did. I pity them for willingly becoming victims of their own grief.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;The rest is between them and God.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1234953837283832282-2012613328090586970?l=blog.golemon.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.golemon.com/feeds/2012613328090586970/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.golemon.com/2009/06/slashdotted-post-mortem.html#comment-form' title='9 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1234953837283832282/posts/default/2012613328090586970'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1234953837283832282/posts/default/2012613328090586970'/><link rel='alternate' type='text/html' href='http://blog.golemon.com/2009/06/slashdotted-post-mortem.html' title='Slashdotted; Post-mortem'/><author><name>Sara Golemon</name><uri>http://www.blogger.com/profile/14557640555210645219</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_GiRlhVCzImE/S-yLymDCzMI/AAAAAAAAAAM/z2eVl2oHzKs/s72-c/flickr-stats.png' height='72' width='72'/><thr:total>9</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1234953837283832282.post-5331687903367167725</id><published>2009-06-05T12:41:00.000-07:00</published><updated>2010-05-13T16:25:59.525-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='schadenfreude'/><category scheme='http://www.blogger.com/atom/ns#' term='death'/><category scheme='http://www.blogger.com/atom/ns#' term='epic'/><category scheme='http://www.blogger.com/atom/ns#' term='win'/><category scheme='http://www.blogger.com/atom/ns#' term='catholicism wow'/><category scheme='http://www.blogger.com/atom/ns#' term='queer'/><title type='text'>Wait, did you seriously just say that?</title><content type='html'>&lt;p&gt;I grew up in California, and my state is pretty well true to it's reputation of being....less conservative than average. Granted, I've been harassed, shunned, even outright beaten over being queer, but I always thought that when it comes to certain things, especially family, there's a line that just isn't crossed. This is why the events of the past weekend so thoroughly amazed me.&lt;/p&gt;&lt;p&gt;Several months ago, when she told me that her mother had Cancer, I promised my kinda-ex-nevermind-it's-complicated-girlfriend that when the time came, I'd jump on a plane and fly out to the Midwest to help her bury her mom. So it was, that when she called me from Toronto (she was in the middle of a business trip), I booked a one-way flight (we weren't sure how long things would take), and flew off to Cleveland to meet her and offer my sympathies.&lt;/p&gt;&lt;p&gt;Death is hard, no matter how prepared for the end you are, but for my friend it was doubly difficult. For the past four years, she'd only rarely been able to see her mom, due to both distance and conflict between her and other people in her mother's family. We'd hoped that in the darkness of losing a loved one, those hard feelings and prejudices could be set aside, that family could come together for just one day to share grief and say good-bye. We were unbelievably wrong...&lt;/p&gt;&lt;p&gt;We landed together at CLE on friday night and headed over to her dad's house (her parents had been long divorced). He greeted us, filled her in on the past few months and her mother's last days, and we left feeling the weight of the occasion, but ready to grieve. On the way out, her sister called saying, "Some of the family have asked that you don't show up to the viewing. They say you can come into the funeral home for a few minutes afterward, but not during the general viewing."&lt;/p&gt;&lt;p&gt;I know, take a minute to absorb that statement. Who are these family members? Vague mumbles always answered this question, but they were certainly not going to tolerate my friend's presence. We resolved to call around the next day...&lt;/p&gt;&lt;p&gt;It was Saturday and the obituary had come out. Anachronistic newsprint mourned the loss of a sainted mother to my friend's sister, "special mother" to my friend's ex-spouse, but no mention of my friend. &lt;b&gt;They had simply erased her&lt;/b&gt;, with a nod to her ex as a special kind of insult.&lt;/p&gt;&lt;p&gt;My friend called her sister back, wanting to understand how so much animosity could survive and flourish like that. She wasn't going to be erased, so she told her sister that the family could just deal with the fact that she &lt;i&gt;would&lt;/i&gt; be present at the viewing. It was her mother that'd died, and she intended to say good-bye. A few hours later, news had filtered through to her step-father who called and delivered a matter-of-fact edict. "Here's your options, and I'm only going to say this once. You can come at 7, after everyone else is done, and take your 15 minutes to say good-bye, or you can not come at all. I'll have a cop at the door to make sure of that. *click*"&lt;/p&gt;&lt;p&gt;Yes, you heard that right, he was hiring an off-duty police officer to keep her out of her own mother's services.&lt;/p&gt;&lt;p&gt;And before you ask, yes, her step-father had that legal right, as the funeral home was private property contracted by him. So it was, that the next day, we (My friend, another friend of her's, and myself), drove to a shopping center near the funeral home and parked where our cars couldn't be identified and vandalized, and we walked to the funeral home at the official start time. Sure enough, a uniformed police officer stood guard at the entrace.&lt;/p&gt;&lt;br /&gt;&lt;h3&gt;Arriving&lt;/h3&gt; &lt;p&gt;We sent in the third member of our party, as she comes off much less threatening than I, and hadn't been explicitly told not to show up. She went inside, and formally asked the funeral home's director (with the step-father standing nearby), if we could be allowed inside. "Oh my God! They're here! They're here!", I wasn't present, of course, but I'm told the step-father reacted like we'd just stormed the beach at Normandy. "Those people are not to be allowed inside under any circumstances!", the funeral director could only agree with his client's request, so our other friend walked back to the sidewalk, where we sat down and initiated project Ghandi.&lt;/p&gt;&lt;p&gt;Okay, we didn't have any clever name for it at the time, but the premise was simple enough. We were in a labor state where the right to strike is sacrosanct. Being a public easement, we knew we were in our legal rights to remain there. This was the crux moment. Although we had legal rights, the police officer could have trumped up a reason to remove us for the duration of the ceremony, and we'd have lost our gamble completely, but he just stood at the door, showing no hint of emotion of sympathies for either side. A credit to his uniform.&lt;/p&gt;&lt;p&gt;I'm told, from those who were inside, that the step-father was yelling at the cop to have us removed and/or arrested. The cop answered that we were on public grounds and not causing a disturbance, so there was nothing he could do. I'm told he would get up every 15 minutes to look out the window and see if we were still there. We were. I'm told he called the police department to have additional officers sent around to "round us up", each new arrival told him the same story, no laws were being broken.&lt;/p&gt;&lt;br /&gt;&lt;h3&gt;The challenge&lt;/h3&gt; &lt;p&gt;About half an hour into the services, we were approached by the ex, who calmly flipped through the binder full of memories my friend had brought with her. They hugged, but didn't say much... What can be said at that point? Then my friend's ex-mother-in-law came over and just as I thought we were going to see another calm, but sad episode of sharing... "&lt;i&gt;You know, you brought this on yourself.&lt;/i&gt;"&lt;/p&gt;&lt;p&gt;I felt numb for a moment. I couldn't possibly have heard that come out of her mouth, not with my friend's mother lying in a casket 20 feet away... My friend managed to utter, "No", then turned away and began crying. "Yes, you did. You brought this on yourself." Our other friend interjected, "That's really not necessary..." "Yes it is", the mother in law replied, "this situation is because of her actions..."&lt;/p&gt;&lt;br /&gt;&lt;p&gt;She didn't get to finish that sentence. Something inside me snapped and a wellspring of rage came over me. I stood directly in front of the MiL, and found the most even temped voice I could manage, "Ma'am, I understand that you've just lost someone dear to you. I understand that you're in pain, and I understand that you think you're doing good, so I'm going to try to say this in the nicest way possible.", from here, my decorum ran out of rehearsed speeches and my rage took over, "You are an unchristian, bad...bad... Horrible person."&lt;/p&gt;&lt;p&gt;"No she isn't.", I heard from my firend's ex, but I ignored that. I stared at, and through her MiL, almost wanting a physical confrontation. "Sara..." The plaintive caution of our other friend snapped me out of my anger and I stepped away, andrenaline thundering through my blood. The MiL gave up trying to berate my friend and began to walk away. "I'm sorry", I offered, "That was unnecessary and uncalled for, I apologize." I don't remember much of the next several minutes, as my stress level slowly calmed down.&lt;/p&gt;&lt;p&gt;"Thank you", my friend told me. "I needed some strength right there and that's exactly what you gave me." After a moment she smiled, "You did unload on her a bit though...". "Yeah", I smiled back, "I was killing a few of my own demons there at the same time, might've over-estimated the firepower...&lt;/p&gt;&lt;p&gt;Soon afterward, her step-grandmother came around. "Why don't you just leave? You've making a spectacle of your mother's viewing!" She continued and I held myself back as long as I could. My friend held her own against this onslaught much better, continually drawing the conversation back to her mother, and trying to remember the best of her mother and focus on the mourning of her passing. The step-grandmother continued to catalouge all the (made-up) offenses my friend had allegedly committed against the family (all of which were thinly veiled reproachments for her queerness), until I spoke up, asking her if Jesus taught forgiveness, "Yes, BUT... we someone, when you have, when the person that has brought you into this world..." Honestly, even though I captured video of the entire event, I couldn't tell you for certain what she said as her argument descended and crashed into incoherency. Eventually she threw her hands up and walked away. Our other friend looked at me a little dumb-founded... "That... Was almost a thing of beauty the way she fell apart..." Yeah, I felt a little guilty at the efficacy of it too....&lt;/p&gt;&lt;br /&gt;&lt;h3&gt;Redemption&lt;/h3&gt; &lt;p&gt;Next up, was my friend's cousin. "What are y'all doing out here? Aren't you coming inside?" We told him what the step-father had said. His curious smile fell into disbelief, then anger rose in his face until his aura throbbed a dark crimson red. "That's ridiculous, I'll be right back." He stormed inside, and I'm told he raised holy hell on our behalf. Shortly thereafter, several more family members came out until there was all but a line queuing up around my friend to console her and share grief over her mother's death. For myself, I began to worry that we'd start to qualify as an unruly mob and give the police something to raise a fuss about. Nothing happened though, I think I even saw the cop smile.&lt;/p&gt;&lt;h3&gt;Vindication&lt;/h3&gt; &lt;p&gt;Eventually her mother's nurse, who was no part of the family, pulled my friend aside. "I only knew your mother for a few months, but she told me things about you in that time. Good things.", and she proceeded to list off things that she couldn't have made up. Things that proved to my friend that her mother really had loved her at the end, but was too afraid to show it.&lt;/p&gt;&lt;p&gt;My friend visibly brightened after that. As though she'd let go of something sour and offal. A few more hours passed in the pleasant late-spring weather. People came out and went back in, arrived and departed, noone else said an unkind word after her step-grandmother. Finally, when the funeral home was nearly empty, the cop approached us, "The funeral director's told me it's okay for you to come in now. I'm sorry for your loss." We thanked him and shook his hand and made our way inside. The step-father and other naysayers were nowhere to be seen, but there at the end of an array of fold-out chairs, was my friend's mother.&lt;/p&gt;&lt;br /&gt;&lt;h3&gt;A poetic ending&lt;/h3&gt; &lt;p&gt;I won't go into the details of her weeping, but she cried out the last of her grief. After hours of sharing, but not having access to the body, my friend had excised the worst of her grief already. She had prepared herself and found the peace she needed to see her mother's still form. For all her step-father's machinations and attempts to rob her of her mother and her place in her family, my friend was able to grieve her mother's passing in a way that couldn't possibly have been any better or more complete. If we had been inside the whole time, the shock of seeing her with so many unresolved things would have been devastating. If we had simply taken orders and not shown up until the last few minutes, there would not have been nearly enough time, and there would have been no family to lean on. By standing on the sidewalk, we took away that power, we reclaimed it as our own, and we amplified it even further. We said good-bye.&lt;/p&gt;&lt;p&gt;And the naysayers?  They just looked like monsters.  Love: 1, Hate: 0; Schadenfreude, I haz it.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1234953837283832282-5331687903367167725?l=blog.golemon.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.golemon.com/feeds/5331687903367167725/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.golemon.com/2009/06/wait-did-you-seriously-just-say-that.html#comment-form' title='8 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1234953837283832282/posts/default/5331687903367167725'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1234953837283832282/posts/default/5331687903367167725'/><link rel='alternate' type='text/html' href='http://blog.golemon.com/2009/06/wait-did-you-seriously-just-say-that.html' title='Wait, did you seriously just say that?'/><author><name>Sara Golemon</name><uri>http://www.blogger.com/profile/14557640555210645219</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>8</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1234953837283832282.post-6481754090518525902</id><published>2009-01-08T23:16:00.000-08:00</published><updated>2010-08-04T10:48:18.226-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='yahoo'/><category scheme='http://www.blogger.com/atom/ns#' term='audio'/><title type='text'>Yahoo!, doing something right!</title><content type='html'>&lt;p&gt;I love it when Yahoo! manages to just &lt;b&gt;get something right&lt;/b&gt;.  Checkout the awesome sauce of a &lt;a href="http://mediaplayer.yahoo.com/"&gt;media player&lt;/a&gt; widget.  By doing &lt;i&gt;nothing more&lt;/i&gt; than linking to an external script.  All three of these P3 podcasts become magically playable directly from my blog.&lt;/p&gt; &lt;ul&gt;&lt;li&gt;&lt;a href="http://devzone.zend.com/content/audio/zendcon_sessions/zendcon_sessions_podcast_022.mp3"&gt;ZendCon 2008, PHP Extension Writing&lt;/a&gt; (Apologies for the gay-disco lead-in)&lt;/li&gt;&lt;li&gt;&lt;a href="http://c7y.phparch.com/c/attachment/1/p3,20060602/external/20060602.mp3"&gt;Interview following php|tek 2006&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://c7y.phparch.com/c/attachment/1/p3,20070531/external/20070531.mp3"&gt;Guest hosting for the newscast&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://c7y.phparch.com/c/attachment/1/p3,20071018/external/20071018.mp3"&gt;Ramblecast 2.0&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;Click the play buttons, but don't forget to notice the little slide-out player in the lower-left corner.  Swanky, n'est-ce pas?&lt;/p&gt;&lt;script src="http://mediaplayer.yahoo.com/js" type="text/javascript"&gt;&lt;/script&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1234953837283832282-6481754090518525902?l=blog.golemon.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.golemon.com/feeds/6481754090518525902/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.golemon.com/2009/01/yahoo-doing-something-right.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1234953837283832282/posts/default/6481754090518525902'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1234953837283832282/posts/default/6481754090518525902'/><link rel='alternate' type='text/html' href='http://blog.golemon.com/2009/01/yahoo-doing-something-right.html' title='Yahoo!, doing something right!'/><author><name>Sara Golemon</name><uri>http://www.blogger.com/profile/14557640555210645219</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1234953837283832282.post-2220063454745699688</id><published>2008-12-30T20:49:00.000-08:00</published><updated>2010-05-13T16:16:37.859-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='yahoo'/><category scheme='http://www.blogger.com/atom/ns#' term='php'/><category scheme='http://www.blogger.com/atom/ns#' term='lookback'/><title type='text'>2008 Lookback</title><content type='html'>&lt;p&gt;It's been a helluva year... No, seriously, it's been... unique.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Last &lt;b&gt;January&lt;/b&gt;, I started off the year with a presentation at &lt;a href="http://geeksessions.com/"&gt;geekSessions-1.3&lt;/a&gt;, along with some associated "hanging-out" in San Francisco (a city I normally avoid, because I dislike large crowds of people). I also got a brand new insulin pump to replace the seven year old beast who's LCD display had finally died. The pump itself didn't die (kudos to Medtronic for that), just the display. I've enjoyed my new "pocket pancreas" about as much as the old one, though of course the incremental improvements to its design haven't gone unappreciated.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;February&lt;/b&gt; was a fairly quiet month for me professionally. A mixup in some of my medications (not related to the new pump), left me really distracted and irritable. The medications have been sorted, but I got to &lt;i&gt;like&lt;/i&gt; the fear I induced in my coworker's eyes to the point that I keep up the show for appearances sake. :)&lt;/p&gt; &lt;p&gt;&lt;b&gt;March&lt;/b&gt; was a flurry of activity getting things sorted at home and at work so that I could take a much needed month off in &lt;b&gt;April&lt;/b&gt;.  This month would ultimately turn into a mere three weeks since I refuse to relax, but it was time well spent anyway.  During &lt;b&gt;March&lt;/b&gt; I met two new friends who I've since come to appreciate deeply, and in &lt;b&gt;April&lt;/b&gt; I got to spend a lot of time with my grandma; Something I do far too little of.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;b&gt;May&lt;/b&gt; saw the launch of &lt;a href="http://developer.search.yahoo.com/"&gt;Yahoo! Search Monkey&lt;/a&gt; move into full swing, bringing a lot of time and effort by the entire Search team along with it. As part of the launch, we held a developer event in Sunnyvale, and I learned that if you blog &lt;strike title="wow, bad choice of words..."&gt;long and hard&lt;/strike&gt; enough, random strangers will eventually &lt;a href="http://saragolemon.blogspot.com/2008/05/i-have-officially-arrived.html"&gt;show you naked pictures of themselves&lt;/a&gt;.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;b&gt;June&lt;/b&gt; was a hard month to handle. My wife of more than 10 years got herself a 1 bedroom apartment and moved out. We're both feeling the repercussions of that, and while reconciliation is a possibility, we really haven't fixed any of the things were wrong with our relationship. See, we're just as F-ed up as a straight couple, but with twice the estrogen! It was also at this time that my grandfather's cancer took a turn for the worse and he found himself spending a great deal of time in ICU. His children and grandchildren did their best to avoid feeling useless as we waited outside him room, not sure if he was going to pull out of it...&lt;/p&gt;&lt;br /&gt;&lt;p&gt;In &lt;b&gt;July&lt;/b&gt;, my grandfather was feeling good enough that we threw a small party for my cousin's graduation, and brought him along for what we all knew was going to be his last summer. There was a lot of smiling outdoors and crying in the bathroom. During this party my grandfather pulled me aside and gave me a gift that... I'm not even sure he understood how much it meant to me... My sister took photos, and we all doted a bit more than we should have, but we built a new memory around him that we can carry with us.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Having managed some pretty downer months so far this summer, I took a week at the end of &lt;b&gt;August&lt;/b&gt; to take a &lt;i&gt;real&lt;/i&gt; vacation to south Utah where I went hiking with four complete strangers I'd met over the internet. Hrmmm... desert... strangers... dangerous climbs? Not the most sane thing I've ever done, but I made some really good friendships that'll last for years to come, and if all goes well, I'll be taking another trip with them this coming June, back to Zion National Park.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;b&gt;September&lt;/b&gt; saw &lt;a href="http://zendcon.com/"&gt;ZendCon08&lt;/a&gt; and &lt;a href="http://phpappalachia.org/"&gt;PHP Appalachia&lt;/a&gt;, the latter of which spawned far too many anecdotes about the rowdiness of the PHP community. Where should I start? The semi-naked toxic hot tub? The jagged piece of glass that Chris tried to kill Ben with but got stuck in Cal's foot instead? The fire department we bribed with a cute blonde? Nonono, what happens in Pigeon Forge, stays in Pigeon Forge...&lt;/p&gt;&lt;br /&gt;&lt;p&gt;In &lt;b&gt;October&lt;/b&gt;, my grandfather fell ill again, holding on just long enough to say good-bye to his children and grandchildren. Sadly his great-grandchildren aren't likely to remember him very well, but thankfully I know that my last words to him were, "I love you", and at least he went quickly. We can all hope for so much when out time eventually comes.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;b&gt;November&lt;/b&gt; led to another rowdy conference get together.  This time it was &lt;a href="http://phparch.com/"&gt;php|works&lt;/a&gt; in Atlanta, GA, and I dunno about you, but Marco &lt;i&gt;really&lt;/i&gt; needs to stop letting me near the open bar. I'm not a frequent drinker, so my tolerance is really very low, and I do... unconventional things when I've had my ninth vodka/cranberry... Doesn't hurt that the bartender was &lt;i&gt;very&lt;/i&gt; generous... Oh well, at least I didn't throw up in the taxi on the way to Cal's going-away party. ((Note: I didn't say who did... assuming anyone did... which I didn't say either...))&lt;/p&gt;&lt;br /&gt;&lt;p&gt;And oh yeah... the election... biggest sack full of mixed emotions in a long time... Okay, sure, let me get it out, YAY! Obama won. I have HUGE hopes for this guy, and given what I've seen of his transition process, I think he &lt;i&gt;might&lt;/i&gt; just stand a chance of living up to his hype.  &lt;b&gt;YES. WE. CAN.&lt;/b&gt; There, now that that's out of my system, I can go back to being really dissapointed in the One Million californians who voted in favor of Proposition 8. I can go back to slamming my face into the desk whenever I hear the &lt;b&gt;FALSE&lt;/b&gt; argument that equal marriage rights will lead to sodomy in the streets and pedophilia in the classrooms. I can go back to being disappointed by my fellow Christians who call homosexuality &lt;a href="http://www.americamagazine.org/blog/entry.cfm?blog_id=2&amp;amp;id=603830D3-1438-5036-4F5E0C8022A6327E"&gt;as significant a threat to humanity as global warming&lt;/a&gt; and &lt;a href="http://www.bgay.com/news/index.php?option=com_content&amp;amp;task=view&amp;amp;id=85&amp;amp;Itemid=23"&gt;a threat to world peace&lt;/a&gt;.  That's not just any Christian saying that by the way, that's the ever-lovin' POPE.&lt;/p&gt;&lt;br /&gt; &lt;p&gt;And then here it is: &lt;b&gt;December&lt;/b&gt;. My wife and I are talking about getting back together, though I'm not sure we're making progress... I'm doing my best to focus back on my work. I've gotten back into rock climbing, and am eagerly awaiting the snow season to start in earnest. I got up to my dad's for another Christmas with the family, strained by not having gramps around, but I can tell my dad's trying to step up and fill the patriarchal void that's been left. I've spent the past week fighting off a cold and baking cookies. Tomorrow I'll head back into the office and get some work done before having friends over for a new year's eve bash. On thursday, it'll all start over again...&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Happy new year.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1234953837283832282-2220063454745699688?l=blog.golemon.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.golemon.com/feeds/2220063454745699688/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.golemon.com/2008/12/2008-lookback.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1234953837283832282/posts/default/2220063454745699688'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1234953837283832282/posts/default/2220063454745699688'/><link rel='alternate' type='text/html' href='http://blog.golemon.com/2008/12/2008-lookback.html' title='2008 Lookback'/><author><name>Sara Golemon</name><uri>http://www.blogger.com/profile/14557640555210645219</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1234953837283832282.post-5162680721027196658</id><published>2008-05-15T23:26:00.000-07:00</published><updated>2010-05-13T16:11:18.966-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='fail'/><category scheme='http://www.blogger.com/atom/ns#' term='work'/><category scheme='http://www.blogger.com/atom/ns#' term='yahoo'/><category scheme='http://www.blogger.com/atom/ns#' term='win'/><category scheme='http://www.blogger.com/atom/ns#' term='what is wrong with men?'/><category scheme='http://www.blogger.com/atom/ns#' term='search'/><category scheme='http://www.blogger.com/atom/ns#' term='php'/><category scheme='http://www.blogger.com/atom/ns#' term='book'/><title type='text'>I have officially arrived</title><content type='html'>&lt;p&gt;I was at the &lt;a href="http://developer.yahoo.com/searchmonkey/event.html/"&gt;Search Monkey Developer Launch&lt;/a&gt; tonight to answer questions and give demos to the attendees. The event itself was a nice success, but that's not what I'm writing about. What I'm writing about is one particular attendee. Apologies to this guy if I embarrass him, but he had to know I'd say something.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;After getting through the initial queue of developers asking about Search Monkey, I was approach by a tall young man:&lt;/p&gt; &lt;blockquote style="font-size: small"&gt;&lt;pre&gt;&amp;lt;guy&amp;gt; Hey, you're Sara Golemon, right?&lt;br /&gt;&amp;lt;me&amp;gt;  Yeah...&lt;br /&gt;&amp;lt;guy&amp;gt; Nice to meet you, I really like your blog entries about how PHP works,&lt;br /&gt;     and I bought your book!&lt;br /&gt;&amp;lt;me&amp;gt;  Oh fantastic! Are you enjoying it?&lt;br /&gt;&amp;lt;guy&amp;gt; Yeah, it's really heavy, and I haven't had a chance to use a lot,&lt;br /&gt;     but I was experimenting with writing my own libssh2 wrapper...&lt;br /&gt;&lt;/pre&gt;&lt;/blockquote&gt; &lt;p&gt; By this point, I'm suitably blushing. I'm easily swayed by compliments thanks to my lack of self-esteem. Then he takes a turn... &lt;/p&gt;&lt;blockquote&gt;&lt;pre&gt;&amp;lt;guy&amp;gt; I almost emailed this to you, it's a photo my girlfriend took of me without warning...&lt;br /&gt;     Let me just find it in my camera&lt;br /&gt;* guy shows photo of himself lying in a water-filled bathtub, naked, covering his... bits&lt;br /&gt;     with a copy of my book&lt;br /&gt;&lt;/pre&gt;&lt;/blockquote&gt; &lt;p&gt;I... um... well... okay... I can see why you wouldn't email that out of the blue.... Now, I try to think of myself as a fairly progressive, hard-to-phase sort. I can tell a dirty joke with the best of 'em, but this just... left me giggly for the next hour. Like, um...wow... okay... Thanks for sharing...&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Is this a sign?  Is it a measure of notoriety when strangers show you naked photos of themselves at random tech gatherings?&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1234953837283832282-5162680721027196658?l=blog.golemon.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.golemon.com/feeds/5162680721027196658/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.golemon.com/2008/05/i-have-officially-arrived.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1234953837283832282/posts/default/5162680721027196658'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1234953837283832282/posts/default/5162680721027196658'/><link rel='alternate' type='text/html' href='http://blog.golemon.com/2008/05/i-have-officially-arrived.html' title='I have officially arrived'/><author><name>Sara Golemon</name><uri>http://www.blogger.com/profile/14557640555210645219</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1234953837283832282.post-2354185950912853844</id><published>2008-01-19T01:59:00.000-08:00</published><updated>2011-04-14T01:10:30.409-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='opcode'/><category scheme='http://www.blogger.com/atom/ns#' term='lexer'/><category scheme='http://www.blogger.com/atom/ns#' term='zend'/><category scheme='http://www.blogger.com/atom/ns#' term='php'/><category scheme='http://www.blogger.com/atom/ns#' term='compiler'/><title type='text'>Understanding Opcodes</title><content type='html'>&lt;p&gt;A blog reader (I have readers???) recently shared his wishlist, "&lt;i&gt;I'm trying to figure out how to show the opcodes like you have in your post...&lt;/i&gt;".  I promised that I'd throw something together, so here it is:&lt;/p&gt;&lt;br /&gt;&lt;h3&gt;Slow down, wtf is an "Opcode"?&lt;/h3&gt; &lt;p&gt;Short answer: It's the compiled form of a PHP script, similar in principle to Java bytecode or .NET's MSIL. For example, say you've got the following bit of PHP script:&lt;/p&gt;&lt;blockquote style="font-size: small"&gt; &lt;pre&gt;&amp;lt;?php&lt;br /&gt; echo "Hello World";&lt;br /&gt; $a = 1 + 1;&lt;br /&gt; echo $a;&lt;br /&gt;&lt;/pre&gt; &lt;/blockquote&gt; &lt;p&gt;PHP (and it's actual compiler/executor component, the Zend Engine)  are going to go through a multi-stage process: &lt;/p&gt;&lt;ol&gt;&lt;li&gt;Scanning (a.k.a. Lexing) - The human readable source code is turned into tokens.&lt;/li&gt;&lt;li&gt;Parsing - Groups of tokens are collected into simple, meaningful expressions.&lt;/li&gt;&lt;li&gt;Compilation - Expressions are translated into instruction (opcodes)&lt;/li&gt;&lt;li&gt;Execution - Opcode stacks are processed (one opcode at a time) to perform the scripted tasks.&lt;/li&gt;&lt;/ol&gt; Side note: Opcode caches (like &lt;a href="http://pecl.php.net/package/APC"&gt;APC&lt;/a&gt;), let the engine perform the first three of these steps, then store that compiled form so that the next time a given script is used, it can use the stored version without having to redo those steps only to come to the same result. &lt;br /&gt;&lt;h3&gt;Er... okay... can you elaborate a little? What's lexing? I thought superman put him in jail...&lt;/h3&gt; &lt;p&gt;That's &lt;b&gt;Lex Luthor&lt;/b&gt; you nit-wit!  The most expedient way to explain lexing is by example.  Take a look at the manual page for &lt;a href="http://php.net/function.token-get-all"&gt;token_get_all()&lt;/a&gt;, this gem is actually a wrapper around the Zend Engine's own language scanner. Play around with it a bit, and you'll notice that plugging the short script above into it will produce:&lt;/p&gt; &lt;blockquote style="font-size: small"&gt; &lt;pre&gt;Array&lt;br /&gt;(&lt;br /&gt;   [0] =&gt; Array&lt;br /&gt;       (&lt;br /&gt;           [0] =&gt; 367&lt;br /&gt;           [1] =&gt; &amp;lt;?php&lt;br /&gt;       )&lt;br /&gt;   [1] =&gt; Array&lt;br /&gt;       (&lt;br /&gt;           [0] =&gt; 316&lt;br /&gt;           [1] =&gt; echo&lt;br /&gt;       )&lt;br /&gt;   [2] =&gt; Array&lt;br /&gt;       (&lt;br /&gt;           [0] =&gt; 370&lt;br /&gt;           [1] =&gt;&lt;br /&gt;       )&lt;br /&gt;   [3] =&gt; Array&lt;br /&gt;       (&lt;br /&gt;           [0] =&gt; 315&lt;br /&gt;           [1] =&gt; "Hello World"&lt;br /&gt;       )&lt;br /&gt;   [4] =&gt; ;&lt;br /&gt;   [5] =&gt; Array&lt;br /&gt;       (&lt;br /&gt;           [0] =&gt; 370&lt;br /&gt;           [1] =&gt;&lt;br /&gt;       )&lt;br /&gt;   [6] =&gt; =&lt;br /&gt;   [7] =&gt; Array&lt;br /&gt;       (&lt;br /&gt;           [0] =&gt; 370&lt;br /&gt;           [1] =&gt;&lt;br /&gt;       )&lt;br /&gt;   [8] =&gt; Array&lt;br /&gt;       (&lt;br /&gt;           [0] =&gt; 305&lt;br /&gt;           [1] =&gt; 1&lt;br /&gt;       )&lt;br /&gt;   [9] =&gt; Array&lt;br /&gt;       (&lt;br /&gt;           [0] =&gt; 370&lt;br /&gt;           [1] =&gt;&lt;br /&gt;       )&lt;br /&gt;   [10] =&gt; +&lt;br /&gt;   [11] =&gt; Array&lt;br /&gt;       (&lt;br /&gt;           [0] =&gt; 370&lt;br /&gt;           [1] =&gt;&lt;br /&gt;       )&lt;br /&gt;   [12] =&gt; Array&lt;br /&gt;       (&lt;br /&gt;           [0] =&gt; 305&lt;br /&gt;           [1] =&gt; 1&lt;br /&gt;       )&lt;br /&gt;   [13] =&gt; ;&lt;br /&gt;   [14] =&gt; Array&lt;br /&gt;       (&lt;br /&gt;           [0] =&gt; 370&lt;br /&gt;           [1] =&gt;&lt;br /&gt;       )&lt;br /&gt;   [15] =&gt; Array&lt;br /&gt;       (&lt;br /&gt;           [0] =&gt; 316&lt;br /&gt;           [1] =&gt; echo&lt;br /&gt;       )&lt;br /&gt;   [16] =&gt; Array&lt;br /&gt;       (&lt;br /&gt;           [0] =&gt; 370&lt;br /&gt;           [1] =&gt;&lt;br /&gt;       )&lt;br /&gt;   [17] =&gt; ;&lt;br /&gt;)&lt;br /&gt;&lt;/pre&gt; &lt;/blockquote&gt; &lt;p&gt;In the array returned by token_get_all(), you have two types of tokens: Single character non-label characters are returned as just that. The character that was found in the source file at that point. Everything else, from labels, to language constructs, to multi-character operators (like &gt;&gt;, +=, etc...) are returned as an array containing two elements: The token ID (which corresponds to T_* constants -- e.g. T_ECHO, T_STRING, T_VARIABLE, etc...), and the actual text which that token came from. What the engine actually gets is slightly more detailed than what you see in the output from token_get_all(), but not by much...&lt;/p&gt;  &lt;h3&gt;Okay, tokenization just breaks the script into bite-size pieces, how does parsing work then?&lt;/h3&gt;  &lt;p&gt;The first thing the parser does is throw away all whitespace (Unlike some other P* language...). From the reduced set of tokens, the engine looks for irreducible expressions. How many expressions do you see in the example above? Did you say three? &lt;b&gt;WRONG&lt;/b&gt;  There are three &lt;i&gt;statements&lt;/i&gt;, but one of those statements is made of two distinct expressions.  In the case of &lt;span style="font-family: courier;"&gt;$a = 1 + 1;&lt;/span&gt; the first expression is the addition, followed by the assignment to the variable as a second, distinct expression. All together our expression list is: &lt;/p&gt;&lt;ol&gt;&lt;li&gt;echo a constant string&lt;/li&gt;&lt;li&gt;add two numbers together&lt;/li&gt;&lt;li&gt;store the result of the prior expression to a variable&lt;/li&gt;&lt;li&gt;echo a variable&lt;/li&gt;&lt;/ol&gt;  &lt;h3&gt;Hey! That's starting to sound familiar! Did I see that kind of description before?&lt;/h3&gt;  &lt;p&gt;Oh, you must mean my post about &lt;a href="http://blog.golemon.com/2006/06/how-long-is-piece-of-string.html"&gt;strings&lt;/a&gt; (plug). That's correct, because these expressions are exactly the pieces which go into making up oplines! Given the expression list we've just reached, the resulting opcodes look something like: &lt;/p&gt;&lt;ul&gt;&lt;li&gt;ZEND_ECHO            'Hello World'&lt;/li&gt;&lt;li&gt;ZEND_ADD       ~0    1    1&lt;/li&gt;&lt;li&gt;ZEND_ASSIGN  !0    ~0&lt;/li&gt;&lt;li&gt;ZEND_ECHO    !0&lt;/li&gt;&lt;/ul&gt;  &lt;h3&gt;What happened to $a?  What's the difference between ~0 and !0?&lt;/h3&gt;  &lt;p&gt;Short answer: !0 &lt;b&gt;is&lt;/b&gt; $a&lt;/p&gt;&lt;br /&gt;&lt;p&gt;So here's the deal.... oplines have five principle parts:&lt;/p&gt; &lt;ul&gt;&lt;li&gt;&lt;b&gt;Opcode&lt;/b&gt; - Numeric identifier which distinguishes what the opline will do.  This is what coresponds to ZEND_ECHO, ZEND_ADD, etc...&lt;/li&gt;&lt;li&gt;&lt;b&gt;Result Node&lt;/b&gt; - Most opcodes perform "non-terminal" actions. That is; after executing there's some result which can be consumed as an input to a later opline. The result node identifies what temporary location to place the result of the operation in.&lt;/li&gt;&lt;li&gt;&lt;b&gt;Op1 Node&lt;/b&gt; - One of two inputs to the given opcode. An input may be a constant zval, a reference to a previous result node, a simple variable (CV), or in some cases a "special" data element, such as a class definition. Note that an opcode may use both, one, or neither input node. (Some even use more, see ZEND_OPDATA)&lt;/li&gt;&lt;li&gt;&lt;b&gt;Op2 Node&lt;/b&gt; - Ditto&lt;/li&gt;&lt;li&gt;&lt;b&gt;Extended Value&lt;/b&gt; - Simple integer value used to differentiate specific behaviors of an overloaded opcode.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;p&gt;So obviously the nodes are the most complicated parts of an opline, here's the important parts of what they look like:&lt;/p&gt; &lt;ul&gt;&lt;li&gt;&lt;b&gt;op_type&lt;/b&gt; - One of IS_CONST, IS_TMP_VAR, IS_VAR, IS_UNUSED, or IS_CV&lt;/li&gt;&lt;li&gt;&lt;b&gt;u&lt;/b&gt; - A union of the following elements (the one which is used depends on the value of op_type):     &lt;ul&gt;&lt;li&gt;&lt;b&gt;constant&lt;/b&gt; (IS_CONST) - zval value. This node results which you include a literal value in your script, such as the 'Hello World' or 1 values in the example above.&lt;/li&gt;&lt;li&gt;&lt;b&gt;var&lt;/b&gt; (IS_VAR or IS_TMP_VAR or IS_CV) - Integer value corresponding to a temporary slot in a lookup table used by the engine.&lt;/li&gt;&lt;/ul&gt;   &lt;/li&gt;&lt;/ul&gt; &lt;p&gt;Now let's look at the difference between those optypes, particularly with respect to u.var:&lt;/p&gt; &lt;ul&gt;&lt;li&gt;&lt;b&gt;IS_TMP_VAR&lt;/b&gt; - These ephemeral values are strictly for use by non-assignment non-terminal expressions. They don't support any refcounting because they're guaranteed not to be shared by any other variable. These are denoted in the examples I use on this site (and in VLD output) as tilde characters (~)&lt;/li&gt;&lt;li&gt;&lt;b&gt;IS_VAR&lt;/b&gt; - Usually the result of a ZEND_FETCH(_DIM|_OBJ)?_(R|W|RW), or one of the assignment opcodes (which are technically non-terminal expressions since they can be used as inputs to other expressions. Since these are tied to real variables, they have to respect reference counting and are passed about at an extra degree of indirection. They're stored in the same table though. These are denoted by the string symbol ($)&lt;/li&gt;&lt;li&gt;&lt;b&gt;IS_CV&lt;/b&gt; - "CV" stands for "Compiled Variables". These are basicly cached hash lookups for fetching simple variables from the local symbol table. Once a variable is actually looked up at runtime, it's stored at an extra level of indirection in an even faster lookup table using an index into a vector. That's what the number in this node denotes. These types of nodes are distinguished by a bang (!)&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;h3&gt;Boggle... You...so lost me there...&lt;/h3&gt; &lt;p&gt;Yeah, that explanation sort of got away from me didn't it?  What can I clear up?&lt;/p&gt;&lt;br /&gt;&lt;h3&gt;All I really want to know is how to translate some source code into an opcode..list...thingy...&lt;/h3&gt; &lt;p&gt;Heh, okay... first off, that "opcode list thingy" is called an op_array, and you can generate those really easily using one of two PECL packages. You can use my &lt;a href="http://pecl.php.net/package/parsekit"&gt;parsekit&lt;/a&gt; package, which is useful for programmatic analysis of script compilation, but frankly... it's not what you're looking for and there's not much call for scripts analyzing other scripts anyway. I recommend Derick's &lt;a href="http://pecl.php.net/package/vld"&gt;VLD (Vulcan Logic Disasembler)&lt;/a&gt; which is what'll actually generate the kinds of opcode lists you'll see me use in blog posts.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Once you've got it installed (it installs like any other PECL extension), you can run it with a command like the following:&lt;/p&gt; &lt;blockquote&gt;&lt;pre&gt;php -d vld.active=1 -d vld.execute=0 -f yourscript.php&lt;br /&gt;&lt;/pre&gt;&lt;/blockquote&gt; &lt;p&gt;Then sit back and watch the opcodes fly! Important note: Using -r with command line code may not work due to a quirk of the way the engire parses files in older versions of PHP (and with older versions of VLD). Be sure to put your script on disk and reference it using -f if -r doesn't work for you.&lt;/p&gt;&lt;br /&gt;&lt;h3&gt;Holy schnikies!  That's a lot of opcodes!  How can I tell what they all do?&lt;/h3&gt; &lt;p&gt;Take a look at Zend/zend_vm_def.h in your PHP source tree. In here you'll find a meta-definition of every single opcode used by the engine. Side note: It's used as a source for zend_vm_gen.php which generates the actual code file zend_vm_execute.h. How's that for chicken and egg? Every version of PHP since 5.1.0 has required PHP be already built in order to build it!&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1234953837283832282-2354185950912853844?l=blog.golemon.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.golemon.com/feeds/2354185950912853844/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.golemon.com/2008/01/understanding-opcodes.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1234953837283832282/posts/default/2354185950912853844'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1234953837283832282/posts/default/2354185950912853844'/><link rel='alternate' type='text/html' href='http://blog.golemon.com/2008/01/understanding-opcodes.html' title='Understanding Opcodes'/><author><name>Sara Golemon</name><uri>http://www.blogger.com/profile/14557640555210645219</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1234953837283832282.post-7744965055596383814</id><published>2008-01-17T22:40:00.000-08:00</published><updated>2010-05-12T12:43:37.906-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='photo'/><category scheme='http://www.blogger.com/atom/ns#' term='hawaii'/><category scheme='http://www.blogger.com/atom/ns#' term='creative commons'/><category scheme='http://www.blogger.com/atom/ns#' term='cats'/><category scheme='http://www.blogger.com/atom/ns#' term='win'/><title type='text'>I'm syndicated, and it has nothing to do with PHP!</title><content type='html'>I was running some test queries using my usual spread of values and came across a result of "&lt;a href="http://www.loe.org/shows/segments.htm?programID=08-P13-00002&amp;amp;segmentID=7"&gt;Lieutenant Fluffy?&lt;/a&gt;" which was far too whimsical a topic to ignore. Turns out someone thought my holiday photos made for a good creative commons pick. Kudos to the news site for respecting licensing terms properly!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1234953837283832282-7744965055596383814?l=blog.golemon.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.golemon.com/feeds/7744965055596383814/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.golemon.com/2008/01/im-syndicated-and-it-has-nothing-to-do.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1234953837283832282/posts/default/7744965055596383814'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1234953837283832282/posts/default/7744965055596383814'/><link rel='alternate' type='text/html' href='http://blog.golemon.com/2008/01/im-syndicated-and-it-has-nothing-to-do.html' title='I&apos;m syndicated, and it has nothing to do with PHP!'/><author><name>Sara Golemon</name><uri>http://www.blogger.com/profile/14557640555210645219</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1234953837283832282.post-2256583879280401635</id><published>2008-01-07T12:14:00.000-08:00</published><updated>2010-05-12T12:41:22.100-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='minimed'/><category scheme='http://www.blogger.com/atom/ns#' term='pump'/><category scheme='http://www.blogger.com/atom/ns#' term='csii'/><category scheme='http://www.blogger.com/atom/ns#' term='diabetes'/><title type='text'>Houston, we have a bolus</title><content type='html'>&lt;p&gt;It took three weeks to filter through &lt;a href="http://www.kp.org/"&gt;Kaiser&lt;/a&gt;, but my new insulin pump finally arrived (the purple one on top in the photo below is the new one). My old pump was about seven years old when it broke down for the second time (the first was under warranty, about four years ago). By the way, the old one *IS* turned on, and you *SHOULD* see something on the display.... Hence my problem... Anyway, I wasn't expecting it till tomorrow, but christmas came early (well, I guess technically late) 'cause the FedEx guy rang the bell just as I was headed out the door for work.&lt;/p&gt;&lt;p&gt;SHINEY!!!!!! I haven't had a decent basal profile in nearly a month, so I ripped open the packaging, read the important parts of the instructions and plugged in.... Ah, that's the stuff... I'm now reading through the rest of the manual, here's my thoughts so far:&lt;/p&gt; &lt;p&gt; &lt;/p&gt;&lt;ul&gt;&lt;li&gt;Batteries: &lt;b&gt;A+&lt;/b&gt; The MiniMed508 takes three Energizer 357s which... while not terribly hard to find, can be pretty annoying when you forget to replace them and the unit shuts down at 1AM... The new 722 fixes that by taking the larger, but more readily available AAA size.&lt;/li&gt;&lt;li&gt;Menus: &lt;b&gt;B&lt;/b&gt; There's more complexity to the menus (driven by a wider feature set), but the most common task (bolusing) is a quick single-button action. &lt;strike&gt;I'd have marked this as an A, but for the fact the bolus amounts no longer wrap-around. Pressing down from 0.0 stays at 0.0, and pressing up from 10.0 stays at 10.0.&lt;/strike&gt;&lt;b&gt;Update&lt;/b&gt;: Turns out the wrap-around does work. You just have to enable it.... Not sure how I enabled it though... Anyway, I'm leaving this at B since the the nag-messages are a bit too insistent... I know what I'm doing damnit... you don't have to be so annoying!&lt;/li&gt;&lt;li&gt;Backlight: &lt;b&gt;C&lt;/b&gt;  Same backlight, still not quite enough contrast...&lt;/li&gt;&lt;li&gt;Delivery mechanics: &lt;b&gt;A&lt;/b&gt; Blatently stolen from Diesetronic (a competitor), but a good steal. Smoother, quicker delivery and a nice resevoir window to boot.&lt;/li&gt;&lt;li&gt;Loading mechanics: &lt;b&gt;A-&lt;/b&gt; The resevoir-vial interface is a tiny bit temperamental, but once I get the knack of it, I expect cartridge loading will be twice as fast and accurate as it used to be. The priming mechanics also manage to overcome one of my long standing gripes about volume detection.&lt;/li&gt;&lt;li&gt;Interface/API: &lt;b&gt;F&lt;/b&gt; Same gripe as I had with the MM508. The system is capable of interfacing with external equipment, but the company won't share anything useful about their specs (I knew this from research before hand, but I can still complain about it).&lt;/li&gt;&lt;li&gt;Durability: &lt;b&gt;TBD&lt;/b&gt; We'll see how this one puts up with my.... abuse is too harsh a word.... "active lifestyle".... Let's go with that... At least it's (supposedly) more water-proof than the old one...&lt;/li&gt;&lt;/ul&gt; &lt;br /&gt;&lt;a href="http://flickr.com/photos/pollita/2176268408/"&gt;&lt;img src="http://farm3.static.flickr.com/2179/2176268408_ea5147dfe8_m.jpg" border="0" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1234953837283832282-2256583879280401635?l=blog.golemon.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.golemon.com/feeds/2256583879280401635/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.golemon.com/2008/01/houston-we-have-bolus.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1234953837283832282/posts/default/2256583879280401635'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1234953837283832282/posts/default/2256583879280401635'/><link rel='alternate' type='text/html' href='http://blog.golemon.com/2008/01/houston-we-have-bolus.html' title='Houston, we have a bolus'/><author><name>Sara Golemon</name><uri>http://www.blogger.com/profile/14557640555210645219</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://farm3.static.flickr.com/2179/2176268408_ea5147dfe8_t.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1234953837283832282.post-1581034862015670583</id><published>2007-09-27T23:31:00.000-07:00</published><updated>2010-05-12T12:38:49.471-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='fail'/><category scheme='http://www.blogger.com/atom/ns#' term='unicode'/><category scheme='http://www.blogger.com/atom/ns#' term='facebook'/><title type='text'>Hey Facebook! What gives?</title><content type='html'>&lt;p&gt;One of the ways in which I prepare for an interview is to research the person I'm going to be interviewing. The first step is to toss their name into one (or more) search engines and see what falls out. Not getting any useful results isn't a negative (many people work on internal stuff with no concern for fame fortune and glory, and they're very good at it), but if I happen to learn a little about them from a blog entry or a profile on a social networking site, then I can direct my questions in a way that more precisely fits the candidate.&lt;/p&gt;&lt;p&gt;So today, I sat down to read through the resumé of an upcoming candidate and punched his name into &lt;a href="http://search.yahoo.com/"&gt;the best damned search engine ever&lt;/a&gt;. What's relatively unique about this candidate is that his name contains an accented character. The search results handled this accented character cleanly of course, and when I followed the first result for "José Smith" (Not his real name -- I'm respecting privacy here), I found myself looking at his &lt;a href="http://www.facebook.com/"&gt;Facebook&lt;/a&gt; profile.  All well and great of course, but then I noticed the URL in the address bar: &lt;u&gt;http://www.facebook.com/Jos_Smith/123456789&lt;/u&gt;.&lt;/p&gt;&lt;p&gt;Jos???  The only Jos I know is a director with a penchant for vampires.&lt;/p&gt;&lt;p&gt;Now, I get not putting the UTF8 or latin1 literal in the URL, browsers don't agree nearly enough on URL encoding to be able to expect it to work reliably. And putting the urlencoded version would just be silly since /Jos%C3%A9_Smith/ looks even uglier. I get that. But what if his name were entirely non-ascii? Perhaps a chinesse name? Would it be so hard to do a transliteration? I seem to recall Derick &lt;a href="http://derickrethans.nl/transliteration_in_use.php"&gt;sharing a few ideas&lt;/a&gt; on the subject a couple years ago...&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1234953837283832282-1581034862015670583?l=blog.golemon.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.golemon.com/feeds/1581034862015670583/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.golemon.com/2007/09/hey-facebook-what-gives.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1234953837283832282/posts/default/1581034862015670583'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1234953837283832282/posts/default/1581034862015670583'/><link rel='alternate' type='text/html' href='http://blog.golemon.com/2007/09/hey-facebook-what-gives.html' title='Hey Facebook! What gives?'/><author><name>Sara Golemon</name><uri>http://www.blogger.com/profile/14557640555210645219</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1234953837283832282.post-7125487907145806870</id><published>2007-09-15T10:41:00.000-07:00</published><updated>2010-05-12T12:36:02.402-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='prank'/><category scheme='http://www.blogger.com/atom/ns#' term='work'/><category scheme='http://www.blogger.com/atom/ns#' term='yahoo'/><title type='text'>Dress Code</title><content type='html'>&lt;h3&gt;The background&lt;/h3&gt; &lt;p&gt;As most know, I work for &lt;a href="http://www.yahoo.com/"&gt;Yahoo!&lt;/a&gt;, the &lt;a href="http://search.yahoo.com/"&gt;US Web Search&lt;/a&gt; front-end team specifically. The company as a whole has (to my knowledge) no more of a dress code than "Don't show up naked". Consequently, most employees, especially those in engineering/operations roles, tend to dress pretty casually. During the summer, this progresses clear into the realm of shorts and sandals.&lt;/p&gt;&lt;p&gt;There's one coworker in our team, Venu, who insists on "dressing for success". Not ultra formal mind you, but we've never seen him wear anything short of a dress shirt, slacks, and nice shoes. At the other end of the spectrum is our boss, Lalit, who has only rarely been seen wearing anything other than shorts (and then, only in the coldest of winters). It was from this, that another coworker, Venkat, hatched his plan.&lt;/p&gt;&lt;br /&gt;&lt;h3&gt;The setup&lt;/h3&gt; &lt;blockquote style="font-size: small"&gt;&lt;pre&gt;To everyone but Lalit:&lt;br /&gt;&lt;venkat&gt; Hey, we should play a prank on Lalit, next monday, everyone should show up in shorts and flip-flops&lt;br /&gt;        to make fun of him for his slacker dressing...&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Meanwhile, to everyone but Venu:&lt;br /&gt;&lt;venkat&gt; Okay, Venu's falling for it, now the REAL prank will be on him.  He'll show up in shorts,&lt;br /&gt;        and the rest of us will dress formally...&lt;br /&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;p&gt;Sure enough, today Venu "the slob" showed up in shorts and some (but not all) the rest of us showed him up in our "business professional" attire. Looking at my towering stature in this photo, I'm doubting the wisdom of wearing heels, but somehow flats just didn't create the right effect ;)&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;center&gt; &lt;a href="http://www.flickr.com/photos/vudayas/1254271679/"&gt;&lt;img src="http://farm2.static.flickr.com/1398/1254271679_abfd50c09e_m_d.jpg" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;span style="font-size: small"&gt;Lalit, Me, Venu, Ryan, Venkat, Nam&lt;/span&gt; &lt;/center&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1234953837283832282-7125487907145806870?l=blog.golemon.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.golemon.com/feeds/7125487907145806870/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.golemon.com/2007/09/dress-code.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1234953837283832282/posts/default/7125487907145806870'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1234953837283832282/posts/default/7125487907145806870'/><link rel='alternate' type='text/html' href='http://blog.golemon.com/2007/09/dress-code.html' title='Dress Code'/><author><name>Sara Golemon</name><uri>http://www.blogger.com/profile/14557640555210645219</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1234953837283832282.post-3076611247164796981</id><published>2007-07-26T20:06:00.000-07:00</published><updated>2010-05-12T12:31:06.064-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='unicode'/><category scheme='http://www.blogger.com/atom/ns#' term='zend'/><category scheme='http://www.blogger.com/atom/ns#' term='php'/><title type='text'>Fun with Unicode</title><content type='html'>&lt;p&gt;I caught a &lt;a href="http://blog.milkfarmsoft.com/?p=63"&gt;blog entry&lt;/a&gt; by Alexey Zakhlestin via &lt;a href="http://www.planet-php.net/"&gt;Planet-PHP&lt;/a&gt; today which asked the question "Why aren't unicode math symbols supported by programming languages?". The obvious answer, of course, is that they work just fine with the symbols they have and there's no need to mess with a good thing (it doesn't help that typing these symbols is a pita on your average terminal).&lt;/p&gt;&lt;p&gt;Being a whimsical sort, I decided that actually &lt;a href="#implementation"&gt;implementing&lt;/a&gt; his request would be more fun than simply pish-poshing it. I'm not suggesting this be part of PHP6 (I still don't personally think it's a good idea), but it's a fun exercise and good for a conversation starter... Here's just a few of the things I can do now:&lt;/p&gt;&lt;blockquote style="font-size: small"&gt;&lt;pre&gt;&amp;lt;?php&lt;br /&gt;var_dump(¼, ½ ¾);&lt;br /&gt;// float(0.25)&lt;br /&gt;// float(0.5)&lt;br /&gt;// float(0.75)&lt;br /&gt;&lt;br /&gt;var_dump(1 ≤ 2, 2 ≯ 3, 5 ≠ 6);&lt;br /&gt;// bool(true)&lt;br /&gt;// bool(true)&lt;br /&gt;// bool(true)&lt;br /&gt;&lt;br /&gt;var_dump(3 × 4, 15 ÷ 5);&lt;br /&gt;// int(12)&lt;br /&gt;// int(3)&lt;br /&gt;&lt;br /&gt;var_dump(1 « 3);&lt;br /&gt;// int(8)&lt;br /&gt;&lt;br /&gt;/* Your font may be too small,&lt;br /&gt; * but that's a skull and crossbones&lt;br /&gt; */&lt;br /&gt;☠('aka die/exit');&lt;br /&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;p&gt;P.S. - Just FYI, I am aware that the patch referenced above has flaws... The problems are fixable, I just didn't bother fixing 'em because this isn't a serious patch anyway.... Best spend that time on something worthwhile...&lt;/p&gt;&lt;br /&gt;&lt;p&gt;P.P.S. - Since the original posting of this article, PHP6-Unicode has been... well, essentially scrapped.  So the patch itself is no longer relevant.&lt;/p&gt;&lt;br /&gt;&lt;a name="implementation"&gt;&lt;pre style="font-size: small"&gt;Index: Zend/zend_language_scanner.l&lt;br /&gt;===================================================================&lt;br /&gt;RCS file: /repository/ZendEngine2/zend_language_scanner.l,v&lt;br /&gt;retrieving revision 1.167&lt;br /&gt;diff -u -p -r1.167 zend_language_scanner.l&lt;br /&gt;--- Zend/zend_language_scanner.l 12 Jul 2007 09:23:48 -0000 1.167&lt;br /&gt;+++ Zend/zend_language_scanner.l 27 Jul 2007 05:05:47 -0000&lt;br /&gt;@@ -402,6 +402,109 @@ ZEND_API int zend_copy_scanner_string(zv&lt;br /&gt;  return 1;&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt;+/* Used by {LABEL} for converting unicode operator symbols */&lt;br /&gt;+static inline int zend_scan_unicode_operator(zval *zendlval, char *str, zend_uint str_len, UConverter *conv, int *oplen, int have_equal TSRMLS_DC)&lt;br /&gt;+{&lt;br /&gt;+ int ret = 0;&lt;br /&gt;+&lt;br /&gt;+ switch (Z_USTRVAL_P(zendlval)[0]) {&lt;br /&gt;+  case 0x2260: /* NOT EQUAL TO */&lt;br /&gt;+   ret = T_IS_NOT_EQUAL;&lt;br /&gt;+   break;&lt;br /&gt;+&lt;br /&gt;+  case 0x2264: /* LESS-THAN OR EQUAL TO */&lt;br /&gt;+  case 0x226F: /* NOT GREATER-THAN */&lt;br /&gt;+   ret = T_IS_SMALLER_OR_EQUAL;&lt;br /&gt;+   break;&lt;br /&gt;+&lt;br /&gt;+  case 0x2265: /* GREATER-THAN OR EQUAL TO */&lt;br /&gt;+  case 0x226E: /* NOT LESS-THAN */&lt;br /&gt;+   ret = T_IS_GREATER_OR_EQUAL;&lt;br /&gt;+   break;&lt;br /&gt;+&lt;br /&gt;+  case 0x00AB: /* LEFT-POINTING DOUBLE ANGLE QUOTATION MARK */&lt;br /&gt;+  case 0x226A: /* MUCH LESS THAN */&lt;br /&gt;+   ret = have_equal ? T_SL_EQUAL : T_SL;&lt;br /&gt;+   break;&lt;br /&gt;+&lt;br /&gt;+  case 0x00BB: /* RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK */&lt;br /&gt;+  case 0x226B: /* MUCH MORE THAN */&lt;br /&gt;+   ret = have_equal ? T_SR_EQUAL : T_SR;&lt;br /&gt;+   break;&lt;br /&gt;+&lt;br /&gt;+  case 0x2270: /* NEITHER LESS-THAN NOR EQUAL TO */&lt;br /&gt;+   ret = '&gt;';&lt;br /&gt;+   break;&lt;br /&gt;+&lt;br /&gt;+  case 0x2271: /* NEITHER GREATER-THAN NOR EQUAL TO */&lt;br /&gt;+   ret = '&lt;';&lt;br /&gt;+   break;&lt;br /&gt;+&lt;br /&gt;+  case 0x2276: /* LESS-THAN OR GREATER-THAN */&lt;br /&gt;+  case 0x2277: /* GREATER-THAN OR LESS-THAN */&lt;br /&gt;+   ret = T_IS_NOT_EQUAL;&lt;br /&gt;+   break;&lt;br /&gt;+&lt;br /&gt;+  case 0x2278: /* NEITHER LESS-THAN NOR GREATER-THAN */&lt;br /&gt;+  case 0x2279: /* NEITHER GREATER-THAN NOR LESS-THAN */&lt;br /&gt;+   ret = T_IS_EQUAL;&lt;br /&gt;+   break;&lt;br /&gt;+&lt;br /&gt;+  case 0x00D7: /* MULTIPLICATION SIGN */&lt;br /&gt;+   ret = have_equal ? T_MUL_EQUAL : '*';&lt;br /&gt;+   break;&lt;br /&gt;+&lt;br /&gt;+  case 0x00F7: /* DIVISION SIGN */&lt;br /&gt;+   ret = have_equal ? T_DIV_EQUAL : '/';&lt;br /&gt;+   break;&lt;br /&gt;+&lt;br /&gt;+  case 0x00BC: /* VULGAR FRACTION ONE QUARTER */&lt;br /&gt;+   zval_dtor(zendlval);&lt;br /&gt;+   ZVAL_DOUBLE(zendlval, 0.25);&lt;br /&gt;+   ret = T_DNUMBER;&lt;br /&gt;+   break;&lt;br /&gt;+&lt;br /&gt;+  case 0x00BD: /* VULGAR FRACTION ONE HALF */&lt;br /&gt;+   zval_dtor(zendlval);&lt;br /&gt;+   ZVAL_DOUBLE(zendlval, 0.5);&lt;br /&gt;+   ret = T_DNUMBER;&lt;br /&gt;+   break;&lt;br /&gt;+&lt;br /&gt;+  case 0x00BE: /* VULGAR FRACTION THREE QUARTERS */&lt;br /&gt;+   zval_dtor(zendlval);&lt;br /&gt;+   ZVAL_DOUBLE(zendlval, 0.75);&lt;br /&gt;+   ret = T_DNUMBER;&lt;br /&gt;+   break;&lt;br /&gt;+&lt;br /&gt;+  case 0x2620: /* SKULL AND CROSSBONES */&lt;br /&gt;+   ret = T_EXIT;&lt;br /&gt;+   break;&lt;br /&gt;+ }&lt;br /&gt;+&lt;br /&gt;+ if (ret) {&lt;br /&gt;+  /* How much of the input do we need to consume for this codepoint in this character set? */&lt;br /&gt;+  UChar buffer[2], *buffer_ptr = buffer;&lt;br /&gt;+  UErrorCode status = U_ZERO_ERROR;&lt;br /&gt;+  const char *str_ptr = str;&lt;br /&gt;+&lt;br /&gt;+  ucnv_toUnicode(conv, &amp;buffer_ptr, buffer + 1, &amp;str_ptr, str + str_len, NULL, TRUE, &amp;status);&lt;br /&gt;+  if (U_FAILURE(status) &amp;&amp; status != U_BUFFER_OVERFLOW_ERROR) {&lt;br /&gt;+   /* Shouldn't happen... */&lt;br /&gt;+   ret = 0;&lt;br /&gt;+  } else {&lt;br /&gt;+   *oplen = (str_ptr - str);&lt;br /&gt;+  }&lt;br /&gt;+ }&lt;br /&gt;+&lt;br /&gt;+ if (ret &amp;&amp; ret != T_DNUMBER) {&lt;br /&gt;+  zval_dtor(zendlval);&lt;br /&gt;+  ZVAL_NULL(zendlval);&lt;br /&gt;+ }&lt;br /&gt;+&lt;br /&gt;+&lt;br /&gt;+ return ret;&lt;br /&gt;+}&lt;br /&gt;+&lt;br /&gt; static inline int zend_check_and_normalize_identifier(zval *zendlval)&lt;br /&gt; {&lt;br /&gt;  UChar *norm;&lt;br /&gt;@@ -2217,13 +2320,47 @@ HEREDOC_CHARS       ("{"*([^$\n\r\\{]|("&lt;br /&gt;  return T_ENCAPSED_AND_WHITESPACE;&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt;-&lt;ST_IN_SCRIPTING&gt;{LABEL} {&lt;br /&gt;- if (!zend_copy_scanner_string(zendlval, yytext, yyleng, UG(unicode)?IS_UNICODE:IS_STRING, SCNG(output_conv) TSRMLS_CC)) {&lt;br /&gt;-  return 0;&lt;br /&gt;+&lt;ST_IN_SCRIPTING&gt;{LABEL}"="? {&lt;br /&gt;+ zend_bool have_equal = 0;&lt;br /&gt;+&lt;br /&gt;+ if (yytext[yyleng-1] == '=') {&lt;br /&gt;+  have_equal = 1;&lt;br /&gt;  }&lt;br /&gt;- if (UG(unicode) &amp;&amp; !zend_check_and_normalize_identifier(zendlval)) {&lt;br /&gt;+&lt;br /&gt;+ if (!zend_copy_scanner_string(zendlval, yytext, yyleng - have_equal, UG(unicode)?IS_UNICODE:IS_STRING, SCNG(output_conv) TSRMLS_CC)) {&lt;br /&gt;   return 0;&lt;br /&gt;  }&lt;br /&gt;+&lt;br /&gt;+ if (UG(unicode)) {&lt;br /&gt;+  UChar *norm;&lt;br /&gt;+  int norm_len;&lt;br /&gt;+&lt;br /&gt;+  if (!zend_is_valid_identifier(Z_USTRVAL_P(zendlval), Z_USTRLEN_P(zendlval))) {&lt;br /&gt;+   int oplen = 0, ret = zend_scan_unicode_operator(zendlval, yytext, yyleng, SCNG(output_conv), &amp;oplen, have_equal TSRMLS_CC);&lt;br /&gt;+&lt;br /&gt;+   if (ret) {&lt;br /&gt;+    yyless(oplen + have_equal);&lt;br /&gt;+    return ret;&lt;br /&gt;+   }&lt;br /&gt;+&lt;br /&gt;+   zval_dtor(zendlval);&lt;br /&gt;+   zend_error(E_COMPILE_WARNING, "Invalid identifier syntax: %r", Z_USTRVAL_P(zendlval));&lt;br /&gt;+   return 0;&lt;br /&gt;+  }&lt;br /&gt;+&lt;br /&gt;+  if (zend_normalize_identifier(&amp;norm, &amp;norm_len, Z_USTRVAL_P(zendlval), Z_USTRLEN_P(zendlval), 0) == FAILURE) {&lt;br /&gt;+   zend_error(E_COMPILE_WARNING, "Could not normalize identifier: %r", Z_USTRVAL_P(zendlval));&lt;br /&gt;+   efree(Z_USTRVAL_P(zendlval));&lt;br /&gt;+   return 0;&lt;br /&gt;+  }&lt;br /&gt;+&lt;br /&gt;+  if (norm != Z_USTRVAL_P(zendlval)) {&lt;br /&gt;+   efree(Z_USTRVAL_P(zendlval));&lt;br /&gt;+   ZVAL_UNICODEL(zendlval, norm, norm_len, 0);&lt;br /&gt;+  }&lt;br /&gt;+ }&lt;br /&gt;+ yyless(yyleng - have_equal);&lt;br /&gt;+&lt;br /&gt;  return T_STRING;&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt;&lt;/pre&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1234953837283832282-3076611247164796981?l=blog.golemon.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.golemon.com/feeds/3076611247164796981/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.golemon.com/2007/07/fun-with-unicode.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1234953837283832282/posts/default/3076611247164796981'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1234953837283832282/posts/default/3076611247164796981'/><link rel='alternate' type='text/html' href='http://blog.golemon.com/2007/07/fun-with-unicode.html' title='Fun with Unicode'/><author><name>Sara Golemon</name><uri>http://www.blogger.com/profile/14557640555210645219</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1234953837283832282.post-4440523839286820056</id><published>2007-05-19T07:13:00.000-07:00</published><updated>2010-05-12T12:21:03.239-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='zend'/><category scheme='http://www.blogger.com/atom/ns#' term='php'/><category scheme='http://www.blogger.com/atom/ns#' term='eval'/><title type='text'>create_function() is not your friend, buddy</title><content type='html'>&lt;p&gt;While browsing through &lt;a href="http://www.phpdeveloper.org/"&gt;PHP Developer&lt;/a&gt; today, I came across this blog entry: &lt;a href="http://www.thinkingphp.org/2007/05/18/my-new-best-friend-phps-create_function/"&gt;"My new best friend"&lt;/a&gt; extolling the virtues of &lt;a href="http://www.php.net/create_function"&gt;create_function()&lt;/a&gt;.  Let me tell you why create_function() is &lt;b&gt;not&lt;/b&gt; my best friend...&lt;/p&gt;&lt;p&gt;First, despite the disclaimer in the mentioned blog entry, it &lt;i&gt;is&lt;/i&gt; as bad as its kissing-cousin &lt;a href="http://php.net/eval"&gt;eval()&lt;/a&gt;.  Let's take a look at what create_function() actually does by translating it into userland code:&lt;/p&gt; &lt;blockquote style="font-size:small"&gt;&lt;pre&gt;function create_function($args, $code)&lt;br /&gt;{&lt;br /&gt;   static $id = 0;&lt;br /&gt;   eval("function __lambda_func($args) { $code }");&lt;br /&gt;   while (!&lt;a href="http://php.net/runkit_function_rename"&gt;runkit_function_rename&lt;/a&gt;('__lambda_func', "\0lambda_" . (++$id)));&lt;br /&gt;   return "\0lambda_$id";&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;p&gt;I'll let you contemplate on that awhile....You should be noticing the following sets of problems: &lt;/p&gt;&lt;ul&gt;&lt;li&gt;Prone to &lt;i&gt;critical&lt;/i&gt; abuse by user-supplied code&lt;/li&gt;&lt;li&gt;Skips opcode cache optimizations&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;You should also be thinking about the practical issues with it: &lt;/p&gt;&lt;ul&gt;&lt;li&gt;Code lives inside quoted strings which means awkward escaping of embedded quotes&lt;/li&gt;&lt;li&gt;Encourages not using comments (evil)&lt;/li&gt;&lt;li&gt;100% blind to reflection or PHPDoc style documentation generation&lt;/li&gt;&lt;li&gt;I'm sure you can come up with a couple more...&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;p&gt;"If eval() is the answer, then you're asking the wrong question"&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1234953837283832282-4440523839286820056?l=blog.golemon.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.golemon.com/feeds/4440523839286820056/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.golemon.com/2007/05/createfunction-is-not-your-friend-buddy.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1234953837283832282/posts/default/4440523839286820056'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1234953837283832282/posts/default/4440523839286820056'/><link rel='alternate' type='text/html' href='http://blog.golemon.com/2007/05/createfunction-is-not-your-friend-buddy.html' title='create_function() is not your friend, buddy'/><author><name>Sara Golemon</name><uri>http://www.blogger.com/profile/14557640555210645219</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1234953837283832282.post-7463055242272584443</id><published>2007-01-26T12:21:00.000-08:00</published><updated>2010-05-12T12:14:00.759-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='zval'/><category scheme='http://www.blogger.com/atom/ns#' term='zend'/><category scheme='http://www.blogger.com/atom/ns#' term='php'/><category scheme='http://www.blogger.com/atom/ns#' term='oop'/><title type='text'>You're being lied to</title><content type='html'>&lt;p&gt;If you're among the crowd who have migrated an OOP based application from PHP4 to PHP5, then I'm sure you've heard the expression "Objects are copied by reference by default in PHP5".   Whoever told you that, was lying.&lt;/p&gt;&lt;p&gt;Now, to be fair, it's an innocent lie, since objects do &lt;b&gt;behave&lt;/b&gt; in a &lt;i&gt;reference-like manner&lt;/i&gt;, but references are NOT what they are.  Let's start with a simple illustration proving that they aren't references:&lt;/p&gt;&lt;blockquote style="font-size: small"&gt;&lt;pre&gt;&amp;lt;?php&lt;br /&gt;  $a = new stdClass;&lt;br /&gt;  $b = $a;&lt;br /&gt;  $a-&amp;gt;foo = 'bar';&lt;br /&gt;  var_dump($b);&lt;br /&gt;  /* Notice at this point, that $a and $b &lt;b&gt;are&lt;/b&gt;,&lt;br /&gt;   * indeed sharing the same object instance.&lt;br /&gt;   * This is their reference-like behavior at work.&lt;br /&gt;   */&lt;br /&gt;&lt;br /&gt;  $a = 'baz';&lt;br /&gt;  var_dump($b);&lt;br /&gt;&lt;br /&gt;  /* Notice now, that $b is still that original object.&lt;br /&gt;   * Had it been an actual reference with $a,&lt;br /&gt;   * it would have changed to a simple string as well.&lt;br /&gt;   */&lt;br /&gt;?&amp;gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;p&gt;What's going on here?  Well, the answer is easiest to explain by explaining what the underlying structure of objects are.  In PHP5, a variable containing an object identifies the instance by storing a simple numeric value.  When an action is going to be performed on an object, that numeric value is used with a lookup table to retreive the actual instance.  In PHP4, by contrast, a variable containing an array identifies that object by carrying around the actual properties table itself.  What this means in practice is that when you assign (not by reference) a PHP5 object to a new variable, that integer handle is copied into the new variable, but it still points at the same instance, because it's still the same number.  Assigning a PHP4 object however, means copying all the properties, effectively generating a new instance, since changes to one will not effect the other.&lt;/p&gt;&lt;p&gt;To put this another way, PHP4 objects are basically Arrays with functions associated with them, PHP5 objects are basicly Resources (a la MySQL result handles, or file pointers) again with functions loosely associated to them.  Consider the following code in PHP4 (or any version):&lt;br /&gt;&lt;/p&gt;&lt;blockquote style="font-size: small"&gt;&lt;pre&gt;&amp;lt;?php&lt;br /&gt;  $fp = fopen('foo.txt', 'r');&lt;br /&gt;  $otherVar = $fp;&lt;br /&gt;  fwrite($fp, "One\n");&lt;br /&gt;  fwrite($otherVar, "Two\n");&lt;br /&gt;  fclose($fp);&lt;br /&gt;&lt;br /&gt;  /* This fails, because the file is closed */&lt;br /&gt;  fwrite($otherVar, "Three\n");&lt;br /&gt;?&amp;gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;p&gt;You'd fully expect data to be written to the same file, as though you'd used $fp everywhere, rather than interchanging the variables right?  Well, PHP5 objects are the same.  The instance itself isn't duplicated when you assign to a new variable, just the unique identifier.&lt;/p&gt;&lt;br /&gt;&lt;h3&gt;I'm lying to you also&lt;/h3&gt;&lt;p&gt;"Copying" a variable doesn't exactly mean copying.  Take the following code block:&lt;/p&gt;&lt;blockquote style="font-size: small"&gt;&lt;pre&gt;&amp;lt;?php&lt;br /&gt;  $a = 'foo';&lt;br /&gt;  $b = $a;&lt;br /&gt;  $a = 'bar';&lt;br /&gt;?&amp;gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;p&gt;Now, you know PHP well enough to know that by the end of this code block, the value of &lt;span style="font-family:courier;"&gt;$b&lt;/span&gt; will still be &lt;span style="font-family:courier;"&gt;'foo'&lt;/span&gt;.  What you may not know, is that the original copy of &lt;span style="font-family:courier;"&gt;'foo'&lt;/span&gt; that was in &lt;span style="font-family:courier;"&gt;$a&lt;/span&gt;, was &lt;i&gt;never actually duplicated&lt;/i&gt;.&lt;/p&gt;&lt;p&gt;To understand what PHP is doing, you need to understand the internal structure of the variable and how it relates to userspace visible variable names ('a' and 'b' in this case).  First off, the actual contents of a variable (known as a &lt;span style="font-family:courier;"&gt;zval&lt;/span&gt;) consists of four parts: &lt;i&gt;type&lt;/i&gt; (e.g. NULL, Boolean, Integer, Float, String, Array, Resource, Object), a specific &lt;i&gt;value&lt;/i&gt; (e.g. 123, 3.1415926535, etc...), &lt;i&gt;is_ref&lt;/i&gt; - a flag indicating if the value is a reference or not, and &lt;i&gt;refcount&lt;/i&gt; which tells how many times this value is being shared.&lt;/p&gt;&lt;p&gt;What you think of as a variable (e.g. &lt;span style="font-family:courier;"&gt;$x&lt;/span&gt;) is actually just a label, that label ('x' in this case) is used as a lookup to find the &lt;span style="font-family:courier;"&gt;zval&lt;/span&gt; which conatins the actual value.  These are just like keys in an associative array, in fact, the mechanisms are identical.&lt;/p&gt;&lt;p&gt;With me so far?  Good.  Now, when you first create a variable (e.g. &lt;span style="font-family:courier;"&gt;$x = 123;&lt;/span&gt;, PHP allocates a new &lt;span style="font-family:courier;"&gt;zval&lt;/span&gt; for it, stores the specific value, and associates the label with the value:&lt;/p&gt;&lt;blockquote style="font-size: small"&gt;&lt;pre&gt;  'x' =&gt; zval ( type       =&gt; IS_LONG,&lt;br /&gt;                value.lval =&gt; 123,&lt;br /&gt;                is_ref     =&gt; 0,&lt;br /&gt;                refcount   =&gt; 1 )&lt;/pre&gt;&lt;/blockquote&gt;&lt;p&gt;So far, refcount is 1 since the zval value is only being referenced by one label.  If we now put this value into a full-reference set using &lt;span style="font-family: courier"&gt;$y =&amp;amp; $x;&lt;/span&gt;, the same zval is reused.  It's simply associated with a new label and it's reference counters are adjusted properly.&lt;/p&gt;&lt;blockquote style="font-size: small"&gt;&lt;pre&gt;  'x' =&gt; zval ( type       =&gt; IS_LONG,&lt;br /&gt;      |         value.lval =&gt; 123,&lt;br /&gt;      |         is_ref     =&gt; 1,&lt;br /&gt;      |         refcount   =&gt; 2 )&lt;br /&gt;  'y' /&lt;/pre&gt;&lt;/blockquote&gt;&lt;p&gt;This way, when you later change the value of $x, $y appears to change as well because it's looking at the same internal value.  But what if we hadn't done a reference assignment, what if we'd done a normal assignment: &lt;span style="font-family:courier;"&gt;$y = $x;&lt;/span&gt;, surprisingly, the result would be &lt;b&gt;almost&lt;/b&gt; the same.&lt;/p&gt;&lt;blockquote style="font-size:small"&gt;&lt;pre&gt;  'x' =&gt; zval ( type       =&gt; IS_LONG,&lt;br /&gt;      |         value.lval =&gt; 123,&lt;br /&gt;      |         is_ref     =&gt; 0,&lt;br /&gt;      |         refcount   =&gt; 2 )&lt;br /&gt;  'y' /&lt;/pre&gt;&lt;/blockquote&gt;&lt;p&gt;Again, the original zval associated with $x is reused, the only difference this time is that is_ref is not set to 1.  This is known as a &lt;u&gt;copy-on-write reference set&lt;/u&gt; (as opposed to the full-reference set described above).  This 0 flag tells the engine that if anyone tries to change this value (regardless of which label they use to reach it), any other references to it should be left alone.  Here's what happens if we take that current state and do &lt;span style="font-family:courier;"&gt;$x = 456;&lt;/span&gt;&lt;/p&gt;&lt;blockquote style="font-size: small"&gt;&lt;pre&gt;  'y' =&gt; zval ( type       =&gt; IS_LONG,&lt;br /&gt;                value.lval =&gt; 123,&lt;br /&gt;                is_ref     =&gt; 0,&lt;br /&gt;                refcount   =&gt; 1 )&lt;br /&gt;  'x' =&gt; zval ( type       =&gt; IS_LONG,&lt;br /&gt;                value.lval =&gt; 456,&lt;br /&gt;                is_ref     =&gt; 0,&lt;br /&gt;                refcount   =&gt; 1 )&lt;/pre&gt;&lt;/blockquote&gt;&lt;p&gt;$x has been disassociated from the original zval (thus dropping its refcount back to 1), and new zval has been created for it.&lt;/p&gt;&lt;br /&gt;&lt;h3&gt;&lt;a name="badrefs"&gt;Why referencing when you don't have to is a bad idea.&lt;/a&gt;&lt;/h3&gt;&lt;a name="badrefs"&gt;&lt;/a&gt;&lt;p&gt;Let's consider one more situation, take a look at this code block:&lt;/p&gt;&lt;blockquote style="font-size: small"&gt;&lt;pre&gt;&amp;lt;?php&lt;br /&gt;  $a = 'foo';&lt;br /&gt;  $b = $a;&lt;br /&gt;  $c = &amp;amp;$a;&lt;br /&gt;?&amp;gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;p&gt;At the first instruction, a single zval is created, associated to a single label:&lt;/p&gt;&lt;blockquote style="font-size: small"&gt;&lt;pre&gt;  'a' =&gt; zval ( type =&gt; IS_STRING, value.str.val = 'foo', is_ref = 0, refcount = 1 )&lt;/pre&gt;&lt;/blockquote&gt;&lt;p&gt;At the second intstruction, that zval is associated to a second label, so far so good:&lt;/p&gt;&lt;blockquote style="font-size: small"&gt;&lt;pre&gt;  'a' =&gt; zval ( type          =&gt; IS_STRING,&lt;br /&gt;      |         value.str.val =&gt; 'foo',&lt;br /&gt;      |         is_ref        =&gt; 0,&lt;br /&gt;      |         refcount      =&gt; 2 )&lt;br /&gt;  'b' /&lt;/pre&gt;&lt;/blockquote&gt;&lt;p&gt;At the third intstruction, however, we run into problems.  Since this zval is already tied up in a copy-on-write reference set which include $b, that zval can't be simply promoted to is_ref==1.  Doing so would drag $b into $a and $c's full-reference set, and that would be wrong.  In order to resolve this, the engine is forced to duplicate that zval into two identical copies, from which it can begin to shuffle around reference flags and counts:&lt;/p&gt;&lt;blockquote style="font-size: small"&gt;&lt;pre&gt;  'b' =&gt; zval ( type          =&gt; IS_STRING,&lt;br /&gt;                value.str.val =&gt;'foo',&lt;br /&gt;                is_ref        =&gt; 0,&lt;br /&gt;                refcount      =&gt; 1 )&lt;br /&gt;  'a' =&gt; zval ( type          =&gt; IS_STRING,&lt;br /&gt;      |         value.str.val =&gt; 'foo',&lt;br /&gt;      |         is_ref        =&gt; 1,&lt;br /&gt;      |         refcount      =&gt; 2 )&lt;br /&gt;  'c' /&lt;/pre&gt;&lt;/blockquote&gt;&lt;p&gt;Now you've got two copies of the same literal value, so you're wasting memory for the storage, and processing time required to actually make the duplication.  Since a LOT of events lead to copy-on-write uses (including simply passing an argument to a function), this sort of forced duplication actually happens very commonly when you start involving actual references.&lt;/p&gt;&lt;br /&gt;&lt;h3&gt;The moral of the story&lt;/h3&gt;&lt;p&gt;Assigning values by references when you don't need to (in order to later modify the original value through a different label) is &lt;b&gt;NOT&lt;/b&gt; a case of you outsmarting the silly engine and gaining speed and performance.  It's the opposite, it's you &lt;b&gt;TRYING&lt;/b&gt; to outsmart the engine and failing, because the engine is already doing a better job than you think.&lt;/p&gt;&lt;p&gt;How does this reflect on objects?  They're not special.  They're not different from other variables.  They are not pretty snowflakes.  In this code block:&lt;/p&gt;&lt;blockquote style="font-size: small"&gt;&lt;pre&gt;&amp;lt;?php&lt;br /&gt;  $a = new stdClass;&lt;br /&gt;  $b = $a;&lt;br /&gt;?&amp;gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;p&gt;The labels are still placed into copy-on-write reference sets.  What's important, is that even when a duplication does occur, (A) only that unique integer is copied (which is cheap), and (B) the duplicated integer still points to the same place.  Hence you get &lt;i&gt;reference-like behavior&lt;/i&gt;, but not an actual reference by default.&lt;/p&gt;&lt;p&gt;Hungry for more?  Check out my &lt;a href="http://devzone.zend.com/node/view/id/1022"&gt;coverage of the zval&lt;/a&gt;.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1234953837283832282-7463055242272584443?l=blog.golemon.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.golemon.com/feeds/7463055242272584443/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.golemon.com/2007/01/youre-being-lied-to.html#comment-form' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1234953837283832282/posts/default/7463055242272584443'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1234953837283832282/posts/default/7463055242272584443'/><link rel='alternate' type='text/html' href='http://blog.golemon.com/2007/01/youre-being-lied-to.html' title='You&apos;re being lied to'/><author><name>Sara Golemon</name><uri>http://www.blogger.com/profile/14557640555210645219</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1234953837283832282.post-6897864222444070454</id><published>2006-12-28T18:54:00.000-08:00</published><updated>2010-04-23T15:20:47.140-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='php'/><category scheme='http://www.blogger.com/atom/ns#' term='lookback'/><title type='text'>PHP-2006: A look back</title><content type='html'>&lt;div class="serendipity_entry_body"&gt;  &lt;span class="entry-content"&gt;&lt;p&gt;Well, &lt;a href="http://pixelated-dreams.com/"&gt;Davey Shafik&lt;/a&gt; started us off with &lt;a href="http://pixelated-dreams.com/archives/279-A-Year-in-Review.html"&gt;his year-end wrapup&lt;/a&gt; so I'll follow suit with mine. The thoughts below are mine and mildly influenced by alcohol. They represent a foggy review of how I experienced the year through the imperfect recollection of mailing list archives.&lt;/p&gt;   &lt;p&gt;&lt;b&gt;January&lt;/b&gt; began with releases of 4.4.2 and 5.1.2. Version 5.1.2 was especially close to my heart since it was the first version to ship an &lt;a href="http://pecl.php.net/package/hash"&gt;extension&lt;/a&gt; of mine not only bundled, but enabled by default. I've had my hands in most of the PHP runtime, but this was the first time I could point at a standard extension and say that it was basicly my work (Note: Mike Wallner did a fair bit of work adding to the number of hash algorithms supported, don't let me discount his efforts). Tim Starling &lt;a href="http://news.php.net/php.internals/21441"&gt;wrote&lt;/a&gt; to ask why PHP4 refcounts are 16bit, and what he could do about getting that counter increased in future versions of PHP4. Since such a change would break binary compatability and since the PHP4 branch is already quite dead, the request was ultimately left alone with an admonishment to "not do that".&lt;/p&gt;  &lt;p&gt;A few other requests were broached or continued, such as support for &lt;a href="http://news.php.net/php.internals/21469"&gt;Friend Classes&lt;/a&gt;, Named Arguments, and &lt;a href="http://news.php.net/php.internals/21565"&gt;Naming Arguments&lt;/a&gt; (The last of which would eventually be implemented).  It was also this month in which Rasmus &lt;a href="http://news.php.net/php.internals/21591"&gt;suggested&lt;/a&gt; adding JSON to the standard distribution, this quietly morphed into votes for including filter; Both were eventually linked in. James Crane had the &lt;a href="http://news.php.net/php.internals/21715"&gt;idea&lt;/a&gt; that Array Literals in PHP could use sprucing up, meanwhile Sean Coates &lt;a href="http://news.php.net/php.internals/21659"&gt;planted the seed&lt;/a&gt; for what would become the PHP6 &lt;a href="http://www.php.net/%7Escoates/unicode/"&gt;Unicode Progress&lt;/a&gt; tracker.&lt;/p&gt;   &lt;p&gt;&lt;b&gt;February&lt;/b&gt; came in fairly quiet, mostly wrapping up the topics from January. Appearantly Steph didn't like the quiet and decided to stir up the hornet's nest with some four letter words cleverly disguised under the heading of &lt;a href="http://news.php.net/php.internals/21912"&gt;True Labeled Breaks&lt;/a&gt;. For those who have blocked out 2005, this was easily one of the longest threads of that year and this resumption promised to be just as bad. By &lt;a href="http://blog.libssh2.org/index.php?/archives/2-GOTO...No,-seriously,-for-real-this-time..html"&gt;March&lt;/a&gt;, this thread would finnally be brought to a halt as the functionality was slipped quietly into the engine. I did not see that coming...&lt;/p&gt;  &lt;p&gt;Amidst this unexpected addition, others were busily pulling things out, with Andi &lt;a href="http://news.php.net/php.internals/21935"&gt;slashing away at safe_mode&lt;/a&gt; in HEAD, and Marcus integrating support for &lt;a href="http://news.php.net/php.internals/21939"&gt;function deprecation&lt;/a&gt; into the 5.2 branch.&lt;/p&gt; &lt;/span&gt;                                      &lt;div class="serendipity_entry_extended"&gt;&lt;p&gt;&lt;b&gt;March&lt;/b&gt; came in like a lion with Marcus &lt;a href="http://news.php.net/php.internals/22044"&gt;poking the list&lt;/a&gt; about Late Static Binding with less argument about Why, and a healthy focus on How. Johannes Schlueter made a very pragmatic and uncontroversial &lt;a href="http://news.php.net/php.internals/22103"&gt;suggestion&lt;/a&gt; to change the internal symbol prefix applied to methods in order to distinguish them from functions. Pierre ran with some PDM recommendations shouting &lt;a href="http://news.php.net/php.internals/22122"&gt;Adieu register_globals&lt;/a&gt; and &lt;a href="http://news.php.net/php.internals/22162"&gt;Adieu a la magie&lt;/a&gt;.  Sebastian Bergmann was frustrated with trying to &lt;a href="http://news.php.net/php.internals/22242"&gt;apply streams filters&lt;/a&gt; to include and require, until I pointed him at the &lt;a href="http://www.php.net/wrappers.php"&gt;php://filter&lt;/a&gt; wrapper. Though this met his need, he made a strong case for being able to set an automatic filter to be applied to all streams. I promised to do this after streams in HEAD had been cleaned up, and while I've gotten streams where I want them, I still havn't fullfilled his feature request... Shame on me.&lt;/p&gt;  &lt;p&gt;All this time, the GOTO debate was still raging and similar types of language altering features were being put on the table. Finally, Zeev decided he'd &lt;a href="http://news.php.net/php.internals/22275"&gt;had enough&lt;/a&gt; calling for people to "Give the language a rest".  This managed to have a decent effect which Rasmus soon channeled into his &lt;a href="http://news.php.net/php.internals/22357"&gt;call for performance geeks&lt;/a&gt; to narrow the performance gap between 4.4 and 5.1.  Towards the end of the month, I suggested adding an &lt;a href="http://news.php.net/php.internals/22572"&gt;open_basedir_for_include&lt;/a&gt; directive. While there was some interrest for this, Ilia quickly convinced me that my approach to the problem was flawed and wouldn't give any real benefit.&lt;/p&gt;   &lt;p&gt;&lt;b&gt;April&lt;/b&gt; showered the internals list with &lt;a href="http://news.php.net/php.internals/22617"&gt;Round 2&lt;/a&gt; of the Late Static Binding discussion, and Thomas Boutell's anouncement that he'd be turning over primary development of the GD library to the PHP project, spearheaded by Pierre. I made some more noise &lt;a href="http://news.php.net/php.internals/22649"&gt;complaining&lt;/a&gt; of RETURN_RT_STRING() (and family)'s leakage of memory under certain not-uncommon conditions, while Nuno brought the infamous &lt;a href="http://news.php.net/php.internals/22665"&gt;Coverity Report&lt;/a&gt; to attention.&lt;/p&gt;  &lt;p&gt;Richard Lynch shared his &lt;a href="http://news.php.net/php.internals/22728"&gt;WTF&lt;/a&gt; concerning the oft misunderstood &lt;i&gt;tsrm_ls&lt;/i&gt; parameter in PHP's sources.  Sadly, I hadn't written my &lt;a href="http://blog.libssh2.org/index.php?/archives/22-What-the-heck-is-TSRMLS_CC-anyway.html"&gt;summary&lt;/a&gt; of the topic yet, but although noone gave him a detailed description (It's a bit long to go into in an email), several helpful links were supplied. Round about the middle of the month, Rasmus &lt;a href="http://news.php.net/php.internals/22774"&gt;announced&lt;/a&gt; PHP's eminent participation in the Google Summer of Code project (wait, don't you work for Yahoo!?). After signing up as a mentor (though I never actually mented -- is that a word?), I gathered up my materials and &lt;a href="http://blog.libssh2.org/index.php?/archives/13-phptek-Day-One.html"&gt;flew off&lt;/a&gt; to &lt;a href="http://blog.libssh2.org/index.php?/archives/14-phptek-Day-Two.html"&gt;php|tek&lt;/a&gt; 2006 in &lt;a href="http://blog.libssh2.org/index.php?/archives/15-Bow-to-your-neighbor,-do-see-do....html"&gt;Orlando&lt;/a&gt;.&lt;/p&gt;   &lt;p&gt;&lt;b&gt;May&lt;/b&gt; opened to the initial planning rounds for PHP 5.2.0, and the &lt;a href="http://news.php.net/php.internals/23101"&gt;resumption&lt;/a&gt; of the ifsetor() request, now dressed up as coalesce(). By the way, why havn't we embraced this feature request yet? About a week into the month, Ilia &lt;a href="http://news.php.net/php.internals/23169"&gt;branched&lt;/a&gt; the PHP_5 tree leaving room for the earnest development of 5.2.&lt;/p&gt;  &lt;p&gt;William Candillon wrote in to &lt;a href="http://news.php.net/php.internals/23239"&gt;request&lt;/a&gt; a PHP version of C's #line macro, but was drowned out by the roar of Derick's &lt;a href="http://news.php.net/php.internals/23242"&gt;plea&lt;/a&gt; to "Stop breaking our apps for the sake of OO". Once the din of that had quieted down a little, Jason Garber decided to ask about making it possible to mark properties as &lt;a href="http://news.php.net/php.internals/23291"&gt;read only&lt;/a&gt;.  In case anyone was curious, none of these proposals gained footing.&lt;/p&gt;   &lt;p&gt;&lt;b&gt;June&lt;/b&gt; now, and &lt;a href="http://www.amazon.com/dp/067232704X"&gt;my book&lt;/a&gt; is finally released bringing with it an invitation to appear on php|architect's &lt;a href="http://podcast.phparch.com/main/index.php/episodes:20060602"&gt;Pro::PHP podcast&lt;/a&gt;.  Marcus Boerger &lt;a href="http://news.php.net/php.internals/23875"&gt;suggested&lt;/a&gt; that array indices could benefit from implicit __toString() calls, but he was eventually shot down.  Dimitry's &lt;a href="http://news.php.net/php.internals/23988"&gt;suggestion&lt;/a&gt; however, which provided for automatic module global registration via the module entry, did receive a warm welcome and you'll see it if you look inside PHP 5.2.0.&lt;/p&gt;  &lt;p&gt;Clearly this was the month of bright ideas, because Nuno Lopes tossed in gcc &lt;a href="http://news.php.net/php.internals/24149"&gt;branch prediction&lt;/a&gt;. It got a warm initial reception from the engine folk including Zeev stating "I actually like how it makes the code more readable hinting which branches are rare.". Andi agreed that it was a nice idea, but brought in the sobering reality that it didn't really do much for performance and could potentially bring unexpected results if applied heavily.&lt;/p&gt;   &lt;p&gt;&lt;b&gt;July&lt;/b&gt; was a busy month for me as I &lt;a href="http://blog.libssh2.org/index.php?/archives/31-Moving-on....html"&gt;changed jobs&lt;/a&gt; for the first time in over six years. I'm loving the new job by the way. Fantastic coworkers and....interresting challenges.... Laupretre François thought it'd be a &lt;a href="http://news.php.net/php.internals/24307"&gt;good idea&lt;/a&gt; to extend include_path to support stream wrappers. Those of us who know what trouble include_path already causes for performance and security were quick to nix that particular idea; Short version: No.&lt;/p&gt;  &lt;p&gt;Marcus popped in mid-month with an &lt;a href="http://news.php.net/php.internals/24402"&gt;implementation&lt;/a&gt; of the #line directive suggested back in May. Still no love from the internals community at large though; Short version: no #line for you. Dmitry committed a large patch to the Zend Engine to change how non-persistent memory is allocated and freed within a request. The good news is that emallocs are now faster, the bad news is that a hack I'd made in PHP5.1 for manipulating the non-persistent memory pool no longer worked...Grrrr.....&lt;/p&gt;  &lt;p&gt;On July 27th, Jani said &lt;a href="http://news.php.net/php.internals/25023"&gt;Good-Bye&lt;/a&gt;.&lt;/p&gt;   &lt;p&gt;&lt;b&gt;August&lt;/b&gt; picked up Mike Wallner's July &lt;a href="http://news.php.net/php.internals/24804"&gt;post&lt;/a&gt; decrying the state of OO strictness building up in PHP. This maelstrom took up most of the first week with no real conclusion (at least, not a satisfactory one). A &lt;i&gt;different&lt;/i&gt; Mike made some more noise later in the month &lt;a href="http://news.php.net/php.internals/25277"&gt;asking&lt;/a&gt; why accessing non-existant functions/methods has to be so darned fatal. The good news is that they aren't so much anymore. Yay for E_RECOVERABLE_ERROR.&lt;/p&gt; &lt;b&gt;September&lt;/b&gt; brought a &lt;a href="http://blog.libssh2.org/index.php?/archives/38-PHP6-News-from-the-front....html"&gt;landslide&lt;/a&gt; of movement in the PHP6 function migration/review process. There was some degree of question as to whether unicode.semantics should be SYSTEM, PERDIR, or USER. Noone really considered the latter as a possibility as it wrecks way too many assumptions, but the SYSTEM/PERDIR debate raged for awhile with the idealists wanting PERDIR support to aid migration, and the realists clinging to the maintainable simplicity of SYSTEM. In the end, SYSTEM won.   &lt;p&gt;&lt;b&gt;October&lt;/b&gt; was a relatively slow month, leading up to conference season such as it was.  Midmonth sometime I tossed out the &lt;a href="http://news.php.net/php.internals/26040"&gt;idea&lt;/a&gt; of allowing open_basedir to be tightened (but not loosened) during runtime and it was green-lighted surprisingly quietly. Ilia got a little &lt;a href="http://news.php.net/php.internals/26214"&gt;frustrated&lt;/a&gt; with the mounting delays holding back the release of PHP 5.2.0 which was already way behind schedule. Tragicly, this plea made the delay last even longer. Finally at the end of the month, he rolled final.&lt;/p&gt;   &lt;p&gt;&lt;b&gt;November&lt;/b&gt; was a big conference month for me.  First I crashed the nearby &lt;a href="http://blog.libssh2.org/index.php?/archives/41-ZendCon06-Wrapup.html"&gt;ZendCon&lt;/a&gt;, then turned right around and flew off to Germany for the &lt;a href="http://blog.libssh2.org/index.php?/archives/44-International-PHP-Conference-2006,-Frankfurt-am-Main.html"&gt;International PHP Conference&lt;/a&gt;.  Sean poked the &lt;a href="http://news.php.net/php.internals/26472"&gt;namespaces&lt;/a&gt; topic with a sharp stick and managed to generate a week's worth of noise resulting in no actual commitments by any capable/interrested parties. No sooner had that comotion died down than did Antony Dovgal bemoan a regression in fgets()'s behavior which I introduced in HEAD. I still think it's a silly behavior for a userspace function, but BCs are BCs, so the regression's been reverted.&lt;/p&gt;   &lt;p&gt;&lt;b&gt;December&lt;/b&gt;'s most exciting event was a &lt;a href="http://news.php.net/php.internals/26756"&gt;debaucle&lt;/a&gt; over the backward/forward compatability of serialize given the additional escaping concerns that processing unicode strings imposes. Ilia brought forward a &lt;a href="http://news.php.net/php.internals/26845"&gt;proposal&lt;/a&gt; to finally remove the unnecessary COM/Sockets/MHash extensions from the distribution bundle. After some light debate it was decided to keep COM around and only nix Sockets and MHash as of PHP6 (possibly 5.3 if such a version comes about). Wietse Venema brought back the &lt;a href="http://news.php.net/php.internals/26979"&gt;concept&lt;/a&gt; of introducing a taint mode for PHP.  The topic is still being discussed, but things don't look good for Wietse...&lt;/p&gt;   &lt;p&gt;And now here we are, at year's end. PHP6's unicode function migration process has passed the 50% mark and a preview release is sure to come once we handle a couple more extensions. PHP 5.2 is grabbing hold amongst the serious PHP shops, and even web hosters are trickling away from PHP4. There's still a huge, bright future ahead for this language, together we can make it happen.&lt;/p&gt;   &lt;p&gt;¡Feliz Año Nuevo!&lt;/p&gt;&lt;/div&gt;                      &lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1234953837283832282-6897864222444070454?l=blog.golemon.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.golemon.com/feeds/6897864222444070454/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.golemon.com/2006/12/php-2006-look-back.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1234953837283832282/posts/default/6897864222444070454'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1234953837283832282/posts/default/6897864222444070454'/><link rel='alternate' type='text/html' href='http://blog.golemon.com/2006/12/php-2006-look-back.html' title='PHP-2006: A look back'/><author><name>Sara Golemon</name><uri>http://www.blogger.com/profile/14557640555210645219</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1234953837283832282.post-8891310087271099868</id><published>2006-11-29T13:26:00.000-08:00</published><updated>2010-04-23T15:18:24.700-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='fail'/><category scheme='http://www.blogger.com/atom/ns#' term='unicode'/><title type='text'>When good encodings go bad</title><content type='html'>&lt;div class="serendipity_entry_body"&gt;  &lt;span class="entry-summary"&gt;&lt;p&gt;In the past year, I've been doing some work with Unicode as part of the PHP6 upgrade. I've learned more than I wanted to know about all sorts of encodings from UTF-7 to koi8-r to good old iso-8859-1. I've picked apart the picayune differences between UCS-2 and UTF-16, and played the game of surrogate pairing and orphaning. Despite all that exposure however, I wasn't prepared when a question crossed my inbox about a lesser known encoding called AL32UTF8.&lt;/p&gt;  &lt;p&gt;I'd never heard of this one before, so I went to my favorite search engine for some answers. Turns out it's something Oracle came up with and later got adopted as a proper standard with the name CESU-8. At first glance, CESU-8 looks identical to UTF-8 in the same way that UCS-2 looks a lot like UTF-16. In fact every codepoint from U+0000 to U+FFFF is encoded identically under both sets of rules: 16 bits, split up over one, two, or three bytes, with leftover bits framing the encoding protocol.&lt;/p&gt;  &lt;p&gt;When you jump up above U+FFFF however, into the realm of CJK codepoints and the like (such as my personal nom du pointe: &lt;a href="http://www.fileformat.info/info/unicode/char/236ba/index.htm" alt="Get a new font if you can't see this"&gt;𣚺&lt;/a&gt;) something funny starts to happen. In the UTF8 world, these codepoints are accomodated by adding one extra byte to the mix which allows for up to 22bits of data (All of unicode only requires 21). In the CESU-8 world however, the code point is split according to UTF-16 surrogacy rules making two separate unicode points (each in the range U+D800 - U+DFFF). These two unicode points are then encoded &lt;i&gt;individually&lt;/i&gt; into UTF-8 sequences. This means that we've now promoted our variable length (4 max) multibyte encoding to a variable length (6 max) multibyte-multibyte encoding. Thank you Oracle. Thank you for adding complexity to encoding rules while increasing data storage requirements. What would the world do without you?&lt;/p&gt;  &lt;p&gt;P.S. - Java is at fault too... its 'Modified UTF-8' uses nearly identical rules.&lt;/p&gt;&lt;/span&gt;                                   &lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1234953837283832282-8891310087271099868?l=blog.golemon.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.golemon.com/feeds/8891310087271099868/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.golemon.com/2006/11/when-good-encodings-go-bad.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1234953837283832282/posts/default/8891310087271099868'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1234953837283832282/posts/default/8891310087271099868'/><link rel='alternate' type='text/html' href='http://blog.golemon.com/2006/11/when-good-encodings-go-bad.html' title='When good encodings go bad'/><author><name>Sara Golemon</name><uri>http://www.blogger.com/profile/14557640555210645219</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1234953837283832282.post-6232844034518888166</id><published>2006-11-05T23:08:00.000-08:00</published><updated>2010-04-23T15:17:32.663-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='conference'/><category scheme='http://www.blogger.com/atom/ns#' term='europe'/><category scheme='http://www.blogger.com/atom/ns#' term='php'/><title type='text'>Don't worry, I slept last Thursday</title><content type='html'>&lt;div class="serendipity_entry_body"&gt;  &lt;span class="entry-summary"&gt;&lt;p&gt;On this, my first foray to Europe, indeed my first real trip outside the US (Those couple hours in Tijuana don't count), I'm faced with one undeniable, inexcapable fact. &lt;b&gt;&lt;u&gt;Jet lag sucks.&lt;/u&gt;&lt;/b&gt;&lt;/p&gt;  &lt;p&gt;It doesn't help that all last week I was staying up past my normal bedtime partying with the attendees of ZendCon06, but I think my real mistake was trying to outsmart my own circadian rhythm. See, I figured "I've got this long flight across the atlantic, it'll go faster if I can fall asleep at some point." Seems reasonable so far. How to ensure sleep? Why, stay up all night before the flight. Brilliant! But wait, what if I can't fall asleep during the flight?&lt;/p&gt;  &lt;p&gt;Sometime sunday morning, my plane lands in Frankfurt and I wander, zombie-like, through passport control, baggage claim, and customs somehow managing to board the right shuttle to reach the conference hotel. Based on advices from battle-hardened globetrotters, I was planning to put in a one hour power nap, then go for a walk to "reset" my internal clock. Unfortunately the sixty-plus hour run of consciousness had other plans and by the time I awoke, the sun had set.&lt;/p&gt;  &lt;p&gt;Finally this morning (Monday), I managed to put in that walk, touring a nearby suburb which reminded me somewhat spookily of the setting from "Shaun of the Dead" (more zombie tie-ins). Five euros and three liter bottles of diet coke later and I'm almost coherent enough to....what the hell was I gonna say? Sorry, my brain has been cutting out a lot the past few days...&lt;/p&gt;  &lt;p&gt;Guten Morgen!&lt;/p&gt;&lt;/span&gt;                                   &lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1234953837283832282-6232844034518888166?l=blog.golemon.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.golemon.com/feeds/6232844034518888166/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.golemon.com/2006/11/dont-worry-i-slept-last-thursday.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1234953837283832282/posts/default/6232844034518888166'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1234953837283832282/posts/default/6232844034518888166'/><link rel='alternate' type='text/html' href='http://blog.golemon.com/2006/11/dont-worry-i-slept-last-thursday.html' title='Don&apos;t worry, I slept last Thursday'/><author><name>Sara Golemon</name><uri>http://www.blogger.com/profile/14557640555210645219</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1234953837283832282.post-6781434532120260403</id><published>2006-07-05T13:34:00.000-07:00</published><updated>2010-04-23T15:13:44.101-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='work'/><category scheme='http://www.blogger.com/atom/ns#' term='yahoo'/><category scheme='http://www.blogger.com/atom/ns#' term='ucb'/><title type='text'>Moving right along</title><content type='html'>&lt;span class="entry-summary"&gt;After well over half a decade at the &lt;a href="http://www.berkeley.edu/"&gt;University of California at Berkeley&lt;/a&gt;, I'm moving on to greener pastures. Well, maybe not greener (Berkeley is full of evergreens and...other verdant plant substances), but pastures at the very least. Next monday, my life's journy will bring me to that farmland come technopolis known the world over as Silicon Valley. I'll be cubefarming private sector style for one of the few dotcom survivors, a little mom &amp;amp; pop outfit called &lt;a href="http://search.yahoo.com/"&gt;Yahoo!&lt;/a&gt;. I've worked in education and the public sector since 1997 and while I'm optimistic everything will go smoothly, well....I think Dan Aykroyd put it best as Dr. Raymond Stantz in &lt;a href="http://imdb.com/title/tt0087332/"&gt;Ghostbusters&lt;/a&gt;: "You don't know what it's like out there, you've never worked in the private sector, They expect &lt;b&gt;results&lt;/b&gt;! (shudder)". If nothing else it'll be nice to get my commute back down to the 20minute zone. At any rate, I've got 2 days and as many going-away parties to get through, then it's on to the enemy camp (Yahoo's birth {not as a company, but as the index site it started out as} was at UCBerkeley's long-time rival, Stanford University).&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1234953837283832282-6781434532120260403?l=blog.golemon.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.golemon.com/feeds/6781434532120260403/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.golemon.com/2006/07/moving-right-along.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1234953837283832282/posts/default/6781434532120260403'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1234953837283832282/posts/default/6781434532120260403'/><link rel='alternate' type='text/html' href='http://blog.golemon.com/2006/07/moving-right-along.html' title='Moving right along'/><author><name>Sara Golemon</name><uri>http://www.blogger.com/profile/14557640555210645219</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1234953837283832282.post-6618893132754240091</id><published>2006-06-18T19:05:00.000-07:00</published><updated>2010-04-23T15:11:53.093-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='zend'/><category scheme='http://www.blogger.com/atom/ns#' term='strings'/><category scheme='http://www.blogger.com/atom/ns#' term='php'/><title type='text'>How long is a piece of string</title><content type='html'>&lt;div&gt;&lt;span&gt;&lt;p&gt;Sunday morning I was asked by an IRC regular: "Where does the engine parse quoted strings?". Being a sunday morning, I began to launch into a sermon on the distinction between &lt;span style="font-family:courier;"&gt;CONSTANT_ENCAPSED_STRING&lt;/span&gt; and the problems which befall a single-pass compiler when you start to introduce interpolation. Not what he asked precisely, but an important component in answering his question. Unfortunately, at the time I was busy watching the Brasil-Australia game so I didn't go into the kind of detail I would have. Now, some 12 hours later, since Angela is off buying toe-socks in Santa Cruz, I'll bore anyone with little enough life to read my blog by explaining the pitfalls of using PHP's string interpolation without using an optimizer.&lt;/p&gt;&lt;/span&gt;&lt;div&gt;&lt;p&gt;To start things off, let's take a page from my earlier discourse on &lt;a href="http://saragolemon.blogspot.com/2006/05/last-month-at-phptek-i-gave.html"&gt;Compiled Variables&lt;/a&gt; and look at the opcodes generated by a few simple PHP scripts:&lt;/p&gt;&lt;blockquote&gt;&lt;pre style="font-family:courier new;font-size:78%;line-spacing:0"&gt;&amp;lt;?php&lt;br /&gt;echo "This is a constant string";&lt;br /&gt;?&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;p&gt;Yields the nice, simple opcode:&lt;/p&gt; &lt;blockquote&gt;&lt;pre style="font-family:courier new;font-size:78%;"&gt;ECHO            'This is a constant string'&lt;br /&gt;&lt;/pre&gt;&lt;/blockquote&gt; &lt;p&gt;No problem... Exactly what you'd expect...  Now let's complicate the expressions a little:&lt;/p&gt; &lt;blockquote&gt;&lt;pre&gt;&lt;span style="font-family:courier new;font-size:78%;"&gt;&amp;lt;?php&lt;/span&gt;&lt;span style="font-size:78%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:78%;"&gt;echo "This is an interpolated $string";&lt;/span&gt;&lt;span style="font-size:78%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:78%;"&gt;?&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/blockquote&gt; &lt;p&gt;Yields the surprisingly messy instruction set:&lt;/p&gt; &lt;blockquote&gt;&lt;pre style="font-family:courier new;font-size:78%;"&gt;INIT STRING  ~0&lt;br /&gt;ADD_STRING   ~0 ~0 'This'&lt;br /&gt;ADD_STRING   ~0 ~0 ' '&lt;br /&gt;ADD_STRING   ~0 ~0 'is'&lt;br /&gt;ADD_STRING   ~0 ~0 ' '&lt;br /&gt;ADD_STRING   ~0 ~0 'an'&lt;br /&gt;ADD_STRING   ~0 ~0 ' '&lt;br /&gt;ADD_STRING   ~0 ~0 'interpolated'&lt;br /&gt;ADD_STRING   ~0 ~0 ' '&lt;br /&gt;ADD_VAR      ~0 ~0 !0&lt;br /&gt;ECHO            ~0&lt;br /&gt;&lt;/pre&gt;&lt;/blockquote&gt; &lt;p&gt;Where !0 represents the compiled variable named &lt;span style="font-family:courier;"&gt;$string&lt;/span&gt;.  Looking at these opcodes: &lt;span style="font-family:courier;"&gt;INIT_STRING&lt;/span&gt; allocates an &lt;span style="font-family:courier;"&gt;IS_STRING&lt;/span&gt; variable of one byte (to hold the terminating &lt;span style="font-family:courier;"&gt;NULL&lt;/span&gt;).  Then it's realloc'd to five bytes by the first &lt;span style="font-family:courier;"&gt;ADD_STRING&lt;/span&gt; ('This' plus the terminating &lt;span style="font-family:courier;"&gt;NULL&lt;/span&gt;). Next it's realloc'd to six bytes in order to add a space, then again to eight bytes for 'is', then nine to add a space, and so on until the temporary string has the contents of the interpolated variable copied into its contents before being used by the echo statement and finally discarded. Now let's rewrite that line to avoid interpolation and use concatenation instead:&lt;/p&gt; &lt;blockquote&gt;&lt;pre style="font-family:courier new;font-size:78%;"&gt;&amp;lt;?php&lt;br /&gt;echo "This is a concatenated " . $string;&lt;br /&gt;?&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;/blockquote&gt; &lt;p&gt;Which yields the significantly shorter and simpler set of ops:&lt;/p&gt; &lt;blockquote&gt;&lt;pre style="font-family:courier new;font-size:78%;"&gt;CONCAT       ~0 'This is a concatenated ' !0&lt;br /&gt;ECHO            ~0&lt;br /&gt;&lt;/pre&gt;&lt;/blockquote&gt; &lt;p&gt;A vast improvement already, but this version still creates a temporary &lt;span style="font-family:courier;"&gt;IS_STRING&lt;/span&gt; variable to hold the combined string contents meaning that data is duplicated when it's being used in a &lt;span style="font-family:courier;"&gt;const&lt;/span&gt; context anyway.  Now let's try out this oft-overlooked use of the echo statement:&lt;/p&gt; &lt;blockquote&gt;&lt;pre&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;&amp;lt;?php&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;echo "This is a stacked echo " , $string;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;?&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/blockquote&gt; &lt;p&gt;Look close, there is a meaningful difference from the last one. This time we're using a comma rather than a dot between the operands. If you don't know what the comma is doing there, ask &lt;a href="http://www.php.net/echo"&gt;the manual&lt;/a&gt; then check back here.  Here's the resulting opcodes:&lt;/p&gt; &lt;blockquote&gt;&lt;pre&gt;&lt;span style="font-family:courier new;font-size:78%;"&gt;ECHO            'This is a stacked echo '&lt;/span&gt;&lt;span style="font-size:78%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:78%;"&gt;ECHO            !0&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;p&gt;Same number of opcodes, but this time no temporary variables are being created so there's no duplication and no pointless copying (unless of course &lt;span style="font-family:courier;"&gt;$string&lt;/span&gt; wasn't of type &lt;span style="font-family:courier;"&gt;IS_STRING&lt;/span&gt;, in which case it does have to be converted for output, but don't get picky now). Think this is bad? Consider the average heredoc string which spans several lines of prepared output embedding perhaps a handful of variables along the way. Here's one of several such blocks found in &lt;span style="font-family:courier;"&gt;run-tests.php&lt;/span&gt; within the PHP distribution source tree:&lt;/p&gt; &lt;br /&gt;&lt;blockquote&gt;&lt;pre style="font-family:courier new;font-size:78%;"&gt;&amp;lt;?php&lt;br /&gt;echo &amp;lt;&amp;lt;NO_PCRE_ERROR&lt;br /&gt;&lt;br /&gt;+-----------------------------------------------------------+&lt;br /&gt;|                       ! ERROR !                           |&lt;br /&gt;| The test-suite requires that you have pcre extension      |&lt;br /&gt;| enabled. To enable this extension either compile your PHP |&lt;br /&gt;| with --with-pcre-regex or if you've compiled pcre as a    |&lt;br /&gt;| shared module load it via php.ini.                        |&lt;br /&gt;+-----------------------------------------------------------+&lt;br /&gt;&lt;br /&gt;NO_PCRE_ERROR;&lt;br /&gt;?&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;/blockquote&gt; &lt;br /&gt;&lt;p&gt;Notice that we're not even embedding variables to be interpolated here, yet does this come out to a simple, single opcode? Nope, because the rules necessary to catch a heredoc's end token demand the same careful examination as double-quoted variable substitution and you wind up (in this case) with SEVENTY-EIGHT opcodes! One &lt;span style="font-family:courier;"&gt;INIT_STRING&lt;/span&gt;, 76 &lt;span style="font-family:courier;"&gt;ADD_STRING&lt;/span&gt;s. and a final &lt;span style="font-family:courier;"&gt;ECHO&lt;/span&gt;. That means a malloc, 76 reallocs, and a free which will be executed every time that code snippet comes along. Even the original contents take up more memory because they're stored in 76 distinct zval/&lt;span style="font-family:courier;"&gt;IS_STRING&lt;/span&gt; structures.&lt;/p&gt;&lt;p&gt;Why does this happen? Because there are about a dozen ways that a variable can be hidden inside an interpolated string. Similarly, when looking for a heredoc end-token, the token can be an arbitrary length, containing any of the label characters, and may or may not sit on a line by itself. Put simply, it's too difficult to encompass in one regular expression.&lt;/p&gt;  &lt;p&gt;The engine &lt;i&gt;could&lt;/i&gt; perform a second-pass during compilation, however the time saved reassembling these strings will typically be about the same amount of time spent actually processing them during runtime (if one assumes that each instance will execute exactly once). Rather than complicate the build process (potentially slowing down overall run-times in the process), the compiler leaves this optimization step to opcode caches which can achieve exponentially greater advantage cleaning up this mess then caching the results and reusing the faster, leaner versions on all subsequent runs.&lt;/p&gt;&lt;p&gt;If you're using &lt;a href="http://pecl.php.net/package/apc"&gt;APC&lt;/a&gt;, you'll find just such an optimizer built in, but not enabled by default.  To turn it on, you'll need to set &lt;span style="font-family:courier;"&gt;apc.optimization=on&lt;/span&gt; in your php.ini. In addition to stitching these run-on opcodes back together, it'll also add run-time speed-ups like pre-resolving persistent constants to their actual values, folding static scalar expressions (like 1 + 1) to their fixed results (e.g. 2), and simpler stuff like avoiding the use of JMP when the target is the next opcode, or boolean casts when the original expression is known to be a boolean value. (It should be noted that these speed-ups also break some of the runtime-manipulation features of &lt;a href="http://pecl.php.net/package/runkit"&gt;runkit&lt;/a&gt;, but that was stuff you....probably should have been doing anyway)&lt;/p&gt;&lt;p&gt;Can't use an optimizer because your webhost doesn't know how to set php.ini options?  You can still avoid 90% of the &lt;span style="font-family:courier;"&gt;INIT_STRING&lt;/span&gt;/&lt;span style="font-family:courier;"&gt;ADD_STRING&lt;/span&gt; dilema by simply using single quotes and concatenation (or commas when dealing with echo statements). It's a simple trick and one which shouldn't harm maintainability too much, but on a large, complicated script, you just might see an extra request or two per second.&lt;/p&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1234953837283832282-6618893132754240091?l=blog.golemon.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.golemon.com/feeds/6618893132754240091/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.golemon.com/2006/06/how-long-is-piece-of-string.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1234953837283832282/posts/default/6618893132754240091'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1234953837283832282/posts/default/6618893132754240091'/><link rel='alternate' type='text/html' href='http://blog.golemon.com/2006/06/how-long-is-piece-of-string.html' title='How long is a piece of string'/><author><name>Sara Golemon</name><uri>http://www.blogger.com/profile/14557640555210645219</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1234953837283832282.post-4489018663909033530</id><published>2006-06-07T14:20:00.000-07:00</published><updated>2010-04-20T16:54:17.160-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='win'/><category scheme='http://www.blogger.com/atom/ns#' term='php'/><category scheme='http://www.blogger.com/atom/ns#' term='book'/><title type='text'>Extending and Embedding PHP</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://farm1.static.flickr.com/75/174928046_e59eef7e6d_o.jpg"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer; width: 154px; height: 113px;" src="http://farm1.static.flickr.com/75/174928046_e59eef7e6d_o.jpg" alt="" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;span class="entry-summary"&gt;It's official!!!! After a year in development Extending and Embedding PHP is now shipping from fine book stores everywhere.&lt;br /&gt;&lt;p&gt;&lt;a href="http://blog.libssh2.org/uploads/eephp_stack.jpg" target="_new"&gt;&lt;br /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;I've gotten good reviews from the half dozen people I know who've gotten their hands on it, and I &lt;i&gt;am&lt;/i&gt; really satisfied with most of it. Do I think it could be better? Of course I do, but I don't think I was ever going to be completely satisfied.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;I've learned a lot through this process and while I don't see any more titles in my immediate future (there are things coming down the pipe which are likely to change my availability), I do expect that my next book, should it materialize, will be even better.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;If you pre-ordered it, you should see it soon, if you've already got your copy, let me know what you think! Did I skim over some topic too quickly? Did I belabour something else? If this book eventually finds it's way into a 2&lt;sup&gt;nd&lt;/sup&gt; edition (no promises mind you), are there topics you want to see added?  Tossed out?  Expanded/Compressed?&lt;/p&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1234953837283832282-4489018663909033530?l=blog.golemon.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.golemon.com/feeds/4489018663909033530/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.golemon.com/2006/06/extending-and-embedding-php.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1234953837283832282/posts/default/4489018663909033530'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1234953837283832282/posts/default/4489018663909033530'/><link rel='alternate' type='text/html' href='http://blog.golemon.com/2006/06/extending-and-embedding-php.html' title='Extending and Embedding PHP'/><author><name>Sara Golemon</name><uri>http://www.blogger.com/profile/14557640555210645219</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1234953837283832282.post-2778191266369728679</id><published>2006-06-01T13:08:00.000-07:00</published><updated>2010-04-20T16:50:58.804-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='tsrmls_cc'/><category scheme='http://www.blogger.com/atom/ns#' term='zend'/><category scheme='http://www.blogger.com/atom/ns#' term='favorite'/><category scheme='http://www.blogger.com/atom/ns#' term='php'/><category scheme='http://www.blogger.com/atom/ns#' term='tsrmls'/><title type='text'>What the heck is TSRMLS_CC, anyway?</title><content type='html'>&lt;span class="entry-content"&gt;&lt;p&gt;If you've ever worked on the PHP internals or built an extension, you've seen this construct floating around here and there, but noone ever talks about it. Those who know what this is typically answer questions from those who don't with "Don't worry about what it is, just use it here here here and here. And if the compiler says you're missing a &lt;span style="font-family: courier;"&gt;tsrm_ls&lt;/span&gt;, put it there too..." This isn't laziness on the part of the person answering the question (okay, maybe it is a little bit), it's just that the engine goes so far out of its way to simplify what this magic values does, that there's no profit in a new extension developer knowing the mechanics of it. The information is like a cow's opinion, it doesn't matter, it's Moo.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Since I love to listen to myself rattle on about pointless topics (and I havn't blogged much this month), I thought I'd cover this topic and see if anyone manages to stay awake through it. You can blame Lukas, he got me rolled onto planet-php.net...&lt;/p&gt;&lt;/span&gt;                                      &lt;h3&gt;Glossary&lt;/h3&gt; &lt;div class="serendipity_entry_extended"&gt;&lt;dt&gt;TSRM&lt;/dt&gt; &lt;dd&gt;&lt;b&gt;T&lt;/b&gt;hread &lt;b&gt;S&lt;/b&gt;afe &lt;b&gt;R&lt;/b&gt;esource &lt;b&gt;M&lt;/b&gt;anager - This is an oft overlooked, and seldom if ever discussed layer hiding in the /TSRM directory of your friendly neighborhood PHP source code bundle. By default, the TSRM layer is only enabled when compiling a SAPI which requires it (e.g. apache2-worker). All Win32 builds have this layer enabled enabled regardless of SAPI choice.&lt;/dd&gt;&lt;br /&gt;&lt;br /&gt;&lt;dt&gt;ZTS&lt;/dt&gt; &lt;dd&gt;&lt;b&gt;Z&lt;/b&gt;end &lt;b&gt;T&lt;/b&gt;hread &lt;b&gt;S&lt;/b&gt;safety - Often used synonymously with the term &lt;i&gt;TSRM&lt;/i&gt;.  Specifically, ZTS is the term used by &lt;span style="font-family: courier;"&gt;./configure&lt;/span&gt; ( &lt;span style="font-family: courier;"&gt;--enable-experimental-zts&lt;/span&gt; for PHP4, &lt;span style="font-family: courier;"&gt;--enable-maintainer-zts&lt;/span&gt; for PHP5), and the name of the &lt;span style="font-family: courier;"&gt;#define&lt;/span&gt;'d preprocessor token used inside the engine to determine if the TSRM layer is being used.&lt;/dd&gt;&lt;br /&gt;&lt;br /&gt;&lt;dt&gt;tsrm_ls&lt;/dt&gt; &lt;dd&gt;TSRM &lt;b&gt;l&lt;/b&gt;ocal &lt;b&gt;s&lt;/b&gt;torage - This is the actual variable name being passed around inside the TSRMLS_* macros when ZTS is enabled. It acts as a pointer to the start of that thread's independent data storage block which I'll cover in just a minute&lt;/dd&gt;&lt;br /&gt;&lt;br /&gt;&lt;dt&gt;TSRMLS_??&lt;/dt&gt; &lt;dd&gt;A quartet of macros designed to make the differences between ZTS and non-ZTS mode as painless as possible.  When ZTS is &lt;i&gt;not&lt;/i&gt; enabled, all four of these macros evaluate to nothing. When ZTS is enabled however, they expand out to the following definitions: &lt;ul style="font-family: courier new;"&gt;&lt;li&gt;TSRMLS_C   tsrm_ls&lt;/li&gt;&lt;li&gt;TSRMLS_D   void ***tsrm_ls&lt;/li&gt;&lt;li&gt;TSRMLS_CC  , tsrm_ls&lt;/li&gt;&lt;li&gt;TSRMLS_DC  , void ***tsrm_ls&lt;/li&gt;&lt;/ul&gt;&lt;/dd&gt; &lt;h3&gt;Globals&lt;/h3&gt; &lt;p&gt;In any normal C program (just like in PHP) you have two methods of getting data access to the same block of data in two different functions. One method is to pass the value on the parameter stuck like so:&lt;/p&gt; &lt;blockquote&gt;&lt;pre&gt;&lt;span style="font-family: courier new;font-size:78%;" &gt;#include &lt;stdio.h&gt;&lt;br /&gt;&lt;br /&gt;void output_func(char *message)&lt;br /&gt;{&lt;br /&gt;   printf("%s\n", message);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;int main(int argc, char *argv[])&lt;br /&gt;{&lt;br /&gt;   output_func(argv[0]);&lt;br /&gt;&lt;br /&gt;   return 0;&lt;br /&gt;}&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/blockquote&gt; &lt;p&gt;Alternately, you could store the value in a variable up in the global scope and let the function access it there:&lt;/p&gt; &lt;blockquote&gt;&lt;pre&gt;&lt;span style="font-family: courier new;font-size:78%;" &gt;#include &lt;stdio.h&gt;&lt;br /&gt;&lt;br /&gt;char *message;&lt;br /&gt;&lt;br /&gt;void output_func(void)&lt;br /&gt;{&lt;br /&gt;   printf("%s\n", message);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;int main(int argv, char *argv[])&lt;br /&gt;{&lt;br /&gt;   message = argv[0];&lt;br /&gt;   output_func();&lt;br /&gt;&lt;br /&gt;   return 0;&lt;br /&gt;}&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/blockquote&gt; &lt;p&gt;Both approaches have their merits and drawbacks and typically you'll see some combination of the two used in a real application. Indeed, PHP is covered in global variables from resource type identifiers, to function callback pointers, to request specific information such as the symbol tables used to store userspace variables. Attempting to pass these values around in the parameter stack would be more than unruly, it'd be impossible for an application like PHP where it's often necessary to register callbacks with external libraries which don't support context data.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;So common information, like the execution stack, the function and class tables, and extension registries all sit up in the global scope where they can be picked up and used at any point in the application. For single-threaded SAPIs like CLI, Apache1, or even Apache2-prefork, this is perfectly fine. Request specific structures are initialized during the RINIT/Activation phase, and reset back to their original values during the RSHUTDOWN/Deactivation phase in preparation for the next request. A given webserver like Apache1 can serve up multiple pages at once because it spawns multiple processes each in their own process space with their own independant copies of global data.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Now let's introduce threaded webservers like Apache2-worker, or IIS. Under these conditions, only one process space is active at a given time with multiple threads spun off. Each of these threads then act in the same manner as a single-threaded process might; Servicing requests one-at-a-time as dispatched by inbound requests. The trouble starts to brew as two or more threads try to service the a request at the same time. Each thread wants to use the global scope to store its request-specific information, and tries to do so by writing to the same storage space. At the least, this would result in userspace variables declared in one script showing up in another. In practice, it leads to quick and disasterous segfaults and completely unpredictable behavior as memory is double freed or written with conflicting information by separate threads.&lt;/p&gt;&lt;br /&gt;&lt;h3&gt;Non-Global Globals&lt;/h3&gt; &lt;p&gt;The solution is to require the engine, the core, and any extension using global storage to determine how much memory will be used by request-specific data. Then, at the spin-up of each new thread, allocate a chunk of memory for each of these players to store their data into thus giving each thread its own &lt;i&gt;local storage&lt;/i&gt;. In order to group all the individual chuncks used by a given thread together, one last vector of pointers is allocated to store the individual sub-structure pointers into. It's the pointer to this vector which is passed around as the &lt;span style="font-family: courier;"&gt;tsrm_ls&lt;/span&gt; variable by the TSRMLS_* family of macros.  To see how this works, let's look at a example extension:&lt;/p&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;span style="font-family: courier new;font-size:78%;" &gt;typedef struct _zend_myextension_globals {&lt;br /&gt;   int foo;&lt;br /&gt;   char *bar;&lt;br /&gt;} zend_myextension_globals;&lt;br /&gt;&lt;br /&gt;#ifdef ZTS&lt;br /&gt;int myextension_globals_id;&lt;br /&gt;#else&lt;br /&gt;zend_myextension_globals myextension_globals;&lt;br /&gt;#endif&lt;br /&gt;&lt;br /&gt;/* Triggered at the beginning of a thread */&lt;br /&gt;static void php_myextension_globals_ctor(zend_myextension_globals *myext_globals TSRMLS_DC)&lt;br /&gt;{&lt;br /&gt;   myext_globals-&gt;foo = 0;&lt;br /&gt;   myext_globals-&gt;bar = NULL;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;/* Triggered at the end of a thread */&lt;br /&gt;static void php_myextension_globals_dtor(zend_myextension_globals *myext_globals TSRMLS_DC)&lt;br /&gt;{&lt;br /&gt;   if (myext_globals-&gt;bar) {&lt;br /&gt;       efree(myext_globals-&gt;bar);&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;PHP_MINIT_FUNCTION(myextension)&lt;br /&gt;{&lt;br /&gt;#ifdef ZTS&lt;br /&gt;   ts_allocate_id(&amp;amp;myextension_globals_id, sizeof(zend_myextension_globals),&lt;br /&gt;                  php_myextension_globals_ctor, php_myextension_globals_dtor);&lt;br /&gt;#else&lt;br /&gt;   php_myextension_globals_ctor(&amp;amp;myextension_globals TSRMLS_CC);&lt;br /&gt;#endif&lt;br /&gt;&lt;br /&gt;   return SUCCESS;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;PHP_MSHUTDOWN_FUNCTION(myextension)&lt;br /&gt;{&lt;br /&gt;#ifndef ZTS&lt;br /&gt;   php_myextension_globals_dtor(&amp;amp;myextension_globals TSRMLS_CC);&lt;br /&gt;#endif&lt;br /&gt;&lt;br /&gt;   return SUCCESS;&lt;br /&gt;}&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/blockquote&gt; &lt;p&gt;Here you can see the extension declaring its global requirements to the TSRM layer by stating that it needs &lt;span style="font-family: courier;"&gt;sizeof(zend_myextension_globals)&lt;/span&gt; bytes of storage, and providing callbacks to use when initializing (or destroying) a given thread's local storage. The value populated into &lt;span style="font-family: courier;"&gt;myextension_globals_id&lt;/span&gt; represents the offset (common to all threads) into the &lt;span style="font-family: courier;"&gt;tsrm_ls&lt;/span&gt; vector where the pointer to that thread's local storage can be found. In the event that ZTS is not enabled, the data storage is simply placed into the true global scope and the thread initialization and shutdown routines are called manually during the Module's Startup and Shutdown phases. If you're wondering why &lt;span style="font-family: courier;"&gt;TSRMLS_CC&lt;/span&gt; was included in the non-ZTS blocks, then I clearly havn't made you fall asleep yet. Those aren't needed there since we know they evaluate to nothing, but it helps encourage good habits to include them anywhere the function's prototype calls for them.&lt;/p&gt;&lt;br /&gt;&lt;h3&gt;Putting it all together&lt;/h3&gt; &lt;p&gt;The final piece of this thread-safe puzzle comes from the question: "How do I access data in these structures?" And the answer to that question comes in the form of another familiar looking macro. Each extension or core component defines, in one of its header files, a macro which looks something like the following:&lt;/p&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;span style="font-size:78%;"&gt;&lt;span style="font-family: courier new;"&gt;#ifdef ZTS&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;# define   MYEXTENSION_G(v)     \&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;             (((zend_myextension_globals*)(*((void ***)tsrm_ls))[(myextension_globals_id)-1])-&gt;v)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;#else&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;# define   MYEXTENSION_G(v)     (myextension_globals.v)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;#endif&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/blockquote&gt; &lt;p&gt;Thus, when ZTS is not enabled, this macro simply plucks the right value out of the imediate value in the global scope, otherwise it uses the ID to locate the thread's local storage copy of the structure and derefence the value from there.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Wanna know more, like how to deal with foreign callbacks where &lt;span style="font-family: courier;"&gt;tsrm_ls&lt;/span&gt; isn't available?  &lt;b&gt;Buy my book!&lt;/b&gt;&lt;/p&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1234953837283832282-2778191266369728679?l=blog.golemon.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.golemon.com/feeds/2778191266369728679/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.golemon.com/2006/06/what-heck-is-tsrmlscc-anyway.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1234953837283832282/posts/default/2778191266369728679'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1234953837283832282/posts/default/2778191266369728679'/><link rel='alternate' type='text/html' href='http://blog.golemon.com/2006/06/what-heck-is-tsrmlscc-anyway.html' title='What the heck is TSRMLS_CC, anyway?'/><author><name>Sara Golemon</name><uri>http://www.blogger.com/profile/14557640555210645219</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1234953837283832282.post-91752335487318752</id><published>2006-05-24T10:15:00.000-07:00</published><updated>2010-10-21T13:48:24.325-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='zend'/><category scheme='http://www.blogger.com/atom/ns#' term='favorite'/><category scheme='http://www.blogger.com/atom/ns#' term='compiled variables'/><category scheme='http://www.blogger.com/atom/ns#' term='php'/><category scheme='http://www.blogger.com/atom/ns#' term='CV'/><title type='text'>Compiled Variables</title><content type='html'>&lt;span class="entry-content"&gt;&lt;p&gt;Last month at &lt;a href="http://www.phparch.com/tek/"&gt;php|tek&lt;/a&gt; I gave a presentation on "How PHP Ticks" where I covered, among other things the process of compiling source code into opcodes (an intermediate psuedo-language similar to what java calls "bytecode" or what .NET calls "MSIL"). As part of this section of the presentation, I showed one of the more interresting changes between ZE 2.0 (PHP 5.0) and ZE 2.1 (PHP 5.1), namely: How variables are retreived and used in an operation. More specifically, how they provide a small, yet cumulative, speedup to applications in a way that's transparent to the end-user -- One more reason to like PHP 5.1 right?&lt;/p&gt;&lt;br /&gt;&lt;p&gt;After listening to Marcus Whitney's &lt;a href="http://podcast.phparch.com/main/index.php/episodes:20060519"&gt;interview with Brion Vibber of WikiMedia&lt;/a&gt; in which he mentions my presentation and makes reference to this engine change, I realized that I should clarify what this feature is (and more importantly, what it isn't) before any FUD spreads.&lt;/p&gt;&lt;/span&gt;                                      &lt;h3&gt;What Compiled Variables (CVs) are&lt;/h3&gt; &lt;p&gt;First, let's look at the anantomy of an OpArray.  Say you have the following simple script:&lt;/p&gt; &lt;blockquote&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;?php&lt;br /&gt;$a = 123;&lt;br /&gt;$b = 456;&lt;br /&gt;$c = $a + $b;&lt;br /&gt;echo $c;&lt;br /&gt;&lt;/pre&gt;&lt;/blockquote&gt; &lt;p&gt;Now let's see how ZE 2.0 (PHP5.0) compiles this (ZE1.x/PHP4.x comes out to nearly identical opcodes). The $0 and ~0 references you see are (for lack of a better one sentence explanation) types of temporary variables (the latter moreso than the former, but don't worry about the distinction right now). What's important to know about this block and its statements are in the accompaning comments:&lt;/p&gt; &lt;blockquote&gt;&lt;pre&gt;&lt;span style="font-size:78%;"&gt;&lt;span style="font-family:courier new;"&gt;FETCH_W                  $0, 'a'          /* Retreive the $a variable for writing */&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;ASSIGN                   $1, $0, 123      /* Assign the numeric value 123 to retreived variable 0 */&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;FETCH_W                  $2, 'b'          /* Retreive the $b variable for writing */&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;ASSIGN                   $3, $2, 456      /* Assign the numeric value 456 to retreived variable 2 */&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;FETCH_R                  $5, 'a'          /* Retreive the $a variable for reading */&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;FETCH_R                  $6, 'b'          /* Retreive the $b variable for reading */&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;ADD                      ~7, $5, $6       /* Add the retreived variables (5 &amp;amp; 6) to gether and store the result in 7 */&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;FETCH_W                  $4, 'c'          /* Retreive the $c variable for writing */&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;ASSIGN                   $8, $4, ~7       /* Assign the value in temporary variable 7 into retreived variable 4 */&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;FETCH_R                  $9, 'c'          /* Retreive the $c variable for reading */&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;ECHO                         $9           /* Echo the retreived variable 9 */&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/blockquote&gt; &lt;p&gt;Seem like a lot of work for one plus one?  It is, here's the same code snippet compiled by ZE 2.1/PHP 5.1 (or later).&lt;/p&gt; &lt;blockquote&gt;&lt;pre&gt;&lt;span style="font-size:78%;"&gt;&lt;span style="font-family:courier new;"&gt;ASSIGN                   $0, !0, 123      /* Assign the numeric value 123 to compiled variable 0 */&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;ASSIGN                   $1, !1, 456      /* Assign the numeric value 456 to compiled variable 1 */&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;ADD                      ~2, !0, !1       /* Add compiled variable 0 to compiled variable 1 */&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;ASSIGN                   $3, !2, ~2       /* Assign the value of temporary variable 2 to compiled variable 2 */&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;ECHO                         !2           /* Echo the value of compiled variable 2 */&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/blockquote&gt; &lt;p&gt;These !0 variables refer to a new structure in the execution stack which stores and references to the "real" variables out in userspace. The hash value for each variable is computed at compile time (meaning that it's only done once per variable no matter how often it's used and that opcode caches save this work from being done during subsequent page views at all). The first time one of these CVs is used, the engine looks it up in the active symbol table and updates the CV cache to know where it is. All subsequent uses of that compiled variable use that pre-fetched address and don't have to look it up again. On an individual lookup, this isn't a major leap forward in speed, however consider a for loop where the test value is checked on every iteration; To put it in PHP terms, which would you rather do?&lt;/p&gt; &lt;blockquote&gt;&lt;pre&gt;&lt;span style=";font-family:courier new;font-size:78%;"  &gt;for($i = 0; $i &lt; foo =" lookup_variable('foo');"&gt;increment();&lt;br /&gt;$foo = lookup_variable('foo');&lt;br /&gt;$foo-&gt;check_value();&lt;br /&gt;}&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/blockquote&gt; &lt;p&gt;or&lt;/p&gt; &lt;blockquote&gt;&lt;pre&gt;&lt;span style=";font-family:courier new;font-size:78%;"  &gt;$foo = lookup_variable('foo');&lt;br /&gt;for($i = 0; $i &lt;&gt;increment();&lt;br /&gt;$foo-&gt;check_value();&lt;br /&gt;}&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;h3&gt;What compiled variables are not&lt;/h3&gt; &lt;p&gt;Don't assume you're going to get a speedup on all of your code, especially if you use arrays or objects (which most code taking advantage of PHP5's new features does). The CV speedup has one minor achilles heel: It only works on simple variables. Putting it in terms of opcodes, let's consider this PHP source:&lt;/p&gt; &lt;blockquote&gt;&lt;pre&gt;&lt;span style="font-size:78%;"&gt;&amp;lt;?php&lt;br /&gt;$f-&gt;a = 123;&lt;br /&gt;$f-&gt;b = 456;&lt;br /&gt;$f-&gt;c = $f-&gt;a + $f-&gt;b;&lt;br /&gt;echo $f-&gt;c;&lt;br /&gt;?&gt;&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/blockquote&gt; &lt;p&gt;Basicly the same code right?  Just a little oopified...  Let's look at the ZE2.1/PHP5.1 compilation of that:&lt;/p&gt; &lt;blockquote&gt;&lt;pre&gt;&lt;span style="font-size:78%;"&gt;ASSIGN_OBJ                $0, !0, 'a'     /* Assign the numeric value 123 to property 'a' of compiled variable 0 object */&lt;br /&gt;OP_DATA                       123         /* Additional data for ASSIGN_OBJ opcode */&lt;br /&gt;ASSIGN_OBJ                $1, !0, 'b'     /* Assign the numeric value 456 to property 'b' of compiled variable 0 object */&lt;br /&gt;OP_DATA                       456         /* Additional data for ASSIGN_OBJ opcode */&lt;br /&gt;FETCH_OBJ_R               $3, !0, 'a'     /* Retreive property 'a' from compiled variable 0 object */&lt;br /&gt;FETCH_OBJ_R               $4, !0, 'b'     /* Retreive property 'b' from compiled variable 0 object */&lt;br /&gt;ADD                       ~5, $3, $4      /* Add those values and store the result in temp var 5 */&lt;br /&gt;ASSIGN_OBJ                $2, !0, 'c'     /* Assign the ADD result to property 'c' of compiled variable 0 object */&lt;br /&gt;OP_DATA                       ~5          /* Additional data for ASSIGN_OBJ opcode */&lt;br /&gt;FETCH_OBJ_R               $6, !0, 'c'     /* Retreive property 'c' from compiled variable 0 object */&lt;br /&gt;ECHO                          $6          /* Echo the value */&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/blockquote&gt; &lt;p&gt;What's important to see here is that the properties are refetched each time a read or write is performed on them, which at first glance looks as bad as the pre PHP5.1 way of dealing with variables. Don't let your enthusiam for compiled variables blind you though. Remember the magic __get(), __set(), __offsetget(), and __offsetset() methods which objects allow for. These overloading tricks are great, but they mean that the variable returned by one fetch may not be the variable returned by a subsequent fetch. It's unfortunate that this can't be guaranteed, but it's the reality of a dynamic language like PHP. Know your particular class isn't overloaded? You can get that speedup (at least some of it) back by using good 'ol references to turn your object variables into simple variables:&lt;/p&gt; &lt;blockquote&gt;&lt;pre&gt;&lt;span style="font-size:78%;"&gt;&amp;lt;?php&lt;br /&gt;$a = &amp;amp;$f-&gt;a;&lt;br /&gt;$b = &amp;amp;$f-&gt;b;&lt;br /&gt;$c = &amp;amp;$f-&gt;c;&lt;br /&gt;$a = 123;&lt;br /&gt;$b = 456;&lt;br /&gt;$c = $a + $b;&lt;br /&gt;echo $c;&lt;br /&gt;?&gt;&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/blockquote&gt; &lt;p&gt;Becomes:&lt;/p&gt; &lt;blockquote&gt;&lt;pre&gt;&lt;span style="font-size:78%;"&gt;FETCH_OBJ_W               $0, !1, 'a'     /* Retreive property 'a' from compiled variable 1 object */&lt;br /&gt;ASSIGN_REF                $1, !0, $0      /* Make compiled variable 0 a reference to the retreived variable */&lt;br /&gt;FETCH_OBJ_W               $2, !1, 'b'     /* Retreive property 'b' from compiled variable 1 object */&lt;br /&gt;ASSIGN_REF                $3, !2, $2      /* Make compiled variable 2 a reference to the retreived variable */&lt;br /&gt;FETCH_OBJ_W               $4, !1, 'c'     /* Retreive property 'c' from compiled variable 1 object */&lt;br /&gt;ASSIGN_REF                $5, !3, $4      /* Make compiled variable 3 a reference to the retreived variable */&lt;br /&gt;ASSIGN                    $6, !0, 123     /* Assign the numeric value 123 to compiled variable 0 */&lt;br /&gt;ASSIGN                    $7, !2, 456     /* Assign the numeric value 456 to compiled variable 2 */&lt;br /&gt;ADD                       ~8, !0, !2      /* Add compiled variable 0 to compiled variable 2 */&lt;br /&gt;ASSIGN                    $9, !3, ~8      /* Assign the value of temporary variable 8 to compiled variable 3 */&lt;br /&gt;ECHO                          !3          /* Echo the value of compiled variable 3 */&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/blockquote&gt; &lt;p&gt;Now, this particular example is actually a few more opcodes, and a little bit more work for the engine too, but the more your code following this point uses the local/simple-variable/reference copies rather than the object copies, the balance will quickly tip towards your favor because the variables are already fetched, and they don't need to go through the expensive re-fetch process (which is worse for objects than it ever was for regular variables).&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Another caveat to CVs, is that they are entirely scope-local. This should make since as $a in the globals scope is not the same as $a in a given function. What this means for your script, is that when execution enters a new function (execution scope) the CVs for that function are a blank slate and everything has to be fetched anew, even if that function was called before.&lt;/p&gt; &lt;h3&gt;Globals and Statics&lt;/h3&gt; &lt;p&gt;Statics and Globals are treated to CV status, but only by way of the reference trick I just mentioned:&lt;/p&gt; &lt;blockquote&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;?php&lt;br /&gt;static $bar;&lt;br /&gt;echo $bar;&lt;br /&gt;&lt;/pre&gt;&lt;/blockquote&gt; &lt;p&gt;Turns into:&lt;/p&gt; &lt;blockquote&gt;&lt;pre&gt;&lt;span style="font-size:78%;"&gt;FETCH_W      static      $0, 'bar'&lt;br /&gt;ASSIGN_REF                   !0, $0&lt;br /&gt;ECHO                         !0&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/blockquote&gt; &lt;p&gt;What does that mean for your use of the &lt;span style="font-family:courier;"&gt;$GLOBALS&lt;/span&gt; array?  That's right, the global keyword is &lt;i&gt;technically&lt;/i&gt; faster. &lt;disclaimer&gt;Now, I want to be really clear about one thing here. The minor speed affordance given by using your globals as localized CVs needs to be seriously weighed against the maintainability of looking at your code in five years and knowing that &lt;span class="font-family: courier"&gt;$foo&lt;/span&gt; came from the global scope.  &lt;span style="font-family:courier;"&gt;something_using($GLOBALS['foo']);&lt;/span&gt; will ALWAYS be clearer to you down the line than &lt;span style="font-family:courier;"&gt;global $foo; /* buncha code */ something_using($foo);&lt;/span&gt;  Don't be penny-wise and pound foolish.&lt;/disclaimer&gt;.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;b&gt;No, seriously.  This post shouldn't be taken as a guide-book to speeding up your apps, they're slow for other reasons.&lt;/b&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1234953837283832282-91752335487318752?l=blog.golemon.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.golemon.com/feeds/91752335487318752/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.golemon.com/2006/05/last-month-at-phptek-i-gave.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1234953837283832282/posts/default/91752335487318752'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1234953837283832282/posts/default/91752335487318752'/><link rel='alternate' type='text/html' href='http://blog.golemon.com/2006/05/last-month-at-phptek-i-gave.html' title='Compiled Variables'/><author><name>Sara Golemon</name><uri>http://www.blogger.com/profile/14557640555210645219</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1234953837283832282.post-8623411030578766695</id><published>2006-05-10T15:48:00.000-07:00</published><updated>2010-04-20T16:39:38.413-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='fail'/><category scheme='http://www.blogger.com/atom/ns#' term='php'/><title type='text'>Doctor! Doctor! It hurts when I do this!</title><content type='html'>&lt;div class="serendipity_entry_body"&gt;  &lt;span class="entry-content"&gt;&lt;p&gt;I came across a bug while working on &lt;a href="http://pecl.php.net/packages/runkit"&gt;runkit&lt;/a&gt; today. On testing a batch of changes I'd made I was suddenly* running into a buffer overrun error on any request which instantiates the &lt;a href="http://www.php.net/Runkit_Sandbox"&gt;Runkit_Sandbox&lt;/a&gt; class.  A few valgrind and gdb rounds later and I'd traced the corruption to &lt;span style="font-family: courier;"&gt;apc.enabled&lt;/span&gt;'s ini_entry-&gt;value which was actually encountering a form of double-free.&lt;/p&gt;&lt;br /&gt; &lt;p&gt;Now, I have no illusions regarding the fact that runkit is a black sheep. The things it does are contrary to PHP's design and probably shouldn't be done, so my first assumption is that APC is not the one at fault and that runkit is just coincidentally stepping on APC's toes. Time to break out the caffeine and get dirty...&lt;/p&gt;&lt;/span&gt;                                      &lt;div class="serendipity_entry_extended"&gt;&lt;p&gt;After a little more digging I notice this block of code in APC:&lt;/p&gt;&lt;br /&gt;&lt;pre style="font-family: courier new;"&gt;&lt;span style="font-size:78%;"&gt;PHP_MINIT_FUNCTION(apc)&lt;br /&gt;{&lt;br /&gt;   ZEND_INIT_MODULE_GLOBALS(apc, php_apc_init_globals, php_apc_shutdown_globals);&lt;br /&gt;&lt;br /&gt;   REGISTER_INI_ENTRIES();&lt;br /&gt;&lt;br /&gt;   /* Disable APC in cli mode unless overridden by apc.enable_cli */&lt;br /&gt;   if(!APCG(enable_cli) &amp;amp;&amp;amp; !strcmp(sapi_module.name, "cli")) {&lt;br /&gt;       zend_alter_ini_entry("apc.enabled", sizeof("apc.enabled"), "0", 1,&lt;br /&gt;                       PHP_INI_SYSTEM, PHP_INI_STAGE_ACTIVATE);&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   if (APCG(enabled)) {&lt;br /&gt;       apc_module_init(module_number TSRMLS_CC);&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   return SUCCESS;&lt;br /&gt;}&lt;/span&gt;&lt;/pre&gt; &lt;p&gt;Ignore for the moment the fact that it's claiming we're in the &lt;span style="font-family: courier;"&gt;ACTIVATE&lt;/span&gt; stage (we're really in the &lt;span style="font-family: courier;"&gt;STARTUP&lt;/span&gt; phase -- but that's not where the problem lies).  The problem with this statement is that &lt;span style="font-family: courier;"&gt;zend_alter_ini_entry()&lt;/span&gt; uses &lt;span style="font-family: courier;"&gt;estrndup()&lt;/span&gt;, a call which assumes that thread storage has been spun up and that the per-request pointer list is ready for the new entry to be indexed. During &lt;span style="font-family: courier;"&gt;MINIT&lt;/span&gt;, that's just not the case.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;The "right" solution for this is to move the &lt;span style="font-family: courier;"&gt;CLI&lt;/span&gt; mode override to &lt;span style="font-family: courier;"&gt;RINIT&lt;/span&gt; and sure enough, this fixes the overrun/double-free issues just fine. The trouble is, it's also a wasteful proposition. Compound this by the fact that the error only presents itself when all of the following conditions are met:&lt;/p&gt; &lt;ul&gt;&lt;li&gt;APC being used on command line&lt;/li&gt;&lt;li&gt;apc.enable_cli switch not set&lt;/li&gt;&lt;li&gt;Thread Safety turned on (requires &lt;span style="font-family: courier;"&gt;--enable-maintainer-zts&lt;/span&gt; during bulid)&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;Should APC take a performance hit in order to satisfy such an edge case scenario? &amp;amp;#@% NO! This is one bug that can be casually swept under the rug. Move along now, nothing to see here.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;P.S. - In case you were wondering, the only reason I didn't notice this before is that I'd only just recently added APC to my development build. The coincidence of this bug showing up with this last batch of changes was precisely that, a coincidence.&lt;/p&gt;&lt;/div&gt;                      &lt;/div&gt;          &lt;!--         &lt;rdf:rdf rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" trackback="http://madskills.com/public/xml/rss/module/trackback/" dc="http://purl.org/dc/elements/1.1/"&gt;         &lt;rdf:description about="http://blog.libssh2.org/index.php?/feeds/ei_20.rdf" ping="http://blog.libssh2.org/comment.php?type=trackback&amp;amp;entry_id=20" title="Doctor! Doctor! It hurts when I do this!" identifier="http://blog.libssh2.org/index.php?/archives/20-Doctor!-Doctor!-It-hurts-when-I-do-this!.html"&gt;         &lt;/rdf:RDF&gt;         --&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1234953837283832282-8623411030578766695?l=blog.golemon.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.golemon.com/feeds/8623411030578766695/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.golemon.com/2006/05/doctor-doctor-it-hurts-when-i-do-this.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1234953837283832282/posts/default/8623411030578766695'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1234953837283832282/posts/default/8623411030578766695'/><link rel='alternate' type='text/html' href='http://blog.golemon.com/2006/05/doctor-doctor-it-hurts-when-i-do-this.html' title='Doctor! Doctor! It hurts when I do this!'/><author><name>Sara Golemon</name><uri>http://www.blogger.com/profile/14557640555210645219</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1234953837283832282.post-6448318050554253530</id><published>2006-05-08T17:51:00.000-07:00</published><updated>2010-04-20T16:40:14.760-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='sql'/><category scheme='http://www.blogger.com/atom/ns#' term='pecl'/><category scheme='http://www.blogger.com/atom/ns#' term='re2c'/><category scheme='http://www.blogger.com/atom/ns#' term='php'/><category scheme='http://www.blogger.com/atom/ns#' term='pdo'/><title type='text'>re2c is no lemon</title><content type='html'>&lt;div class="serendipity_entry_body"&gt;  &lt;span class="entry-content"&gt;&lt;p&gt;For the longest time I've been wanting to learn how to actually write a compiler. Sure, I've been twiddling the Zend Engine here and there for a few years, but there's this gulf between tweaking and actually building up from scratch which, until today, I had just never found my way across. Enter &lt;a href="http://pecl.php.net/package/pdo_user"&gt;PDO_User&lt;/a&gt;, my most recent extension for implementing PDO drivers in userspace. Although some uses of PDO_User might be as simple as wrapping real database drivers that don't have a PDO version (e.g. informix), there's also a class of userspace implementation that might want to perform decidedly non-SQL actions via a SQL front end.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Since writing a compiler in userspace is... difficult to say the least, I decided this was the perfect opportunity to sharpen my teeth on the task and provide a generic SQL compiler via the PDO_User class. For the lexer I chose &lt;a href="http://re2c.sourceforge.net/"&gt;re2c&lt;/a&gt; as Marcus has been pushing that and what I'd seen of the syntax made it look pretty straight forward, for the parser I went with &lt;a href="http://www.hwaci.com/sw/lemon/"&gt;lemon&lt;/a&gt; which &lt;a href="http://netevil.org/"&gt;Wez&lt;/a&gt; is generally ga-ga over. I considerd flex and yacc, but tossed them out since I've already got a basic understanding of their syntaxes. I wanted a start fresh.&lt;/p&gt;&lt;/span&gt;                                      &lt;div class="serendipity_entry_extended"&gt;&lt;p&gt;After a couple-three days and some aborted attempts, I've managed to implement a relatively feature-rich SQL tokenizer and compiler accessible to userspace via &lt;span style="font-family:courier;"&gt;array PDO_User::tokenizeSQL($sql[, $ignore_whitespce=true])&lt;/span&gt; and &lt;span style="font-family:courier;"&gt;array PDO_User::parseSQL($sql)&lt;/span&gt;. Those of you intimately familiar with SQL specs will certainly find faults in my grammar, and just about everyone should notice that there's no support for floating point numbers yet (a minor oversight). What's important is: (A) I've got a working implementation to build from, and (B) It was damned easy to learn both these tools.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Some thoughts on re2c and lemon: &lt;/p&gt;&lt;ul&gt;&lt;li&gt;Not enough samples provided on the manual pages. As an OSS documentation maintainer myself I know that this is easier to complain of than actually do something about.&lt;/li&gt;&lt;li&gt;I got stuck early on with re2c due to having an old version (the one packaged with debian) which didn't support case-insensitive matching. If you run into this problem, check your re2c version. If `re2c -v` isn't even able to output a version, then it's certainly too old.&lt;/li&gt;&lt;li&gt;What the @!#&amp;amp; is the "error" non-terminal for in lemon? The documentation talks about using it to gracefully deal with parse errors, but doesn't talk about how to use it.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;p&gt;If all you want is some sample output, have a look at this:&lt;br /&gt;&lt;/p&gt;&lt;dir&gt; &lt;pre&gt;&lt;span style="font-family:courier new;"&gt;&amp;lt;?php&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  print_r(PDO_User::parseSQL("SELECT foo,bar as b,baz&lt;br /&gt;                            FROM boop LEFT JOIN doop as d&lt;br /&gt;                            ON (bid=did)"));&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Array&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;(&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  [type] =&gt; statement&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  [statement] =&gt; select&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  [fields] =&gt; Array&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;    (&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;      [0] =&gt; foo&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;      [1] =&gt; Array&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;        (&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;          [type] =&gt; alias&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;          [field] =&gt; bar&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;          [as] =&gt; b&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;        )&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;      [2] =&gt; baz&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;    )&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  [from] =&gt; Array&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;    (&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;      [type] =&gt; join&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;      [table1] =&gt; boop&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;      [join-type] =&gt; left&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;      [table2] =&gt; Array&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;        (&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;          [type] =&gt; alias&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;          [table] =&gt; doop&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;          [as] =&gt; d&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;        )&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;      [on] =&gt; Array&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;        (&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;          [type] =&gt; condition&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;          [op1] =&gt; bid&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;          [condition] =&gt; =&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;          [op2] =&gt; did&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;        )&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;    )&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  [modifiers] =&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  [terminating-semicolon] =&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt; &lt;/dir&gt;&lt;/div&gt;                      &lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1234953837283832282-6448318050554253530?l=blog.golemon.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.golemon.com/feeds/6448318050554253530/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.golemon.com/2006/05/re2c-is-no-lemon.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1234953837283832282/posts/default/6448318050554253530'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1234953837283832282/posts/default/6448318050554253530'/><link rel='alternate' type='text/html' href='http://blog.golemon.com/2006/05/re2c-is-no-lemon.html' title='re2c is no lemon'/><author><name>Sara Golemon</name><uri>http://www.blogger.com/profile/14557640555210645219</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1234953837283832282.post-2889715794556356548</id><published>2006-05-03T14:59:00.000-07:00</published><updated>2010-04-20T16:34:28.995-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='conference'/><category scheme='http://www.blogger.com/atom/ns#' term='pecl'/><category scheme='http://www.blogger.com/atom/ns#' term='php'/><title type='text'>PDO_User and the effects of Slide Driven Development</title><content type='html'>&lt;div class="serendipity_entry_body"&gt;  &lt;span class="entry-content"&gt;&lt;p&gt;Last Fall, &lt;a href="http://www.netevil.org/" alt="Wez Furlong"&gt;Wez&lt;/a&gt; and I (and others) met up at the &lt;a href="http://www.zend.com/" alt="Zend Technologies"&gt;Zend&lt;/a&gt; conferrence in Burlingame, CA (US). This was primarily a pre-PDM checkin for those of us who wouldn't be able to make it to Paris to get our thoughts in on the direction of PHP6. Apart from these topics, Wez mentioned wanting to have a userspace bridge for implementing &lt;a href="http://www.php.net/pdo"&gt;PDO&lt;/a&gt; drivers, but that there was entirely too much going on that was (in all honesty) more important.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;I agreed on both counts. At the time I was doing my best to ignore the temptation to work on &lt;a href="http://pecl.php.net/package/operator" alt="PHP Operator Overloading"&gt;operator&lt;/a&gt;... Click through and you'll see just how weak willed I can be :)&lt;/p&gt;&lt;/span&gt;                                      &lt;div class="serendipity_entry_extended"&gt;&lt;p&gt;Fast forward to last week in Orlando, FL (US) and the &lt;a href="http://www.phparch.com/tek/"&gt;php|tek&lt;/a&gt; conferrence. As mentioned in earlier blog posts, I think my presentations went over okay for a first couple of talks, but if I have to make one complaint, it's that the subject matter was ill-aimed. I spoke to &lt;a href="http://blog.phpdoc.info/" alt="Sean Coates"&gt;Sean&lt;/a&gt; (one of the conferrence organizers) after the closing keynote and asked him about the upcoming php|works conf in toronto. When he said that one of the focuses would be on database interaction (since it would be taking place along side db|works), my thoughts immediately jumped to the PDO userspace driver which had been running around the back of my mind for months.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;By the end of my flight back I had half the implementation written and had generally come to the conclusion that the PDO API was pretty damned nice. Long story short, I've just uploaded release 0.1 of &lt;a href="http://pecl.php.net/package/pdo_user"&gt;pdo_user&lt;/a&gt; which is ready for testing. The file you'll want to pay attention to is: &lt;a href="http://cvs.php.net/pecl/pdo_user/README.OBJECTS"&gt;README.OBJECTS&lt;/a&gt; as that describes the mechanics of actually implementing a driver in userspace. Another interresting spot to look is &lt;a href="http://cvs.php.net/pecl/pdo_user/tests/globals.phpt"&gt;tests/globals.phpt&lt;/a&gt; which includes a simple, yet functional userspace driver for accessing variable contents as database resources.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;I don't expect it to work perfect right out of the box, but it should get the job done. Please &lt;a href="http://pecl.php.net/bugs/report.php?package=pdo_user"&gt;Report Bugs&lt;/a&gt; when you find them so I can get 'em fixed.&lt;/p&gt;&lt;/div&gt;                      &lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1234953837283832282-2889715794556356548?l=blog.golemon.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.golemon.com/feeds/2889715794556356548/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.golemon.com/2006/05/pdouser-and-effects-of-slide-driven.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1234953837283832282/posts/default/2889715794556356548'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1234953837283832282/posts/default/2889715794556356548'/><link rel='alternate' type='text/html' href='http://blog.golemon.com/2006/05/pdouser-and-effects-of-slide-driven.html' title='PDO_User and the effects of Slide Driven Development'/><author><name>Sara Golemon</name><uri>http://www.blogger.com/profile/14557640555210645219</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1234953837283832282.post-6857285210898816511</id><published>2006-04-28T18:25:00.000-07:00</published><updated>2010-04-20T16:31:48.457-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='conference'/><category scheme='http://www.blogger.com/atom/ns#' term='php'/><category scheme='http://www.blogger.com/atom/ns#' term='DYG'/><title type='text'>Let's go out to the movies</title><content type='html'>&lt;span class="entry-summary"&gt;&lt;p&gt;As promised yesterday, I've gotten the videos from php|tek uploaded. Note: They're all coverage of the beer chugging contest, so don't expect to be clicking into any presentations.&lt;/p&gt;&lt;p&gt; &lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;a title="Winner: Andrei" href="http://flickr.com/photos/pollita/2401224645/"&gt;Andrei vs Chris&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a title="Winner: Andrei" href="http://flickr.com/photos/pollita/2402061608/"&gt;Andrei vs Amy&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a title="Winner: ???" href="http://flickr.com/photos/pollita/2401234257/"&gt;Rasmus vs Joe&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a title="Winner and Still Champion: Andrei" href="http://flickr.com/photos/pollita/2401230055/"&gt;Andrei vs Chris: The Rematch&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a title="Winner: Sara" href="http://flickr.com/photos/pollita/2402064248/"&gt;Ilia vs Sara&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a title="Winner: Chris" href="http://flickr.com/photos/pollita/2401235083/"&gt;Ilia vs Chris&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1234953837283832282-6857285210898816511?l=blog.golemon.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.golemon.com/feeds/6857285210898816511/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.golemon.com/2006/04/lets-go-out-to-movies.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1234953837283832282/posts/default/6857285210898816511'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1234953837283832282/posts/default/6857285210898816511'/><link rel='alternate' type='text/html' href='http://blog.golemon.com/2006/04/lets-go-out-to-movies.html' title='Let&apos;s go out to the movies'/><author><name>Sara Golemon</name><uri>http://www.blogger.com/profile/14557640555210645219</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1234953837283832282.post-6667767765865904031</id><published>2006-04-23T10:54:00.000-07:00</published><updated>2010-04-20T16:29:37.121-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='sql'/><category scheme='http://www.blogger.com/atom/ns#' term='fail'/><category scheme='http://www.blogger.com/atom/ns#' term='code'/><title type='text'>Please don't code like this...</title><content type='html'>&lt;div class="serendipity_entry_body"&gt;  &lt;span class="entry-summary"&gt;&lt;p&gt;As a component of my job, I'm overseeing a fledgling developer in another department as he sharpens his teeth on putting together a simple application for one of my units. The first draft of his code was....well....It's a good example of why some people associate PHP with insecure applications. After some lengthy back and forths we've cleaned up the security related problems and gotten the functionality working. In my recent code review however, I came across this gem:&lt;/p&gt;&lt;blockquote dir="ltr" style="margin-right: 0px; font-family: courier new;"&gt;&lt;p&gt;&lt;span style="font-size:78%;"&gt;SELECT userid FROM (&lt;br /&gt;SELECT COMPETENCY.userid,&lt;br /&gt;SUM(CASE WHEN COMPETENCY.cid = 1 THEN 1 ELSE 0 END) AS comp_01,&lt;br /&gt;SUM(CASE WHEN COMPETENCY.cid = 2 THEN 1 ELSE 0 END) AS comp_02,&lt;br /&gt;SUM(CASE WHEN COMPETENCY.cid = 3 THEN 1 ELSE 0 END) AS comp_03,&lt;br /&gt;SUM(CASE WHEN COMPETENCY.cid = 4 THEN 1 ELSE 0 END) AS comp_04,&lt;br /&gt;SUM(CASE WHEN COMPETENCY.cid = 5 THEN 1 ELSE 0 END) AS comp_05,&lt;br /&gt;...You get the idea...&lt;br /&gt;SUM(CASE WHEN COMPETENCY.cid = 35 THEN 1 ELSE 0 END) AS comp_35,&lt;br /&gt;SUM(CASE WHEN COMPETENCY.cid = 36 THEN 1 ELSE 0 END) AS comp_36,&lt;br /&gt;SUM(CASE WHEN COMPETENCY.cid = 37 THEN 1 ELSE 0 END) AS comp_37,&lt;br /&gt;SUM(CASE WHEN COMPETENCY.cid = 38 THEN 1 ELSE 0 END) AS comp_38,&lt;br /&gt;SUM(CASE WHEN COMPETENCY.cid = 39 THEN 1 ELSE 0 END) AS comp_39,&lt;br /&gt;SUM(CASE WHEN COMPETENCY.cid = 40 THEN 1 ELSE 0 END) AS comp_40,&lt;br /&gt;FROM COMPETENCY, COMPETENCY_CODE&lt;br /&gt;WHERE COMPETENCY.cid = COMPETENCY_CODE.cid&lt;br /&gt;GROUP BY COMPETENCY.userid) AS my_view&lt;br /&gt;WHERE (comp_20 = 1 AND comp_19 = 1)&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;Now, I generally don't like to be TOO abrasive with new developers, don't want to scare them off or anything, but can someone buy this child a SQL book?&lt;/p&gt;&lt;/span&gt;                                   &lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1234953837283832282-6667767765865904031?l=blog.golemon.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.golemon.com/feeds/6667767765865904031/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.golemon.com/2006/04/please-dont-code-like-this.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1234953837283832282/posts/default/6667767765865904031'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1234953837283832282/posts/default/6667767765865904031'/><link rel='alternate' type='text/html' href='http://blog.golemon.com/2006/04/please-dont-code-like-this.html' title='Please don&apos;t code like this...'/><author><name>Sara Golemon</name><uri>http://www.blogger.com/profile/14557640555210645219</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1234953837283832282.post-2010276660824470391</id><published>2006-04-18T16:10:00.000-07:00</published><updated>2010-04-20T16:25:58.663-07:00</updated><title type='text'>Simple Pleasures</title><content type='html'>About a week ago a coworker came to me for recommendations on hooking up some broadband at home.  I gave her the usual breakdown of the differences between Cable and DSL, what she would need in her laptop to make it connect properly, blah blah blah...  So after a little back and forth she settled on a DSL package which offered a decent price and a wireless package which she was told initially included a pcmcia card (later found out it didn't, but they'd be happy to sell her one...).&lt;br /&gt;&lt;br /&gt;Since her 266Mhz laptop (running Win98E) only had 28MB of memory we ordered her up a 128MB stick to fill the empty slot (she's trying to do this all on a constrained budget, but there are limits!).  We got the memory installed and plugged in an old 10BT pcmcia card I had lying around (a useless spare part to me, but a helpful token for her while she waited for the wireless card to appear) and she was up and running.&lt;br /&gt;&lt;br /&gt;A few days later the 802.11g card appeared and this is where things went wonky.  She installed the full set of the ISP's software (which included absolutely pointless crap that I'd avoided for her initially when I put the wired card in) in order to get to the wireless card drivers.  Not only did the wireless card not work, but the setup died midway, the wired connection stopped working, several random error dialogs started appearing, and the coup de gras.... The backlight on the LCD winked out completely.  In short, her one-year contract with the ISP  was going to be worthless because her only computer had just exploded.&lt;br /&gt;&lt;br /&gt;So she brought the PC back to work with a heartwrenching face of woe.  After two days of twiddling with it in between the stuff UC actually pays me to be doing, the laptop is officially singing.  The software problems just required uninstalling the ISP's mierda, getting updated drivers from the card vendor, and a tiny bit of registry hacking, nothing phenomenal for a IT person, but not something she could have managed without a reinstall (the process of which would have likely led to the same end result).  The LCD was a bit trickier, turns out the lead from the step-up transformer to the backlight lamp had snapped off (coincidental to the software problem, though perhaps aggravated by her frustration induced thwacking) at the bulb so I had to tear open the whole panel and resolder it.  Again, nothing more amazing than (effectively) reseating a cable, but this was fun because I'd never dissasembled a panel to that degree before.&lt;br /&gt;&lt;br /&gt;Best part of all, when I opened up her laptop to show a vibrant screen (actually better than it had looked before all this started) and successful connectivity to AirBears (UCB's wireless network), the look on her face just said it all.&lt;br /&gt;&lt;br /&gt;Sometimes, doing helpdesk work kicks ass.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1234953837283832282-2010276660824470391?l=blog.golemon.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.golemon.com/feeds/2010276660824470391/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.golemon.com/2006/04/simple-pleasures.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1234953837283832282/posts/default/2010276660824470391'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1234953837283832282/posts/default/2010276660824470391'/><link rel='alternate' type='text/html' href='http://blog.golemon.com/2006/04/simple-pleasures.html' title='Simple Pleasures'/><author><name>Sara Golemon</name><uri>http://www.blogger.com/profile/14557640555210645219</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1234953837283832282.post-7673002104121659717</id><published>2006-04-18T14:46:00.000-07:00</published><updated>2010-04-20T16:27:28.979-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='oss'/><category scheme='http://www.blogger.com/atom/ns#' term='php'/><title type='text'>Good Old Times</title><content type='html'>&lt;div class="serendipity_entry_body"&gt;  &lt;span class="entry-summary"&gt;&lt;p&gt;&lt;span style="background-color: rgb(250, 255, 255);"&gt;&lt;a title="Andrei's Good Old Times" href="http://www.gravitonic.com/blog/archives/000140.html"&gt;Andrei&lt;/a&gt; and &lt;a title="Zak's Good Old Times" href="http://zak.greant.com/good-old-times/"&gt;Zak&lt;/a&gt; recently posted their "Good Old Times" references to getting into the PHP project so I thought I'd put &lt;a title="Sara's First Patch" href="http://marc.theaimsgroup.com/?l=php-dev&amp;amp;m=103696559900546&amp;amp;w=2"&gt;mine&lt;/a&gt; forward for good measure.  Never let it be said I'm not a follower...&lt;/span&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;span style="background-color: rgb(250, 255, 255);"&gt;At any rate, it didn't take long for &lt;a title="Derick's Response" href="http://marc.theaimsgroup.com/?l=php-dev&amp;amp;m=103696579500674&amp;amp;w=2"&gt;Derick&lt;/a&gt; to suggest I refer to the CODING_STANDARDS and resubmit the patch as a unified diff against HEAD.  After resubmitting, the patch was accepted and, bouyed by my response, led to another contribution in the form of the &lt;a title="getanyrr()" href="http://marc.theaimsgroup.com/?l=php-dev&amp;amp;m=103748333421127&amp;amp;w=2"&gt;getanyrr()&lt;/a&gt; function which would later come to be named dns_get_record().&lt;/span&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;span style="background-color: rgb(250, 255, 255);"&gt;Three and a half years later and I've managed to touch nearly every part of the PHP Core distribution and make a lot of friends (and perhaps some not-so-friendlies) along the way.  Cheers to all, you know who you are.&lt;/span&gt;&lt;/p&gt;&lt;/span&gt;                                   &lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1234953837283832282-7673002104121659717?l=blog.golemon.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.golemon.com/feeds/7673002104121659717/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.golemon.com/2006/04/good-old-times.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1234953837283832282/posts/default/7673002104121659717'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1234953837283832282/posts/default/7673002104121659717'/><link rel='alternate' type='text/html' href='http://blog.golemon.com/2006/04/good-old-times.html' title='Good Old Times'/><author><name>Sara Golemon</name><uri>http://www.blogger.com/profile/14557640555210645219</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1234953837283832282.post-3201780495217067736</id><published>2006-04-10T11:25:00.000-07:00</published><updated>2010-04-20T16:22:50.797-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='coincidence'/><category scheme='http://www.blogger.com/atom/ns#' term='cats'/><title type='text'>Bunnies bunnies everywhere</title><content type='html'>&lt;span class="entry-content"&gt;&lt;p&gt;I've long been convinced that coincidence is never an accident.  On a day to day basis, the questions that come through ##php will gather in bunches to the point where I can often just up-key to find the last time I answered the question, and state it again.  What does this have to do with bunnies?  I'm glad you asked.&lt;/p&gt;&lt;/span&gt;                                      &lt;p&gt;It started with a random link posted in IRC: &lt;a href="http://blog.jonnay.net/archives/632-Introducing-BunnyRegex-easy-regular-expressions,-and-mini-languages-inside-of-PHP..html"&gt;http://blog.jonnay.net/archives/632-Introducing-BunnyRegex-easy-regular-expressions,-and-mini-languages-inside-of-PHP..html&lt;/a&gt; With a title like that, who can resist?  The topic itself is fairly uninterresting, however it turned the conversation to rabbits, or at least rabbit stew.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Within moments, a coworker came by my office with a thank-you present (I'd helped her upgrade her personal laptop and get setup with DSL at home).  As part of this thank-you present she offered up a stuffed animal (okay, so I have a thing for stuffed animals, sue me).  Guess what species she'd selected?  That's right.  Wabbit.&lt;/p&gt;&lt;p&gt;Is it Fox Mulder spooky? No. But it's a little bit freak-o...&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Speaking of rabbits:  Check out my cat (who happens to be named "Bunny"):&lt;/p&gt;&lt;p&gt;&lt;span&gt;&lt;span class="entry-content"&gt;&lt;a href="http://www.flickr.com/photos/pollita/144088313/in/set-72157594163869323"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 518px; height: 388px;" src="http://farm1.static.flickr.com/44/144088313_1108f33bd9_o.jpg" alt="" border="0" /&gt;&lt;/a&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1234953837283832282-3201780495217067736?l=blog.golemon.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.golemon.com/feeds/3201780495217067736/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.golemon.com/2006/04/bunnies-bunnies-everywhere.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1234953837283832282/posts/default/3201780495217067736'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1234953837283832282/posts/default/3201780495217067736'/><link rel='alternate' type='text/html' href='http://blog.golemon.com/2006/04/bunnies-bunnies-everywhere.html' title='Bunnies bunnies everywhere'/><author><name>Sara Golemon</name><uri>http://www.blogger.com/profile/14557640555210645219</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1234953837283832282.post-5785437947117027590</id><published>2006-01-04T16:38:00.000-08:00</published><updated>2010-04-20T16:14:00.349-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='oss'/><category scheme='http://www.blogger.com/atom/ns#' term='misogyny'/><title type='text'>You're not bad...for a girl...</title><content type='html'>&lt;div class="serendipity_entry_body"&gt;  &lt;span class="entry-summary"&gt;&lt;p&gt;In response to &lt;a href="http://news.php.net/php.internals/21374"&gt;http://news.php.net/php.internals/21374&lt;/a&gt; I offered up a fairly simple extension dubbed "callable" (note, I never wound up dropping this in PECL) which overrides the builtin is_callable() function to call $object-&gt;__callable($methodname) in order to determine if a __call() overloaded object is actually capable of calling a particular method.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;  &lt;p&gt;Those who wanted the funcitonality were happy to have the code and it brought the already-too-long discussion to a close saving list traffic for more important topics.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;That same day, one of the list lurkers sent me an email which included the following.....quizzical paragraph:&lt;/p&gt;&lt;br /&gt;&lt;blockquote style="font-family: courier new;"&gt;Not to sound chauvinistic or anything and not meant to be, but you are a woman, I'm very impressed with the code, it's direct and too the point, not what I would expect from someone of your gender as most female programmers I've come across are into a lot of fluff and eye-candy and not so much in pure functionality.&lt;br /&gt;&lt;br /&gt;&lt;/blockquote&gt;  &lt;p&gt;Now, I'm about 95% certain that he did, in fact mean it as a compliment. And while I appreciate the....hrmmm praise isn't quite the right word...good wishes, I'm not really really clear on just how appreciative I should be. It's a little like what I would expect hearing "You're remarkably well spoken for a black person*." would be like... Or something.... How do you successfully answer a comment like that? Is it even possible?&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;  &lt;p&gt;*Not the cliche'd expression, but my liberal-guilt won't let me use it, even as an example of poor taste.&lt;/p&gt;&lt;/span&gt;                                   &lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1234953837283832282-5785437947117027590?l=blog.golemon.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.golemon.com/feeds/5785437947117027590/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.golemon.com/2006/01/youre-not-badfor-girl.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1234953837283832282/posts/default/5785437947117027590'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1234953837283832282/posts/default/5785437947117027590'/><link rel='alternate' type='text/html' href='http://blog.golemon.com/2006/01/youre-not-badfor-girl.html' title='You&apos;re not bad...for a girl...'/><author><name>Sara Golemon</name><uri>http://www.blogger.com/profile/14557640555210645219</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry></feed>
