2015-04-24 5 views
0

Я использую библиотеку PHPExcel для чтения файлов xls и xlsx. Ниже приведен пример функции для демонстрации проблемы, что у меня есть:PHPExcel - утечка памяти при прохождении всех строк

public function memoryAction() 
{ 
    $filename = "example.xlsx"; 

    echo "<br>Script started<br>"; 
    echo memory_get_usage(true); 

    $inputFileType = PHPExcel_IOFactory::identify($filename); 
    $objReader = PHPExcel_IOFactory::createReader($inputFileType); 
    $objReader->setReadDataOnly(true); 
    $objReader->setLoadSheetsOnly(array('OTMS','Printing')); 

    $excelReader = $objReader->load($filename); 

    echo "<br>Reader Initiliazed<br>"; 
    echo memory_get_usage(true); 

    foreach ($excelReader->setActiveSheetIndex(0)->getRowIterator() as $row) { 
     if ($row->getRowIndex() == 1) { 
      continue; 
     } 

     $cellIterator = $row->getCellIterator(); 
     $cellIterator->setIterateOnlyExistingCells(false); 

     $excelRow = array(); 

     foreach ($cellIterator as $cell) { 
      $columnIndex = $cell->getColumn(); 
      $cellValue = $cell->getCalculatedValue(); 
      $excelRow[$columnIndex] = $cellValue; 

     } 

     if (empty($excelRow)) { 
      continue; 
     } 

     echo "<br>Row ".$row->getRowIndex()."<br>"; 
     echo memory_get_usage(true); 



    } 

    echo "<br>Went through each row<br>"; 
    echo memory_get_usage(true); 

    die(); 


} 

Таким образом, в основном я иду через каждую строку в таблице и выходной памяти использования Excel. Дело в том, что использование памяти увеличивается после каждых 20-30 строк.

Вот значения, которые я получаю:

Сценарий начал 1835008 -1,75 Mb

Считыватель инициализирован 19660800 - 18,75 Mb

Пошел через каждую строку 47972352 - 45,75 Mb

Я прочитал несколько сообщений в Интернете о проблеме памяти PHPExcel. Да, он потребляет много памяти. Вы можете видеть, что я использую функцию setReadDataOnly() и что я загрузил только конкретные рабочие листы. Но я до сих пор не понимаю, почему просто цикл по рядам потребляет память.

Есть ли способ отключить объекты строки/ячейки в цикле и освободить память? Цените любую помощь.


UPD

Я запустить код Марка и вот результат для моего файла:

Base Memory: 1835008 
Reader Initialised/File Loaded 
19660800 
Row 256 memory usage: 24903680 
Row 512 memory usage: 33030144 
Row 768 memory usage: 38797312 
Went through each row 
Final memory usage: 48234496 

Я использую PHPExcel версии 1.7.8. и PHP 5.5.11. Вероятно, стоит обновить библиотеку PHPExcel.


UPD 2

Я установил версию 1.8.0 библиотеки PHPExcel. Реализованные проекты:

Base Memory: 1835008 
Reader Initialised/File Loaded 
15990784 
Row 256 memory usage: 20185088 
Row 512 memory usage: 27262976 
Row 768 memory usage: 31719424 
Went through each row 
Final memory usage: 40108032 

Любые идеи, почему это происходит? Я использую Zend Framework и называю этот код в контроллере действий. Тестовый файл содержит 4 вкладки, размер файла - 619 КБ. Код работает только с первой вкладкой, которая содержит 1000 строк.

+0

Это фактический код, который вы используете для тестирования использования памяти? Потому что вы должны отображать память после итерации по столбцам в каждой строке, и это не отображается в вопросе. Я вижу, что вы создаете массив ячеек из каждой строки ('$ excelRow [$ columnIndex] = $ cellValue;': вы на самом деле строите массив строк? Это поднимает вопрос о том, почему вы чувствуете необходимость сначала создайте массив, а во-вторых, почему вы не используете встроенные методы PHPExcel, чтобы сделать это для вас. –

+0

Простое переключение по строкам не требует дополнительной памяти в PHPExcel –

+0

@MarkBaker да, это фактический код, который Я использую для тестирования. Я не добавлял информацию об использовании памяти после каждой итерации, потому что в выводе много строк. Я создаю массив ячеек, потому что в конце концов я передам данные каждой строки в другую функцию для обработки. – Tamara

ответ

0

Я создал один файл листа с 8192 строками и 32 столбцами, как тест. Сценарий, который я бегу, чтобы прочитать это на основе сценария вы публикуемую выше:

echo "Base Memory: ", memory_get_usage(true), PHP_EOL; 

$inputFileType = PHPExcel_IOFactory::identify('volumeTest.xlsx'); 
$objReader = PHPExcel_IOFactory::createReader($inputFileType); 
$objReader->setReadDataOnly(true); 

$excelReader = $objReader->load('volumeTest.xlsx'); 

echo "Reader Initialised/File Loaded", PHP_EOL; 
echo memory_get_usage(true), PHP_EOL; 

foreach ($excelReader->setActiveSheetIndex(0)->getRowIterator() as $row) { 
    $cellIterator = $row->getCellIterator(); 
    $cellIterator->setIterateOnlyExistingCells(false); 

    foreach ($cellIterator as $cell) { 
     $columnIndex = $cell->getColumn(); 
     $cellValue = $cell->getCalculatedValue(); 
    } 
    if (($row->getRowIndex() % 256) == 0) { 
     echo "Row ".$row->getRowIndex(), ' memory usage: ', memory_get_usage(true), PHP_EOL; 
    } 
} 

echo "Went through each row", PHP_EOL; 
echo "Final memory usage: ", memory_get_usage(true), PHP_EOL; 

поэтому я перебором строк и столбцов точно так же, как вы, и единственным реальным различия в том, что я показываю только использование памяти каждые 256 строк итерации, а не каждую строку, и что я не строю массив значений ячеек.

Вывод, что это порождает является:

Base Memory: 524288 Reader Initialised/File Loaded 105119744 Row 256 memory usage: 105119744 Row 512 memory usage: 105119744 Row 768 memory usage: 105119744 Row 1024 memory usage: 105119744 Row 1280 memory usage: 105119744 Row 1536 memory usage: 105119744 Row 1792 memory usage: 105119744 Row 2048 memory usage: 105119744 Row 2304 memory usage: 105119744 Row 2560 memory usage: 105119744 Row 2816 memory usage: 105119744 Row 3072 memory usage: 105119744 Row 3328 memory usage: 105119744 Row 3584 memory usage: 105119744 Row 3840 memory usage: 105119744 Row 4096 memory usage: 105119744 Row 4352 memory usage: 105119744 Row 4608 memory usage: 105119744 Row 4864 memory usage: 105119744 Row 5120 memory usage: 105119744 Row 5376 memory usage: 105119744 Row 5632 memory usage: 105119744 Row 5888 memory usage: 105119744 Row 6144 memory usage: 105119744 Row 6400 memory usage: 105119744 Row 6656 memory usage: 105119744 Row 6912 memory usage: 105119744 Row 7168 memory usage: 105119744 Row 7424 memory usage: 105119744 Row 7680 memory usage: 105119744 Row 7936 memory usage: 105119744 Row 8192 memory usage: 105119744 Went through each row Final memory usage: 105119744

не показывает никаких изменений использования памяти в любой момент во время итераций строки

Я запустить эти тесты в настоящее время с использованием версии 1.7.9 PHPExcel , 1.8.0 и последняя ветвь разработки против версий PHP 5.2.17, 5.3.27, 5.4.7, 5.4.21, 5.5.5 и 5.6.0 и не видели изменений в использовании памяти в итераторах с любой комбинацией PHPExcel/PHP.

+0

Благодарим вас за помощь, Марк. Я обновил сообщение с результатом этого теста. К сожалению, в моем случае память увеличивается. Я использую PHPExcel 1.7.8 - это может быть проблемой? – Tamara

+0

1.7.8 не должно отличаться от итераторов по сравнению с более поздними версиями, код итератора не изменился между 1.7.8 и 1.8.0: и хотя у разработки есть некоторые отличия (итератор столбца, определяющий диапазоны начала и конца, и т. д.), ни одна из них не обнаруживает утечки памяти –

Смежные вопросы