Archive for the 'performance' Category

Installing a bunch of PNG tools on the Mac

Friday, June 12th, 2009

This is one of those note-to-self type of posts. Just went through the exercise of installing a number of PNG tools on the Mac and here are some notes. The instructions below should probably work on any unix box.

AdvDef, AdvPng, ...

There is a number of Adv* tools (advdef, advpng, advmng, advzip) packed together as AdvComp. Installation difficulty: fairly straighforward.

Download:

$ curl http://softlayer.dl.sourceforge.net/sourceforge/advancemame/advancecomp-1.15.tar.gz \
         > advcomp.tar.gz

Uncompress:

$ tar -xzvf advcomp.tar.gz

Compile and install:

$ cd advancecomp-1.15/
$ sudo ./configure
$ sudo make install

Test:

$ advdef
advancecomp v1.15 by Andrea Mazzoleni
Usage: advpng [options] [FILES...]

Modes:
  -z, --recompress      Recompress the specified files
Options:
  -0, --shrink-store    Don't compress
  -1, --shrink-fast     Compress fast
  -2, --shrink-normal   Compress normal
  -3, --shrink-extra    Compress extra
  -4, --shrink-insane   Compress extreme
  -f, --force           Force the new file also if it's bigger
  -q, --quiet           Don't print on the console
  -h, --help            Help of the program
  -V, --version         Version of the program

Excellent! Next.

OptiPng

OptiPng is another easy install.

Download and decompress:

$ curl http://superb-west.dl.sourceforge.net/sourceforge/optipng/optipng-0.6.3.tar.gz \
            > optipng.tar.gz
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100 1035k  100 1035k    0     0   171k      0  0:00:06  0:00:06 --:--:--  196k
$ tar -xzvf optipng.tar.gz

Compile and install:

$ cd optipng-0.6.3
$ sudo ./configure
$ sudo make install

Test:

$ optipng
OptiPNG 0.6.3: Advanced PNG optimizer.
Copyright (C) 2001-2009 Cosmin Truta.

Synopsis:
    optipng [options] files ...
Files:
    Image files of type: PNG, BMP, GIF, PNM or TIFF
Basic options:
    -?, -h, -help	show the extended help
    -o <level>		optimization level (0-7)		default 2
    -v			verbose mode / show copyright and version info
Examples:
    optipng file.png			(default speed)
    optipng -o5 file.png		(moderately slow)
    optipng -o7 file.png		(very slow)
Type "optipng -h" for extended help.

Beauty! Next - pngout.

PNGout

PNGOut's source is not distributed openly. But there are binaries for a number of platforms here.

Download:

$ curl http://static.jonof.id.au/dl/kenutils/pngout-20070430-darwin.tar.gz \
         > pngout.tar.gz
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100 97597  100 97597    0     0  46704      0  0:00:02  0:00:02 --:--:-- 56739
$ tar -xzvf pngout.tar.gz

This way you end up with a binary named pngout-darwin. Rename and move somewhere where executables live:

$ sudo mv pngout-darwin /usr/bin/pngout 

Test:

$ pngout
PNGOUT [In:{PNG,JPG,GIF,TGA,PCX,BMP}] (Out:PNG) (options...)        Apr 30 2007
by Ken Silverman (http://advsys.net/ken)
Mac port assistance by Jonathon Fowler (http://jonof.edgenetwork.org/pngout)
PNGOUT optimizes PNG size losslessly using my own deflate algorithm (not Zlib)
With the right options, it can often beat other programs by 5-10%. Options:
   -c# PNG output color type: 0=Gray, 2=RGB, 3=Pal, 4=Gray+Alpha, 6=RGB+Alpha
   -f# PNG output filter...

PngRewrite

PNGRewrite was a little trickier, until I realized I need to install libpng first.

Download and install libpng:

$ curl ftp://ftp.simplesystems.org/pub/libpng/png/src/libpng-1.2.37.tar.gz \
         > libpng.tar.gz
$ tar -xzvf libpng.tar.gz
$ cd libpng-1.2.37/
$ sudo ./configure
$ sudo make install

Download, unzip pngrewrite:

$ curl http://entropymine.com/jason/pngrewrite/pngrewrite-1.3.0.zip \
         > pngrewrite.zip
$ unzip pngrewrite.zip

Compile pngrewrite (the make file didn't work for me) and copy the binary where executables are comfortable.

$ gcc -lpng pngrewrite.c -o pngrewrite
$ sudo cp pngrewrite /usr/bin/

Test:

$ pngrewrite
pngrewrite v1.3.0: PNG image palette optimizer
Usage: pngrewrite infile.png outfile.png

That's all, folks

Installing PNGCrush? Blogged before.

And if anyone has an idea how to get deflopt installed, please comment.

 

Slides from JSConf

Tuesday, April 28th, 2009

I'm back from the most excellent JSConf (JavaScript Conference) in Washington D.C. I'm tired and need sleep but the conference was, hands down, the best conference I've ever attended. It was all about the community, it was inexpensive, with parties all around, both speakers and attendees were treated exceptionally well, in fact there wasn't a big difference since attendees presented just as good content on the B-track as did the A-track.

Here are my slides, "High Performance Kick Ass Web Apps (the JavaScript edition)". I changed the slides on the night before the presentation (and after the first night's party). The thing is that I was halfway through the slides and approaching 90 slides and I realized there's no way I will deliver so much content. One day... I'll prepare my slides way in advance and will actually practice delivering the talk...

 

MHTML - when you need data: URIs in IE7 and under

Friday, April 10th, 2009

In the previous post I described what data: URIs are and how they are useful to reduce the number of HTTP requests. Now, the problem with data: URIs is that they are not supported by IE < 8. But, thanks to this article (in Russian), here's a way to work around that limitation: using MHTML for IE7 and under.

MHTML-a-what?

MHTML is MIME HTML, or if you insist on me spelling it out completely is like "Multipurpose Internet Mail Extensions HyperText Markup Language". In short it's HTML but like email with attachments. In one "multipart" email you can have several... hm, things - HTML version of the email, text-only version, attachment, another attachment...

MHTML is the same but for HTML. In one file you put a bunch of stuff (e.g. image files) and you save on the precious HTTP requests.

MHTML example

Let's check out an example. The HTML is actually not important, it's the CSS where we'll stick all our inline images. Once with data: sheme for all normal browsers and once with the mhtml: scheme for IE before 8.

The overall "template" would look like so:

/*
Content-Type: multipart/related; boundary="_ANY_SEPARATOR"

--_ANY_SEPARATOR
Content-Location:somestring
Content-Transfer-Encoding:base64

iVBORw0KGgoAAAANSUhEUgAAAAQAAAADCAIAA[...snip...]SuQmCC
*/

#myid {
  /* normal browsers */
  background-image: url("data:image/png;base64,iVBORw0[...snip...]");
  /* IE < 8 targeted with the star hack */
  *background-image: url(mhtml:http://phpied.com/mhtml.css!somestring);
}

The multipart stuff goes into a CSS comment. You then use data: URI scheme for all normal browsers. Then you use the star hack to target IE browsers before 8. For these browsers you give the URL of the CSS, exclamation and then a string that uniquely identifies the desired "part" in the multipart comment. Simple, eh? Didn't think so, but hey, it's not exactly rocket science.

Demo example with more parts

Check out a demo page that has two "parts" in the multipart MHTML comment.

The HTML is noting special and the CSS goes like:

/*
Content-Type: multipart/related; boundary="_ANY_STRING_WILL_DO_AS_A_SEPARATOR"

--_ANY_STRING_WILL_DO_AS_A_SEPARATOR
Content-Location:locoloco
Content-Transfer-Encoding:base64

iVBORw0KGgoAAAANSUhEUgAAAAQAAAADCAIAAAA7ljmRAAAAGElEQVQIW2P4DwcMDAxAfBvMAhEQMYgcACEHG8ELxtbPAAAAAElFTkSuQmCC
--_ANY_STRING_WILL_DO_AS_A_SEPARATOR
Content-Location:polloloco
Content-Transfer-Encoding:base64

iVBORw0KGgoAAAANSUhEUgAAABkAAAAUBAMAAACKWYuOAAAAMFBMVEX///92dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnYvD4PNAAAAD3RSTlMAACTkfhvbh3iEewTtxBIFliR3AAAAUklEQVQY02NgIBMwijgKCgrAef5fkHnz/y9E4kn+/4XEE6z/34jEE///A4knev7zAwQv7L8RQk40/7MiggeUQpjJff+zIpINykbIbhFSROIRDQAWUhW2oXLWAQAAAABJRU5ErkJggg==
*/

#test1 {
  background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAADCAIAAAA7ljmRAAAAGElEQVQIW2P4DwcMDAxAfBvMAhEQMYgcACEHG8ELxtbPAAAAAElFTkSuQmCC"); /* normal */
  *background-image: url(mhtml:http://phpied.com/files/mhtml/mhtml.css!locoloco); /* IE < 8 */
}

#test2 {
  background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABkAAAAUBAMAAACKWYuOAAAAMFBMVEX///92dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnYvD4PNAAAAD3RSTlMAACTkfhvbh3iEewTtxBIFliR3AAAAUklEQVQY02NgIBMwijgKCgrAef5fkHnz/y9E4kn+/4XEE6z/34jEE///A4knev7zAwQv7L8RQk40/7MiggeUQpjJff+zIpINykbIbhFSROIRDQAWUhW2oXLWAQAAAABJRU5ErkJggg=="); /* normal */
  *background-image: url(mhtml:http://phpied.com/files/mhtml/mhtml.css!polloloco); /* IE < 8 */
}

div {
  width: 100px;
  height: 100px;
  font: bold 24px Arial;
}

Drawback

In addition to the drawbacks of data: URIs (bigger CSS, small CSS change invalidates your cached inline images), this method has the obvious drawback that the inline images are repeated twice. But sometimes... a person's gotta do what a person's gotta do ;)

 

data:urls - what are they and how to use them

Friday, April 10th, 2009

If you follow this blog you already know the infamous website performance rule #1 - reduce the number of HTTP requests. Actually, to celebrate Earth Day and to jump the "go-green" wagon/jargon, my favourite performance mantra as of late is "Reduce, Reuse, Recycle" (the Recycle part is a wee fuzzy but, oh well)

So to reduce the number of requests for JavaScript files, you combine all .js into one monolithic file.

Same for .css

For images - use CSS sprites to create one image files that contains all your little icons.

Yet another way to minimize the number of HTTP requests is to use data URLs (proper name is data URI scheme).

"data... uri? urgh-i? An example, please!"

Say you have this minuscule image:

which you include like:

<img src="http://phpied.com/images/check.png" />

This way you're actually using the http URI scheme.

Same thing using data URI will look like:

And the code for it:

<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAADCAIAAAA7ljmRAAAAGElEQVQIW2P4DwcMDAxAfBvMAhEQMYgcACEHG8ELxtbPAAAAAElFTkSuQmCC" />

This way the image in inlined in the HTML and there is no extra HTTP request to retrieve it.

data URI syntax

Let's take a look again at this img tag and its slightly disturbing syntax:

<img src="data:image/png;base64,iVBOR..." />

You have:

  • data - name of the scheme
  • image/png - content type
  • base64 - the type of encoding used to encode the data
  • iVBOR... - the encoded data
  • some , and ; and : sprinked for good measure

How do I base64-encode?

While there are some online tools that will let you upload an image or point to a URL, you can simply do it from PHP and the command line.

Say you have the filename check.png. Then go:

$ php -r "echo base64_encode(file_get_contents('check.png'));"

This will spit out encoded content for copy-pasting pleasure. Naturally you can also do this from your application code, if needed.

Using data URLs in CSS

If you want the same image as a repeating CSS background, you can use it like this:

<div id="data-uri-test"></div>
<style type="text/css">
#data-uri-test {
  width: 20px;
  height: 20px;
  background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAADCAIAAAA7ljmRAAAAGElEQVQIW2P4DwcMDAxAfBvMAhEQMYgcACEHG8ELxtbPAAAAAElFTkSuQmCC");
}
</style>

Where the gist of it really boils down to the same:

background-image: url("data:image/png;base64,iVBOR...");

Lights, camera... IE!

Everybody's favourite part of every technique... IE support. The thing is IE8 supports data URIs. Earlier IEs do not. But, there is a solution involving MHTML, which I'll describe in a follow-up post, since this one turn out kinda longish.

For the impatient and Russian-speaking among you - click here.

 

204 No Content

Sunday, March 8th, 2009

Sometimes you want to send an HTTP request and you don't care about the response. This is often used for logging stuff on the server. Usually you request a 1x1 pixel GIF file and send a bunch of query parameters. E.g.
htp://example.org/blank.gif?user=stoyan&browser=msie&creditcard=123JUSTKIDDING567

Such 1x1 gifs are often called "web bugs" or "beacons" and sometimes used for sneaky purposes such as checking whether-you-opened-that-email-I-sent-you-that-you-didn't-reply-to-although-I-told-you-it-was-urgent-dammit-now-I'm-gonna-tell-the-boss-yes-this-time-I'm-telling-the-boss!

Now (after we relax a bit)... instead of having your server send a blank GIF, however small, can you just send.. nothing? Yep, you can. Your server can respond with a "204 No content" header. Cool, eh, especially when you want to squeeze every bit of network traffic?

So the example above can look like:
htp://example.org/nope.php?user=stoyan&browser=msie&creditcard=123JUSTKIDDING567

And nope.php could be like:

<?php
// .... log whatever you need to log, then reply:
header("HTTP/1.0 204 No Content");
?>

Here's what this looks like in Net Panel.

204

And an example in the wild (Google search beacon)

Google search beacon

Another application of 204s I was thinking could be favicons. If you don't want to deal with favicons, but you don't want to respond with a 404 Not Found either, you can just configure Apache to send 204 to favicon requests. Could be useful when your application generates subdomains for your users, since the browser will request the favicon from each subdomian (unless you have a link-ed favicon).

 

Picassa’s progressive photo rendering

Thursday, March 5th, 2009

If you've followed the series of image optimization posts on the YUIblog, you've probably seen the one about progressive JPEGs. In short, if a photo is over 10K it has a high probability of being smaller in file size when you use progressive JPEG.

How do you turn a normal, baseline JPEG into a progressive one? Well, most image software has this capability. On the command line you can use JPEGTRAN's -progressive flag.

Progressive JPEGs don't render progressively in IE but that's not a big deal, they still render.

Mi casa, Pi-cassa

That's all nice and good, but as I was browsing Picassa, I noticed some serious progressive photo rendering going on. Imagine my surprise when I found the photos on picassa seemed to be rendering progressively even in IE. And upon inspecting one photo - it wasn't even using progressive encoding!

small thumb first, bigger image later

Picassa uses a clever trick where they quickly load a small thumbnail of the photo you want to see, and then start loading the real big image. This way you get something that gives you an idea of the image and if you don't like it, you can click next and move on without loading for the whole image. And what gives the feeling of progressive loading is the fact that the thumbnail is stretched to take the whole width/height of the real image.

See for yourself

This page initially shows a small 128x96 image:
small thumb

But this image is stretched to 640x480 so it looks like:
small thumb stretched

The actual final image is
big image

This is pretty trivial to achieve, something like (not tested, just typing away):

var i = new Image();
i.onload = function() {
    document.getElementById('small').src = i.src;
}
i.src = "big.jpg";

So once the big image arrives, it replaces the small one and the visual effect is like progressive rendering - as if the image increases quality gradually.

 

Content-to-markup ratio bookmarklet

Thursday, March 5th, 2009

When you care about performance, or SEO (or just doing a good job as web dev) an interesting data point is the ratio of page content vs. the markup used to present this content. Or... how much crap we put in HTML in order to present what the users want to see - the content.

So I played tonight with a bookmarklet to provide this piece of stats.

Install

Right-click, add to favourites/bookmarks. Or simply click to see the ratio of this page.

content/markup

How it works

Since the scripts on the page may modify the content and markup, the bookmarklet makes an Ajax request to get a fresh copy of the page from the server. Then it runs a few regular expressions ("borrowed" from prototype.js) to strip all tags and the scripts/styles content. The first metric it provides is the size of the stripped content divided by the size of the original markup.

Then the bookmarklet tries to be more fair and count the alt, title and value attributes as content, including the size of attribute names themselves. And this is the second, "fair", metric. The content attributes are inspected using DOM methods, not regexp, so they can be affected by any javascript that has modified the page. Oh well, life's not fair.

Code

The bookmarklet code is served from here. The code is also on github.

Results

Here are some random results of running the bookmarklet on different sites.

http://www.cnn.com:
Total size: 92004 bytes
Content size: 11475 bytes
Content-to-markup ratio: 0.12
Fair ratio * : 0.16

http://www.sitepoint.com
Total size: 65989 bytes
Content size: 16199 bytes
Content-to-markup ratio: 0.25
Fair ratio * : 0.60

Article on http://en.wikipedia.org:
Total size: 21648 bytes
Content size: 3315 bytes
Content-to-markup ratio: 0.15
Fair ratio * : 0.35

http://www.phpied.com
Total size: 31899 bytes
Content size: 7933 bytes
Content-to-markup ratio: 0.25
Fair ratio * : 0.48

http://www.google.com SERP
Total size: 29963 bytes
Content size: 3351 bytes
Content-to-markup ratio: 0.11
Fair ratio * : 0.14

 

The 5 Laws of the Website Anything

Wednesday, March 4th, 2009

Via Eric Goldsmith, I found today this nice Web Performance 101 article, where the author, Alberto Savoia, states Top Four Laws of Web Site Performance. The article is as old as 2001 (heh, back then "website", being a relatively newer concept was spelled "web site" ;) ) and the topic is performance, but the "laws" are strikingly fresh and applicable not only to performance, but to any aspect of the web development, and to the websites in general. I couldn't resist the urge to comment and add a 5-th law, so here goes.

1. The Law of Stickiness

People find a website they like which seems to do the job and they tend to stick around. Rarely are people loyal to a web site, so it's not uncommon for people to grow dissatisfied, or irritated, bored, or just find a better option... and migrate and stick around for a while at another site. Friendster-MySpace-Facebook anyone?

As a Yahoo! Search developer I would testify it's not easy to move people over from where they've been sticking around for a while, but it's already happening (Yahoo! Search grew the market share for 5 months in a row) and just the nature of things.

2. The Law of User Perspective

Successful sites are best developed when the developer is the user, when you build something for you and something you would want to use. But that's not always the case. So if your visitors are IE6, dial-up users a continent or two away from your server, don't assume that your Safari Mac browsing session from the room next to the server will be any indication of what users are experiencing.

3. The Law of Responsibility (a.k.a. It's Always Your Fault)

Whatever you do on the website - front-end, back-end, DB, network, whatever... you can change things for the better. So often we find excuses instead of solutions.

And as front-end developers (I assume most of you who read my blog), as, if I'm not mistaken, Nate Koechley puts it, "we're the last line of defense" for our users.

4. The Law of Expectations

People spend most of their time on other sites. Don't be the smart-ass with the cool, but useless and confusing feature. You'll be the only one who finds it cool. Be as fast as the competition, offer user experience people are accustomed to, e.g. put your logo at the top left corner.

OK, let me quickly wrap-up with my addition, before I get too cheesy and inspirational...

5. The Law of the Task

At the end of it, it's about the task. If people come to your site and are able to achieve their task (make a reservation, purchase, subscription, read an article, whatever) with minimum effort and distraction, they'll be happy. They'll recommend you, they'll say your site is fast (although technically, your roundtrip time may be not as good as the competition), they'll stick around (law #1). Don't request too much information in a form, don't be a PITA with your validation, walk the user through as little steps as possible... and get out of the way. People have more interesting things to do than spend time on your site. "If you love somebody, set them free". And you love your users, right :)

 

Installing JPEGTRAN on a Mac or Unix/Linux

Friday, January 16th, 2009

JPEGtran is cool because it lets you optimize JPEG images losslessly by:

  1. Stripping meta data (meta is sometimes bulky and useless for web display)
  2. Optimizing Huffman tables or
  3. Convert a JPEG to progressive encoding

From my experience 1 is more important than 2 or 3 and 3 gives better results than 2 for images over 10K

Installation

I never had to install jpegtran before because all unix/linux machines I've touched already have it. And on windows you just copy a binary somewhere in your path.

Well, I got this MacBook now and it doesn't have jpegtran so had to figure it out myself. Here's how you can do it, worked for me on Mac OS should work on any unix/linux too.

BTW, jpegtran is part of a package of few tools known as libjpeg, so you'll be installing a few programs not only jpegtran.

  1. Get the source code from here. It's the file called jpegsrc.v6b.tar.gz. Using cURL you can download like:
    curl http://www.ijg.org/files/jpegsrc.v6b.tar.gz > /tmp/libjpeg.tar.gz
  2. Uncompres the package, e.g. tar -xzvf /tmp/libjpeg.tar.gz
  3. go to the directory that contains the uncompressed code, e.g. cd /tmp/jpeg-6b
  4. ./configure
  5. sudo make install

Done.

You can test your shiny new set of tools like this and get some help information about the various options:

> jpegtran -h
> cjpeg -h
> djpeg -h
> rdjpgcom -h
> wrjpgcom -h

You also test by optimizing my book cover from Amazon like:

curl http://ecx.images-amazon.com/images/I/41ckBp3bBUL._SL500_AA240_.jpg > oojs.jpg
jpegtran -copy none -progressive oojs.jpg > oojs-opt.jpg

This gives you 10% smaller file with not a pixel of quality loss. Not bad, eh, for a minute of work, or less.

 

Image optimization - in Chinese

Thursday, January 8th, 2009

Thanks to Joseph Jiang who translated in Chinese parts of my image optimization articles from the YUI blog

If you read Chinese, visit http://josephj.com/entry.php?id=209.

 

PNG optimization tools

Monday, December 22nd, 2008

I'm currently experimenting with different tools for optimizing PNG images to figure out strengths/weaknesses of each. Only considering free, ideally open-source, tools that can be run from the command line. For smush.it I just picked pngcrush for no particluar reason and I was thinking that once I have the optimization tool up and running and get the point across that images can be optimized with no human intervention as part of the normal "push" process... then the actual behind-the-scenes png optimizer can be tweaked without affecting the overall workflow.

So, I'm considering these PNG optimizers:

Can you think of any other PNG optimizers out there? Please comment.

Well, I just came back from a cruise with no internet access ($1/minute is unacceptable!) so I used my laptop's idle time to run some of the tools on a bunch of files (well over 10 000 PNG files, smartly collected right before the cruise ;) ).

So far some (very preliminary!) results from running the tools.

  1. pngcrush's -brute option is slower, as expected and usually doesn't help much
  2. pngcrush with -rem alla (strip all chunks only keeping the transparency chunk) doesn't get much better than -rem none (keep all chunks, even useless ones)
  3. pngout seems to give the best results, but it's probably the slowest
  4. pngrewrite is only for pallete PNGs (PNG8), it also seems to convert truecolor PNGs with less than 256 colors to PNG8

Again, these are very preliminary and again, please let me know if you know of any other PNG optimizers.

And keep an eye on the YUIblog's img opt series for more detailed report of the results.

 

Start wearing purple

Tuesday, December 2nd, 2008

Today was officially my first day at my new job at in Yahoo! Search. In the spirit of less-is-more I'm stepping out of the position of improving the performance of all Yahoo's sites worldwide to improving the performance of just one Yahoo! Search - in the US first, then maybe helping globally. I'm excited by the new opportunity and I'm not just saying it. Having in mind how smart I am (muhaha) and how committed YSearch is to performance, can't help but give a friendly warning to all the dear readers of my blog: if you own GOOG stock, now is the time to consider a second look at your portfolio :P

Anyway, I felt like doing something silly and here's what I came up - my first online video (videos of my kids don't count). I decided to play a rendition of "Start Wearing Purple" by Gogol Bordello on my acoustic and video tape it. This song (here's a vid of the original) is something of a hymn for Y!

So here's the video, enjoy!


start wearing purple @ Yahoo! Video
 

php|works Atlanta

Thursday, November 13th, 2008

Thanks to everyone who attended my image optimization talk at the php|works + PyWorks conference in Atlanta. And thanks for all the questions! I love questions, feels more natural - just geeks talking to geeks - as opposed to one guy sitting on a podium and talking.

And the slides:

 

Smush.it presentations

Sunday, October 5th, 2008

Smush.it is getting more and more buzz all over the internets. Now there's even a song about it! Me and Nicole are pretty busy answering email, but a little slow to document the thing, I though I should at least shed some light on how the tool works by using some of the presentations.

What the tool does can be summarized in these steps:

  • Turn GIFs into PNG8. Results are reported only if there's a saving, the file name then becomes source.gif.png. Smush.it uses imagemagick to do the conversion and then pngcrush to crush the pngs
  • Crush PNGs using pngcrush
  • Strip JPEG metadata and make them progressive, using jpegtran
  • GIF animations: use gifsicle to remove pixels that don't change from one frame to another

This has been documented here on developer.yahoo.com together with the command line tools and options.

So all the tool does is run the appropriate command for each file type. Easy as that ;) All the tools mentioned are free open-source and available on all operating systems, including Windows.

Here are some presentations on slideshare that might explain things a little more:

  1. High-perf web sites - PHP Quebec Montreal, March 2008
  2. 7 mistakes in image optimization - O'Reilly's Velocity, SFO, June 2008
  3. Ajax Experience, Boston, earlier this week. Draft 1, Draft 2. The final and shortest version is below. It doesn't say much but the talk was just 5 minutes and included a demo. It's weird how little you can say in 5 minutes, I mean just "hello, my name, ... welcome to blah, blah..." is 20 seconds
Images - 7 mistakes
View SlideShare presentation or Upload your own. (tags: images optimization)

Happy smushing!

"Smush it! Smush it real good..." - hothardware.com ;)

 

smush.it is a smash hit

Thursday, October 2nd, 2008

Since me and Nicole announced smush.it yesterday at Ajax Experience and thanks to Christian Heilmann posting it on Ajaxian and Yahoo Developer Network, this thing seems to have exploded! It's all over the blogosphere, twitter-sphere and every other sphere.

BTW, Chris never seizes to amaze - he posted the video on Ajaxian at 11:01 am and our talk was from 10:30 to 10:35 am :)

Last night, about 12 hours after the announcement, I checked the directory that stores the results and it had over 10 000 entries. There's one entry for every smush.it run, which means for example every page you smush using the FF extension. If you have 5 images on a page on average, this means over 50 000K smushed images in a day, nice!

We've received great feadback and great suggestions, keep'em coming. People are already making smush.it part of their dev/build process. People are already seeing response time performance improvement.

I'm really looking forward to releasing the official API, open source the code, the command-line version and all the fun stuff. We were just too busy trying to come up with something presentable for the Ajax conference.

The URL again: http://smushit.com

So, what's a smu? ;)

 

Installing pngcrush at dreamhost

Thursday, September 4th, 2008

pngcrush is an excellent optimizer for png images, simple and fast, highly recommended. Basically any time before you post a PNG on the web, you should run it through PNGCrush. It's a command line utility, there's a quick way to integrate pngcrush in windows explorer. (note to self: I actually wrote a wordpress plugin to do crush uploaded images, gotta find and post it)

I'm working (together with Nicole) on an online image optimizer, using the free command line tools I talked about at PHP Quebec, Montreal, O'Reilly's Velocity and the Yahoo! Performance pages. The tool will be free, of course, and hosted on Dreamhost. OK, finally getting to the point, am I?

Here's what I did to install pngcrush on Dreamhost, hope it helps anyone out there who's sweating with the same task.

  1. ssh to your dreamhost box, you need to give yourself ssh privileges from the dreamhost control panel
  2. mkdir tmp - make a temp directory
  3. cd tmp - enter the temp directory
  4. wget http://voxel.dl.sourceforge.net/sourceforge/pmt/pngcrush-1.6.10.tar.gz - download latest version of the pngcrush source code, this is the sourceforge mirror, closest to me, yours might be different and the pngcrush version might be newer at the time you install it, you can check here
  5. tar zxvf pngcrush-1.6.10.tar.gz - uncompress the code. This creates a new directory, enter it like so: cd pngcrush-1.6.10
  6. now all you need to do is run make, but didn't work for me, so I edited the Makefile file first, like so vi Makefile. In the vi editor, press i to enter INSERT mode and once you're done with the changes, press ESC, then type :wq (meaining write, quit). Here I removed the version information from the gcc compiler, so the two lines I edited became
    CC = gcc
    LD = gcc
  7. make - this compiles the pngcrush code and creates a binary called pngcrush
  8. cp pngcrush ~ - copy the new binary to your home directory
  9. chmod 0755 ~/pngcrush - make the binary executable
  10. All set, try if everything is ok ~/pngcrush, this should display the pngcrush's help information

Crush'em PNGs!

Like so:
~/pngcrush image.png -rem alla -reduce -brute result.png

Need hosting?

[advertisement]Dreamhost is a really good host, use this code MAXDI for $50 off [/advertisement] ;)

 

Vote for my SXSW 2009 panel

Wednesday, August 13th, 2008

Stuart Colville has put up a proposal for the South By Southwest Interactive 2009 conference, or SXSWi 2009 for short. This is a panel with me and Nicole from Yahoo!'s performance team and Stuart and Ed (ex-UK-Yahoo!s, currently in GCAP Media). In Stuart's own words:

... a panel on practical performance techniques featuring Stoyan Stefanov and Nicole Sullivan of Yahoo!’s Exceptional performance team alongside Ed Eliot and myself. In this panel we'd like to talk about all aspects of the practical things that can be applied to any site to improve the front-end performance.

To vote for this panel please visit "Practical Website Performance"

The way SXSWi works is the community votes for the proposals they consider worthy. And the selected proposals get to go to the conference.

This was the long version.

Short version: vote for me!

 

When PNG8 is not the right choice

Saturday, July 26th, 2008

Dave Artz has a nice post about PNG8 and alpha transparency, my extensive comments on his article are awaiting moderation right now :)

Dave has a very cool blog btw, only a few posts but they are all really good, there's a video tutorial of AOL's Pagetest tool and a discussion on non-blocking javascripts, something I just talked about over at the YUI blog.

PNG8
(Illustration by Dave)

 

fun: front-end performance vs back-end performance

Friday, July 25th, 2008

I'm explaining to .. let's call him "This guy" what I work at Yahoo!:

[2:10:32 AM] stoyanstefanov says: research, experiments, building tools
[2:10:38 AM] stoyanstefanov says: all around performance
[2:10:45 AM] stoyanstefanov says: and focused on the front-end
[2:11:33 AM] This guy says: front-end performance sounds so rude
[2:11:58 AM] stoyanstefanov says: haha :D
[2:12:10 AM] This guy says: but back-end performance sounds even worse

 

My online footprint lately

Wednesday, July 23rd, 2008

This is a sort of a catch-up post for listing what I've been up to lately.

  • YUI Blog just published my first article, I'm so proud. It's about loading JavaScript in non-blocking fashion, because JavaScripts, they, you know, like, block downloads. Luckily, there's an easy fix - DOM includes, which I've previously discussed, discussed and discussed.
  • SitePoint published an update to my older article that introduces AJAX, ok, Ajax, by creating a command-line-like interface with PHP on the server side. The updated article features improved code, jQuery example, YUI example, JSON discussion and example. Check it out, bookmark and recommend to your friends that keep asking you "What's this AJAX (they are new, don't know it's now spelled "Ajax") thing? Do you know of a good article?"
  • YDN (developer.yahoo.com) published a video presentation of me and my lovely teammate Nicole Sullivan where we talk about some new and cool front-end performance techniques. So if you wandered how I look and are eager to hear my fabulous Balkan peninsula accent, give it a shot. The talk is called "After YSlow 'A'" and is targeted at those of you who have reached performance nirvana, but are still hungry for more. We talk about preloading components, post-loading, javascript, images, using flush() in PHP to send first byte early on and other fun stuff.
  • Last, not least, I decided to try and find some time to update my JavaScript patterns site. Unfortunately I got sidetracked (yep, I'm easily distracted by shiny objects) and played with a not-so-javascript pattern. The post I published (includes a pretty lame screencast! and) demonstrates how you can use animated background position to indicate loading progress.

Whew, c'est tout pout ce moment, expect a lot more now that the JavaScript book is out of the way. Ah, yep, if you feel like it, join me on Facebook, I created a JS book page.

 

Image optimization - 7 mistakes

Thursday, June 26th, 2008

The slides from my talk at the Velocity conference

» Download

 

www vs no-www and cookies

Tuesday, May 13th, 2008

One of Yahoo's performance rules says: Use cookie-free domains for static components. This is good because the server has no use for cookie information when serving a JPEG or another static component, so all this cookie information creates network traffic for no reason.

One of the implications of following the rule is related to the whole www vs no-www question. Basically you should always use www if you're planning to use any other sub-domains and you want them cookie-free. This is because you have no way to set a cookie only to the top-level domain. So for example you cannot write a cookie only to phpied.com. If you load component from img.phpied.com, the cookie from phpied.com will be sent again. In Firefox this doesn't seem to be the case, but in IE it is.

Here are two test scripts that demonstrate the behavior:

Load both of these pages and then reload them to see what cookies are sent. They both try to set cookies in all possible ways:

  1. omitting the domain name
  2. .domain.com
  3. domain.com
  4. www.domain.com

Here's the source code of the files:

nowww.php [test]

<?php
setcookie('no0', 'no www, no domain');
setcookie('no1', 'no www, .phpied.com', 0, '/', '.phpied.com');
setcookie('no2', 'no www, phpied.com', 0, '/', 'phpied.com');
setcookie('no3', 'no www, www.phpied.com', 0, '/', 'www.phpied.com');

echo '<pre>';
print_r($_COOKIE);
?>

yeswww.php [test]

<?php
setcookie('yes0', 'yes www, no domain');
setcookie('yes1', 'yes www, .phpied.com',    0, '/', '.phpied.com');
setcookie('yes2', 'yes www, phpied.com',     0, '/', 'phpied.com');
setcookie('yes3', 'yes www, www.phpied.com', 0, '/', 'www.phpied.com');

echo '<pre>';
print_r($_COOKIE);
?>

Loading the two pages twice shows how in IE, no0, no1, and no2 are all visible when using www as well as when not using it. In Firefox it's almost the same, only that no0 is not visible when using www.

As a take-home:

  • use www
  • write cookies to the appropriate domain level (e.g. don't write to *.domain.com)
 

Rules for fast web pages

Monday, April 14th, 2008

... just updated.

http://developer.yahoo.com/performance/rules.html

The list (used to be 13 items, then 14, now 34) is becoming too overwhelming so it's now split into categories:

  • content
  • server
  • cookie
  • css
  • javascript
  • images
  • mobile

Act now to improve you page loading speed, your user will thank you later ;)

 

Background repeat and CSS sprites

Thursday, April 3rd, 2008

CSS sprites are a great way to improve the loading speed of your pages. One of the problems you might face with sprites is how to deal with cases when the background repeats.

The rule is pretty simple: if you want the background to repeat vertically (top to bottom), place the images in the sprite horizontally (left to right) and make sure the individual images in the sprite have the same height. For the opposite case: when you want to repeat horizontally, sprite vertically.

Example

» Demo

You have three divs and you want to repeat their background vertically, so that the background takes the whole height of the div, according to the content.

Source images:

  1. 1.png
  2. 2.png
  3. 3.png

Singe image sprite:

sprite8.png

CSS definitions to make this work:

    div {
        background-image:url(sprite8.png);
        background-repeat: repeat-y;
        width: 160px;
        padding: 20px;
        margin: 20px;
        float: left;
    }

    #my {
        background-position: 0px;
    }
    #my2 {
        background-position: -200px;
    }
    #my3 {
        background-position: -400px;
    }

Every image is 200px wide. Because of the 2x20px margin left and right, the width is 160px (=200 - 20 - 20)

The tree divs have IDs: my, my2, my3

Result

Once again, the result

Tested on Windows with IE7, FF, O, S.

 

JoJo: Javascript Junk generator

Tuesday, March 25th, 2008

Ever needed to be able to generate random, but valid JavaScript code? Well, today is your lucky day: meet J.J. or JoJo, the Javascript Junk code generator.

All you need to specify is how many kilobytes of code you need. Available also as a web service.

» tools.w3clubs.com/jojo

If anyone can think of any application of JoJo, other than performance experiments, I'll be most intrigued to hear it.