Skip to content

Commit

Permalink
perf(ns-asyncapi-2-0): introduce visitor shortcut
Browse files Browse the repository at this point in the history
Visitor shotcut improves performance by 8-9% during refracting
phase.

Closes #398
  • Loading branch information
char0n committed May 7, 2021
1 parent 1cb7d7a commit 78a54dc
Show file tree
Hide file tree
Showing 27 changed files with 111 additions and 66 deletions.
2 changes: 2 additions & 0 deletions apidom/packages/apidom-ns-asyncapi-2-0/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
"lint:fix": "eslint ./ --fix",
"clean": "rimraf ./es ./cjs ./dist ./types",
"test": "cross-env BABEL_ENV=cjs mocha",
"perf": "cross-env BABEL_ENV=cjs node ./test/perf/index.js",
"perf:visitor-shortcut": "cross-env BABEL_ENV=cjs node ./test/perf/visitor-shortcut.js",
"typescript:check-types": "tsc --noEmit",
"typescript:declaration": "tsc -p declaration.tsconfig.json"
},
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import stampit from 'stampit';
import { pathSatisfies, path, pick, pipe, keys } from 'ramda';
import { isFunction } from 'ramda-adjunct';
import { isFunction, isUndefined } from 'ramda-adjunct';
import { visit } from 'apidom';

import { keyMap, getNodeType } from '../../traversal/visitor';
Expand Down Expand Up @@ -42,7 +42,27 @@ const SpecificationVisitor = stampit(Visitor, {
},

toRefractedElement(specPath: string[], element, options = {}) {
const visitor = this.retrieveVisitorInstance(specPath);
/**
* This is `Visitor shortcut`: mechanism for short circuiting the traversal and replacing
* it by basic node cloning.
*
* Visiting the element is equivalent to cloning it if the prototype of a visitor
* is the same as the prototype of FallbackVisitor. If that's the case, we can avoid
* bootstrapping the traversal cycle for fields that don't require any special visiting.
*/
const visitor = this.retrieveVisitorInstance(specPath, options);
const visitorPrototype = Object.getPrototypeOf(visitor);

if (isUndefined(this.fallbackVisitorPrototype)) {
this.fallbackVisitorPrototype = Object.getPrototypeOf(
this.retrieveVisitorInstance(['value']),
);
}
if (this.fallbackVisitorPrototype === visitorPrototype) {
return element.clone();
}

// standard processing continues
visit(element, visitor, { keyMap, ...options, nodeTypeGetter: getNodeType });
return visitor.element;
},
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import stampit from 'stampit';

import FallbackVisitor from '../../FallbackVisitor';

const $RefVisitor = stampit(FallbackVisitor);
const $RefVisitor = FallbackVisitor;

export default $RefVisitor;
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import stampit from 'stampit';

import FallbackVisitor from '../../FallbackVisitor';

const DescriptionVisitor = stampit(FallbackVisitor);
const DescriptionVisitor = FallbackVisitor;

export default DescriptionVisitor;
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import stampit from 'stampit';

import FallbackVisitor from '../../FallbackVisitor';

const EmailVisitor = stampit(FallbackVisitor);
const EmailVisitor = FallbackVisitor;

export default EmailVisitor;
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import stampit from 'stampit';

import FallbackVisitor from '../../FallbackVisitor';

const NameVisitor = stampit(FallbackVisitor);
const NameVisitor = FallbackVisitor;

export default NameVisitor;
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import stampit from 'stampit';

import FallbackVisitor from '../../FallbackVisitor';

const UrlVisitor = stampit(FallbackVisitor);
const UrlVisitor = FallbackVisitor;

export default UrlVisitor;
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import stampit from 'stampit';

import FallbackVisitor from '../../FallbackVisitor';

const DescriptionVisitor = stampit(FallbackVisitor);
const DescriptionVisitor = FallbackVisitor;

export default DescriptionVisitor;
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import stampit from 'stampit';

import FallbackVisitor from '../../FallbackVisitor';

const TermsOfServiceVisitor = stampit(FallbackVisitor);
const TermsOfServiceVisitor = FallbackVisitor;

export default TermsOfServiceVisitor;
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import stampit from 'stampit';

import FallbackVisitor from '../../FallbackVisitor';

const TitleVisitor = stampit(FallbackVisitor);
const TitleVisitor = FallbackVisitor;

export default TitleVisitor;
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import stampit from 'stampit';

import FallbackVisitor from '../../FallbackVisitor';

const NameVisitor = stampit(FallbackVisitor);
const NameVisitor = FallbackVisitor;

export default NameVisitor;
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import stampit from 'stampit';

import FallbackVisitor from '../../FallbackVisitor';

const UrlVisitor = stampit(FallbackVisitor);
const UrlVisitor = FallbackVisitor;

export default UrlVisitor;
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import stampit from 'stampit';

import FallbackVisitor from '../../FallbackVisitor';

const DescriptionVisitor = stampit(FallbackVisitor);
const DescriptionVisitor = FallbackVisitor;

export default DescriptionVisitor;
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import stampit from 'stampit';

import FallbackVisitor from '../../FallbackVisitor';

const LocationVisitor = stampit(FallbackVisitor);
const LocationVisitor = FallbackVisitor;

export default LocationVisitor;
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import stampit from 'stampit';

import FallbackVisitor from '../../FallbackVisitor';

const $RefVisitor = stampit(FallbackVisitor);
const $RefVisitor = FallbackVisitor;

export default $RefVisitor;
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import stampit from 'stampit';

import FallbackVisitor from '../../FallbackVisitor';

const DefaultVisitor = stampit(FallbackVisitor);
const DefaultVisitor = FallbackVisitor;

export default DefaultVisitor;
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import stampit from 'stampit';

import FallbackVisitor from '../../FallbackVisitor';

const DescriptionVisitor = stampit(FallbackVisitor);
const DescriptionVisitor = FallbackVisitor;

export default DescriptionVisitor;
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import stampit from 'stampit';

import FallbackVisitor from '../../FallbackVisitor';

const EnumVisitor = stampit(FallbackVisitor);
const EnumVisitor = FallbackVisitor;

export default EnumVisitor;
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import stampit from 'stampit';

import FallbackVisitor from '../../FallbackVisitor';

const ExamplesVisitor = stampit(FallbackVisitor);
const ExamplesVisitor = FallbackVisitor;

export default ExamplesVisitor;
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import stampit from 'stampit';

import FallbackVisitor from '../../FallbackVisitor';

const DescriptionVisitor = stampit(FallbackVisitor);
const DescriptionVisitor = FallbackVisitor;

export default DescriptionVisitor;
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import stampit from 'stampit';

import FallbackVisitor from '../../FallbackVisitor';

const ProtocolVersionVisitor = stampit(FallbackVisitor);
const ProtocolVersionVisitor = FallbackVisitor;

export default ProtocolVersionVisitor;
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import stampit from 'stampit';

import FallbackVisitor from '../../FallbackVisitor';

const ProtocolVisitor = stampit(FallbackVisitor);
const ProtocolVisitor = FallbackVisitor;

export default ProtocolVisitor;
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import stampit from 'stampit';

import FallbackVisitor from '../../FallbackVisitor';

const UrlVisitor = stampit(FallbackVisitor);
const UrlVisitor = FallbackVisitor;

export default UrlVisitor;
5 changes: 5 additions & 0 deletions apidom/packages/apidom-ns-asyncapi-2-0/test/perf/.eslintrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"rules": {
"@typescript-eslint/no-var-requires": 0
}
}
19 changes: 19 additions & 0 deletions apidom/packages/apidom-ns-asyncapi-2-0/test/perf/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
require('@babel/register')({ extensions: ['.js', '.ts'], rootMode: 'upward' });

const Benchmark = require('benchmark');

const visitorShortcutBench = require('./visitor-shortcut');

const suite = new Benchmark.Suite();

suite
.add(visitorShortcutBench)
// add listeners
.on('cycle', function (event) {
console.info(String(event.target));
})
.on('complete', function () {
console.info('\nAll benchmarks have completed');
})
// run
.run();
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
require('@babel/register')({ extensions: ['.js', '.ts'], rootMode: 'upward' });

const Benchmark = require('benchmark');
const { ObjectElement } = require('apidom');

const { AsyncApi2_0Element } = require('../../src');

const genericObjectElement = new ObjectElement({
asyncapi: '2.0.0',
info: {
title: 'Webhook Example',
version: '1.0.0',
description: 'description',
termsOfService: 'tos',
},
});

const options = {
name: 'visitor-shortcut',
minSamples: 700,
expected: '640 ops/sec ±0.82% (780 runs sampled)',
fn() {
AsyncApi2_0Element.refract(genericObjectElement);
},
};

module.exports = options;

// we're running as a script
if (module.parent === null) {
const bench = new Benchmark({
...options,
onComplete(event) {
console.info(String(event.target));
},
onError(event) {
console.error(event);
},
});
bench.run();
}
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ const FixedFieldsVisitor = stampit(SpecificationVisitor, {
);
this.element.content.push(extensionElement);
} else if (!this.ignoredFields.includes(key.toValue())) {
this.element.content.push(memberElement);
this.element.content.push(memberElement.clone());
}
});

Expand Down

0 comments on commit 78a54dc

Please sign in to comment.