In the OXID software, language constants are defined in an associative array (lang.php).
They are referenced in the template files like “[{ oxmultilang ident=“COMPARE_PRODUCTATTRIBUTES” }]”
As accessing an associative array is extremely time-consuming (especially if the keys are not sorted to allow a binary search algorithm), and knowing, that most any programmin language can handle constans much more effixciently than literals, I was wondering, if defining the language constants as PHP constants (like xtCommerce does) would not be much more efficient.
Now the retrieval of each language constant requires calling a Smarty function plugin (“oxmultilang”) with some significant PHP code behind it, whereas .defining the language constants as PHP constants is compiled by Smarty to a direct (and thus much more efficient) PHP constant access.
These constants would be used in the templates like “[{$smarty.const.COMPARE_PRODUCTATTRIBUTES }]”.
Smarty will compile the access to the current language texts to
<?php echo smarty_function_oxmultilang(array('ident' => 'COMPARE_PRODUCTATTRIBUTES'), $this);?>
whereas the second approach would result in
<?php echo @COMPARE_PRODUCTATTRIBUTES;?>
In order to determine the efficiency of accessing the language texts in both ways, I did a timing study.
Besides the already defined language texts in the associative array, I additionally “defined” all language texts as PHP constants, like
define('ACCOUNT_LOGIN_LOGIN','Anmeldung');
define('ACCOUNT_LOGIN_BACKTOSHOP','Zurück zum Shop');
define('ACCOUNT_MAIN_TITLE','Mein Konto');
define('ACCOUNT_MAIN_BACKTOSHOP','Zurück zum Shop');
define('ACCOUNT_NEWSLETTER_TITLE','Newsletter');
define('ACCOUNT_NEWSLETTER_LOCATION','Mein Konto / ');
define('ACCOUNT_NEWSLETTER_SETTINGS','Newslettereinstellungen');
define('ACCOUNT_NEWSLETTER_SUBSCRIPTIONSUCCESS','Der Newsletter wurde abonniert.');
define('ACCOUNT_NEWSLETTER_SUBSCRIPTIONREJECT','Der Newsletter wurde abbestellt.');
define('ACCOUNT_NEWSLETTER_SUBSCRIPTION','Newsletter abonnieren:');
define('ACCOUNT_NEWSLETTER_YES','Ja');
define('ACCOUNT_NEWSLETTER_NO','Nein');
define('ACCOUNT_NEWSLETTER_SAVE','Speichern');
define('ACCOUNT_NEWSLETTER_BACKTOSHOP','Zurück zum Shop');
define('ACCOUNT_NOTICELIST_TITLE','Mein Merkzettel');
........
Then all language texts names were stored in another array (1390 entries).
$lang_names=array(
'ACCOUNT_LOGIN_LOGIN',
'ACCOUNT_LOGIN_BACKTOSHOP',
'ACCOUNT_MAIN_TITLE',
'ACCOUNT_MAIN_BACKTOSHOP',
'ACCOUNT_NEWSLETTER_TITLE',
'ACCOUNT_NEWSLETTER_LOCATION',
'ACCOUNT_NEWSLETTER_SETTINGS',
'ACCOUNT_NEWSLETTER_SUBSCRIPTIONSUCCESS',
'ACCOUNT_NEWSLETTER_SUBSCRIPTIONREJECT',
'ACCOUNT_NEWSLETTER_SUBSCRIPTION',
'ACCOUNT_NEWSLETTER_YES',
'ACCOUNT_NEWSLETTER_NO',
'ACCOUNT_NEWSLETTER_SAVE',
'ACCOUNT_NEWSLETTER_BACKTOSHOP',
.......
};
The timing-test was then executed with the following module:
<?php
$max_i=100;
$_start = microtime();
for ($i=1;$i<=$max_i;$i++)
{
reset($lang_names);
foreach ($lang_names as $lang_name)
{
$text=smarty_function_oxmultilang(array('ident' => $lang_name), $this);
}
}
$diff_a=diff_microtime($_start,microtime());
echo $max_i." accesses to language texts via 'oxmultilang': ".number_format($diff_a, 4)." second<br>
";
$_start = microtime();
for ($i=1;$i<=$max_i;$i++)
{
reset($lang_names);
foreach ($lang_names as $lang_name)
{
reset($lang_names);
$text=constant($lang_name);
}
}
$diff_c=diff_microtime($_start,microtime());
echo $max_i." accesses to language texts via PHP constants: ".number_format($diff_c, 4)." seconds<br><br>
";
$faktor=$diff_a/$diff_c;
echo "The access to language texts via 'oxmultilang' takes ".number_format($faktor, 0)." times longer than access to language texts via PHP-constants!";
exit();
// diff_microtime *********************************************************
// Calculate the difference between two different microtimes
// I like this better than the `getmicrotime()` option on PHP.net
function diff_microtime($mt_old,$mt_new)
{
list($old_usec, $old_sec) = explode(' ',$mt_old);
list($new_usec, $new_sec) = explode(' ',$mt_new);
$old_mt = ((float)$old_usec + (float)$old_sec);
$new_mt = ((float)$new_usec + (float)$new_sec);
return $new_mt - $old_mt;
}
?>
The module iterates 100 times over the code, which assigns all 1390 language texts by their name to a variable using the method Smarty would generate for both cases.
The result is just stunning!
100 accesses to all language texts via ‘oxmultilang’: 27.1311 second
100 accesses to all language texts via PHP constants: 0.1714 seconds
The access to language texts via ‘oxmultilang’ takes 158 times longer than access to language texts via PHP-constants!
This means, that the method of retrieving a language text from the associative language array takes 158 times longer than the method of treating the language texts als PHP constants.
So I believe that it would be worth considering a change here…
Every little helps (for performance)…