Saturday, February 28, 2015

Speeding up Grep on Large Files

Here are a few tips to improve the performance of grep on large files:

  1. Prefix your command with LC_ALL=C, in order to use the C locale with its smaller ASCII charset, instead of UTF-8
  2. Use grep -F to search for a fixed string (if possible), rather than a regex
  3. Remove the -i option, if you don't need it
LC_ALL=C grep -F searchString largeFile

Thursday, January 01, 2015

fahd.blog in 2014

Happy 2015, everyone!
I'd like to wish everyone a great start to an even greater new year!

In keeping with tradition, here's one last look back at fahd.blog in 2014.

During 2014, I posted a measly 19 new entries on fahd.blog. That's not a lot (I blame work and stackoverflow!) but I promise to write more this year. Thanks for reading and especially for giving feedback.

Top 5 posts of 2014:

I'm going to be writing a lot more this year, so stay tuned for more great techie tips, tricks and hacks! :)

Related posts:

Saturday, December 27, 2014

A Bookmarklet to Tick All Checkboxes on a Webpage

Recently, I found myself on a website where I had to tick 100+ checkboxes and there was no "Select all" button on the page. Obviously, I couldn't do this manually, so I wrote the following bookmarklet.

javascript:(function(){for(i of document.getElementsByTagName('input')){if(i.type=='checkbox') i.checked=!i.checked;}})()

Save this as a bookmark in your browser and click on it to toggle all checkboxes on the page you are on.

Sunday, November 30, 2014

Logging the Duration of Ext Ajax Requests

The following snippet shows how to log the duration of ajax requests in your Ext JS application:

Ext.Ajax.on('beforerequest', function(conn, response, options){
    console.log("Requesting:" + response.url);
    console.time(response.url);
});
Ext.Ajax.on('requestcomplete', function(conn, response, options){
    console.timeEnd(options.url);
});

Note that this code uses console.time(), which is a non-standard feature and may not work in all browsers.

Saturday, November 22, 2014

Ext JS - Caching AJAX Responses to HTML5 Web Storage for Better Performance

This post shows how you can improve performance of your Ext JS applications by using a "Caching AJAX Proxy". This proxy saves URL responses to HTML5 Web Storage (e.g. session storage or local storage), which means that when the same URL is requested multiple times, a cached response is returned, instead of sending a request to the server each time. This makes the application more responsive and also reduces load on the server handling the requests.

/**
 * A Caching Ajax Proxy which uses AJAX requests to get data from a server and
 * then stores the data to HTML5 Web Storage. If the storage fills up, it removes
 * entries from the cache until space is available.
 * (Compatible with Ext JS 4.2)
 */
Ext.define('App.data.proxy.CachingAjax', {
  extend: 'Ext.data.proxy.Ajax',
  alias: 'proxy.cachingajax',

  // use session storage, but can be configured to localStorage too
  storage: window.sessionStorage,

  // @Override
  doRequest: function(operation, callback, scope) {
    var cachedResponse = this.getItemFromCache(this.url);
    if (!cachedResponse) {
        this.callParent(arguments);
    }
    else {
        console.log('Got cached data for: ' + this.url);
        this.processResponse(true, operation, null, cachedResponse,
                             callback, scope, true);
    }
  },

  // @Override
  processResponse: function(success, operation, request, response,
                            callback, scope, isCached) {
    if (success === true && !isCached) {
        this.putItemInCache(this.url, response.responseText);
    }
    this.callParent(arguments);
  },

  /**
   * @private
   * Returns the data from the cache for the specified key
   * @param {String} the url
   * @return {String} the cached url response, or null if not in cache
   */
  getItemFromCache: function(key) {
    return this.storage ? this.storage.getItem(key) : null;
  },

  /**
   * @private
   * Puts an entry in the cache.
   * Removes a third of the entries if the cache is full.
   * @param {String} the url
   * @param {String} the data
   */
  putItemInCache: function(key, value) {
    if (!this.storage) return;
    try {
      this.storage.setItem(key, value);
    } catch (e) {
      // this might happen if the storage is full.
      // Remove a third of the items and retry.
      // If it fails again, disable the cache quietly.
      console.log('Error putting data in cache. CacheSize: ' + this.storage.length +
                  ', ErrorCode: ' + e.code + ', Message: ' + e.name);

      while (this.storage.length != 0) {
        var toRemove = this.storage.length / 3;
        for (var i = 0; i < toRemove ; i++) {
          var item = this.storage.key(0);
          if (item) this.storage.removeItem(item);
          else break;
        }
        console.log('Removed one-third of the cache. Cache size is now: ' + this.storage.length);
        try {
          this.storage.setItem(key, value);
          break;
        } catch (e) {
          console.log('Error putting data in cache again. CacheSize: ' + this.storage.length +
                      ', ErrorCode: ' + e.code + ', Message: ' + e.name);
        }
      }
      if (this.storage.length == 0) {
        console.log("Cache disabled");
        this.storage = null;
      }
    }
  }
});
Usage:
var store = Ext.create('Ext.data.Store', {
  model: 'User',
  proxy: {
    type: 'cachingajax',
    url : 'http://mywebsite/path'
  }
});

Obviously, you should only use this caching proxy when the server-side data is static, because if it is changing frequently your application will end up displaying stale, cached data.

This proxy can also be extended in the future to remove cached entries after specific time intervals or clear out the entire cache when the application starts up.