Skip to content

Commit

Permalink
Performance improvements
Browse files Browse the repository at this point in the history
  • Loading branch information
svrnm committed Aug 18, 2014
1 parent b1fad6d commit afa9d8b
Show file tree
Hide file tree
Showing 4 changed files with 134 additions and 23 deletions.
49 changes: 49 additions & 0 deletions examples/performance.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<?php
ini_set('memory_limit', '2048M');
require_once('../vendor/autoload.php');
$in = 'spec.xlsx';
$out = 'test.xlsx';
$lastPeak = 0;

$rows = 64;
$cols = 20;

while($lastPeak < 1024*1024*300) {


$data = array();
for($i = 0; $i < $rows; $i++) {
$row = array();
for($j = 0; $j < $cols; $j++) {
switch($j%3) {
case 0:
$row[] = $i;
break;
case 1:
$row[] = '('.$i.','.$j.')' ;
break;
case 2:
$row[] = new DateTime('2014-01-01');
break;
}
}
$data[] = $row;
}

$start = microtime(true);
$dataTable = new ELearningAG\ExcelDataTables\ExcelDataTable();
$dataTable->showHeaders();
$dataTable->addRows($data);
$time0 = microtime(true) - $start;
$dataTable->attachToFile($in, $out);
$time1 = microtime(true)-$start;
$lastPeak = memory_get_peak_usage();
echo $rows.' x '.$cols.":\t";
echo ($time0)." s\t";
echo ($time1)." s\t";
echo floor((($rows)/$time1))." rows/s\t";
echo floor((($rows*$cols)/$time1))." entries/s\t";
echo ($lastPeak/(1024*1024)).' MB'.PHP_EOL;
$rows*=2;
}
?>
3 changes: 2 additions & 1 deletion src/ELearningAG/ExcelDataTables/ExcelDataTable.php
Original file line number Diff line number Diff line change
Expand Up @@ -395,7 +395,8 @@ public function attachToFile($srcFilename, $targetFilename = null) {
if(!is_null($targetFilename)) {
$xlsx->setFilename($targetFilename);
}
$xlsx->addWorksheet($worksheet->addRows($this->toArray()), $this->sheetId, $this->sheetName)->save();
$worksheet->addRows($this->toArray());
$xlsx->addWorksheet($worksheet, $this->sheetId, $this->sheetName)->save();
return $this;
}

Expand Down
1 change: 0 additions & 1 deletion src/ELearningAG/ExcelDataTables/ExcelWorkbook.php
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,6 @@ public function addWorksheet(ExcelWorksheet $worksheet, $id = null, $name = 'Dat
$newSheetData = $document->importNode( $worksheet->getDocument()->getElementsByTagName('sheetData')->item(0), true );
$oldSheetData->parentNode->replaceChild($newSheetData, $oldSheetData);
$this->getXLSX()->addFromString('xl/worksheets/sheet'.$id.'.xml', $document->saveXML());

}
if($this->isAutoSaveEnabled()) {
$this->save();
Expand Down
104 changes: 83 additions & 21 deletions src/ELearningAG/ExcelDataTables/ExcelWorksheet.php
Original file line number Diff line number Diff line change
Expand Up @@ -64,9 +64,22 @@ class ExcelWorksheet

protected $dateTimeColumns = array();

protected $rows = array();

protected $dirty = false;

protected $rowCounter = 1;

const COLUMN_TYPE_STRING = 0;
const COLUMN_TYPE_NUMBER = 1;
const COLUMN_TYPE_DATETIME = 2;

protected static $columnTypes = array(
'string' => 0,
'number' => 1,
'datetime' => 2
);

/**
* Setup a default document: XML head, Worksheet element, SheetData element.
*
Expand All @@ -83,10 +96,11 @@ public function setupDefaultDocument() {
* @return $this
*/
public function setDateTimeFormatId($id) {
$this->dirty = true;
$this->dateTimeFormatId = $id;
foreach($this->dateTimeColumns as $column) {
/*foreach($this->dateTimeColumns as $column) {
$column->setAttribute('s', $id);
}
}*/
return $this;
}

Expand Down Expand Up @@ -153,68 +167,70 @@ public function toXML() {
* @return \DOMElement
*/
protected function getNewRow() {
$sheetData = $this->getSheetData();
/*$sheetData = $this->getSheetData();
$row = $this->append('row', array(), $sheetData);
$row->setAttribute('r', $this->rowCounter++);
return $row;
return $row;*/
$this->rows[] = array();
return count($this->rows)-1;
}

/**
/*
* Set the inner text for $element to $text. Returns the DOMNode
* representing the text.
*
* @return \DOMText
*/
protected function setText($element, $text) {
/*protected function setText($element, $text) {
$textElement = $this->getDocument()->createTextNode($text);
$element->appendChild($textElement);
return $textElement;
}
}*/

/**
/*
* Add an inline string column to the given $row.
*
* @param \DOMElement $row
* @param string $column
* @return \DOMElement
*/
protected function addStringColumnToRow($row, $column) {
/*protected function addStringColumnToRow($row, $column) {
$c = $this->append('c', array('t' => 'inlineStr'), $row);
$is = $this->append('is', array(), $c);
$t = $this->append('t', array(), $is);
$this->setText($t, $column);
return $t;
}
}*/

/**
/*
* Add an number column to the given $row.
*
* @param \DOMElement $row
* @param int|string $column
* @return \DOMElement
*/
protected function addNumberColumnToRow($row, $column) {
/*protected function addNumberColumnToRow($row, $column) {
$c = $this->append('c', array(), $row);
$v = $this->append('v', array(), $c);
$this->setText($v, $column);
return $v;
}
}*/

/**
/*
* Add a date time dolumn to the given $row. $column is converted to a numerical
* value relativ to the static::$baseDate value
*
* @param \DOMElement $row
* @param \DateTimeInterface $column
* @return \DOMElement
*/
protected function addDateTimeColumnToRow($row, \DateTimeInterface $column) {
/*protected function addDateTimeColumnToRow($row, \DateTimeInterface $column) {
$c = $this->append('c', array('s' => $this->dateTimeFormatId), $row);
$this->dateTimeColumns[] = $c;
$v = $this->append('v', array(), $c);
$this->setText($v, static::convertDate($column) );
return $v;
}
}*/

/**
* Add a column to a row. The type of the column is deferred by its value
Expand All @@ -228,14 +244,56 @@ protected function addColumnToRow($row, $column) {
&& isset($column['type'])
&& isset($column['value'])
&& in_array($column['type'], array('string', 'number', 'datetime'))) {
$function = 'add'.ucfirst($column['type']).'ColumnToRow';
return $this->$function($row, $column['value']);
//$function = 'add'.ucfirst($column['type']).'ColumnToRow';
//return $this->$function($row, $column['value']);
$this->rows[$row][] = array(self::$columnTypes[$column['type']], $column['value']);
} elseif(is_numeric($column)) {
return $this->addNumberColumnToRow($row, $column);
$this->rows[$row][] = array(self::COLUMN_TYPE_NUMBER, $column);
//return $this->addNumberColumnToRow($row, $column);
} elseif($column instanceof \DateTimeInterface) {
return $this->addDateTimeColumnToRow($row, $column);
$this->rows[$row][] = array(self::COLUMN_TYPE_DATETIME, $column);
//return $this->addDateTimeColumnToRow($row, $column);
} else {
$this->rows[$row][] = array(self::COLUMN_TYPE_STRING, $column);
}
return $this->addStringColumnToRow($row, (string)$column);
//return $this->addStringColumnToRow($row, (string)$column);
}

protected function toXMLColumn($column) {
switch($column[0]) {
case self::COLUMN_TYPE_NUMBER:
return '<c><v>'.$column[1].'</v></c>';
break;
case self::COLUMN_TYPE_DATETIME:
return '<c s="'.$this->dateTimeFormatId.'"><v>'.static::convertDate($column[1]).'</v></c>';
break;
// case self::COLUMN_TYPE_STRING:
default:
return '<c t="inlineStr"><is><t>'.$column[1].'</t></is></c>';
break;
}
}

protected function updateDocument() {
if($this->dirty) {
$this->dirty = false;
$self = $this;
$this->rowCounter = 1;
$fragment = $this->document->createDocumentFragment();
$xml = implode('', array_map(function($row) use ($self) {
return '<row r="'.($self->rowCounter++).'">'.implode('', array_map(function($column) use ($self) {
return $self->toXMLColumn($column);
}, $row)).'</row>';
}, $this->rows));
$fragment->appendXML($xml);
$this->getSheetData()->parentNode->replaceChild(
$s = $this->getSheetData()->cloneNode( false ),
$this->getSheetData()
);
$this->sheetData = $s;
$this->getSheetData()->appendChild($fragment);

}
}

/**
Expand All @@ -251,6 +309,7 @@ protected function addColumnToRow($row, $column) {
* @return $this
*/
public function addRow($columns = array()) {
$this->dirty = true;
$row = $this->getNewRow();
foreach($columns as $column) {
$this->addColumnToRow($row, $column);
Expand All @@ -268,6 +327,7 @@ public function getDocument() {
$this->document = new \DOMDocument('1.0', 'utf-8');
$this->document->xmlStandalone = true;
}
$this->updateDocument();
return $this->document;
}

Expand All @@ -280,6 +340,7 @@ public function getSheetData() {
if(is_null($this->sheetData)) {
$this->sheetData = $this->append('sheetData');
}
$this->updateDocument();
return $this->sheetData;
}

Expand All @@ -304,6 +365,7 @@ public function getWorksheet() {
$this->worksheet = $this->append('worksheet', array(), $document);
$this->worksheet->setAttributeNS(static::$namespaces['xmlns'], 'xmlns:r', static::$namespaces['relationships']);
}
$this->updateDocument();
return $this->worksheet;
}

Expand Down

0 comments on commit afa9d8b

Please sign in to comment.