You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This paper serves as a whitepaper for feasible performance optimizations proposals which can be performed on ApiDOM monorepo. Paper is divided into sections (single top level section represents one monorepo package) and each of these sections is further divided into sub-sections describing the actual performance optimization proposal.
Paper also contains references to various revisions. Keep in mind that code can change between specific revision and master branch as time goes on. This can render certain performance optimization proposal invalid.
For every use of transclude function all the parent edges needs to be computed.
Single transclution
It is more optimal to use single traversal run for this usecase. As soon as search element is found, it is transcluded with replace element and traversal is immediately stopped.
Multi transclution
This is a usecase where multiple search elements needs to be replaced by multiple replace elements. Again it is more optimal to use traversal to replace/transclude the nodes.
Repeated transclution
This is more a corner case - we want to transclude one or multiple elements during different points in time on the same ApiDOM structure. It's possible to use current implementation of transclution to cover this usecase.
All the fore-mentioned usecases are currently embedded in one single implementation which makes it less then optimal.
Parallel visiting or megring of the visitors is implemented in a way where all the "merged" visitors are iterated in every enter or leave visitor function and appropriate visitFn is obtained and executed. This can be implemented in more performant way where static chain of visitor functions is constructed by merging the visitors before they're executed.
Parallel visiting (merging) is used in refractor layers in all the namespace packages.
During refracting phase traversal is executed on every field of every Object Element or item of Array Element. This has potentially significant performance implications. We could device a more performant mechanism (let's call it visitor-shortcut) that would not run traversal on any field that we expect is going to be a primitive or generic element (String Element, Number Element, Object Element, etc...). Instead fields like those are going to be directly translated from generic form to semantic form by simple cloning.
Currently every primitive field has it's own file even though it's using generic FallbackVisitor. We can eliminate those files and attach visitors directly in specification objects. By this we will save a lot of code and file imports and lower the overall size of resulting UMD bundles.
If refractor plugins are utilized, they require additional full traversal after the refracting phase has finished. It would be convenient to run refractor plugins without additional full traversal. Running plugins inside refracting phase is not feasible as refraction transforms generic ApiDOM into semantic progressively. If we would run refractor plugins inside refracting phase it would mean that plugins will receive either generic ApiDOM elements or semantic ones depending on the state of refracting at the point of refractor plugin intercepting it. One feasible solution would be to fold our build-in defaults plugins into refracting phase directly and if there would be need for additional ad-hoc plugins, person that attaches them to refractor must expect that there will be performance implication.
During refracting phase traversal is executed on every field of every Object Element or item of Array Element. This has potentially significant performance implications. We could device a more performant mechanism (let's call it visitor-shortcut) that would not run traversal on any field that we expect is going to be a primitive or generic element (String Element, Number Element, Object Element, etc...). Instead fields like those are going to be directly translated from generic form to semantic form by simple cloning.
Currently every primitive field has it's own file even though it's using generic FallbackVisitor. We can eliminate those files and attach visitors directly in specification objects. By this we will save a lot of code and file imports and lower the overall size of resulting UMD bundles.
If refractor plugins are utilized, they require additional full traversal after the refracting phase has finished. It would be convenient to run refractor plugins without additional full traversal. Running plugins inside refracting phase is not feasible as refraction transforms generic ApiDOM into semantic progressively. If we would run refractor plugins inside refracting phase it would mean that plugins will receive either generic ApiDOM elements or semantic ones depending on the state of refracting at the point of refractor plugin intercepting it. One feasible solution would be to fold our build-in defaults plugins into refracting phase directly and if there would be need for additional ad-hoc plugins, person that attaches them to refractor must expect that there will be performance implication.
In order to parse source JSON string into generic ApiDOM following parsing phases are peformed:
Lexical analysis (tree-sitter)
Source JSON string is parsed and tokenized. The result of these operations is a structure that technically categorizes as CST, but contains further APIs for AST like manipulation.
Syntactical analysis
CST is transformed into JSON AST.
Transform
During this phase JSON AST is transformed into generic ApiDOM.
We could possibly fold phase 2. and 3. into a single phase. By doing this we would avoid one full traversal and maintaining additional JSON AST structure in memory. Syntactical analysis phase doesn't contain any additional logic that couldn't be folded easily into Transform phase because JSON is very simple format to process.
In order to parse source YAML 1.2 string into generic ApiDOM following parsing phases are peformed:
Lexical analysis (tree-sitter)
Source YAML string is parsed and tokenized. The result of these operations is a structure that technically categorizes as CST, but contains further APIs for AST like manipulation.
Syntactical analysis
CST is transformed into YAML AST. These transformations includes resolving YAML anchors, processing YAML Schemas and creating surrogate AST nodes wherever they're missing.
Transform
During this phase YAML AST is transformed into generic ApiDOM.
We could possibly fold phase 2. and 3. into a single phase. By doing this we would avoid one full traversal and maintaining additional YAML AST structure in memory. Unfortunately YAML 1.2 is pretty complex and folding the two phases would create complex code that would not be easy to maintain. IMHO in this case code readability and maintenance wins over performance. It is always possible to create additional YAML 1.2 adapter with folded phases in future.
This is a hollow adapter composed of two main packages: apidom-parser-adapter-json and apidom-ns-asyncapi-2-0. All the performance optimizations that will be performed on these two main packages will inevitably increase performance of this adapter.
This adapter goes through following phases:
Lexical analysis
Syntactical analysis
Transform
Refracting
It's possible to create a super performant version of this adapter folding all the aforementioned phases into single one.
This is a hollow adapter composed of two main packages: apidom-parser-adapter-yaml-1-2 and apidom-ns-asyncapi-2-0. All the performance optimizations that will be performed on these two main packages will inevitably increase performance of this adapter.
This adapter goes through following phases:
Lexical analysis
Syntactical analysis
Transform
Refracting
It's possible to create a super performant version of this adapter folding all the aforementioned phases into single one.
This is a hollow adapter composed of two main packages: apidom-parser-adapter-json and apidom-ns-openapi-3-1. All the performance optimizations that will be performed on these two main packages will inevitably increase performance of this adapter.
This adapter goes through following phases:
Lexical analysis
Syntactical analysis
Transform
Refracting
It's possible to create a super performant version of this adapter folding all the aforementioned phases into single one.
This is a hollow adapter composed of two main packages: apidom-parser-adapter-yaml-1-2 and apidom-ns-openapi-3-1. All the performance optimizations that will be performed on these two main packages will inevitably increase performance of this adapter.
This adapter goes through following phases:
Lexical analysis
Syntactical analysis
Transform
Refracting
It's possible to create a super performant version of this adapter folding all the aforementioned phases into single one.
No feasible performance optimization are currently proposed for this package. The performance and optimal memory management were kept in check during all implementations.
Performance analytics
All performance analytics are performed using benchmark.js library. This library contains proper statistical model for performing analysis.
char0n
changed the title
Creates not about possible optimizations and performance
Creates notes about possible optimizations and performance
Apr 29, 2021
char0n
changed the title
Creates notes about possible optimizations and performance
ApiDOM performance whitepaper
May 4, 2021
This paper serves as a whitepaper for feasible performance optimizations proposals which can be performed on ApiDOM monorepo. Paper is divided into sections (single top level section represents one monorepo package) and each of these sections is further divided into sub-sections describing the actual performance optimization proposal.
Paper also contains references to various revisions. Keep in mind that code can change between specific revision and master branch as time goes on. This can render certain performance optimization proposal invalid.
apidom
Transcluder
For every use of transclude function all the parent edges needs to be computed.
Single transclution
It is more optimal to use single traversal run for this usecase. As soon as
search
element is found, it is transcluded withreplace
element and traversal is immediately stopped.Multi transclution
This is a usecase where multiple
search
elements needs to be replaced by multiplereplace
elements. Again it is more optimal to use traversal to replace/transclude the nodes.Repeated transclution
This is more a corner case - we want to transclude one or multiple elements during different points in time on the same ApiDOM structure. It's possible to use current implementation of transclution to cover this usecase.
All the fore-mentioned usecases are currently embedded in one single implementation which makes it less then optimal.
apidom-ast
Parallel visiting
Parallel visiting or megring of the visitors is implemented in a way where all the "merged" visitors are iterated in every
enter
orleave
visitor function and appropriatevisitFn
is obtained and executed. This can be implemented in more performant way where static chain of visitor functions is constructed by merging the visitors before they're executed.Parallel visiting (merging) is used in refractor layers in all the namespace packages.
apidom-ns-asyncapi-2-0
Refracting primitive fields
During refracting phase traversal is executed on every field of every Object Element or item of Array Element. This has potentially significant performance implications. We could device a more performant mechanism (let's call it visitor-shortcut) that would not run traversal on any field that we expect is going to be a primitive or generic element (String Element, Number Element, Object Element, etc...). Instead fields like those are going to be directly translated from generic form to semantic form by simple cloning.
Refracting primitive fields - utilize specification object
Currently every primitive field has it's own file even though it's using generic
FallbackVisitor
. We can eliminate those files and attach visitors directly in specification objects. By this we will save a lot of code and file imports and lower the overall size of resulting UMD bundles.Refractor plugins
If refractor plugins are utilized, they require additional full traversal after the refracting phase has finished. It would be convenient to run refractor plugins without additional full traversal. Running plugins inside refracting phase is not feasible as refraction transforms generic ApiDOM into semantic progressively. If we would run refractor plugins inside refracting phase it would mean that plugins will receive either generic ApiDOM elements or semantic ones depending on the state of refracting at the point of refractor plugin intercepting it. One feasible solution would be to fold our build-in defaults plugins into refracting phase directly and if there would be need for additional ad-hoc plugins, person that attaches them to refractor must expect that there will be performance implication.
apidom-ns-openapi-3-1
Refracting primitive fields
During refracting phase traversal is executed on every field of every Object Element or item of Array Element. This has potentially significant performance implications. We could device a more performant mechanism (let's call it visitor-shortcut) that would not run traversal on any field that we expect is going to be a primitive or generic element (String Element, Number Element, Object Element, etc...). Instead fields like those are going to be directly translated from generic form to semantic form by simple cloning.
Refracting primitive fields - utilize specification object
Currently every primitive field has it's own file even though it's using generic
FallbackVisitor
. We can eliminate those files and attach visitors directly in specification objects. By this we will save a lot of code and file imports and lower the overall size of resulting UMD bundles.Refractor plugins
If refractor plugins are utilized, they require additional full traversal after the refracting phase has finished. It would be convenient to run refractor plugins without additional full traversal. Running plugins inside refracting phase is not feasible as refraction transforms generic ApiDOM into semantic progressively. If we would run refractor plugins inside refracting phase it would mean that plugins will receive either generic ApiDOM elements or semantic ones depending on the state of refracting at the point of refractor plugin intercepting it. One feasible solution would be to fold our build-in defaults plugins into refracting phase directly and if there would be need for additional ad-hoc plugins, person that attaches them to refractor must expect that there will be performance implication.
apidom-parser
No feasible performance optimization are currently proposed for this package.
apidom-parser-adapter-json
Syntactical analysis
In order to parse source JSON string into generic ApiDOM following parsing phases are peformed:
Source JSON string is parsed and tokenized. The result of these operations is a structure that technically categorizes as CST, but contains further APIs for AST like manipulation.
CST is transformed into JSON AST.
During this phase JSON AST is transformed into generic ApiDOM.
We could possibly fold phase 2. and 3. into a single phase. By doing this we would avoid one full traversal and maintaining additional JSON AST structure in memory.
Syntactical analysis phase
doesn't contain any additional logic that couldn't be folded easily intoTransform
phase because JSON is very simple format to process.apidom-parser-adapter-yaml-1-2
Syntactical analysis
In order to parse source YAML 1.2 string into generic ApiDOM following parsing phases are peformed:
Source YAML string is parsed and tokenized. The result of these operations is a structure that technically categorizes as CST, but contains further APIs for AST like manipulation.
CST is transformed into YAML AST. These transformations includes resolving YAML anchors, processing YAML Schemas and creating surrogate AST nodes wherever they're missing.
During this phase YAML AST is transformed into generic ApiDOM.
We could possibly fold phase 2. and 3. into a single phase. By doing this we would avoid one full traversal and maintaining additional YAML AST structure in memory. Unfortunately YAML 1.2 is pretty complex and folding the two phases would create complex code that would not be easy to maintain. IMHO in this case code readability and maintenance wins over performance. It is always possible to create additional YAML 1.2 adapter with folded phases in future.
apidom-parser-adapter-asyncapi-json-2-0
This is a hollow adapter composed of two main packages: apidom-parser-adapter-json and apidom-ns-asyncapi-2-0. All the performance optimizations that will be performed on these two main packages will inevitably increase performance of this adapter.
This adapter goes through following phases:
It's possible to create a super performant version of this adapter folding all the aforementioned phases into single one.
Transclution
We could avoid transclusion here completely or use one of the already optimized transcluder described in this paper.
apidom-parser-adapter-asyncapi-yaml-2-0
This is a hollow adapter composed of two main packages: apidom-parser-adapter-yaml-1-2 and apidom-ns-asyncapi-2-0. All the performance optimizations that will be performed on these two main packages will inevitably increase performance of this adapter.
This adapter goes through following phases:
It's possible to create a super performant version of this adapter folding all the aforementioned phases into single one.
Transclution
We could avoid transclusion here completely or use one of the already optimized transcluder described in this paper.
apidom-parser-adapter-openapi-json-3-1
This is a hollow adapter composed of two main packages: apidom-parser-adapter-json and apidom-ns-openapi-3-1. All the performance optimizations that will be performed on these two main packages will inevitably increase performance of this adapter.
This adapter goes through following phases:
It's possible to create a super performant version of this adapter folding all the aforementioned phases into single one.
Transclution
We could avoid transclusion here completely or use one of the already optimized transcluder described in this paper.
apidom-parser-adapter-openapi-yaml-3-1
This is a hollow adapter composed of two main packages: apidom-parser-adapter-yaml-1-2 and apidom-ns-openapi-3-1. All the performance optimizations that will be performed on these two main packages will inevitably increase performance of this adapter.
This adapter goes through following phases:
It's possible to create a super performant version of this adapter folding all the aforementioned phases into single one.
Transclution
We could avoid transclusion here completely or use one of the already optimized transcluder described in this paper.
apidom-reference
No feasible performance optimization are currently proposed for this package. The performance and optimal memory management were kept in check during all implementations.
Performance analytics
All performance analytics are performed using benchmark.js library. This library contains proper statistical model for performing analysis.
Resources
Performance optimizations
The text was updated successfully, but these errors were encountered: