This PR adds support for importing from Google's pprof format, which is a gzipped, protobuf encoded file format (that's incredibly well documented!) The [pprof http library](https://golang.org/pkg/net/http/pprof/) also offers an output of the trace file format, which continues to not be supported in speedscope to date (See #77). This will allow importing of profiles generated by the standard library go profiler for analysis of profiles containing heap allocation information, CPU profile information, and a few other things like coroutine creation information.
In order to add support for that a number of dependent bits of functionality were added, which should each provide an easier path for future binary input sources
- A protobuf decoding library was included ([protobufjs](https://www.npmjs.com/package/protobufjs)) which includes both a protobuf parser generator based on a .proto file & TypeScript definition generation from the resulting generated JavaScript file
- More generic binary file import. Before this PR, all supported sources were plaintext, with the exception of Instruments 10 support, which takes a totally different codepath. Now binary file import should work when files are dropped, opened via file browsing, or opened via invocation of the speedscope CLI.
- Transparent gzip decoding of imported files (this means that if you were to gzip compress another JSON file, then importing it should still work fine)
Fixes#60.
--
This is a [donation motivated](https://github.com/jlfwong/speedscope/issues/60#issuecomment-419660710) PR motivated by donations by @davecheney & @jmoiron to [/dev/color](https://www.devcolor.org/welcome) 🎉
More broadly, this just supports multiple profiles loaded into the editor in the same time, which supports import from profiles which are multithreaded by importing each thread as a different profile.
For now, the only two file formats that support multiprocess import are Instruments .trace files and speedscope's own file format
In the process of doing this, I refactored the container code considerably and extracted all the dispatch calls into containers rather than them being part of the non-container view code. This is nice because it means that views don't have to be aware of which Flamechart they are or which profile index is being operated upon.
Fixes#66Fixes#82Fixes#91
While it was kind of nice having everything at the top level, the number of files is now getting a bit unwieldy and hard to understand, so I took a stab at organizing the directories without introducing too much nesting.
Test Plan:
- Ran `npm run serve` to ensure that local builds still work
- Ran `npm run prepack` then `open dist/release/index.html` to ensure that release builds still work
- Ran `scripts/deploy.sh` to ensure that the deployed version of the site will still work when I eventually redeploy
- Ran `npm run jest` to ensure that tests still work correctly
This should allow state to be more easily retained globally when switching views, and should make implementation of cross-view features like search easier too.
It also removes the need for `ReloadableComponent`
Fixes#78
Test Plan:
This changes a lot of how the app works, and a lot of stuff that isn't currently covered by tests, so here's a rough manual test plan:
1. Loaded up http://localhost:1234/, click to load the example profile
2. Switch between views, see that viewport & selection position is now retained when switching views
3. See that clicking on nodes selects them in Time Order & Left Heavy views
4. See that hitting Cmd+S saves a profile
5. See that dropping a profile in works
6. See that dropping a profile + a symbol map works
7. See that visiting localhost:1234/#profileURL=https://raw.githubusercontent.com/jlfwong/speedscope/master/sample/profiles/speedscope/0.1.2/simple-sampled.speedscope.json works
8. See that hitting "r" to toggle recursion flattening works
This PR add a CLI speedscope which load file given as an argument in your default browser. Expected usage looks like:
```
speedscope /path/to/profile
```
Note that since we're using base64 encoded strings as a transport for this, this won't work with multi-file profiles, like the Instruments .trace files. This could be augmented to support that by archiving the contents, but that can be handled in a different PR.
This PR also set up a viable model for integrating speedscope into other projects. By replicating the contents of `cli.js` in other languages, integration should be possible in other languages with no dependency upon node in any way. Distribution should consist of just HTML, JS, and CSS assets to be loaded in browser.
Test Plan:
- Ran the following to simulate a publish & subsequent installation:
```
$ npm pack
$ mv speedscope-0.1.0.tgz /tmp/
$ cd /tmp
$ tar -xvvf speedscope-0.1.0.tgz
$ cd package
$ npm install --only=production
$ ./cli.js
Opening file:///private/tmp/package/dist/release/index.html in your default browser
$ ./cli.js ~/code/speedscope/sample/profiles/Chrome/65/timeline.json
Creating temp file /var/folders/l0/qtd9z14973s2tw81vmzwkyp00000gp/T/speedscope-1531023992823-3880.js
Creating temp file /var/folders/l0/qtd9z14973s2tw81vmzwkyp00000gp/T/speedscope-1531023992823-3880.html
Opening file:///var/folders/l0/qtd9z14973s2tw81vmzwkyp00000gp/T/speedscope-1531023992823-3880.html in your default browser
```
Fixes#24
This defines a JSON-based file format for speedscope.
The motivation for is primarily two things:
1. To enable others to write tools to output profiles which can be read by speedscope
2. To enable others to write tools to handle the output of speedscope, leveraging the variety of importers that speedscope supports
Fixes#65
* Tests for clamp, Vec2
* Switch to using jsverify for testing math functions
* Add tests for AffineTransform
* Add tests for Rect
* Add tests for rect transformations
#33 added support for importing from instruments indirectly via opening instruments and using the deep copy command. This PR adds support for importing `.trace` files directly, though only for time profiles specifically, and only for the highest sample count thread in the profile.
This PR adds `.trace` files from Instruments 9, and adds support for importing from either Instruments 8 and 9. The only major difference in the file format seems to be that Instruments 9 applies raw `zlib` compression generously throughout the file.
This PR also adds example `.trace` files for memory allocations, which are not supported for direct import. They use a totally different storage format for recording memory allocations, and I haven't yet figured out how that list of allocations references their corresponding callstack.
Lastly, this PR also adds examples from Instruments 7 since I happen to have a machine with an old version of Instruments. Import from Instruments 7 probably wouldn't be hard to add, but I haven't done that in this PR.
This currently only works in Chrome, and only via drag-and-drop of the files.
To test, drag the decompressed `simple-time-profile.trace` from 6016d970b9/sample/profiles/Instruments/9.3.1/simple-time-profile.trace.zip onto speedscope.
The result should be this:
![image](https://user-images.githubusercontent.com/150329/40162338-8fa13502-5968-11e8-8fb3-40626e41884a.png)
Fixes#15
* Install prettier, set up the config file, and run it on all ts and tsx files.
* Install eslint and configure it with just eslint-plugin-prettier to check to
make sure that prettier has been run.
* Add a basic .travis.yml that runs eslint.
There are other style things that might be nice to enforce with ESLint/TSLint,
like using const, import order, etc, but this commit just focuses on prettier,
which gets most of the way there.
One annoying issue for now is that typescript-eslint-parser gives a big warning
message since they haven't updated to officially support TypeScript 2.8 yet. We
aren't even using any ESLint rules that need the parser, but if we don't include
it, ESLint will crash. TS2.8 support is hopefully coming really soon, though:
https://github.com/eslint/typescript-eslint-parser/pull/454
As for the prettier config specifically, see https://prettier.io/docs/en/options.html
for the available options.
Config settings that seem non-controversial:
Semicolons: You don't use semicolons. (I prefer semicolons, but either way is fine.)
Quote style: Looks like you consistently use single quotes outside JSX and double
quotes in JSX, which is the `singleQuote: true` option.
Config settings worth discussion:
Line width: You don't have a specific max. I put 100 since I think it's a good number
for people (like both of us, probably) who find 80 a bit cramped. (At Benchling we use
110.) Prettier has a big red warning box recommending 80, but I still prefer 100ish.
Bracket spacing: This is `{foo}` vs `{ foo }` for imports, exports, object literals,
and destructuring. Looks like you're inconsistent but lean toward spaces. I personally
really dislike bracket spacing (it feels inconsistent with arrays and function calls),
but I'm certainly fine with it and Prettier has it enabled by default, so I kept it
enabled.
Trailing comma style: Options are "no trailing commas", "trailing commas for
everything exception function calls and parameter lists", and "trailing commas
everywhere". TypeScript can handle trailing commas everywhere, so there isn't a
concern with tooling. You're inconsistent, and it looks like you tend to not have
trailing commas, but I think it's probably best to just have them everywhere, so I
enabled them.
JSX Brackets: You're inconsistent about this, I think. I'd prefer to just keep the
default and wrap the `>` to the next line.
Arrow function parens: I only found two cases of arrow functions with one param
(both `c => c.frame === frame`), and both omitted the parens, so I kept the
default of omitting parens. This makes it mildly more annoying to add a typescript
type or additional param, which is a possible reason for always requiring parens.
Everything else is non-configurable, although it's possible some places would be
better with a `// prettier-ignore` comment (but I usually try to avoid those).
Previously, I was doing a hacky release process where I had `index.html` serve contents for `jlfwong.github.io/speedscope`, but used `dev.html` locally. This seems like it broke with the latest parcel release, so I just revamped the release process instead.
Now, the `release.sh` script creates a temporary shallow clone of the repository, overwrites its contents with build artifacts, runs a local server to verify it's working, then commits and pushes to the `gh-pages` branches.