Cache AppInfo in Memory Cache if configured

This saves around 20ms on a bare-bone instance, on bigger ones more (depending on the number of installed apps).

See https://blackfire.io/profiles/compare/fc326ad3-100d-49b8-8ea9-8343240f53f3/graph

Signed-off-by: Lukas Reschke <lukas@statuscode.ch>
This commit is contained in:
Lukas Reschke 2016-10-07 21:15:52 +02:00
parent 67d3574bdf
commit 0c2b17c80f
No known key found for this signature in database
GPG Key ID: B9F6980CF6E759B1
3 changed files with 50 additions and 13 deletions

View File

@ -1,6 +1,7 @@
<?php <?php
/** /**
* @copyright Copyright (c) 2016, ownCloud, Inc. * @copyright Copyright (c) 2016, ownCloud, Inc.
* @copyright Copyright (c) 2016, Lukas Reschke <lukas@statuscode.ch>
* *
* @author Andreas Fischer <bantu@owncloud.com> * @author Andreas Fischer <bantu@owncloud.com>
* @author Christoph Wurst <christoph@owncloud.com> * @author Christoph Wurst <christoph@owncloud.com>
@ -26,7 +27,18 @@
namespace OC\App; namespace OC\App;
use OCP\ICache;
class InfoParser { class InfoParser {
/** @var \OCP\ICache|null */
private $cache;
/**
* @param ICache|null $cache
*/
public function __construct(ICache $cache = null) {
$this->cache = $cache;
}
/** /**
* @param string $file the xml file to be loaded * @param string $file the xml file to be loaded
@ -37,6 +49,13 @@ class InfoParser {
return null; return null;
} }
if(!is_null($this->cache)) {
$fileCacheKey = $file . filemtime($file);
if ($cachedValue = $this->cache->get($fileCacheKey)) {
return json_decode($cachedValue, true);
}
}
libxml_use_internal_errors(true); libxml_use_internal_errors(true);
$loadEntities = libxml_disable_entity_loader(false); $loadEntities = libxml_disable_entity_loader(false);
$xml = simplexml_load_file($file); $xml = simplexml_load_file($file);
@ -119,6 +138,10 @@ class InfoParser {
if (isset($array['background-jobs']['job']) && is_array($array['background-jobs']['job'])) { if (isset($array['background-jobs']['job']) && is_array($array['background-jobs']['job'])) {
$array['background-jobs'] = $array['background-jobs']['job']; $array['background-jobs'] = $array['background-jobs']['job'];
} }
if(!is_null($this->cache)) {
$this->cache->set($fileCacheKey, json_encode($array));
}
return $array; return $array;
} }

View File

@ -682,7 +682,7 @@ class OC_App {
$file = $appPath . '/appinfo/info.xml'; $file = $appPath . '/appinfo/info.xml';
} }
$parser = new InfoParser(); $parser = new InfoParser(\OC::$server->getMemCacheFactory()->create('core.appinfo'));
$data = $parser->parse($file); $data = $parser->parse($file);
if (is_array($data)) { if (is_array($data)) {

View File

@ -1,5 +1,4 @@
<?php <?php
/** /**
* @author Thomas Müller * @author Thomas Müller
* @copyright 2014 Thomas Müller deepdiver@owncloud.com * @copyright 2014 Thomas Müller deepdiver@owncloud.com
@ -14,31 +13,46 @@ use OC\App\InfoParser;
use Test\TestCase; use Test\TestCase;
class InfoParserTest extends TestCase { class InfoParserTest extends TestCase {
/** @var OC\Cache\CappedMemoryCache */
private static $cache;
/** @var InfoParser */ public static function setUpBeforeClass() {
private $parser; self::$cache = new OC\Cache\CappedMemoryCache();
}
public function setUp() {
$this->parser = new InfoParser(); public function parserTest($expectedJson, $xmlFile, $cache = null) {
$parser = new InfoParser($cache);
$expectedData = null;
if (!is_null($expectedJson)) {
$expectedData = json_decode(file_get_contents(OC::$SERVERROOT . "/tests/data/app/$expectedJson"), true);
}
$data = $parser->parse(OC::$SERVERROOT. "/tests/data/app/$xmlFile");
$this->assertEquals($expectedData, $data);
} }
/** /**
* @dataProvider providesInfoXml * @dataProvider providesInfoXml
*/ */
public function testParsingValidXml($expectedJson, $xmlFile) { public function testParsingValidXmlWithoutCache($expectedJson, $xmlFile) {
$expectedData = null; $this->parserTest($expectedJson, $xmlFile);
if (!is_null($expectedJson)) {
$expectedData = json_decode(file_get_contents(OC::$SERVERROOT . "/tests/data/app/$expectedJson"), true);
} }
$data = $this->parser->parse(OC::$SERVERROOT. "/tests/data/app/$xmlFile");
$this->assertEquals($expectedData, $data); /**
* @dataProvider providesInfoXml
*/
public function testParsingValidXmlWithCache($expectedJson, $xmlFile) {
$this->parserTest($expectedJson, $xmlFile, self::$cache);
} }
function providesInfoXml() { function providesInfoXml() {
return array( return array(
array('expected-info.json', 'valid-info.xml'), array('expected-info.json', 'valid-info.xml'),
array(null, 'invalid-info.xml'), array(null, 'invalid-info.xml'),
array('expected-info.json', 'valid-info.xml'),
array(null, 'invalid-info.xml'),
); );
} }
} }