[Phần 2]High performance in Drupal : Lightning fast code

[Phần 2]High performance in Drupal : Lightning fast code

Welcome to the second part of our series on High Performance Drupal. Here we will cover techniques for speeding up your custom modules.

Query builders

Drupal 7 adds an easy to use database abstraction layer letting you quickly produce complex, database independent queries.

Unfortunately there can be a noticeable performance penalty when using these query builders instead of straight SQL. Let's look at a few guidelines for deciding which option is best.

You should use a query builder if:

  • You are creating a dynamic query and want to avoid lots of messy string concatenation
  • You want to make use of query extenders such as table column sorting or a pager
  • You want to allow other modules to alter your query, such as the node access system
  • You need to support multiple databases with the same codebase
  • Code readability is more important than performance of the query
  • The query is long-running or not used often so a small amount of overhead is negligible

<?php
// Create a select query for the `node` table.
$query = db_select('node', 'n')
  // Add a pager.
  ->extend('PagerDefault')
  // Add table click sorting.
  ->extend('TableSort');

// Join our example table.
$query->join('example_table', 'e', 'n.nid = e.nid');

$query
  // Specify the fields we require.
  ->fields('e', array('nid', 'example_data'))
  // We only want to load nodes which the user has access to.
  ->addTag('node_access')
  // We only want 10 results at a time. This works alongside the pager.
  ->limit(10);

if (!empty($nids)) {
  // Add an optional condition. $nids can be an int or an array.
  $query->condition('nid', $nids);
}

// Run our query.
$result = $query->execute();
?>

You should use db_query() if:

  • You have a simple or static query
  • Your query will be run multiple times per page
  • You will never need to switch databases or support more than one database engine
  • You don't need any of the extra functionality provided by query builders

<?php
// Run our simple query.
$result = db_query("SELECT nid, example_data FROM {example_table} WHERE nid IN :nids", array(':nids' => $nids));
?>

Scaling your data

One oft-overlooked area of Drupal's cache and entity systems are their ability to optimise loading data by doing so in bulk.

When loading entities (comments, nodes, terms users, etc.) you can call entity_load() with an array of ID's to load several at a time. This will group together database queries wherever possible to reduce the number of queries per page and reduce page load time.

The corresponding comment_load_multiple(), node_load_multiple(), taxonomy_term_load_multiple() and user_load_multiple() provide entity specific wrappers around entity_load() for ease of use.

Don't do this:

<?php
foreach ($nids as $nid) {
  // Load each node one at a time.
  $node = node_load($nid);
  // Do something with the node.
  example_function($node);
}
?>

This will be much faster:

<?php
$nodes = node_load_multiple($nids);
foreach ($nodes as $node) {
  // Do something with the node.
  example_function($node);
}
?>

The Drupal cache system offers similar functionality using cache_get_multiple() for loading several cache entries at once.

Most but not all cache backends support this functionality, so it's best to double check first. The Drupal database cache, memcache and APC all support this optimisation.

Static caching

Often you need to make use of the same information more than once during a page load. Best practices denote that you should package this code up into a separate function for ease of maintenance.

To avoid expensive calculations or database calls you can use a static cache to keep hold of the data once it has been loaded once as the following example shows.

<?php
function example_function() {
  // Get our static data.
  $example_data = &drupal_static(__FUNCTION__);

  if (!isset($example_data)) {
    // We haven't calculated this yet so load it now.
    $example_data = example_data_load();
  }

  return $example_data;
}
?>

Using drupal_static() allows you to access and clear the static data elsewhere in your page load, in case you need to load a fresh copy later on.

If your function is used heavily you should use the fast Drupal static method, as drupal_static() does have a small overhead associated with it:

<?php
function example_function() {
  // Use the advanced drupal_static() pattern, since this is called very often.
  static $drupal_static_fast;
  if (!isset($drupal_static_fast)) {
    $drupal_static_fast = &drupal_static(__FUNCTION__);
  }

  // Get our static data.
  $example_data = &$drupal_static_fast;

  if (!isset($example_data)) {
    // We haven't calculated this yet so load it now.
    $example_data = example_data_load();
  }

  return $example_data;
}
?>

So you've got your data until the end of the page load, but why stop there? cache_get() and cache_set() let you keep hold of that data for as long as you need it:

<?php
function example_function() {
  // Use the advanced drupal_static() pattern, since this is called very often.
  static $drupal_static_fast;
  if (!isset($drupal_static_fast)) {
    $drupal_static_fast = &drupal_static(__FUNCTION__);
  }

  // Get our static data.
  $example_data = &$drupal_static_fast;

  if (!isset($example_data)) {
    if ($cache = cache_get('example_data')) {
      // Load the data straight from the cache.
      $example_data = $cache->data;
    }
    else {
      // We haven't calculated this yet so load it now.
      $example_data = example_data_load();
      // Store our calculated data in the cache.
      cache_set('example_data', $example_data);
    }
  }

  return $example_data;
}
?>

Profiling your code

XHProf is a really helpful tool for finding bottlenecks in your code.

You can see the amount of time and memory used by each function on a page-by-page basis, so you can work out where there's room for improvement.

It's always worth looking through the most common and most time consuming functions to make sure they really should be running that frequently and for that long. Often seemingly simple, un-optimised functions end up being used much more often than you thought.

There are a couple of ways to use XHProf in your Drupal site:

  • The XHProf module is the quickest to set up as it all comes bundled together
  • If you're already using Devel on your site then you might find it easier to configure the built-in XHProf support

High speed hosting

Tuning your hosting can make or break your site when it comes to performance.

I will be writing a follow up post High speed Drupal hosting with some handy hints and tips.

In the mean time get in touch if you would like a hand tuning your Drupal hosting environment.

Bạn thấy bài viết này như thế nào?: 
No votes yet
Ảnh của Tommy Tran

Tommy owner Express Magazine

Drupal Developer having 9+ year experience, implementation and having strong knowledge of technical specifications, workflow development. Ability to perform effectively and efficiently in team and individually. Always enthusiastic and interseted to study new technologies

  • Skype ID: tthanhthuy

Tìm kiếm bất động sản

 

Advertisement

 

jobsora

Dich vu khu trung tphcm

Dich vu diet chuot tphcm

Dich vu diet con trung

Quảng Cáo Bài Viết

 

Giới thiệu các hàm xử lý chuỗi trong SQL 2005 VÀ SQL 2008

thay thế tất cả các chuỗi con nào đó trong 1 chuỗi thành 1 chuỗi con khác

Kaspersky công bố phiên bản năm 2013 và chương trình Kaspersky Care

Kaspersky công bố phiên bản năm 2013 và chương trình Kaspersky Care

Ngày 16/10, Kaspersky Lab phối hợp cùng Công ty TNHH Bảo Mật Nam Trường Sơn đã tổ chức lễ ra mắt sản phẩm Kaspersky 2013 phiên bản tiếng việt “Sẵn sàng cho 20 triệu lượt download”

Samsung to block iPhone 4S sale in France and Italy

Samsung to block iPhone 4S sale in France and Italy

By now I assume you are getting as tired as we are hearing about the ongoing legal battles between Apple and Samsung.

Công ty diệt chuột T&C

 

Diet con trung