View on GitHub

PHATDocs

Documentation for https://github.com/chgibb/phat

Home

For 0.11.0

Contents

Previous: Repository Structure

Performance

We strive to provide performance in all our functionality implemented in first-party code. That is, features implemented first-party, but most importantly in our genome visualization. That functionality implemented by third-party code/binaries (such as alignment, QC reports etc) is not a focus of our continual profiling and optimization efforts. Monthly manual stress tests of genome visualization are performed using bacterial genomes with simulated alignments on an Acer C720p Chromebook running Ubuntu 14.04LTS. The primary goal being to keep startup times for application components under 1 second, RAM use (especially when visualising genomes with massive coverage) low and genome resizing and rendering times down. Here, we try to explain individual methods and techniques utilized to try to keep PHAT performant.

V8 Switches

On startup, --expose_gc, --nolazy, --serialize_eager, and --always_compact are applied through Electron.app.commandLine.appendSwitch.

V8 Code Caching

Through Node.jsVM module, we make heavy use of V8’s code caching features in our own code caching module. See some discussion here. PHAT never executes any Javascript directly. All Javascript is compiled into .cdata files. In the case where existing .cdata is rejected due to a change in source (such as through updates), new .cdata is compiled and then run on the user’s machine directly. These files are not shipped in updates in an attempt to keep update downloads as small as possible as well as to prevent issues with different CPUs. V8 will reject cached code compiled on a machine with a different microarchitecture.

Javascript Bundle Optimizations

Over time, the currently employed set of bundle optimizations has evolved. Regular benchmarking has shown these specific optimizations, in the specific order they are listed yields fastest loading code (when combined with code caching, as described above). Performance benchmarking should be a continuous process. These are always subject to change if better performance can be had.

--importHelpers Typescript Compiler Switch

While not an optimization applied to a bundle per-se, this switch, when combined with --module ES2015 and RollupJS has been shown to shave a few kilobytes off of bundles which heavily use features which depend on Typescript runtime helpers. A good discussion on the topic can be found here.

RollupJS

RollupJS is used to pair down first party code to the minimum required at runtime. require statements for third-party modules are localised to the functions which require them in an attempt to eliminate bundling of third-party code into processes which don’t require it.

Bundle Collapsing

bundle collapsing is used to remove paths from require statements and turn them into integers. This has shown to be a non-trivial share of bundle size.

Name Mangling

Babel’s minify-mangle-names plugin is used to shorten variable, parameter, class and function names.

Simplify Type Constructors

Using babel-plugin-minify-type-constructors.

Dead Code Elimination

Using babel-plugin-minify-dead-code-elimination.

Simplify Constant Folding

Using babel-plugin-minify-constant-folding.

Minification

Uglify-es is used to eliminate whitespace and strip comments, the majority of bundle size.

IIF/IIFE Optimizations

Optimize-js is applied as a final step. A fantastic explanation and discussion is included at the link.

Currently, property names are depended upon heavily at runtime. If we can figure out how to mangle or safely rename property names without breaking PHAT, there will be far more savings to be had.

Circular Visualization Performance

ngPlasmid drives PHAT’s circular visualization. ngPlasmid was born out of an attempt to improve the performance of Angular Plasmid, upon which PHAT’s circular visualization is based. Discussion on techniques employed can be found in its repository.

Contents