Thursday, November 18, 2010

CSS Sprites

In the field of Web performance, CSS Sprites is one useful skill to merge small images into a bigger one (also called master image) to save number of HTTP requests and to reduce download size. There are a lot of discussions and explanations about CSS Sprites, but the root is simple - rely on CSS background-position property to display partial of bigger image. I don't want to explain the ins and outs of this skill, but want to put some excerpts here for quick reference.

One typical case is building a grid of images and devising a way to get each individual cell out of the grid, we can store all buttons/navigation items/whatever we wish in a single master image file, along with the associated “before” and “after” link states.

CSS sprites are a way to reduce the number of HTTP requests made for image resources referenced by your site. Images are combined into one larger image at defined X and Y coorindates. Having assigned this generated image to relevant page elements the background-position CSS property can then be used to shift the visible area to the required component image.

In this case, multiple images used throughout a website would be combined into the so-called “master image.” To display a single image from the master image, one would use the background-position property in CSS, defining the exact position of the image to be displayed. Any hover, active or focus effects would be implemented using the simple definition of the background-position property for the displayed element. CSS sprites are commonly used, particularly for navigation (such as for hover effects), icons and buttons.

CSS sprites group multiple images into one composite image and display them using CSS background positioning. You can save a significant amount of HTTP requests by consolidating your images into one or more composite sprites and using CSS to selectively display parts of the sprite within your web page.

Yahoo! uses a number of CSS hacks to allow for different browsers in their code.They also create different style sheets optimized for different user agents, a non-trivial amount of work. They include the backslash hack, underscore hack, voice family hack, and property:value; hack which is part of another CSS hack.

The smaller size of sprites is due to the reduced overhead of multiple color tables and formatting information required by separate images. To maximize accessibility and usability, CSS sprites are best used for icons or decorative effects.

There are a bunch of tools for CSS Sprites and image optimization.
SmartSprites http://csssprites.org/
CSS Sprites Generator http://csssprites.com/
SpriteMe http://spriteme.org/

The background-position property sets the starting position of a background image. It is supported in all major browsers. For this to work in Firefox and Opera, the background-attachment property must be set to "fixed". For more information, check out CSS background-position Property

Firebug Net Panel Tooltip Quick Introduction

Firebug is a very popular Firefox plugin for Web developers. When we start to look at front-end performance, its built in Net Panel provides a very handy and useful view for network traffic between browser and originating servers at the back-end. As of this post writing, firebug latest version is 1.5.4.

Software is hard provides many detailed info about firebug, and including blogs and tutorial. I just want to recap what I got from them and other resources, regarding its Tooltip analysis data.

Here is one example










Each request has several phases from the tooltip, here are some notes about each request phase.

    * DNS Lookup: DNS resolution time, from domain name to IP. When it is cached, the time is usually zero.
    * Connecting: Elapsed time required to create a TCP connection (RTT?)
    * Blocking (not on the screenshot): Elapsed time spent in a browser queue waiting for a network connection. Displayed only in the case where this situation happens because browsers have max limit for persistent connections per server.
    * Sending: Time needed to send request data to the server (upload time)
    * Waiting: Waiting for the response (till the first byte is received from the server), usually it is backend server response time, or called SPL (Server Processing Latency).
    * Receiving: Time necessary to download response body (download time)

For more info, check out this blog (firebug-net-panel-timings) from Software is hard

    * DOMContentLoaded event fires when parsing of the current page is complete. If this number is negative the event was fired before the request is started.
    * Load event fires when all files have finished loading from all resources, including ads and images. If this number is negative the event was fired before the request is started.

Microsoft has a test drive to explain DOMContentLoaded and Load 2 events.

Wednesday, November 17, 2010

Deadlock from sorted IN clause

Problem:
Recently we see deadlock in Oracle db caused by a simple IN delete clause (the input parameters are alphabetically sorted). The SQL looks like
DELETE FROM TEST_TABLE WHERE ID IN (:1,:2,:3,:4,:5,:6,:7,:8,:9,:10);

Stack Trace:
com.ibatis.common.jdbc.exception.NestedSQLException:
--- The error occurred while applying a parameter map.
--- Check the BatchDeleteUserContextByCred-InlineParameterMap.
--- Check the statement (update failed).
--- Cause: com.inet.ora.Ora4SQLException: [Oracle] #600 ORA-00060: deadlock detected while waiting for resource
[Oracle] #600
        at com.ibatis.sqlmap.engine.mapping.statement.GeneralStatement.executeUpdate(GeneralStatement.java:91)
        at com.ibatis.sqlmap.engine.impl.SqlMapExecutorDelegate.update(SqlMapExecutorDelegate.java:505)
        at com.ibatis.sqlmap.engine.impl.SqlMapExecutorDelegate.delete(SqlMapExecutorDelegate.java:528)
        at com.ibatis.sqlmap.engine.impl.SqlMapSessionImpl.delete(SqlMapSessionImpl.java:98)
        at com.ibatis.sqlmap.engine.impl.SqlMapClientImpl.delete(SqlMapClientImpl.java:75)

Issue Analysis:
These Global Enqueue Services Deadlock detected messages are indicating that there is row level contention and locking issue caused by the application code. These errors are exactly the same as those seen in an ORA-0060 deadlock scenario except and these messages are indicating the RAC database has detected the deadlock and forced the rollback of a transaction as a result of the deadlock scenario. There is no Oracle RAC issue here, this needs to be addressed at an application coding level.

Why deadlock:
Simply put, two or more guys do the same tasks, there will be conflict. Two delete SQL will have the same problem though they are sorted like below (no official explanation of this, but the guess is Oracle will do SELECT before delete, without sequence guaranteed. )
DELETE FROM TEST_TABLE WHERE ID IN ('A','B','C');
DELETE FROM TEST_TABLE WHERE ID IN ('A','B','C');

Why we did "batch delete using IN clause"?
  1. One by one delete has performance issue - due to redo/undo log, replication cost
  2. Huge batch delete has issue too - causes rollback segment or data-files related errors.

Solution:
  1. Move the cleanup task to DB job
  2. Use JDBC batch delete (multiple deletes with one commit, using addBatch(), executeBatch() etc)

Wednesday, November 3, 2010

Facebook Operations (Jonathan Heiliger)

Key takeaways:
  1. One team (engineer team drivers development, testing and deployment)
  2. Small team (several people for constant communication)
  3. Innovation (Hiphop, Scribe, Cassandra etc etc)

Best Practices:
  1. Version control everything
  2. Automate, automate, automate
  3. Plan to fail (constant failure)
  4. Instrument everything
  5. Don't waste time on dumb stuff
  6. Distribute accountability
  7. Focus on top features (e.g. feed)
  8. Monitor usage to understand customer
  9. Loosely coupled system
Links:
http://www.facebook.com/MySQLatFacebook
http://radar.oreilly.com/2009/06/jonathan-heiliger-facebook-velocity-webops.html