2012-01-27 3 views
2

Я читаю файлы javascript в php и выполняю их с помощью v8js.Почему функция переопределения быстрее, чем вызов первой?

Упрощенный пример:

$javascriptCode = file_get_contents($filename); 
$funcName = 'func'.md5($filename); 
$v8js->executeString(" 
function {$funcName}() { 
    {$javascriptCode} 
}"); 
$v8js->executeString("var testVariable = {$funcName}();"); 

~ 50 звонков = 200мс

Для повышения производительности я уменьшил последующие вызовы только называя имя функции, если функция уже была определена:

if (!isset($this->cache[$filename])) { 
$javascriptCode = file_get_contents($filename); 
$funcName = 'func'.md5($filename); 
$v8js->executeString(" 
    function {$funcName}() { 
    {$javascriptCode} 
    }"); 
    $this->cache[$filename] = $funcName; 
} 
else { 
$funcName = $this->cache[$filename]; 
} 
$v8js->executeString("var testVariable = {$funcName}();"); 

~ 50 звонков = 900 мс

По некоторым причинам это происходит медленнее, чем повторное выполнение определения функции (первая часть кода).

У меня есть несколько десятков файлов и функций javascript, которые я вызываю, все, что выполнялось в течение 200 мс с использованием первого примера кода. После добавления кэширования для уже определенных имен функций и более не переопределяя их, время выполнения для того же самого кода составляло около 900 мс.

Чтобы убедиться в том, что отсутствует повторное определение является единственной причиной потери производительности я изменил, если:

if (!isset($this->cache[$filename]) || true) { 

... имеющий имя функции до сих пор были сохранены в массиве, за исключением PHP-массив как возможная проблема.

Откуда возникают большие потери производительности или как я могу отлаживать это дальше?

ответ

1

Я создал несколько тестов, чтобы идентифицировать все дальше и, наконец, нашел причину, скрытую глубоко внутри моего собственного кода javascript.

Даже о том, что код был идентичен, некоторые if в JavaScript решили боковые и сделали все медленнее :-)

Вот исходный код последнего тест я сделал, который показал, что без повторного определения это быстрее, как и ожидалось:

<?php 
$runList = array(10, 100, 1000, 10000, 100000); 
$jsFunc = 'function myTestFunc() { return {foo: "bar"}; } '; 
foreach ($runList as $runs) { 

    $start = mstime(); 
    $js = new V8Js('Test'); 
    for ($i = $runs; $i > 0; $i--) { 
     $js->executeString($jsFunc, 'Test.Context'); 
     $js->executeString("myTestFunc();", 'Test.Context'); 
    } 
    echo "#1: " . (mstime() - $start)." ({$runs} with re-definition)<br />"; 
    unset($js); 

    $start = mstime(); 
    $js = new V8Js('Test'); 
    $js->executeString($jsFunc, 'Test.Context'); 
    for ($i = $runs; $i > 0; $i--) { 
     $js->executeString("myTestFunc();", 'Test.Context'); 
    } 
    echo "#2: " . (mstime() - $start)." ({$runs} without re-definition)<br />"; 
    unset($js); 
    echo "<hr />"; 
} 

function mstime() { 
    list($usec, $sec) = explode(" ", microtime()); 
    return ((float)$usec + (float)$sec); 
} 

Результаты:

#1: 0.000640869140625 (10 with re-definition) 
#2: 0.0003800392150878906 (10 without re-definition) 
#1: 0.001749992370605469 (100 with re-definition) 
#2: 0.0009560585021972656 (100 without re-definition) 
#1: 0.01554703712463379 (1000 with re-definition) 
#2: 0.04881501197814941 (1000 without re-definition) 
#1: 0.503957986831665 (10000 with re-definition) 
#2: 0.1761679649353027 (10000 without re-definition) 
#1: 4.813416957855225 (100000 with re-definition) 
#2: 1.93553900718689 (100000 without re-definition) 
Смежные вопросы