Skip to content

Commit

Permalink
Memory usage optimization
Browse files Browse the repository at this point in the history
  • Loading branch information
Kirill Kostiukov committed Aug 10, 2019
1 parent 02920ec commit 99caf30
Show file tree
Hide file tree
Showing 10 changed files with 179 additions and 14 deletions.
1 change: 1 addition & 0 deletions src/POData/BaseService.php
Original file line number Diff line number Diff line change
Expand Up @@ -452,6 +452,7 @@ protected function serializeResult(RequestDescription $request, IUriProcessor $u
}
} else {
$odataModelInstance = $objectModelSerializer->writeTopLevelElements($entryObjects);
unset($entryObjects);
if (!$odataModelInstance instanceof ODataFeed) {
throw new InvalidOperationException('!$odataModelInstance instanceof ODataFeed');
}
Expand Down
21 changes: 21 additions & 0 deletions src/POData/ObjectModel/ArrayEntryProvider.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?php

namespace POData\ObjectModel;

class ArrayEntryProvider implements EntryProviderInterface
{
protected $entries;
/**
* EntryProvider constructor.
* @param EntryProviderInterface $provider
*/
function __construct(array &$entries)
{
$this->entries = $entries;
}

function getNextEntry()
{
return array_shift($this->entries);
}
}
26 changes: 17 additions & 9 deletions src/POData/ObjectModel/CynicSerialiser.php
Original file line number Diff line number Diff line change
Expand Up @@ -258,7 +258,7 @@ public function writeTopLevelElement(QueryResult $entryObject)
*/
public function writeTopLevelElements(QueryResult &$entryObjects)
{
$res = $entryObjects->results;
$res = &$entryObjects->results;
if (!(is_array($res) || $res instanceof Collection)) {
throw new InvalidOperationException('!is_array($entryObjects->results)');
}
Expand Down Expand Up @@ -293,16 +293,24 @@ public function writeTopLevelElements(QueryResult &$entryObjects)
if ($this->getRequest()->queryType == QueryType::ENTITIES_WITH_COUNT()) {
$odata->rowCount = $this->getRequest()->getCountValue();
}
foreach ($res as $entry) {
if (!$entry instanceof QueryResult) {
$query = new QueryResult();
$query->results = $entry;
} else {
$query = $entry;
}
$odata->entries[] = $this->writeTopLevelElement($query);

if ($entryObjects->hasEntryProvider()) {
$entryProvider = $entryObjects;
} else {
$entryProvider = new ArrayEntryProvider($entryObjects->results);
}

$odata->setEntryProvider(new ODataEntryProvider($entryProvider, $this));
// while ($entry = $entryProvider->getNextEntry()) {
// if (!$entry instanceof QueryResult) {
// $query = new QueryResult();
// $query->results = $entry;
// } else {
// $query = $entry;
// }
// $odata->entries[] = $this->writeTopLevelElement($query);
// }

$resourceSet = $this->getRequest()->getTargetResourceSetWrapper()->getResourceSet();
$requestTop = $this->getRequest()->getTopOptionCount();
$pageSize = $this->getService()->getConfiguration()->getEntitySetPageSize($resourceSet);
Expand Down
26 changes: 26 additions & 0 deletions src/POData/ObjectModel/EntryProvider.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?php

namespace POData\ObjectModel;

class EntryProvider implements EntryProviderInterface
{
protected $provider;
/**
* EntryProvider constructor.
* @param EntryProviderInterface $provider
*/
function __construct(EntryProviderInterface $provider)
{
$this->setEntryProvider($provider);
}

function setEntryProvider($provider)
{
$this->provider = $provider;
}

function getNextEntry()
{
return $this->provider->getNextEntry();
}
}
8 changes: 8 additions & 0 deletions src/POData/ObjectModel/EntryProviderInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?php

namespace POData\ObjectModel;

interface EntryProviderInterface
{
function getNextEntry();
}
39 changes: 39 additions & 0 deletions src/POData/ObjectModel/ODataEntryProvider.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<?php

namespace POData\ObjectModel;

use POData\Providers\Query\QueryResult;

class ODataEntryProvider implements EntryProviderInterface
{
protected $provider;
protected $serializer;
/**
* EntryProvider constructor.
* @param EntryProviderInterface $provider
*/
function __construct(EntryProviderInterface $provider, $serializer)
{
$this->setEntryProvider($provider);
$this->serializer = $serializer;
}

function setEntryProvider($provider)
{
$this->provider = $provider;
}

function getNextEntry()
{
$entry = $this->provider->getNextEntry();

if (!$entry instanceof QueryResult) {
$query = new QueryResult();
$query->results = $entry;
} else {
$query = $entry;
}

return $this->serializer->writeTopLevelElement($query);
}
}
25 changes: 24 additions & 1 deletion src/POData/ObjectModel/ODataFeed.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
/**
* Class ODataFeed.
*/
class ODataFeed
class ODataFeed implements EntryProviderInterface
{
/**
* Feed iD.
Expand Down Expand Up @@ -44,6 +44,11 @@ class ODataFeed
*/
public $entries = [];

/**
* @var EntryProviderInterface
*/
protected $entryProvider;

/**
* Last updated timestamp.
*
Expand Down Expand Up @@ -93,4 +98,22 @@ public function setEntries(array $entries)
{
$this->entries = $entries;
}

public function hasEntryProvider()
{
return $this->entryProvider !== null;
}

public function getNextEntry()
{
if (isset($this->entryProvider)) {
return $this->entryProvider->getNextEntry();
}
return null;
}

public function setEntryProvider(EntryProviderInterface $provider)
{
$this->entryProvider = $provider;
}
}
29 changes: 27 additions & 2 deletions src/POData/Providers/Query/QueryResult.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,20 @@

namespace POData\Providers\Query;

class QueryResult
use \POData\ObjectModel\EntryProviderInterface;

class QueryResult implements EntryProviderInterface
{
/**
* @var object[]|object|null
*/
public $results;

/**
* @var EntryProviderInterface
*/
protected $entryProvider;

/***
* @var int|null
*/
Expand Down Expand Up @@ -50,4 +57,22 @@ public static function adjustCountForPaging($count, $top, $skip)

return intval(min($count, $top)); //count is top, unless there aren't enough records
}
}

public function hasEntryProvider()
{
return $this->entryProvider !== null;
}

public function getNextEntry()
{
if (isset($this->entryProvider)) {
return $this->entryProvider->getNextEntry();
}
return null;
}

public function setEntryProvider(EntryProviderInterface $provider)
{
$this->entryProvider = $provider;
}
}
8 changes: 7 additions & 1 deletion src/POData/Writers/Atom/AtomODataWriter.php
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,13 @@ protected function writeFeed(ODataFeed $feed, $isTopLevel = false)
$this->xmlWriter->endElement();
}

foreach ($feed->entries as $entry) {
if ($feed->hasEntryProvider()) {
$entryProvider = $feed;
} else {
$entryProvider = new \POData\ObjectModel\ArrayEntryProvider($feed->entries);
}

while ($entry = $entryProvider->getNextEntry()) {
$this->writeEntry($entry);
}

Expand Down
10 changes: 9 additions & 1 deletion src/POData/Writers/Json/JsonODataV1Writer.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
use POData\Common\ODataConstants;
use POData\Common\ODataException;
use POData\Common\Version;
use POData\ObjectModel\ArrayEntryProvider;
use POData\ObjectModel\ODataBagContent;
use POData\ObjectModel\ODataCategory;
use POData\ObjectModel\ODataEntry;
Expand Down Expand Up @@ -135,7 +136,14 @@ public function writeUrlCollection(ODataURLCollection $urls)
*/
protected function writeFeed(ODataFeed $feed)
{
foreach ($feed->entries as $entry) {

if ($feed->hasEntryProvider()) {
$entryProvider = $feed;
} else {
$entryProvider = new ArrayEntryProvider($feed->entries);
}

while ($entry = $entryProvider->getNextEntry()) {
$this->writer->startObjectScope();
$this->writeEntry($entry);
$this->writer->endScope();
Expand Down

0 comments on commit 99caf30

Please sign in to comment.