Skip to content

Commit f02de24

Browse files
committed
Improve performance of EObject.eContents() and Resource._index() by using caching.
1 parent a17f5a2 commit f02de24

File tree

4 files changed

+106
-13
lines changed

4 files changed

+106
-13
lines changed

src/ecore.js

+25-6
Original file line numberDiff line numberDiff line change
@@ -459,17 +459,36 @@ Ecore.EObjectPrototype = {
459459
eContents: function() {
460460
if (!this.eClass) return [];
461461

462-
var eAllFeatures = this.eClass.get('eAllStructuralFeatures'),
463-
eContainments = _.filter(eAllFeatures, function(feature) {
462+
if (_.isUndefined(this.__updateContents)) {
463+
this.__updateContents = true;
464+
465+
var resource = this.eResource();
466+
if (resource) {
467+
var me = this;
468+
resource.on('add remove', function() {
469+
me.__updateContents = true;
470+
})
471+
}
472+
}
473+
474+
if (this.__updateContents) {
475+
var eAllFeatures = this.eClass.get('eAllStructuralFeatures');
476+
var eContainments = _.filter(eAllFeatures, function(feature) {
464477
return feature.isTypeOf('EReference') &&
465478
feature.get('containment') &&
466479
this.isSet(feature.get('name'));
467480
}, this);
468481

469-
return _.flatten(_.map(eContainments, function(c) {
470-
var value = this.get(c.get('name'));
471-
return value instanceof Ecore.EList ? value.array() : value;
472-
}, this));
482+
var value = null;
483+
this.__eContents = _.flatten(_.map(eContainments, function(c) {
484+
value = this.get(c.get('name'));
485+
return value ? (value.array ? value.array() : value) : [];
486+
}, this));
487+
488+
this.__updateContents = false;
489+
}
490+
491+
return this.__eContents;
473492
},
474493

475494
// Returns the URI of the EObject.

src/resource.js

+15-6
Original file line numberDiff line numberDiff line change
@@ -305,11 +305,7 @@ var EClassResource = Ecore.Resource = Ecore.EClass.create({
305305
_: function(fragment) {
306306
if (!fragment) return null;
307307

308-
if (this.__index == null) {
309-
this.__index = buildIndex(this);
310-
}
311-
312-
return this.__index[fragment];
308+
return this._index()[fragment];
313309
}
314310
},
315311
{
@@ -403,7 +399,20 @@ var EClassResource = Ecore.Resource = Ecore.EClass.create({
403399
name: '_index',
404400
eType: JSObject,
405401
_: function() {
406-
return buildIndex(this);
402+
if (_.isUndefined(this.__updateIndex)) {
403+
var res = this;
404+
res.__updateIndex = true;
405+
res.on('add remove', function() {
406+
res.__updateIndex = true;
407+
})
408+
}
409+
410+
if (this.__updateIndex) {
411+
this.__index = buildIndex(this);
412+
this.__updateIndex = false;
413+
}
414+
415+
return this.__index;
407416
}
408417
}
409418
]

test/index.test.js

+65
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
var Ecore = require('../dist/ecore.js');
2+
var assert = require('assert');
3+
var _ = require('underscore');
4+
5+
describe('index', function() {
6+
7+
var resource;
8+
9+
beforeEach(function() {
10+
var resourceSet = Ecore.ResourceSet.create();
11+
12+
var p = Ecore.EPackage.create({ name: 'p' });
13+
var a = Ecore.EClass.create({ name: 'A' });
14+
var b = Ecore.EClass.create({ name: 'B' });
15+
16+
p.get('eClassifiers')
17+
.add(a)
18+
.add(b);
19+
20+
resource = resourceSet.create('test');
21+
resource.add(p);
22+
});
23+
24+
it('should have index', function() {
25+
var index = resource._index();
26+
assert.ok(index);
27+
assert.equal(3, _.keys(index).length);
28+
})
29+
30+
it('should be updated when adding an element', function(done) {
31+
assert.ok(resource._index());
32+
33+
resource.on('add', function(list) {
34+
assert.ok(resource.__updateIndex === true);
35+
36+
var index = resource._index();
37+
assert.equal(4, _.keys(index).length);
38+
39+
assert.strictEqual(index, resource.__index);
40+
41+
done();
42+
})
43+
44+
var c = Ecore.EClass.create({ name: 'C' });
45+
resource.get('contents').at(0).get('eClassifiers').add(c);
46+
})
47+
48+
it('should be update when removing an element', function(done) {
49+
var index = resource._index();
50+
assert.equal(3, _.keys(index).length);
51+
52+
resource.on('remove', function(list) {
53+
assert.ok(resource.__updateIndex === true);
54+
index = resource._index();
55+
assert.equal(2, _.keys(index).length);
56+
57+
done();
58+
})
59+
60+
var root = resource.get('contents').at(0);
61+
root.get('eClassifiers').remove(root.get('eClassifiers').at(1));
62+
})
63+
64+
})
65+

test/resource.test.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
var fs = require('fs');
22
var Ecore = require('../dist/ecore.js');
3-
var assert = require("assert");
3+
var assert = require('assert');
44

55
describe('Resource', function() {
66

0 commit comments

Comments
 (0)