Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

MDL-40585 backup: cache XML parent paths

For $this->groupedpaths, using a key is faster as there is
no need to do in_array searches.

Parent cache allows dirname calls to be substantially reduced.
2048 was chosen as a cache size as this class operates on chunks
of the restore at a time, 8k questions produces a parent cache of
about 500 paths and uses 300K of memory.  Scaling up to 2048 will
use about 1.2M of RAM for really large restores.  This is acceptable
for the 48% function call reduction and the 10% runtime improvement
seen.
  • Loading branch information...
commit 1bdb3dcd2b6384fbb95b3629b4b28e7e461f3676 1 parent 2c66b71
mr-russ mr-russ authored
47 backup/util/xml/parser/processors/grouped_parser_processor.class.php
@@ -42,6 +42,18 @@
42 42
43 43 protected $groupedpaths; // Paths we are requesting grouped
44 44 protected $currentdata; // Where we'll be acummulating data
  45 +
  46 + /**
  47 + * Keep cache of parent directory paths for XML parsing.
  48 + * @var array
  49 + */
  50 + protected $parentcache = array();
  51 +
  52 + /**
  53 + * Remaining space for parent directory paths.
  54 + * @var integer
  55 + */
  56 + protected $parentcacheavailablesize = 2048;
45 57
46 58 public function __construct(array $paths = array()) {
47 59 $this->groupedpaths = array();
@@ -65,7 +77,7 @@ public function add_path($path, $grouped = false) {
65 77 $a->child = $found;
66 78 throw new progressive_parser_exception('xml_grouped_child_found', $a);
67 79 }
68   - $this->groupedpaths[] = $path;
  80 + $this->groupedpaths[$path] = true;
69 81 }
70 82 parent::add_path($path);
71 83 }
@@ -141,7 +153,7 @@ protected function postprocess_chunk($data) {
141 153 }
142 154
143 155 protected function path_is_grouped($path) {
144   - return in_array($path, $this->groupedpaths);
  156 + return isset($this->groupedpaths[$path]);
145 157 }
146 158
147 159 /**
@@ -150,24 +162,49 @@ protected function path_is_grouped($path) {
150 162 * false if not
151 163 */
152 164 protected function grouped_parent_exists($path) {
153   - $parentpath = progressive_parser::dirname($path);
  165 + $parentpath = $this->get_parent_path($path);
  166 +
154 167 while ($parentpath != '/') {
155 168 if ($this->path_is_grouped($parentpath)) {
156 169 return $parentpath;
157 170 }
158   - $parentpath = progressive_parser::dirname($parentpath);
  171 + $parentpath = $this->get_parent_path($parentpath);
159 172 }
160 173 return false;
161 174 }
162 175
163 176 /**
  177 + * Get the parent path using a local cache for performance.
  178 + *
  179 + * @param $path string The pathname you wish to obtain the parent name for.
  180 + * @return string The parent pathname.
  181 + */
  182 + protected function get_parent_path($path) {
  183 + if (!isset($this->parentcache[$path])) {
  184 + $this->parentcache[$path] = progressive_parser::dirname($path);
  185 + $this->parentcacheavailablesize--;
  186 + if ($this->parentcacheavailablesize < 0) {
  187 + // Older first is cheaper than LRU. We use 10% as items are grouped together and the large quiz
  188 + // restore from MDL-40585 used only 600 parent paths. This is an XML heirarchy, so common paths
  189 + // are grouped near each other. eg; /question_bank/question_category/question/element. After keeping
  190 + // question_bank paths in the cache when we move to another area and the question_bank cache is not
  191 + // useful any longer.
  192 + $this->parentcache = array_slice($this->parentcache, 200, null, true);
  193 + $this->parentcacheavailablesize += 200;
  194 + }
  195 + }
  196 + return $this->parentcache[$path];
  197 + }
  198 +
  199 +
  200 + /**
164 201 * Function that will look for any grouped
165 202 * child for the given path, returning it if found,
166 203 * false if not
167 204 */
168 205 protected function grouped_child_exists($path) {
169 206 $childpath = $path . '/';
170   - foreach ($this->groupedpaths as $groupedpath) {
  207 + foreach ($this->groupedpaths as $groupedpath => $set) {
171 208 if (strpos($groupedpath, $childpath) === 0) {
172 209 return $groupedpath;
173 210 }

0 comments on commit 1bdb3dc

Please sign in to comment.
Something went wrong with that request. Please try again.