Thailand Learnings


I just got back from a trip to Thailand for a friend’s wedding.  I learned a few things and am recording them here:

  • If you’re overweight, the best thing you can do to prepare for the trip is to lose weight.  It will make traveling in small seats more comfortable, walking / climbing easier, you will stand out less, and any new clothes you buy will probably fit. Lots of places we visited didn’t sell XL (much less 2X or larger)
  • Learn some Thai words.  I didn’t know any Thai before the trip.  Now I can say:  Hello/Goodbye, thank you (and thank you very much), you’re welcome, cheers (as in “let’s drink”), drunk (and very drunk), glass, and bathroom.  I also learned to gesticulate like a mad man.  When people speak English at you in a foreign country, it’s a bit like saying “I know Windows” on a resume.  Levels of competence vary, so be prepared to act out whatever you want — talking louder doesn’t help.  Also, if you want another something (e.g. you need another purell) bring the thing you want with you.  Acting out “hand sanitizer” is not easy.
  • Luggage — we brought backpacks.  This turned out to be a good decision for some situations (we had to climb stairs, walk on beaches, etc.) where wheeled luggage would be a hassle.  But in other situations, backpacks were a bad idea.  My wife got a bad sunburn on her back so I had to carry 2 backpacks for a few days.  Also, they weren’t organized well (that was probably user error) so staying for 1 night in a hotel meant you had to explode the whole thing and repack it in the morning.

    Luggage.  We got so sick of moving this crap around.

  • Luggage — look up the luggage policies on the airlines before you go.  We flew three different airlines (2 were domestic to Thailand) and one of them had fairly restrictive luggage policies. I paid the extra $7 to upgrade our luggage to a higher weight class when I bought the tickets, but other group members didn’t.  They paid an extra $40 (I think?) to check all of their luggage.
  • Bring Febreeze.  We went to JJ Market and I took my messenger bag to carry some purchases.  It got a serious infection of “shrimp smell.”  That’s just how the market was.  Febreeze cured it when I got home, but I had to endure that smell for a week.  I would’ve paid a small ransom for a 3 oz spray bottle of Febreeze.
  • Bring rehydration powder.  We didn’t, but it was readily available at local pharmacies.  Unfortunately when you’re dehydrated, you don’t feel like traveling. We were also on an island where access to the main land was only between 10am and 6pm (roughly) so if you didn’t have it, you had to wait.
  • Buy TP when you get there.  They have purse packs at 7-11.  Very few places have TP in the stalls.  You have to grab it before you go in (or ladies, have it in your purse).  Also … they have bidets there.  External ones … like the sprayer in your kitchen sink.
  • Ask the hotel staff to show you how to use the hot water.  All 4 hotels we stayed at had different hot water configurations.  We figured them all out, but some other people in our group took cold showers most days.
  • Plan your layovers.  We had an 8 hour layover in Incheon (Seoul’s airport).  We kinda wanted to do a transit tour (it’s a tour around Seoul where you don’t need a visa or have to go through customs/immigration) but we didn’t realize that it was 34 degrees in Seoul this time of year.  We were in tropical weather wear.  So we grabbed a room at the transit hotel, took a nap, used the wifi, and took a shower.  The layover at your airport may offer different amenities.

There’s so much more I could post … this is the stuff I want to remember for next time we travel.

Things we did right:

  • Called the banks / credit card companies.  All of our credit cards / ATM cards worked.  I even found out that one of my credit cards didn’t charge a foreign transaction fee!
  • Bring your own medicine.  A bite stick (mosquito bites), sun screen, bug spray, purell, pepto bismol tablets, immodium, antibiotics (only if needed), neosporin cream.
  • Look at all the clothes you want to pack, and leave half.  I didn’t wear a few of the ones I brought even then.  I bought some clothes while there, and we had laundry done a few times, too.
  • Keep some toiletries in your carry on.  On our trek back, we had 4 flights (20 hours) over a 2 day span including 17 hours of layover time.  We needed a shower, to brush our teeth, and to reapply deodorant during that window.
  • Mobile data plan — this was half right / half wrong.  I borrowed a phone from Verizon (free) and didn’t make any calls, didn’t send any texts, and sipped data for $25.  My wife’s phone didn’t work (VZW didn’t set something up right?) so we bought a burner phone ($26) and 300 baht ($10) worth of time.  Her phone + time was more expensive, but we used the heck out of it.  If we needed a taxi and couldn’t give the driver directions to the hotel, we’d bust out the thai phone and call the hotel.  I don’t know what was said, but we arrived safely and the meter was running.  She still had like 150 baht when we left, too.  So next time, we’ll bring the $26 phone and just pick up a new SIM (if we go to a diff country) and more time at a gas station / airport.  Her thai phone didn’t do data, but we didn’t need that.  My phone did data, but we didn’t really use it — only in a pinch.

Anthony Bourdain is a personal hero.


I have many personal heroes. When I was young, I appreciated Houdini because he was the world’s greatest magician. As I grew older, I appreciated him because of his ability to shape modern magic as he performed his escapes up close and personal. Then he became quite the salesman, and would show up in a new town frequently to put on a free public daredevil act, then let everyone know he’d be selling tickets to his show.

Magic did pay the bills, but he had other passions. He loved his wife Bess, and together they took on all of the psychics and spiritualist frauds during the day.

I would recommend “The Secret Life of Houdini” for further reading.

… but I digress.

I’m inducting Anthony Bourdain into my list of personal heroes. According to his life story so far:

    • Interested in cooking, but got his butt kicked at a real restarant, and fell in love with the lifestyle
    • Went to CIA (Culinary Institute of America)
    • Got back into a restaurant … then catering …. then bigger / better restaurants …. then eventually he became the head chef at Les Halles in Manhattan

That life path is difficult enough to do. But then he took it further. He wrote an article for a newspaper. And it went well. So he wrote a book. And it was a sensation and instantly legitimized him as a culinary insider, not just a poseur.

From there, he’s written a more books and become a world traveller on “No Reservations.” He was never on vacation, but struggled to make sure his trips were varied and interesting. Frequently, he would engage a host family to feed him or tell him stories. He cooked infrequently, but often explained why the food was so good using his frank descriptions and engaging imagery.

And all of this …. and I don’t have any “Tony Bourdain” products in my kitchen. The man has kept his soul intact.

I will miss “No Reservations.” I look forward to what Tony has coming up next.

KCacheGrind Source Code Annotation on WAMP


KCacheGrind is awesome.  But the source code annotation (the “source code” tab) doesn’t work when the profile originated on a WAMP installation. When you take a profile on Windows, the header of the file looks like this:

version: 1
creator: xdebug 2.1.2
cmd: C:\wamp\www\wordpress\wp-admin\index.php
part: 1
positions: line

And all of the file lines contain similar paths (C:\wamp\www\....\functions.php).

The backslashes seem to confuse KCacheGrind’s path resolution. The simple fix was to convert the backslashes to forward slashes. I did this with sed via cygwin:

sed -i 's/\\/\//g' cachegrind.out.*

You could probably achieve similar results with TextPad or GrepWin, though.

After that, all of the source code annotation worked. If it doesn’t work for you, try adding your source folder under KCacheGrind -> Settings -> Source Annotation.

PHPUnit: process isolation and “constant already defined”


This weekend, some WordPress core devs ported the unit tests over to a new phpunit compatible runner. I was very excited about this, particularly because the tests I maintain define a constant (DOING_AJAX) which can impact other tests.  Using process isolation should remove this impact, although at a performance cost.  I used the @runTestsInSeparateProcesses annotation, but the tests failed.  PHPUnit was restoring the global state (e.g. before the test split into a separate process) and it looked like this:

1.) Define all of the constants that were already defined
2.) Include the included files

This is the wrong process for the WordPress framework though. The included files were responsible for defining the constants. When they are included, they generate notices for defining constants that are already defined (by PHPUnit).

We all put our heads together and came up with a fix (props nacin) by hijacking PHPUnit_Framework_TestCase::prepareTemplate().

class MyTestCase extends PHPUnit_Framework_TestCase {

	/**
	 * Define constants after requires/includes
	 * @param Text_Template $template
	 * @return void
	 */
	public function prepareTemplate( Text_Template $template ) {
		$template->setVar( array(
			'constants'    => '',
			'zz_constants' => PHPUnit_Util_GlobalState::getConstantsAsString()
		));
		parent::prepareTemplate( $template );
	}
}

Yes, this is hacky, and PHPUnit warns that prepareTemplate() was deprecated in 3.4.0. But when we looked, there were no other solutions, except disabling process isolation.

How I built "Have Baby. Need Stuff!"

Reblogged from Mark on WordPress:

Click to visit the original post
  • Click to visit the original post
  • Click to visit the original post
  • Click to visit the original post

Have Baby. Need Stuff! is a baby gear site that my wife and I just launched. I thought I'd share how I built it.

WordPress Core

WordPress is a Git submodule, with the content directory moved to the /content/ directory. This makes my Git repo smaller, as WordPress isn't actually in it.

Underscores

For a theme base, I started with the…

Read more… 1,624 more words

Step by step post on how to make WordPress into a full blown product/category site. No ecomm, but very comprehensive.

Apache Traffic Server as a Reverse Proxy


Varnish is a great tool to have if you need a scriptable proxy server. For most sites, though, this will be more complex than necessary. Check out this article on how to speed up WordPress with Varnish.

I propose that most users don’t need the power of VCL, though. They’d be much better off with a high performance proxy server with RFC 2616 compliance and simple configuration.

Allow me to play devil’s advocate and show you how to build and configure Apache Traffic Server, then show you benchmark results:

# built on centos 6.2
# Get traffic server pre-requisites
yum install gcc-c++ openssl-devel tcl-devel expat-devel pcre-devel make

# Get traffic server
wget http://apache.tradebit.com/pub/trafficserver/trafficserver-3.1.3-unstable.tar.bz2
tar -xf trafficserver-3.1.3-unstable.tar.bz2
cd trafficserver-3.1.3-unstable

# Build traffic server
./configure
make -j 8

# Install traffic server
make install
ln -s /usr/local/bin/trafficserver /etc/init.d/trafficserver
chkconfig --add trafficserver
chkconfig trafficserver on

# Configure traffic server URL map
echo "map http://YOURDOMAIN.COM http://localhost" >> /usr/local/etc/trafficserver/remap.config
echo "reverse_map http://localhost http://YOURDOMAIN.COM" >> /usr/local/etc/trafficserver/remap.config

# Run traffic server
trafficserver restart

Note: Traffic Server runs on port 8080. I used my host’s router to map port 80 -> 8080 and left httpd on port 80.

Since traffic server is now handling all incoming requests, the web server logs will be unreliable. You can rely on an in-browser analytics package, or see how to configure Traffic Server for combined logs.

Configuration done

Let’s benchmark.

Note: my test site is using W3 Total Cache. W3TC sets the cache-control, last-modified, and expires headers on the pages, and static content so that traffic server knows how to best cache your content. You can also use the Varnish integration in W3TC with traffic server. This will purge pages from the traffic server proxy whenever you purge them from W3TC.

Protip: If you need to have Traffic Server work without an expires header or cache-control header, look in records.config and find this section:

# required headers: three options:
#   0 - No required headers to make document cachable
#   1 - "Last-Modified:", "Expires:", or "Cache-Control: max-age" required
#   2 - explicit lifetime required, "Expires:" or "Cache-Control: max-age"
CONFIG proxy.config.http.cache.required_headers INT 2

Look at blitz.io. I used this command in the blitzbar:

# If you paid for blitz, you can max out at 1,000 concurrent users
# -p 1-1000:5,1000-1000:55 -r california -H 'Accept-encoding: gzip' http://YOURDOMAIN.COM/
-p 1-250:1,250-250:59 -r california -H 'Accept-encoding: gzip' http://YOURDOMAIN.COM/

For these benchmarks, I paid to upgrade blitz.io to allow 1,000 concurrent users. At 250 concurrent users, the performance profiles of these systems didn’t really shine through.

Here’s the Varnish benchmark.

blitz.io - Varnish

blitz.io - Varnish

Here’s the Traffic Server benchmark:

blitz.io - Traffic Server

blitz.io - Traffic Server

For comparison, here’s Apache HTTPD alone:

blitz.io - Apache HTTPD

blitz.io - Apache HTTPD

Notice how Varnish doesn’t like the initial influx of connections. Notice how Varnish had more timeouts, too. Notice, too, how much of a difference these caching systems make. Remember, the Apache HTTPD benchmark is already using WordPress + W3 Total Cache.

Let’s look at apachebench for a different view. Using this command, I benchmarked raw Apache HTTPD vs. Varnish vs. Traffic Server. This is all done locally over a loopback connection.

# Change the port to 80 to benchmark apache directly
ab -c 250 -n 1000000 -k -H "Host: YOURDOMAIN.COM" http://127.0.0.1:8080/

Apache results (no chance!):

apr_socket_recv: Connection timed out (110)
Total of 17725 requests completed

Varnish results:

Time taken for tests:   95.049 seconds
Complete requests:      1000000
Failed requests:        0
Requests per second:    10520.83 [#/sec] (mean)
Time per request:       23.762 [ms] (mean)
Time per request:       0.095 [ms] (mean, across all concurrent requests)
Transfer rate:          75257.95 [Kbytes/sec] received

Traffic Server results:

Time taken for tests:   50.971 seconds
Complete requests:      1000000
Failed requests:        0
Requests per second:    19619.00 [#/sec] (mean)
Time per request:       12.743 [ms] (mean)
Time per request:       0.051 [ms] (mean, across all concurrent requests)
Transfer rate:          139371.67 [Kbytes/sec] received
Conclusion

According to blitz.io, Varnish and Traffic Server benchmark results are close. According to ab, Traffic Server is twice as fast as Varnish. Configuration is different in each package. Traffic Server has some unique features like the ability to act as as a forward proxy and a reverse proxy, the ability to proxy SSL connections, a plugin architecture, and will soon have SPDY support. If you haven’t heard of Traffic Server yet, you should check it out. If you’re not using a caching proxy, please start using one!

For more information on Apache Traffic Server, check out this 2011 USENIX presentation (PDF, 10.4 MB) by Leif Hedstrom

Apache combined log format with Traffic Server


If you’re using apache traffic server, all of your traffic is going through your proxy, not your web server.  This is a problem if you rely on your logs for visitor data.

You can get traffic server to output logs in apache’s combined log format, though.  Then you just feed traffic server’s logs to your log analysis app.

Here’s how to do it:

Edit /usr/local/etc/trafficserver/logs_xml.config

Add these lines to the bottom:

<LogFormat>
    <Format = "%<chi> - - [%<cqtn>] \"%<cqhm> %<cquup>\" %<pssc> %<psql> \"%<{Referer}cqh>\" \"%<{User-Agent}cqh>\"" />
    <Name = "httpd_combined"/>
</LogFormat>
<LogObject>
    <Format = "httpd_combined"/>
    <Filename = "access"/>
</LogObject>

Edit /usr/local/etc/trafficserver/logs_records.config

Change

CONFIG proxy.config.log.custom_logs_enabled INT 0

to

CONFIG proxy.config.log.custom_logs_enabled INT 1

Then restart traffic server

trafficserver restart

Now you’ll have an apache combined log file in /usr/local/var/log/trafficserver/access.log

You can read more about apache traffic server’s logging options here and the log formats here.