0

私は非常に高価なメソッドremoveColumns(...)を持っていますが、それはさらに複数回呼び出されます。だから私はそのパフォーマンスを向上させたい。最適化の結果、私は2つのツールを使用し分析するために:(1)Webgrind及び(2)簡単な実行時間を計測するスクリプトとXdebug Profiler(それはPHPUnitのテストメソッド内のコマンドラインで実行されます):単純な実行時間のチェックの結果と矛盾するXdebugのプロファイリング結果

$timeStart = microtime(true); 
for ($i=0 ; $i < 1000000; $i++) { 
    // code to measure 
    $this->...->removeColumns($testArray, $columnNames, $isWhitelist); 
} 
$timeStop = microtime(true); 
$resultTime = $timeStop - $timeStart; 
$cycleTime = $resultTime/$i; 
echo number_format($cycleTime, 10, ',', '') . ' sec/run'; 
die(PHP_EOL . '###' . PHP_EOL); 

しかし、今私は結果を見ています - そして、私は、どちらの結果も絶対的に互いに反対であることを見ています。

実行時間測定スクリプトの結果は以下のとおりです。あなたが見ることができるように

variant  sec/run (x69)  sec/run (x1000)  sec/run (x10000) sec/run (x100000) 
1   0,0000121144  0,0000102139  0,0000092316  0,0000089004 
2   0,0000115650  0,0000112779  0,0000098540  0,0000098941 
3   0,0000228260  0,0000240171  0,0000250236  0,0000800230 

difference ms (1-2)  0,0000005494 -0,0000010640 -0,0000006224 -0,0000009937 
yield % (1-2)   4,54%   -10,42%   -6,74%   -11,16% 
difference ms (1-3)  -0,0000107116 -0,0000138032 -0,0000157920 -0,0000711226 
yield % (1-3)   -88,42%   -135,14%  -171,06%  -799,09% 

は、最適化が失敗しました。メソッドがそれほど頻繁に呼び出されない場合は、パフォーマンスは向上しますが、呼び出しが多いほど、非線形(900%のパフォーマンスが失われ、100.000が呼び出されます)。

今度は、Xdebugをプロファイラの結果を見てみましょう:

variant XDP-filename XDP-filesize Calls Total Self (ms) Total Inclusive (ms) 
1  1474536556  445,678 KB  69  77325   77403 
2  1474537523  402,208 KB  69  1267   1270 
3  1474539908  402,963 KB  69  2443   2455 

difference ms (1-2)        76058   76133 
yield % (1-2)         98,36%   98,36% 
difference ms (1-3)        74882   74948 
yield % (1-3)         96,84%   96,83% 

だからここ改善バリアント(23)の性能は/ variant 1のパフォーマンスよりも、著しく良好なようです。

適切なパフォーマンステストの結果を得るためにここで何が問題になっていますか?


方法のすべての3つのバリアント、私は最適化しています:

変種1

public function removeColumns(array $table, array $columnNames, bool $isWhitelist = false) 
{ 
    foreach ($table as $rowKey => $row) { 
     if (is_array($row)) { 
      foreach ($row as $fieldName => $fieldValue) { 
       $remove = $isWhitelist 
        ? ! in_array($fieldName, $columnNames) 
        : in_array($fieldName, $columnNames) 
       ; 
       if ($remove) { 
        unset($table[$rowKey][$fieldName]); 
       } 
      } 
     } 
    } 
    return $table; 
} 

バリアント2

public function removeColumns(array $table, array $columnNames, bool $isWhitelist = false) 
{ 
    $tableKeys = array_keys($table); 
    $firstRowKey = $tableKeys[0]; 
    $firstRow = $table[$firstRowKey]; 
    $allColumnNames = array_keys($firstRow); 
    $resultColumns = []; 
    foreach ($allColumnNames as $columnName) { 
     $remain = $isWhitelist 
      ? in_array($columnName, $columnNames) 
      : ! in_array($columnName, $columnNames) 
     ; 
     if($remain) { 
      $resultColumns[$columnName] = array_column($table, $columnName); 
     } 
    } 
    $index = 0; 
    $resultTable = []; 
    foreach ($resultColumns as $resultColumnName => $resultColumn) { 
     foreach ($tableKeys as $index => $tableKey) { 
      $resultTable[$tableKey][$resultColumnName] = $resultColumn[$index]; 
     } 
    } 
    return $resultTable; 
} 

バリアント3

public function removeColumns(array $table, array $columnNames, bool $isWhitelist = false) 
{ 
    $tableKeys = array_keys($table); 
    $firstRowKey = $tableKeys[0]; 
    $firstRow = $table[$firstRowKey]; 
    $allColumnNames = array_keys($firstRow); 
    $columns = []; 
    $i = 0; 
    $arrayMapInputVarNames = []; 
    foreach ($allColumnNames as $columnName) { 
     $remain = 
      ($isWhitelist && in_array($columnName, $columnNames)) || 
      (! $isWhitelist && ! in_array($columnName, $columnNames)) 
     ; 
     if($remain) { 
      $varName = 'column' . $i++; 
      $$varName = $columns[$columnName] = array_column($table, $columnName); 
      $arrayMapInputVarNames[] = '$' . $varName; 
     } 
    } 
    $arrayMapInputString = implode(', ', $arrayMapInputVarNames); 
    eval('$rows = array_map(null, ' . $arrayMapInputString . ');'); 
    foreach ($rows as $index => $row) { 
     $rows[$index] = array_combine(array_keys($columns), array_values($row)); 
    } 
    $table = array_combine(array_keys($table), $rows); 
    return $table; 
} 

答えて

0

これはあなたの関数が行うためのものは何ですか?

<?php 
$table=array(
    'col1'=>'val1', 
    'col2'=>'val2', 
    'col3'=>'val3', 
    'col4'=>'val4' 
); 

$columnNames=array(
    'col2','col3' 
); 

function removeColumns($table, $columnNames, $isWhitelist = false) { 
    if ($isWhitelist) return array_intersect_key($table,array_flip($columnNames)); 
    return array_diff_key($table,array_flip($columnNames)); 
} 

print 'blacklist:'.var_export(removeColumns($table,$columnNames,false),1).PHP_EOL; 
print 'whitelist:'.var_export(removeColumns($table,$columnNames,true),1).PHP_EOL; 

出力:

blacklist:array (
    'col1' => 'val1', 
    'col4' => 'val4', 
) 
whitelist:array (
    'col2' => 'val2', 
    'col3' => 'val3', 
) 

が、私はパフォーマンスを測定していませんでした。あなたのコードのxdebug出力をどこかにアップロードできますか?

関連する問題