Compare commits

...
8 Commits
Author SHA1 Message Date
Jamie Wong 853164ebbf 0.7.0 2018-08-16 11:56:17 -07:00
Jamie Wong 729d7c771b Add support for importing linux "perf script" output (#135)
Fixes #119
2018-08-16 10:24:12 -07:00
Jamie Wong 9d13d95f8d Add a section about verifying the publish 2018-08-14 10:38:42 -07:00
Jamie Wong 085d6298ec 0.6.0 2018-08-14 10:34:34 -07:00
Jamie Wong aa35b17d20 Downgrade to TypeScript 2.8.1 to fix JSON schema generation (#133)
Fixes #132
2018-08-14 09:37:42 -07:00
Jamie Wong a22ab9301f Add tests for redux store (#131)
This adds some baseline tests for the redux store, and also fixes some bugs I found along the way.

Bugs fixed:
- Changing selection after something has been selected within the sandwich view now works
- Table sort state is now preserved when switching between profiles

Fixes #124
2018-08-13 10:25:01 -07:00
Jamie Wong e404053837 Add support for profiles w/ multiples processes & threads (#130)
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 #66
Fixes #82
Fixes #91
2018-08-11 22:06:53 -07:00
Jamie Wong 558e98d24d 0.5.1 2018-08-11 22:05:39 -07:00
71 changed files with 12515 additions and 558 deletions
+19
View File
@@ -1,9 +1,28 @@
## [Unreleased]
## [0.7.0]
### Added
* Added support to import from linux `perf script` [#135]
## [0.6.0]
### Added
* Added support for multiple threads/processes [#130]
* Import all runs & threads from Instruments .trace files instead of just main thread from selected run [#130]
### Fixed
* Ensure the JSON schema has actual contents [#133]
## [0.5.1] - 2018-08-09
### Fixed
* Fixed broken CLI
## [0.5.0] - 2018-08-09
### Fixed
+78
View File
@@ -0,0 +1,78 @@
This document describes processes needed by admins of this repository.
# Publishing
Publishing speedscope is a multi-step process:
1. Test the release
2. Prepare the release
3. Publish to npm
4. Deploy the website
At time of writing, deployment assumes you're running macOS. It probably
works if you're on a linux, and almost definitely does not work on Windows.
## Test the release
Speedscope is tested in CI, so all the automated tests should be passing. We'll
just be doing a few sanity checks to make sure the build & deployment machinery is working correctly.
Run `scripts/prepare-test-installation.sh`. This will do a mock publish &
installation to ensure that the version we're about to publish is going to
work. At the end of this command, it should echo a `cd` command to run in your shell
to switch to the installation directory. Something like this:
```
Run the following command to switch into the test directory
cd /var/folders/l0/qtd9z14973s2tw81vmzwkyp00000gp/T/speedscope-test-installation.9Ssdd2PZ/package
```
Run this command, to switch to the test directory.
Inside of here, run `bin/cli.js`. This should open a copy of speedscope in browser.
Try importing a profile from disk via the browse button and make sure it works.
Next, try running `bin/cli.js dist/release/perf-vertx*`. This should immediately open
speedscope in browser, and the perf-vertx file should load immediately.
If everything looks good, proceed to "Prepare the release".
## Prepare the release
1. Update the version manually in package.json (we intentionally don't use the `npm version` command)
2. Update CHANGELOG.md to indicate the changes that were made as part of this release
3. Commit the changes with the version name as the commit message, e.g. `git commit -m 0.6.0`
4. `git tag` the release. We use tags like `v0.6.0`, e.g. `git tag v0.6.0`
5. `git push`
## Publish to npm
Assuming everything went well in the previous two phases, publishing should just be
a matter of running `npm publish`.
### Verifying the publish
To verify that the publish was successful, run `npm install -g speedscope`.
Try `speedscope`, which should open speedscope in browser.
Try `speedscope sample/profiles/stackcollapse/simple.txt`, which should immediately load the profile
## Deploying the website
https://www.speedscope.app/ is hosted on GitHub pages, and is published via pushing
to the `gh-pages` branch. The `gh-pages` branch has totally different contents than
other branches of this repository: https://github.com/jlfwong/speedscope/tree/gh-pages.
It's populated by a deploy script which is invoked by running `npm run deploy` script.
This will do a build of the static resources, and boot a local server for you to test
the compiled assets. Please do not skip the manual testing in this step.
If everything looks good, you should be able to hit Ctrl+C, and you should see this prompt:
```
Commit release? [yes/no]:
```
If everything looks good, type `yes` then enter. This will commit to the `gh-pages` branch, and the site should automatically deploy shortly after.
To check if a deploy has happened, you can check https://www.speedscope.app/release.txt
which includes the version, the date, and the commit of the deploy.
+17 -2
View File
@@ -57,9 +57,22 @@ into the browser from Chrome.
If the `raw: true` flag is set when recording a dump, the resulting json dump can be imported into speedscope.
### `perf` and `DTrace`
### Linux `perf`
If you process the output of `perf` or `DTrace` first with Brendan Gregg's `stackcollapse-*.pl` scripts (https://github.com/brendangregg/FlameGraph#2-fold-stacks), the result can be imported into speedscope.
You can import profiles recorded using `perf record` and formatted using `perf script`.
perf record -a -F 999 -g -p PID > perf.data
perf script -i perf.data > profile.linux-perf.txt
Then drop the resulting `perf.txt` into speedscope, or if you have speedscope installed
locally, you can run:
perf record -a -F 999 -g -p PID > perf.data
perf script -i perf.data | speedscope -
### `DTrace`
If you process the output of `DTrace` first with Brendan Gregg's `stackcollapse-*.pl` scripts (https://github.com/brendangregg/FlameGraph#2-fold-stacks), the result can be imported into speedscope.
## Importing via URL
@@ -118,3 +131,5 @@ Once a profile has loaded, the main view is split into two: the top area is the
* `r`: Collapse recursion in the flamegraphs
* `Cmd+S`/`Ctrl+S` to save the current profile
* `Cmd+O`/`Ctrl+O` to open a new profile
* `n`: Go to next profile/thread if one is available
* `p`: Go to previous profile/thread if one is available
+1 -1
View File
@@ -60,7 +60,7 @@ async function main() {
throw new Error('At most one argument expected')
}
let urlToOpen = 'file://' + path.resolve(__dirname, './dist/release/index.html')
let urlToOpen = 'file://' + path.resolve(__dirname, '../dist/release/index.html')
if (process.argv.length === 3) {
const relPath = process.argv[2]
+4 -4
View File
@@ -1,6 +1,6 @@
{
"name": "speedscope",
"version": "0.4.0",
"version": "0.6.0",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
@@ -13387,9 +13387,9 @@
"dev": true
},
"typescript": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-3.0.1.tgz",
"integrity": "sha512-zQIMOmC+372pC/CCVLqnQ0zSBiY7HHodU7mpQdjiZddek4GMj31I3dUJ7gAs9o65X7mnRma6OokOkc6f9jjfBg==",
"version": "2.8.1",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-2.8.1.tgz",
"integrity": "sha512-Ao/f6d/4EPLq0YwzsQz8iXflezpTkQzqAyenTiw4kCUGr1uPiFLC3+fZ+gMZz6eeI/qdRUqvC+HxIJzUAzEFdg==",
"dev": true
},
"typescript-eslint-parser": {
+3 -3
View File
@@ -1,6 +1,6 @@
{
"name": "speedscope",
"version": "0.5.0",
"version": "0.7.0",
"description": "",
"repository": "jlfwong/speedscope",
"main": "index.js",
@@ -12,7 +12,7 @@
"prepack": "./scripts/build-release.sh",
"prettier": "prettier --write 'src/**/*.ts' 'src/**/*.tsx'",
"lint": "eslint 'src/**/*.ts' 'src/**/*.tsx'",
"jest": "./scripts/test-setup.sh && jest",
"jest": "./scripts/test-setup.sh && jest --runInBand",
"coverage": "npm run jest -- --coverage && coveralls < coverage/lcov.info",
"test": "tsc --noEmit && npm run lint && npm run coverage",
"serve": "parcel assets/index.html --open --no-autoinstall"
@@ -42,7 +42,7 @@
"redux": "^4.0.0",
"regl": "1.3.1",
"ts-jest": "22.4.6",
"typescript": "3.0.1",
"typescript": "2.8.1",
"typescript-eslint-parser": "17.0.1",
"uglify-es": "3.2.2"
},
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,6 @@
simple-terminat 10 198792.736893: 1001001 cpu-clock:
643 _Z4betav (/workdir/simple-terminates)
695 _Z5deltav (/workdir/simple-terminates)
6f3 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
@@ -0,0 +1,881 @@
# ========
# captured on: Wed Aug 15 16:01:24 2018
# hostname : e2b5bab9a538
# os release : 4.9.93-linuxkit-aufs
# perf version : 4.15.18
# arch : x86_64
# nrcpus online : 4
# nrcpus avail : 4
# cpudesc : Intel(R) Core(TM) i7-4870HQ CPU @ 2.50GHz
# cpuid : GenuineIntel,6,70,1
# total memory : 2046644 kB
# cmdline : /usr/lib/linux-tools-4.15.0-30/perf record -F 999 -g ./simple-terminates
# event : name = cpu-clock, , type = 1, size = 112, { sample_period, sample_freq } = 999, sample_type = IP|TID|TIME|CALLCHAIN|PERIOD, disabled = 1, inherit = 1, mmap = 1, comm = 1, freq = 1, enable_on_exec = 1, task = 1, sample_id_all = 1, exclude_guest = 1, mmap2 = 1, comm_exec = 1
# CPU_TOPOLOGY info available, use -I to display
# pmu mappings: breakpoint = 5, power = 7, software = 1, tracepoint = 2, msr = 6
# CACHE info available, use -I to display
# missing features: TRACING_DATA NUMA_TOPOLOGY BRANCH_STACK GROUP_DESC AUXTRACE STAT
# ========
#
simple-terminat 9 198789.478194: 1001001 cpu-clock:
63c _Z4betav (/workdir/simple-terminates)
695 _Z5deltav (/workdir/simple-terminates)
6f3 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9 198789.479183: 1001001 cpu-clock:
64e _Z4betav (/workdir/simple-terminates)
6ee main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9 198789.480175: 1001001 cpu-clock:
60c _Z5alphav (/workdir/simple-terminates)
6e9 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9 198789.481194: 1001001 cpu-clock:
643 _Z4betav (/workdir/simple-terminates)
695 _Z5deltav (/workdir/simple-terminates)
6f3 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9 198789.482189: 1001001 cpu-clock:
61e _Z5alphav (/workdir/simple-terminates)
690 _Z5deltav (/workdir/simple-terminates)
6f3 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9 198789.482989: 1001001 cpu-clock:
613 _Z5alphav (/workdir/simple-terminates)
6e9 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9 198789.484239: 1001001 cpu-clock:
613 _Z5alphav (/workdir/simple-terminates)
6e9 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9 198789.485180: 1001001 cpu-clock:
6b1 _Z5gammav (/workdir/simple-terminates)
6f8 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9 198789.486198: 1001001 cpu-clock:
613 _Z5alphav (/workdir/simple-terminates)
690 _Z5deltav (/workdir/simple-terminates)
6f3 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9 198789.487190: 1001001 cpu-clock:
677 _Z5deltav (/workdir/simple-terminates)
6f3 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9 198789.488202: 1001001 cpu-clock:
6aa _Z5gammav (/workdir/simple-terminates)
6f8 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9 198789.489329: 1001001 cpu-clock:
64e _Z4betav (/workdir/simple-terminates)
695 _Z5deltav (/workdir/simple-terminates)
6f3 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9 198789.490298: 1001001 cpu-clock:
613 _Z5alphav (/workdir/simple-terminates)
690 _Z5deltav (/workdir/simple-terminates)
6f3 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9 198789.491297: 1001001 cpu-clock:
643 _Z4betav (/workdir/simple-terminates)
6ee main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9 198789.492295: 1001001 cpu-clock:
613 _Z5alphav (/workdir/simple-terminates)
6e9 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9 198789.493164: 1001001 cpu-clock:
615 _Z5alphav (/workdir/simple-terminates)
690 _Z5deltav (/workdir/simple-terminates)
6f3 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9 198789.494212: 1001001 cpu-clock:
685 _Z5deltav (/workdir/simple-terminates)
6f3 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9 198789.495431: 1001001 cpu-clock:
615 _Z5alphav (/workdir/simple-terminates)
6e9 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9 198789.496316: 1001001 cpu-clock:
655 _Z4betav (/workdir/simple-terminates)
695 _Z5deltav (/workdir/simple-terminates)
6f3 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9 198789.497329: 1001001 cpu-clock:
677 _Z5deltav (/workdir/simple-terminates)
6f3 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9 198789.498322: 1001001 cpu-clock:
613 _Z5alphav (/workdir/simple-terminates)
6e9 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9 198789.499325: 1001001 cpu-clock:
6b1 _Z5gammav (/workdir/simple-terminates)
6f8 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9 198789.500327: 1001001 cpu-clock:
61e _Z5alphav (/workdir/simple-terminates)
690 _Z5deltav (/workdir/simple-terminates)
6f3 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9 198789.501320: 1001001 cpu-clock:
645 _Z4betav (/workdir/simple-terminates)
6ee main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9 198789.502265: 1001001 cpu-clock:
6b1 _Z5gammav (/workdir/simple-terminates)
6f8 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9 198789.503165: 1001001 cpu-clock:
613 _Z5alphav (/workdir/simple-terminates)
690 _Z5deltav (/workdir/simple-terminates)
6f3 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9 198789.504336: 1001001 cpu-clock:
64e _Z4betav (/workdir/simple-terminates)
6ee main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9 198789.505331: 1001001 cpu-clock:
613 _Z5alphav (/workdir/simple-terminates)
6e9 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9 198789.506328: 1001001 cpu-clock:
645 _Z4betav (/workdir/simple-terminates)
695 _Z5deltav (/workdir/simple-terminates)
6f3 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9 198789.507324: 1001001 cpu-clock:
670 _Z5deltav (/workdir/simple-terminates)
6f3 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9 198789.508328: 1001001 cpu-clock:
60c _Z5alphav (/workdir/simple-terminates)
6e9 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9 198789.509334: 1001001 cpu-clock:
63c _Z4betav (/workdir/simple-terminates)
695 _Z5deltav (/workdir/simple-terminates)
6f3 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9 198789.510272: 1001001 cpu-clock:
67c _Z5deltav (/workdir/simple-terminates)
6f3 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9 198789.511373: 1001001 cpu-clock:
64c _Z4betav (/workdir/simple-terminates)
6ee main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9 198789.512319: 1001001 cpu-clock:
6b1 _Z5gammav (/workdir/simple-terminates)
6f8 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9 198789.513188: 1001001 cpu-clock:
677 _Z5deltav (/workdir/simple-terminates)
6f3 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9 198789.514391: 1001001 cpu-clock:
677 _Z5deltav (/workdir/simple-terminates)
6f3 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9 198789.515336: 1001001 cpu-clock:
613 _Z5alphav (/workdir/simple-terminates)
6e9 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9 198789.516359: 1001001 cpu-clock:
64e _Z4betav (/workdir/simple-terminates)
695 _Z5deltav (/workdir/simple-terminates)
6f3 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9 198789.517344: 1001001 cpu-clock:
613 _Z5alphav (/workdir/simple-terminates)
690 _Z5deltav (/workdir/simple-terminates)
6f3 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9 198789.518263: 1001001 cpu-clock:
63c _Z4betav (/workdir/simple-terminates)
6ee main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9 198789.519381: 1001001 cpu-clock:
6b3 _Z5gammav (/workdir/simple-terminates)
6f8 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9 198789.520359: 1001001 cpu-clock:
613 _Z5alphav (/workdir/simple-terminates)
690 _Z5deltav (/workdir/simple-terminates)
6f3 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9 198789.521293: 1001001 cpu-clock:
643 _Z4betav (/workdir/simple-terminates)
6ee main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9 198789.522326: 1001001 cpu-clock:
613 _Z5alphav (/workdir/simple-terminates)
6e9 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9 198789.523217: 1001001 cpu-clock:
643 _Z4betav (/workdir/simple-terminates)
695 _Z5deltav (/workdir/simple-terminates)
6f3 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9 198789.524395: 1001001 cpu-clock:
615 _Z5alphav (/workdir/simple-terminates)
690 _Z5deltav (/workdir/simple-terminates)
6f3 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9 198789.525355: 1001001 cpu-clock:
643 _Z4betav (/workdir/simple-terminates)
6ee main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9 198789.526189: 1001001 cpu-clock:
6b3 _Z5gammav (/workdir/simple-terminates)
6f8 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9 198789.527412: 1001001 cpu-clock:
643 _Z4betav (/workdir/simple-terminates)
695 _Z5deltav (/workdir/simple-terminates)
6f3 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9 198789.528331: 1001001 cpu-clock:
677 _Z5deltav (/workdir/simple-terminates)
6f3 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9 198789.529367: 1001001 cpu-clock:
643 _Z4betav (/workdir/simple-terminates)
6ee main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9 198789.530368: 1001001 cpu-clock:
6b1 _Z5gammav (/workdir/simple-terminates)
6f8 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9 198789.531369: 1001001 cpu-clock:
613 _Z5alphav (/workdir/simple-terminates)
690 _Z5deltav (/workdir/simple-terminates)
6f3 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9 198789.532360: 1001001 cpu-clock:
677 _Z5deltav (/workdir/simple-terminates)
6f3 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9 198789.533218: 1001001 cpu-clock:
6b1 _Z5gammav (/workdir/simple-terminates)
6f8 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9 198789.534427: 1001001 cpu-clock:
643 _Z4betav (/workdir/simple-terminates)
695 _Z5deltav (/workdir/simple-terminates)
6f3 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9 198789.535372: 1001001 cpu-clock:
615 _Z5alphav (/workdir/simple-terminates)
690 _Z5deltav (/workdir/simple-terminates)
6f3 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9 198789.536386: 1001001 cpu-clock:
63c _Z4betav (/workdir/simple-terminates)
6ee main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9 198789.537337: 1001001 cpu-clock:
6b1 _Z5gammav (/workdir/simple-terminates)
6f8 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9 198789.538397: 1001001 cpu-clock:
645 _Z4betav (/workdir/simple-terminates)
695 _Z5deltav (/workdir/simple-terminates)
6f3 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9 198789.539383: 1001001 cpu-clock:
613 _Z5alphav (/workdir/simple-terminates)
690 _Z5deltav (/workdir/simple-terminates)
6f3 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9 198789.540390: 1001001 cpu-clock:
64e _Z4betav (/workdir/simple-terminates)
6ee main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9 198789.541389: 1001001 cpu-clock:
613 _Z5alphav (/workdir/simple-terminates)
6e9 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9 198789.542400: 1001001 cpu-clock:
64e _Z4betav (/workdir/simple-terminates)
695 _Z5deltav (/workdir/simple-terminates)
6f3 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9 198789.543268: 1001001 cpu-clock:
677 _Z5deltav (/workdir/simple-terminates)
6f3 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9 198789.544277: 1001001 cpu-clock:
63c _Z4betav (/workdir/simple-terminates)
6ee main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9 198789.545289: 1001001 cpu-clock:
6b1 _Z5gammav (/workdir/simple-terminates)
6f8 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9 198789.546425: 1001001 cpu-clock:
613 _Z5alphav (/workdir/simple-terminates)
690 _Z5deltav (/workdir/simple-terminates)
6f3 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9 198789.547283: 1001001 cpu-clock:
61e _Z5alphav (/workdir/simple-terminates)
6e9 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9 198789.548516: 1001001 cpu-clock:
613 _Z5alphav (/workdir/simple-terminates)
6e9 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9 198789.549479: 1001001 cpu-clock:
643 _Z4betav (/workdir/simple-terminates)
695 _Z5deltav (/workdir/simple-terminates)
6f3 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9 198789.550495: 1001001 cpu-clock:
677 _Z5deltav (/workdir/simple-terminates)
6f3 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9 198789.551493: 1001001 cpu-clock:
643 _Z4betav (/workdir/simple-terminates)
6ee main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9 198789.552486: 1001001 cpu-clock:
6b1 _Z5gammav (/workdir/simple-terminates)
6f8 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9 198789.553398: 1001001 cpu-clock:
613 _Z5alphav (/workdir/simple-terminates)
690 _Z5deltav (/workdir/simple-terminates)
6f3 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9 198789.554516: 1001001 cpu-clock:
677 _Z5deltav (/workdir/simple-terminates)
6f3 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9 198789.555493: 1001001 cpu-clock:
643 _Z4betav (/workdir/simple-terminates)
6ee main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9 198789.556494: 1001001 cpu-clock:
6b1 _Z5gammav (/workdir/simple-terminates)
6f8 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9 198789.557354: 1001001 cpu-clock:
613 _Z5alphav (/workdir/simple-terminates)
690 _Z5deltav (/workdir/simple-terminates)
6f3 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9 198789.558422: 1001001 cpu-clock:
679 _Z5deltav (/workdir/simple-terminates)
6f3 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9 198789.559521: 1001001 cpu-clock:
645 _Z4betav (/workdir/simple-terminates)
6ee main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9 198789.560351: 1001001 cpu-clock:
6b1 _Z5gammav (/workdir/simple-terminates)
6f8 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9 198789.561388: 1001001 cpu-clock:
613 _Z5alphav (/workdir/simple-terminates)
690 _Z5deltav (/workdir/simple-terminates)
6f3 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9 198789.562544: 1001001 cpu-clock:
677 _Z5deltav (/workdir/simple-terminates)
6f3 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9 198789.563411: 1001001 cpu-clock:
613 _Z5alphav (/workdir/simple-terminates)
6e9 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9 198789.564311: 1001001 cpu-clock:
64e _Z4betav (/workdir/simple-terminates)
695 _Z5deltav (/workdir/simple-terminates)
6f3 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9 198789.565551: 1001001 cpu-clock:
613 _Z5alphav (/workdir/simple-terminates)
690 _Z5deltav (/workdir/simple-terminates)
6f3 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9 198789.566493: 1001001 cpu-clock:
679 _Z5deltav (/workdir/simple-terminates)
6f3 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9 198789.567486: 1001001 cpu-clock:
613 _Z5alphav (/workdir/simple-terminates)
6e9 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9 198789.568508: 1001001 cpu-clock:
6b1 _Z5gammav (/workdir/simple-terminates)
6f8 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9 198789.569498: 1001001 cpu-clock:
61e _Z5alphav (/workdir/simple-terminates)
690 _Z5deltav (/workdir/simple-terminates)
6f3 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9 198789.570501: 1001001 cpu-clock:
682 _Z5deltav (/workdir/simple-terminates)
6f3 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9 198789.571502: 1001001 cpu-clock:
613 _Z5alphav (/workdir/simple-terminates)
6e9 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9 198789.572502: 1001001 cpu-clock:
6b1 _Z5gammav (/workdir/simple-terminates)
6f8 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9 198789.573415: 1001001 cpu-clock:
613 _Z5alphav (/workdir/simple-terminates)
690 _Z5deltav (/workdir/simple-terminates)
6f3 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9 198789.574532: 1001001 cpu-clock:
679 _Z5deltav (/workdir/simple-terminates)
6f3 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9 198789.575498: 1001001 cpu-clock:
613 _Z5alphav (/workdir/simple-terminates)
6e9 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9 198789.576507: 1001001 cpu-clock:
6b1 _Z5gammav (/workdir/simple-terminates)
6f8 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9 198789.577513: 1001001 cpu-clock:
613 _Z5alphav (/workdir/simple-terminates)
690 _Z5deltav (/workdir/simple-terminates)
6f3 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9 198789.578510: 1001001 cpu-clock:
682 _Z5deltav (/workdir/simple-terminates)
6f3 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9 198789.579516: 1001001 cpu-clock:
613 _Z5alphav (/workdir/simple-terminates)
6e9 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9 198789.580509: 1001001 cpu-clock:
643 _Z4betav (/workdir/simple-terminates)
695 _Z5deltav (/workdir/simple-terminates)
6f3 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9 198789.581511: 1001001 cpu-clock:
613 _Z5alphav (/workdir/simple-terminates)
690 _Z5deltav (/workdir/simple-terminates)
6f3 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9 198789.582519: 1001001 cpu-clock:
655 _Z4betav (/workdir/simple-terminates)
6ee main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9 198789.583440: 1001001 cpu-clock:
6b3 _Z5gammav (/workdir/simple-terminates)
6f8 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9 198789.584538: 1001001 cpu-clock:
643 _Z4betav (/workdir/simple-terminates)
695 _Z5deltav (/workdir/simple-terminates)
6f3 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9 198789.585513: 1001001 cpu-clock:
682 _Z5deltav (/workdir/simple-terminates)
6f3 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9 198789.586522: 1001001 cpu-clock:
63c _Z4betav (/workdir/simple-terminates)
6ee main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9 198789.587526: 1001001 cpu-clock:
60c _Z5alphav (/workdir/simple-terminates)
6e9 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9 198789.588513: 1001001 cpu-clock:
643 _Z4betav (/workdir/simple-terminates)
695 _Z5deltav (/workdir/simple-terminates)
6f3 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9 198789.589523: 1001001 cpu-clock:
613 _Z5alphav (/workdir/simple-terminates)
690 _Z5deltav (/workdir/simple-terminates)
6f3 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9 198789.590520: 1001001 cpu-clock:
643 _Z4betav (/workdir/simple-terminates)
6ee main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9 198789.591524: 1001001 cpu-clock:
61e _Z5alphav (/workdir/simple-terminates)
6e9 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9 198789.592527: 1001001 cpu-clock:
643 _Z4betav (/workdir/simple-terminates)
695 _Z5deltav (/workdir/simple-terminates)
6f3 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9 198789.593438: 1001001 cpu-clock:
679 _Z5deltav (/workdir/simple-terminates)
6f3 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9 198789.594550: 1001001 cpu-clock:
643 _Z4betav (/workdir/simple-terminates)
6ee main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9 198789.595513: 1001001 cpu-clock:
6bc _Z5gammav (/workdir/simple-terminates)
6f8 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9 198789.596531: 1001001 cpu-clock:
64e _Z4betav (/workdir/simple-terminates)
695 _Z5deltav (/workdir/simple-terminates)
6f3 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9 198789.597523: 1001001 cpu-clock:
677 _Z5deltav (/workdir/simple-terminates)
6f3 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9 198789.598527: 1001001 cpu-clock:
643 _Z4betav (/workdir/simple-terminates)
6ee main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9 198789.599528: 1001001 cpu-clock:
6b1 _Z5gammav (/workdir/simple-terminates)
6f8 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9 198789.600528: 1001001 cpu-clock:
643 _Z4betav (/workdir/simple-terminates)
695 _Z5deltav (/workdir/simple-terminates)
6f3 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9 198789.601529: 1001001 cpu-clock:
682 _Z5deltav (/workdir/simple-terminates)
6f3 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9 198789.602525: 1001001 cpu-clock:
64e _Z4betav (/workdir/simple-terminates)
6ee main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9 198789.603449: 1001001 cpu-clock:
6b1 _Z5gammav (/workdir/simple-terminates)
6f8 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9 198789.604547: 1001001 cpu-clock:
64e _Z4betav (/workdir/simple-terminates)
695 _Z5deltav (/workdir/simple-terminates)
6f3 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9 198789.605522: 1001001 cpu-clock:
677 _Z5deltav (/workdir/simple-terminates)
6f3 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9 198789.606529: 1001001 cpu-clock:
643 _Z4betav (/workdir/simple-terminates)
6ee main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9 198789.607410: 1001001 cpu-clock:
645 _Z4betav (/workdir/simple-terminates)
695 _Z5deltav (/workdir/simple-terminates)
6f3 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9 198789.608466: 1001001 cpu-clock:
618 _Z5alphav (/workdir/simple-terminates)
690 _Z5deltav (/workdir/simple-terminates)
6f3 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9 198789.609472: 1001001 cpu-clock:
645 _Z4betav (/workdir/simple-terminates)
6ee main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9 198789.610646: 1001001 cpu-clock:
645 _Z4betav (/workdir/simple-terminates)
6ee main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9 198789.611607: 1001001 cpu-clock:
6b1 _Z5gammav (/workdir/simple-terminates)
6f8 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9 198789.612623: 1001001 cpu-clock:
60c _Z5alphav (/workdir/simple-terminates)
690 _Z5deltav (/workdir/simple-terminates)
6f3 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9 198789.613576: 1001001 cpu-clock:
643 _Z4betav (/workdir/simple-terminates)
6ee main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
@@ -0,0 +1,877 @@
simple-terminat 9/9 198791.127353: cpu-clock:
643 _Z4betav (/workdir/simple-terminates)
695 _Z5deltav (/workdir/simple-terminates)
6f3 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9/9 198791.128290: cpu-clock:
677 _Z5deltav (/workdir/simple-terminates)
6f3 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9/9 198791.129324: cpu-clock:
643 _Z4betav (/workdir/simple-terminates)
6ee main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9/9 198791.130316: cpu-clock:
6b3 _Z5gammav (/workdir/simple-terminates)
6f8 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9/9 198791.131320: cpu-clock:
63c _Z4betav (/workdir/simple-terminates)
695 _Z5deltav (/workdir/simple-terminates)
6f3 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9/9 198791.132319: cpu-clock:
682 _Z5deltav (/workdir/simple-terminates)
6f3 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9/9 198791.133315: cpu-clock:
643 _Z4betav (/workdir/simple-terminates)
6ee main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9/9 198791.134322: cpu-clock:
6b1 _Z5gammav (/workdir/simple-terminates)
6f8 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9/9 198791.135321: cpu-clock:
63c _Z4betav (/workdir/simple-terminates)
695 _Z5deltav (/workdir/simple-terminates)
6f3 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9/9 198791.136320: cpu-clock:
677 _Z5deltav (/workdir/simple-terminates)
6f3 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9/9 198791.137351: cpu-clock:
61e _Z5alphav (/workdir/simple-terminates)
6e9 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9/9 198791.138306: cpu-clock:
6b3 _Z5gammav (/workdir/simple-terminates)
6f8 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9/9 198791.139325: cpu-clock:
61e _Z5alphav (/workdir/simple-terminates)
690 _Z5deltav (/workdir/simple-terminates)
6f3 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9/9 198791.140311: cpu-clock:
677 _Z5deltav (/workdir/simple-terminates)
6f3 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9/9 198791.141325: cpu-clock:
613 _Z5alphav (/workdir/simple-terminates)
6e9 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9/9 198791.142313: cpu-clock:
6b1 _Z5gammav (/workdir/simple-terminates)
6f8 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9/9 198791.143342: cpu-clock:
61e _Z5alphav (/workdir/simple-terminates)
690 _Z5deltav (/workdir/simple-terminates)
6f3 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9/9 198791.144354: cpu-clock:
643 _Z4betav (/workdir/simple-terminates)
6ee main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9/9 198791.145382: cpu-clock:
613 _Z5alphav (/workdir/simple-terminates)
6e9 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9/9 198791.146345: cpu-clock:
643 _Z4betav (/workdir/simple-terminates)
695 _Z5deltav (/workdir/simple-terminates)
6f3 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9/9 198791.147357: cpu-clock:
677 _Z5deltav (/workdir/simple-terminates)
6f3 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9/9 198791.148361: cpu-clock:
613 _Z5alphav (/workdir/simple-terminates)
6e9 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9/9 198791.149342: cpu-clock:
643 _Z4betav (/workdir/simple-terminates)
695 _Z5deltav (/workdir/simple-terminates)
6f3 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9/9 198791.150356: cpu-clock:
682 _Z5deltav (/workdir/simple-terminates)
6f3 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9/9 198791.151341: cpu-clock:
643 _Z4betav (/workdir/simple-terminates)
6ee main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9/9 198791.152346: cpu-clock:
6b1 _Z5gammav (/workdir/simple-terminates)
6f8 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9/9 198791.153346: cpu-clock:
613 _Z5alphav (/workdir/simple-terminates)
690 _Z5deltav (/workdir/simple-terminates)
6f3 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9/9 198791.154346: cpu-clock:
643 _Z4betav (/workdir/simple-terminates)
6ee main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9/9 198791.155347: cpu-clock:
6b1 _Z5gammav (/workdir/simple-terminates)
6f8 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9/9 198791.156347: cpu-clock:
643 _Z4betav (/workdir/simple-terminates)
695 _Z5deltav (/workdir/simple-terminates)
6f3 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9/9 198791.157355: cpu-clock:
679 _Z5deltav (/workdir/simple-terminates)
6f3 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9/9 198791.158347: cpu-clock:
61e _Z5alphav (/workdir/simple-terminates)
6e9 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9/9 198791.159352: cpu-clock:
643 _Z4betav (/workdir/simple-terminates)
695 _Z5deltav (/workdir/simple-terminates)
6f3 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9/9 198791.160373: cpu-clock:
613 _Z5alphav (/workdir/simple-terminates)
690 _Z5deltav (/workdir/simple-terminates)
6f3 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9/9 198791.161353: cpu-clock:
64e _Z4betav (/workdir/simple-terminates)
6ee main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9/9 198791.162359: cpu-clock:
6b3 _Z5gammav (/workdir/simple-terminates)
6f8 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9/9 198791.163363: cpu-clock:
643 _Z4betav (/workdir/simple-terminates)
695 _Z5deltav (/workdir/simple-terminates)
6f3 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9/9 198791.164353: cpu-clock:
677 _Z5deltav (/workdir/simple-terminates)
6f3 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9/9 198791.165365: cpu-clock:
613 _Z5alphav (/workdir/simple-terminates)
6e9 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9/9 198791.166367: cpu-clock:
6b3 _Z5gammav (/workdir/simple-terminates)
6f8 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9/9 198791.167368: cpu-clock:
60c _Z5alphav (/workdir/simple-terminates)
690 _Z5deltav (/workdir/simple-terminates)
6f3 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9/9 198791.168370: cpu-clock:
677 _Z5deltav (/workdir/simple-terminates)
6f3 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9/9 198791.169356: cpu-clock:
60c _Z5alphav (/workdir/simple-terminates)
6e9 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9/9 198791.170362: cpu-clock:
643 _Z4betav (/workdir/simple-terminates)
695 _Z5deltav (/workdir/simple-terminates)
6f3 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9/9 198791.171331: cpu-clock:
680 _Z5deltav (/workdir/simple-terminates)
6f3 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9/9 198791.172382: cpu-clock:
64e _Z4betav (/workdir/simple-terminates)
6ee main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9/9 198791.173360: cpu-clock:
6b1 _Z5gammav (/workdir/simple-terminates)
6f8 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9/9 198791.174372: cpu-clock:
643 _Z4betav (/workdir/simple-terminates)
695 _Z5deltav (/workdir/simple-terminates)
6f3 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9/9 198791.175463: cpu-clock:
677 _Z5deltav (/workdir/simple-terminates)
6f3 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9/9 198791.176511: cpu-clock:
60c _Z5alphav (/workdir/simple-terminates)
6e9 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9/9 198791.177286: cpu-clock:
643 _Z4betav (/workdir/simple-terminates)
695 _Z5deltav (/workdir/simple-terminates)
6f3 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9/9 198791.178500: cpu-clock:
613 _Z5alphav (/workdir/simple-terminates)
690 _Z5deltav (/workdir/simple-terminates)
6f3 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9/9 198791.179495: cpu-clock:
64e _Z4betav (/workdir/simple-terminates)
6ee main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9/9 198791.180496: cpu-clock:
613 _Z5alphav (/workdir/simple-terminates)
6e9 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9/9 198791.181506: cpu-clock:
643 _Z4betav (/workdir/simple-terminates)
695 _Z5deltav (/workdir/simple-terminates)
6f3 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9/9 198791.182430: cpu-clock:
682 _Z5deltav (/workdir/simple-terminates)
6f3 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9/9 198791.183529: cpu-clock:
643 _Z4betav (/workdir/simple-terminates)
6ee main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9/9 198791.184491: cpu-clock:
6bc _Z5gammav (/workdir/simple-terminates)
6f8 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9/9 198791.185341: cpu-clock:
61e _Z5alphav (/workdir/simple-terminates)
690 _Z5deltav (/workdir/simple-terminates)
6f3 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9/9 198791.186539: cpu-clock:
682 _Z5deltav (/workdir/simple-terminates)
6f3 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9/9 198791.187500: cpu-clock:
643 _Z4betav (/workdir/simple-terminates)
6ee main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9/9 198791.188512: cpu-clock:
6b1 _Z5gammav (/workdir/simple-terminates)
6f8 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9/9 198791.189509: cpu-clock:
643 _Z4betav (/workdir/simple-terminates)
695 _Z5deltav (/workdir/simple-terminates)
6f3 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9/9 198791.190317: cpu-clock:
643 _Z4betav (/workdir/simple-terminates)
6ee main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9/9 198791.191545: cpu-clock:
63c _Z4betav (/workdir/simple-terminates)
6ee main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9/9 198791.192298: cpu-clock:
63c _Z4betav (/workdir/simple-terminates)
695 _Z5deltav (/workdir/simple-terminates)
6f3 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9/9 198791.193537: cpu-clock:
613 _Z5alphav (/workdir/simple-terminates)
690 _Z5deltav (/workdir/simple-terminates)
6f3 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9/9 198791.194522: cpu-clock:
643 _Z4betav (/workdir/simple-terminates)
6ee main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9/9 198791.195336: cpu-clock:
643 _Z4betav (/workdir/simple-terminates)
695 _Z5deltav (/workdir/simple-terminates)
6f3 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9/9 198791.196578: cpu-clock:
63c _Z4betav (/workdir/simple-terminates)
695 _Z5deltav (/workdir/simple-terminates)
6f3 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9/9 198791.197454: cpu-clock:
643 _Z4betav (/workdir/simple-terminates)
6ee main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9/9 198791.198536: cpu-clock:
613 _Z5alphav (/workdir/simple-terminates)
6e9 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9/9 198791.199525: cpu-clock:
63c _Z4betav (/workdir/simple-terminates)
695 _Z5deltav (/workdir/simple-terminates)
6f3 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9/9 198791.200521: cpu-clock:
677 _Z5deltav (/workdir/simple-terminates)
6f3 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9/9 198791.201544: cpu-clock:
655 _Z4betav (/workdir/simple-terminates)
6ee main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9/9 198791.202435: cpu-clock:
6aa _Z5gammav (/workdir/simple-terminates)
6f8 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9/9 198791.203550: cpu-clock:
64e _Z4betav (/workdir/simple-terminates)
695 _Z5deltav (/workdir/simple-terminates)
6f3 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9/9 198791.204529: cpu-clock:
677 _Z5deltav (/workdir/simple-terminates)
6f3 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9/9 198791.205532: cpu-clock:
63c _Z4betav (/workdir/simple-terminates)
6ee main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9/9 198791.206533: cpu-clock:
6b1 _Z5gammav (/workdir/simple-terminates)
6f8 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9/9 198791.207533: cpu-clock:
643 _Z4betav (/workdir/simple-terminates)
695 _Z5deltav (/workdir/simple-terminates)
6f3 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9/9 198791.208532: cpu-clock:
679 _Z5deltav (/workdir/simple-terminates)
6f3 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9/9 198791.209542: cpu-clock:
643 _Z4betav (/workdir/simple-terminates)
6ee main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9/9 198791.210538: cpu-clock:
6b1 _Z5gammav (/workdir/simple-terminates)
6f8 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9/9 198791.211536: cpu-clock:
643 _Z4betav (/workdir/simple-terminates)
695 _Z5deltav (/workdir/simple-terminates)
6f3 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9/9 198791.212400: cpu-clock:
63c _Z4betav (/workdir/simple-terminates)
6ee main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9/9 198791.213571: cpu-clock:
63c _Z4betav (/workdir/simple-terminates)
6ee main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9/9 198791.214532: cpu-clock:
6b1 _Z5gammav (/workdir/simple-terminates)
6f8 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9/9 198791.215548: cpu-clock:
643 _Z4betav (/workdir/simple-terminates)
695 _Z5deltav (/workdir/simple-terminates)
6f3 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9/9 198791.216391: cpu-clock:
64e _Z4betav (/workdir/simple-terminates)
6ee main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9/9 198791.217575: cpu-clock:
63c _Z4betav (/workdir/simple-terminates)
6ee main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9/9 198791.218511: cpu-clock:
6bf _Z5gammav (/workdir/simple-terminates)
6f8 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9/9 198791.219538: cpu-clock:
615 _Z5alphav (/workdir/simple-terminates)
690 _Z5deltav (/workdir/simple-terminates)
6f3 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9/9 198791.220531: cpu-clock:
64e _Z4betav (/workdir/simple-terminates)
6ee main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9/9 198791.221401: cpu-clock:
6b1 _Z5gammav (/workdir/simple-terminates)
6f8 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9/9 198791.222426: cpu-clock:
645 _Z4betav (/workdir/simple-terminates)
695 _Z5deltav (/workdir/simple-terminates)
6f3 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9/9 198791.223566: cpu-clock:
613 _Z5alphav (/workdir/simple-terminates)
690 _Z5deltav (/workdir/simple-terminates)
6f3 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9/9 198791.224531: cpu-clock:
643 _Z4betav (/workdir/simple-terminates)
6ee main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9/9 198791.225462: cpu-clock:
613 _Z5alphav (/workdir/simple-terminates)
6e9 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9/9 198791.226563: cpu-clock:
64e _Z4betav (/workdir/simple-terminates)
695 _Z5deltav (/workdir/simple-terminates)
6f3 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9/9 198791.227376: cpu-clock:
682 _Z5deltav (/workdir/simple-terminates)
6f3 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9/9 198791.228586: cpu-clock:
645 _Z4betav (/workdir/simple-terminates)
6ee main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9/9 198791.229367: cpu-clock:
63c _Z4betav (/workdir/simple-terminates)
695 _Z5deltav (/workdir/simple-terminates)
6f3 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9/9 198791.230467: cpu-clock:
615 _Z5alphav (/workdir/simple-terminates)
690 _Z5deltav (/workdir/simple-terminates)
6f3 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9/9 198791.231584: cpu-clock:
643 _Z4betav (/workdir/simple-terminates)
6ee main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9/9 198791.232398: cpu-clock:
6aa _Z5gammav (/workdir/simple-terminates)
6f8 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9/9 198791.233591: cpu-clock:
643 _Z4betav (/workdir/simple-terminates)
695 _Z5deltav (/workdir/simple-terminates)
6f3 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9/9 198791.234477: cpu-clock:
643 _Z4betav (/workdir/simple-terminates)
6ee main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9/9 198791.235641: cpu-clock:
613 _Z5alphav (/workdir/simple-terminates)
6e9 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9/9 198791.236770: cpu-clock:
6b1 _Z5gammav (/workdir/simple-terminates)
6f8 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9/9 198791.237747: cpu-clock:
60c _Z5alphav (/workdir/simple-terminates)
690 _Z5deltav (/workdir/simple-terminates)
6f3 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9/9 198791.238743: cpu-clock:
682 _Z5deltav (/workdir/simple-terminates)
6f3 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9/9 198791.239739: cpu-clock:
60c _Z5alphav (/workdir/simple-terminates)
6e9 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9/9 198791.240744: cpu-clock:
6b1 _Z5gammav (/workdir/simple-terminates)
6f8 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9/9 198791.241743: cpu-clock:
615 _Z5alphav (/workdir/simple-terminates)
690 _Z5deltav (/workdir/simple-terminates)
6f3 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9/9 198791.242591: cpu-clock:
63c _Z4betav (/workdir/simple-terminates)
6ee main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9/9 198791.243804: cpu-clock:
60c _Z5alphav (/workdir/simple-terminates)
6e9 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9/9 198791.244620: cpu-clock:
643 _Z4betav (/workdir/simple-terminates)
695 _Z5deltav (/workdir/simple-terminates)
6f3 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9/9 198791.245775: cpu-clock:
615 _Z5alphav (/workdir/simple-terminates)
690 _Z5deltav (/workdir/simple-terminates)
6f3 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9/9 198791.246736: cpu-clock:
643 _Z4betav (/workdir/simple-terminates)
6ee main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9/9 198791.247757: cpu-clock:
61e _Z5alphav (/workdir/simple-terminates)
6e9 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9/9 198791.248761: cpu-clock:
645 _Z4betav (/workdir/simple-terminates)
695 _Z5deltav (/workdir/simple-terminates)
6f3 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9/9 198791.249760: cpu-clock:
60c _Z5alphav (/workdir/simple-terminates)
690 _Z5deltav (/workdir/simple-terminates)
6f3 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9/9 198791.250751: cpu-clock:
643 _Z4betav (/workdir/simple-terminates)
6ee main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9/9 198791.251765: cpu-clock:
613 _Z5alphav (/workdir/simple-terminates)
6e9 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9/9 198791.252616: cpu-clock:
643 _Z4betav (/workdir/simple-terminates)
695 _Z5deltav (/workdir/simple-terminates)
6f3 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9/9 198791.253805: cpu-clock:
613 _Z5alphav (/workdir/simple-terminates)
690 _Z5deltav (/workdir/simple-terminates)
6f3 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9/9 198791.254754: cpu-clock:
643 _Z4betav (/workdir/simple-terminates)
6ee main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9/9 198791.255617: cpu-clock:
6b1 _Z5gammav (/workdir/simple-terminates)
6f8 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9/9 198791.256794: cpu-clock:
6b1 _Z5gammav (/workdir/simple-terminates)
6f8 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9/9 198791.257759: cpu-clock:
61e _Z5alphav (/workdir/simple-terminates)
690 _Z5deltav (/workdir/simple-terminates)
6f3 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9/9 198791.258769: cpu-clock:
670 _Z5deltav (/workdir/simple-terminates)
6f3 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9/9 198791.259766: cpu-clock:
613 _Z5alphav (/workdir/simple-terminates)
6e9 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9/9 198791.260771: cpu-clock:
6b1 _Z5gammav (/workdir/simple-terminates)
6f8 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9/9 198791.261751: cpu-clock:
60c _Z5alphav (/workdir/simple-terminates)
690 _Z5deltav (/workdir/simple-terminates)
6f3 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9/9 198791.262617: cpu-clock:
615 _Z5alphav (/workdir/simple-terminates)
6e9 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
simple-terminat 9/9 198791.263815: cpu-clock:
ffffffffad1ee8b5 [unknown] ([kernel.kallsyms])
ffffffffad1ee98a [unknown] ([kernel.kallsyms])
ffffffffad1f1ca9 [unknown] ([kernel.kallsyms])
ffffffffad1aab1d [unknown] ([kernel.kallsyms])
ffffffffad1c4c94 [unknown] ([kernel.kallsyms])
ffffffffad1c5ab1 [unknown] ([kernel.kallsyms])
ffffffffad1ccc4a [unknown] ([kernel.kallsyms])
ffffffffad0dc851 [unknown] ([kernel.kallsyms])
ffffffffad0e27a4 [unknown] ([kernel.kallsyms])
ffffffffad0e2d50 [unknown] ([kernel.kallsyms])
ffffffffad0e2dc1 [unknown] ([kernel.kallsyms])
ffffffffad0033c0 [unknown] ([kernel.kallsyms])
ffffffffad7fa08e [unknown] ([kernel.kallsyms])
@@ -0,0 +1,6 @@
simple-terminat 10 198792.736893: 1001001 cpu-clock:
643 _Z4betav (/workdir/simple-terminates)
695 _Z5deltav (/workdir/simple-terminates)
6f3 main (/workdir/simple-terminates)
21b97 __libc_start_main (/lib/x86_64-linux-gnu/libc-2.27.so)
6ce258d4c544155 [unknown] ([unknown])
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,29 @@
{
"exporter": "speedscope@0.6.0",
"$schema": "https://www.speedscope.app/file-format-schema.json",
"name": "Two Samples",
"activeProfileIndex": 1,
"profiles": [
{
"type": "sampled",
"name": "one",
"unit": "seconds",
"startValue": 0,
"endValue": 14,
"samples": [[0, 1, 2], [0, 1, 2], [0, 1, 3], [0, 1, 2], [0, 1]],
"weights": [1, 1, 4, 3, 5]
},
{
"type": "sampled",
"name": "two",
"unit": "seconds",
"startValue": 0,
"endValue": 14,
"samples": [[0, 1, 2], [0, 1, 2], [0, 1, 3], [0, 1, 2], [0, 1]],
"weights": [1, 1, 4, 3, 5]
}
],
"shared": {
"frames": [{"name": "a"}, {"name": "b"}, {"name": "c"}, {"name": "d"}]
}
}
+2
View File
@@ -1,4 +1,6 @@
simple
forks
simple-terminates
random
*.dSYM
+12
View File
@@ -0,0 +1,12 @@
FROM ubuntu:bionic
RUN apt-get update
RUN apt-get install -y build-essential
RUN apt-get install -y linux-tools-common linux-tools-generic
RUN ln -sf /usr/lib/linux-tools/4.15.0-30-generic/perf /usr/bin/perf
WORKDIR /workdir
ADD . /workdir
RUN make clean simple-terminates forks
+20 -4
View File
@@ -1,9 +1,25 @@
.PHONY: all
.PHONY: all clean linux-perf
all: simple random
all: simple simple-terminates random forks
clean:
rm -f simple simple-terminates random forks
simple: simple.cpp
g++ -Wall -g -o $@ $<
$(CXX) -Wall -g -o $@ $<
simple-terminates: simple-terminates.cpp
$(CXX) -Wall -g -o $@ $<
forks: forks.cpp
$(CXX) -Wall -g -o $@ $<
random: random.cpp
g++ -Wall -g -o $@ $<
$(CXX) -Wall -g -o $@ $<
linux-perf:
docker build -t speedscope-ubuntu .
docker run --privileged speedscope-ubuntu /bin/bash perf-script.sh forks > ../../profiles/linux-perf/forks.linux-perf.txt
# docker run --privileged speedscope-ubuntu /bin/bash perf-script.sh with-header > ../../profiles/linux-perf/simple-with-header.linux-perf.txt
# docker run --privileged speedscope-ubuntu /bin/bash perf-script.sh with-pid > ../../profiles/linux-perf/simple-with-pid.linux-perf.txt
# docker run --privileged speedscope-ubuntu /bin/bash perf-script.sh > ../../profiles/linux-perf/simple.linux-perf.txt
+81
View File
@@ -0,0 +1,81 @@
#include <cstdlib>
#include <unistd.h>
using namespace std;
void alpha()
{
int z = 3;
for (int i = 0; i < 100000; i++)
{
z *= 3;
}
}
void beta()
{
int z = 3;
for (int i = 0; i < 100000; i++)
{
z *= 3;
}
}
void delta()
{
int z = 3;
for (int i = 0; i < 100000; i++)
{
z *= 3;
}
alpha();
beta();
}
void gamma()
{
int z = 3;
for (int i = 0; i < 100000; i++)
{
z *= 3;
}
}
int main(int argc, char *argv[])
{
pid_t pid1 = fork();
if (pid1 == 0)
{
// Child process 1
for (int i = 0; i < 100; i++)
{
alpha();
beta();
}
}
else
{
pid_t pid2 = fork();
if (pid2 == 0)
{
// Child process 2
for (int i = 0; i < 100; i++)
{
alpha();
beta();
}
}
else
{
for (int i = 0; i < 100; i++)
{
alpha();
beta();
gamma();
delta();
}
}
}
return 0;
}
+33
View File
@@ -0,0 +1,33 @@
#!/bin/bash
set -eoux pipefail
if [[ "$1" == "system-wide" ]]; then
perf record -a -F 999 -g ./simple-terminates > perf.data
perf script -i perf.data
exit 0
fi
if [[ "$1" == "forks" ]]; then
perf record -a -F 999 -g ./forks > perf.data
perf script -i perf.data
exit 0
fi
perf record -F 999 -g ./simple-terminates > perf.data
if [[ "$1" == "with-header" ]]; then
perf script --header -i perf.data
elif [[ "$1" == "with-pid" ]]; then
# perf script -F comm,pid,tid,time,event,ip,sym,dso -i perf.data
# comm: command (maybe truncated)
# pid: process ID
# id: thread ID
# time: time of event
# ip: instruction pointer
# sym: symbol
# dso: dynamic shared object
perf script -F comm,pid,tid,time,event,ip,sym,dso -i perf.data
else
perf script -i perf.data
fi
+52
View File
@@ -0,0 +1,52 @@
#include <cstdlib>
using namespace std;
void alpha()
{
int z = 3;
for (int i = 0; i < 100000; i++)
{
z *= 3;
}
}
void beta()
{
int z = 3;
for (int i = 0; i < 100000; i++)
{
z *= 3;
}
}
void delta()
{
int z = 3;
for (int i = 0; i < 100000; i++)
{
z *= 3;
}
alpha();
beta();
}
void gamma()
{
int z = 3;
for (int i = 0; i < 100000; i++)
{
z *= 3;
}
}
int main(int argc, char *argv[])
{
for (int i = 0; i < 100; i++)
{
alpha();
beta();
delta();
gamma();
}
return 0;
}
+4 -3
View File
@@ -1,7 +1,7 @@
#!/bin/bash
# Fail on first error
set -e
set -euxo pipefail
OUTDIR=`pwd`/dist/release
# Typecheck
@@ -12,7 +12,8 @@ rm -rf "$OUTDIR"
mkdir -p "$OUTDIR"
# Place info about the current commit into the build dir to easily identify releases
date > "$OUTDIR"/release.txt
npm ls -depth -1 | head -n 1 | cut -d' ' -f 1 > "$OUTDIR"/release.txt
date >> "$OUTDIR"/release.txt
git rev-parse HEAD >> "$OUTDIR"/release.txt
# Place a json schema for the file format into the build directory too
+9 -2
View File
@@ -4,8 +4,7 @@
# repository into a temporary directory and copy the release build
# artifacts into there to commit & push to the gh-pages branch
# Fail on first error
set -e
set -euxo pipefail
OUTDIR=`pwd`/dist/release
echo $OUTDIR
@@ -29,7 +28,10 @@ echo www.speedscope.app > CNAME
# Set up a handler to run on Ctrl+C
trap ctrl_c INT
function ctrl_c() {
set +x
read -p "Commit release? [yes/no]: "
set -x
if [[ $REPLY =~ ^yes$ ]]
then
git add --all
@@ -39,7 +41,10 @@ function ctrl_c() {
rm -rf "$TMPDIR"
exit 0
else
set +x
echo "Aborting release."
set -x
popd
rm -rf "$TMPDIR"
exit 1
@@ -47,6 +52,7 @@ function ctrl_c() {
}
# Start a local server for verification of the build
set +x
echo
echo
echo "Build complete. Starting server on http://localhost:4444/"
@@ -54,3 +60,4 @@ echo "Hit Ctrl+C to complete or cancel the release"
echo
echo
python -m SimpleHTTPServer 4444 .
set +x
@@ -9,5 +9,12 @@ let jsonSchema = child_process.execSync(
},
)
jsonSchema = JSON.parse(jsonSchema)
if (!jsonSchema.definitions['FileFormat.File']) {
console.error('SCHEMA GENERATION FAILURE: Could not find FileFormat.File in the definitions list')
console.error(jsonSchema)
process.exit(1)
}
jsonSchema['$ref'] = '#/definitions/FileFormat.File'
console.log(JSON.stringify(jsonSchema, null, 4))
+20
View File
@@ -0,0 +1,20 @@
#!/bin/bash
# Prepare a mock installation of speedscope to test it before the actual npm
# publish
set -euxo pipefail
TMPDIR=`mktemp -d -t speedscope-test-installation`
PACKEDNAME=`npm pack | tail -n1`
mv "$PACKEDNAME" "$TMPDIR"
cd "$TMPDIR"
tar -xvvf "$PACKEDNAME"
cd package
npm install
set +x
echo
echo "Run the following command to switch into the test directory"
echo cd "$TMPDIR"/package
@@ -40,6 +40,7 @@ Object {
"totalWeight": 4,
},
],
"name": "simple.txt",
"stacks": Array [
"a;b;c 2",
"a;b;d 4",
@@ -48,3 +49,7 @@ Object {
],
}
`;
exports[`importFromBGFlameGraph: indexToView 1`] = `0`;
exports[`importFromBGFlameGraph: profileGroup.name 1`] = `"simple.txt"`;
@@ -49,6 +49,7 @@ Object {
"totalWeight": 17557,
},
],
"name": "simple.cpuprofile",
"stacks": Array [
"(anonymous) 11.57ms",
"(anonymous);a;b;d 16.79ms",
@@ -57,6 +58,10 @@ Object {
}
`;
exports[`importFromChromeCPUProfile: indexToView 1`] = `0`;
exports[`importFromChromeCPUProfile: profileGroup.name 1`] = `"simple.cpuprofile"`;
exports[`importFromChromeTimeline 1`] = `
Object {
"frames": Array [
@@ -97,6 +102,7 @@ Object {
"totalWeight": 16987,
},
],
"name": "simple-timeline.json",
"stacks": Array [
"(program) 10.16ms",
" 1.99ms",
@@ -255,3 +261,7 @@ Object {
],
}
`;
exports[`importFromChromeTimeline: indexToView 1`] = `0`;
exports[`importFromChromeTimeline: profileGroup.name 1`] = `"simple-timeline.json"`;
@@ -40,6 +40,7 @@ Object {
"totalWeight": 11.021373999974458,
},
],
"name": "simple-firefox.json",
"stacks": Array [
"a;b;d 989.53µs",
"a;c;d 1.02ms",
@@ -107,6 +108,7 @@ Object {
"totalWeight": 9.954629999992903,
},
],
"name": "recursion.json",
"stacks": Array [
"main;alpha;beta;alpha;beta;alpha;beta;alpha;delta;gamma 998.89µs",
"main 1.19ms",
@@ -120,3 +122,11 @@ Object {
],
}
`;
exports[`importFromFirefox recursion: indexToView 1`] = `0`;
exports[`importFromFirefox recursion: profileGroup.name 1`] = `"recursion.json"`;
exports[`importFromFirefox: indexToView 1`] = `0`;
exports[`importFromFirefox: profileGroup.name 1`] = `"simple-firefox.json"`;
@@ -85,6 +85,7 @@ Object {
"totalWeight": 74448896,
},
],
"name": "random-allocations-deep-copy.txt",
"stacks": Array [
"start;main;delta();alpha();leakMemory();malloc;malloc_zone_malloc 73.00 MB",
"start;main;delta();beta();leakMemory();malloc;malloc_zone_malloc 72.00 MB",
@@ -98,6 +99,10 @@ Object {
}
`;
exports[`importFromInstrumentsDeepCopy allocations profile: indexToView 1`] = `0`;
exports[`importFromInstrumentsDeepCopy allocations profile: profileGroup.name 1`] = `"random-allocations-deep-copy.txt"`;
exports[`importFromInstrumentsDeepCopy time profile 1`] = `
Object {
"frames": Array [
@@ -282,6 +287,7 @@ Object {
"totalWeight": 1,
},
],
"name": "simple-time-profile-deep-copy.txt",
"stacks": Array [
"start;main;delta();alpha();leakMemory();malloc;malloc_zone_malloc;szone_malloc_should_clear;small_malloc_from_free_list 4.00ms",
"start;main;delta();alpha();leakMemory();malloc;malloc_zone_malloc;szone_malloc_should_clear;allocate_pages_securely;mach_vm_map;_kernelrpc_mach_vm_map_trap 1.00ms",
@@ -326,6 +332,10 @@ Object {
}
`;
exports[`importFromInstrumentsDeepCopy time profile: indexToView 1`] = `0`;
exports[`importFromInstrumentsDeepCopy time profile: profileGroup.name 1`] = `"simple-time-profile-deep-copy.txt"`;
exports[`importFromInstrumentsTrace Instruments 8.3.3 1`] = `
Object {
"frames": Array [
@@ -681,6 +691,7 @@ Object {
"totalWeight": 1016403,
},
],
"name": "simple-time-profile.trace - thread 4",
"stacks": Array [
" 730.82ms",
"_dyld_start;dyldbootstrap::start(macho_header const*, int, char const**, long, macho_header const*, unsigned long*);dyld::_main(macho_header const*, unsigned long, int, char const**, char const**, char const**, unsigned long*);dyld::link(ImageLoader*, bool, bool, ImageLoader::RPathChain const&, unsigned int);ImageLoader::link(ImageLoader::LinkContext const&, bool, bool, bool, ImageLoader::RPathChain const&, char const*);ImageLoader::recursiveBind(ImageLoader::LinkContext const&, bool, bool);ImageLoader::recursiveBind(ImageLoader::LinkContext const&, bool, bool);ImageLoader::recursiveBind(ImageLoader::LinkContext const&, bool, bool);ImageLoader::recursiveBind(ImageLoader::LinkContext const&, bool, bool);ImageLoader::recursiveBind(ImageLoader::LinkContext const&, bool, bool);ImageLoader::recursiveBind(ImageLoader::LinkContext const&, bool, bool);ImageLoader::recursiveBind(ImageLoader::LinkContext const&, bool, bool);ImageLoader::recursiveBind(ImageLoader::LinkContext const&, bool, bool);ImageLoader::recursiveBind(ImageLoader::LinkContext const&, bool, bool);ImageLoader::recursiveBind(ImageLoader::LinkContext const&, bool, bool);ImageLoader::recursiveBind(ImageLoader::LinkContext const&, bool, bool);ImageLoader::recursiveBind(ImageLoader::LinkContext const&, bool, bool);ImageLoaderMachOCompressed::doBind(ImageLoader::LinkContext const&, bool);ImageLoaderMachO::setupLazyPointerHandler(ImageLoader::LinkContext const&) 5.06ms",
@@ -3855,24 +3866,6 @@ Object {
"selfWeight": 0,
"totalWeight": 9020084,
},
Frame {
"col": undefined,
"file": undefined,
"key": "null:dyld::paths_expand_roots(char const**, char const*, char const*)",
"line": undefined,
"name": "dyld::paths_expand_roots(char const**, char const*, char const*)",
"selfWeight": 0,
"totalWeight": 0,
},
Frame {
"col": undefined,
"file": undefined,
"key": "null:strlen",
"line": undefined,
"name": "strlen",
"selfWeight": 0,
"totalWeight": 0,
},
Frame {
"col": undefined,
"file": undefined,
@@ -4108,6 +4101,7 @@ Object {
"totalWeight": 1012057,
},
],
"name": "simple-time-profile.trace - thread 4",
"stacks": Array [
" 7.15ms",
"_dyld_start;dyldbootstrap::start(macho_header const*, int, char const**, long, macho_header const*, unsigned long*);dyld::_main(macho_header const*, unsigned long, int, char const**, char const**, char const**, unsigned long*);dyld::initializeMainExecutable();ImageLoader::runInitializers(ImageLoader::LinkContext const&, ImageLoader::InitializerTimingList&);ImageLoader::processInitializers(ImageLoader::LinkContext const&, unsigned int, ImageLoader::InitializerTimingList&, ImageLoader::UninitedUpwards&);ImageLoader::recursiveInitialization(ImageLoader::LinkContext const&, unsigned int, char const*, ImageLoader::InitializerTimingList&, ImageLoader::UninitedUpwards&);ImageLoader::recursiveInitialization(ImageLoader::LinkContext const&, unsigned int, char const*, ImageLoader::InitializerTimingList&, ImageLoader::UninitedUpwards&);ImageLoader::recursiveInitialization(ImageLoader::LinkContext const&, unsigned int, char const*, ImageLoader::InitializerTimingList&, ImageLoader::UninitedUpwards&);ImageLoader::recursiveInitialization(ImageLoader::LinkContext const&, unsigned int, char const*, ImageLoader::InitializerTimingList&, ImageLoader::UninitedUpwards&);ImageLoaderMachO::doInitialization(ImageLoader::LinkContext const&);0x0000000110c55a79;libSystem_initializer;_libc_initializer;__chk_init;_dyld_register_func_for_add_image;_dyld_func_lookup 9.02ms",
File diff suppressed because it is too large Load Diff
@@ -76,6 +76,7 @@ Object {
"totalWeight": 774706,
},
],
"name": "simple-stackprof.json",
"stacks": Array [
"<main>;<main>;block in <main>;Object#a;Object#a;Object#b;Object#b;Object#d;Object#d 6.11ms",
"<main>;<main>;block in <main>;Object#a;Object#a;Object#b;Object#b;Object#d;Object#d;(garbage collection) 1.02ms",
@@ -849,3 +850,7 @@ Object {
],
}
`;
exports[`importFromStackprof: indexToView 1`] = `0`;
exports[`importFromStackprof: profileGroup.name 1`] = `"simple-stackprof.json"`;
@@ -238,6 +238,7 @@ Object {
"totalWeight": 10154,
},
],
"name": "simple.v8log.json",
"stacks": Array [
"(anonymous);startup;setupGlobalVariables;NativeModule.require;NativeModule.compile;(anonymous);NativeModule.require;NativeModule.compile;(anonymous);(c++) v8::internal::Runtime_CreateArrayLiteral;(c++) v8::internal::JSFunction::EnsureHasInitialMap 29.38ms",
"(anonymous);startup;setupGlobalConsole;setupInspectorCommandLineAPI;NativeModule.require;NativeModule.compile;(anonymous);NativeModule.require;NativeModule.compile;(anonymous);(c++) v8::internal::Runtime_StoreIC_Miss;(c++) v8::internal::Map::RawCopy 22.89ms",
@@ -258,3 +259,7 @@ Object {
],
}
`;
exports[`importFromV8ProfLog: indexToView 1`] = `0`;
exports[`importFromV8ProfLog: profileGroup.name 1`] = `"simple.v8log.json"`;
+5 -2
View File
@@ -19,12 +19,15 @@ function parseBGFoldedStacks(contents: string): BGSample[] {
return samples
}
export function importFromBGFlameGraph(contents: string): Profile {
export function importFromBGFlameGraph(contents: string): Profile | null {
const parsed = parseBGFoldedStacks(contents)
const duration = parsed.reduce((prev: number, cur: BGSample) => prev + cur.duration, 0)
const profile = new StackListProfileBuilder(duration)
if (parsed.length === 0) {
return null
}
for (let sample of parsed) {
profile.appendSample(sample.stack, sample.duration)
profile.appendSampleWithWeight(sample.stack, sample.duration)
}
return profile.build()
}
+8
View File
@@ -0,0 +1,8 @@
import {importProfileGroup} from '.'
test('importProfileGroup', async () => {
// Importing garbage should return null
expect(await importProfileGroup('unknown', '')).toBe(null)
expect(await importProfileGroup('unknown', 'Hello world')).toBe(null)
expect(await importProfileGroup('unknown', 'Hello\n\nWorld')).toBe(null)
})
+49 -29
View File
@@ -1,4 +1,4 @@
import {Profile} from '../lib/profile'
import {Profile, ProfileGroup} from '../lib/profile'
import {FileSystemDirectoryEntry} from './file-system-entry'
import {importFromChromeCPUProfile, importFromChromeTimeline} from './chrome'
@@ -7,48 +7,62 @@ import {importFromInstrumentsDeepCopy, importFromInstrumentsTrace} from './instr
import {importFromBGFlameGraph} from './bg-flamegraph'
import {importFromFirefox} from './firefox'
import {importSpeedscopeProfiles} from '../lib/file-format'
import {FileFormat} from '../lib/file-format-spec'
import {importFromV8ProfLog} from './v8proflog'
import {importFromLinuxPerf} from './linux-tools-perf'
export async function importProfile(fileName: string, contents: string): Promise<Profile | null> {
const profile = await _importProfile(fileName, contents)
if (profile && !profile.getName()) {
profile.setName(fileName)
export async function importProfileGroup(
fileName: string,
contents: string,
): Promise<ProfileGroup | null> {
const profileGroup = await _importProfileGroup(fileName, contents)
if (profileGroup) {
if (!profileGroup.name) {
profileGroup.name = fileName
}
for (let profile of profileGroup.profiles) {
if (profile && !profile.getName()) {
profile.setName(fileName)
}
}
return profileGroup
}
return profile
return null
}
function importSingleSpeedscopeProfile(serialized: FileFormat.File) {
const profiles = importSpeedscopeProfiles(serialized)
if (profiles.length === 0) {
throw new Error('Failed to extract any profiles from the imported speedscope profile')
}
return profiles[0]
function toGroup(profile: Profile | null): ProfileGroup | null {
if (!profile) return null
return {name: profile.getName(), indexToView: 0, profiles: [profile]}
}
async function _importProfile(fileName: string, contents: string): Promise<Profile | null> {
async function _importProfileGroup(
fileName: string,
contents: string,
): Promise<ProfileGroup | null> {
// First pass: Check known file format names to infer the file type
if (fileName.endsWith('.speedscope.json')) {
console.log('Importing as speedscope json file')
return importSingleSpeedscopeProfile(JSON.parse(contents))
return importSpeedscopeProfiles(JSON.parse(contents))
} else if (fileName.endsWith('.cpuprofile')) {
console.log('Importing as Chrome CPU Profile')
return importFromChromeCPUProfile(JSON.parse(contents))
return toGroup(importFromChromeCPUProfile(JSON.parse(contents)))
} else if (fileName.endsWith('.chrome.json') || /Profile-\d{8}T\d{6}/.exec(fileName)) {
console.log('Importing as Chrome Timeline')
return importFromChromeTimeline(JSON.parse(contents))
return toGroup(importFromChromeTimeline(JSON.parse(contents)))
} else if (fileName.endsWith('.stackprof.json')) {
console.log('Importing as stackprof profile')
return importFromStackprof(JSON.parse(contents))
return toGroup(importFromStackprof(JSON.parse(contents)))
} else if (fileName.endsWith('.instruments.txt')) {
console.log('Importing as Instruments.app deep copy')
return importFromInstrumentsDeepCopy(contents)
return toGroup(importFromInstrumentsDeepCopy(contents))
} else if (fileName.endsWith('.linux-perf.txt')) {
console.log('Importing as output of linux perf script')
return importFromLinuxPerf(contents)
} else if (fileName.endsWith('.collapsedstack.txt')) {
console.log('Importing as collapsed stack format')
return importFromBGFlameGraph(contents)
return toGroup(importFromBGFlameGraph(contents))
} else if (fileName.endsWith('.v8log.json')) {
console.log('Importing as --prof-process v8 log')
return importFromV8ProfLog(JSON.parse(contents))
return toGroup(importFromV8ProfLog(JSON.parse(contents)))
}
// Second pass: Try to guess what file format it is based on structure
@@ -59,22 +73,22 @@ async function _importProfile(fileName: string, contents: string): Promise<Profi
if (parsed) {
if (parsed['$schema'] === 'https://www.speedscope.app/file-format-schema.json') {
console.log('Importing as speedscope json file')
return importSingleSpeedscopeProfile(parsed)
return importSpeedscopeProfiles(JSON.parse(contents))
} else if (parsed['systemHost'] && parsed['systemHost']['name'] == 'Firefox') {
console.log('Importing as Firefox profile')
return importFromFirefox(parsed)
return toGroup(importFromFirefox(parsed))
} else if (Array.isArray(parsed) && parsed[parsed.length - 1].name === 'CpuProfile') {
console.log('Importing as Chrome CPU Profile')
return importFromChromeTimeline(parsed)
return toGroup(importFromChromeTimeline(parsed))
} else if ('nodes' in parsed && 'samples' in parsed && 'timeDeltas' in parsed) {
console.log('Importing as Chrome Timeline')
return importFromChromeCPUProfile(parsed)
return toGroup(importFromChromeCPUProfile(parsed))
} else if ('mode' in parsed && 'frames' in parsed) {
console.log('Importing as stackprof profile')
return importFromStackprof(parsed)
return toGroup(importFromStackprof(parsed))
} else if ('code' in parsed && 'functions' in parsed && 'ticks' in parsed) {
console.log('Importing as --prof-process v8 log')
return importFromV8ProfLog(parsed)
return toGroup(importFromV8ProfLog(parsed))
}
} else {
// Format is not JSON
@@ -83,7 +97,7 @@ async function _importProfile(fileName: string, contents: string): Promise<Profi
// a deep copy from OS X Instruments.app
if (/^[\w \t\(\)]*\tSymbol Name/.exec(contents)) {
console.log('Importing as Instruments.app deep copy')
return importFromInstrumentsDeepCopy(contents)
return toGroup(importFromInstrumentsDeepCopy(contents))
}
// If every line ends with a space followed by a number, it's probably
@@ -91,7 +105,13 @@ async function _importProfile(fileName: string, contents: string): Promise<Profi
const lineCount = contents.split(/\n/).length
if (lineCount >= 1 && lineCount === contents.split(/ \d+\n/).length) {
console.log('Importing as collapsed stack format')
return importFromBGFlameGraph(contents)
return toGroup(importFromBGFlameGraph(contents))
}
const fromLinuxPerf = importFromLinuxPerf(contents)
if (fromLinuxPerf) {
console.log('Importing from linux perf script output')
return fromLinuxPerf
}
}
+2 -1
View File
@@ -87,7 +87,8 @@ describe('importFromInstrumentsTrace', () => {
})
})
const root = new ZipBackedFileSystemEntry(zip, 'simple-time-profile.trace')
const profile = await importFromFileSystemDirectoryEntry(root)
const profileGroup = await importFromFileSystemDirectoryEntry(root)
const profile = profileGroup.profiles[profileGroup.indexToView]
expect(dumpProfile(profile)).toMatchSnapshot()
}
+121 -52
View File
@@ -1,7 +1,13 @@
// This file contains methods to import data from OS X Instruments.app
// https://developer.apple.com/library/content/documentation/DeveloperTools/Conceptual/InstrumentsUserGuide/index.html
import {Profile, FrameInfo, CallTreeProfileBuilder, StackListProfileBuilder} from '../lib/profile'
import {
Profile,
FrameInfo,
CallTreeProfileBuilder,
StackListProfileBuilder,
ProfileGroup,
} from '../lib/profile'
import {sortBy, getOrThrow, getOrInsert, lastOf, getOrElse, zeroPad} from '../lib/utils'
import * as pako from 'pako'
import {ByteFormatter, TimeFormatter} from '../lib/value-formatters'
@@ -382,92 +388,126 @@ interface SymbolInfo {
addressToLine: Map<number, number>
}
interface FormTemplateData {
selectedRun: number
instrument: string
version: number
interface FormTemplateRunData {
number: number
addressToFrameMap: Map<number, FrameInfo>
}
interface FormTemplateData {
version: number
selectedRunNumber: number
instrument: string
runs: FormTemplateRunData[]
}
async function readFormTemplate(tree: TraceDirectoryTree): Promise<FormTemplateData> {
const formTemplate = getOrThrow(tree.files, 'form.template')
const archive = readInstrumentsKeyedArchive(await readAsArrayBuffer(formTemplate))
const version = archive['com.apple.xray.owner.template.version']
const selectedRun = archive['com.apple.xray.owner.template'].get('_selectedRunNumber')
const selectedRunNumber = archive['com.apple.xray.owner.template'].get('_selectedRunNumber')
let instrument = archive['$1']
if ('stubInfoByUUID' in archive) {
instrument = Array.from(archive['stubInfoByUUID'].keys())[0]
}
let allRunData = archive['com.apple.xray.run.data']
const runData = getOrThrow<number, Map<any, any>>(
allRunData.runData,
allRunData.runNumbers.pop()!,
)
const allRunData = archive['com.apple.xray.run.data']
const symbolsByPid = getOrThrow<string, Map<number, {symbols: SymbolInfo[]}>>(
runData,
'symbolsByPid',
)
const runs: FormTemplateRunData[] = []
for (let runNumber of allRunData.runNumbers) {
const runData = getOrThrow<number, Map<any, any>>(allRunData.runData, runNumber)
const addressToFrameMap = new Map<number, FrameInfo>()
const symbolsByPid = getOrThrow<string, Map<number, {symbols: SymbolInfo[]}>>(
runData,
'symbolsByPid',
)
// TODO(jlfwong): Deal with profiles with conflicts addresses?
for (let symbols of symbolsByPid.values()) {
for (let symbol of symbols.symbols) {
if (!symbol) continue
const {sourcePath, symbolName, addressToLine} = symbol
for (let address of addressToLine.keys()) {
getOrInsert(addressToFrameMap, address, () => {
const name = symbolName || `0x${zeroPad(address.toString(16), 16)}`
const frame: FrameInfo = {
key: `${sourcePath}:${name}`,
name: name,
}
if (sourcePath) {
frame.file = sourcePath
}
return frame
})
const addressToFrameMap = new Map<number, FrameInfo>()
// TODO(jlfwong): Deal with profiles with conflicting addresses?
for (let symbols of symbolsByPid.values()) {
for (let symbol of symbols.symbols) {
if (!symbol) continue
const {sourcePath, symbolName, addressToLine} = symbol
for (let address of addressToLine.keys()) {
getOrInsert(addressToFrameMap, address, () => {
const name = symbolName || `0x${zeroPad(address.toString(16), 16)}`
const frame: FrameInfo = {
key: `${sourcePath}:${name}`,
name: name,
}
if (sourcePath) {
frame.file = sourcePath
}
return frame
})
}
}
runs.push({
number: runNumber,
addressToFrameMap,
})
}
}
return {
version,
instrument,
selectedRun,
addressToFrameMap,
selectedRunNumber,
runs,
}
}
// Import from a .trace file saved from Mac Instruments.app
export async function importFromInstrumentsTrace(
entry: FileSystemDirectoryEntry,
): Promise<Profile> {
): Promise<ProfileGroup> {
const tree = await extractDirectoryTree(entry)
const {version, selectedRun, instrument, addressToFrameMap} = await readFormTemplate(tree)
const {version, runs, instrument, selectedRunNumber} = await readFormTemplate(tree)
if (instrument !== 'com.apple.xray.instrument-type.coresampler2') {
throw new Error(
`The only supported instrument from .trace import is "com.apple.xray.instrument-type.coresampler2". Got ${instrument}`,
)
}
console.log('version: ', version)
console.log(`Importing time profile from run ${selectedRun}`)
console.log(`Importing time profile`)
const core = getCoreDirForRun(tree, selectedRun)
const profiles: Profile[] = []
let indexToView = 0
for (let run of runs) {
const {addressToFrameMap, number} = run
const group = await importRunFromInstrumentsTrace({
fileName: entry.name,
tree,
addressToFrameMap,
runNumber: number,
})
if (run.number === selectedRunNumber) {
indexToView = profiles.length + group.indexToView
}
profiles.push(...group.profiles)
}
return {name: entry.name, indexToView, profiles}
}
export async function importRunFromInstrumentsTrace(args: {
fileName: string
tree: TraceDirectoryTree
addressToFrameMap: Map<number, FrameInfo>
runNumber: number
}): Promise<ProfileGroup> {
const {fileName, tree, addressToFrameMap, runNumber} = args
const core = getCoreDirForRun(tree, runNumber)
let samples = await getRawSampleList(core)
const arrays = await getIntegerArrays(samples, core)
const backtraceIDtoStack = new Map<number, FrameInfo[]>()
const profile = new StackListProfileBuilder(lastOf(samples)!.timestamp)
profile.setName(entry.name)
// For now, we can only display the flamechart for a single thread of execution,
// So let's choose whichever thread had the most sample hits.
//
// TODO(jlfwong): Support displaying flamecharts for multiple threads.
// We'll try to guess which thread is the main thread by assuming
// it's the one with the most samples.
const sampleCountByThreadID = new Map<number, number>()
for (let sample of samples) {
sampleCountByThreadID.set(
@@ -476,9 +516,38 @@ export async function importFromInstrumentsTrace(
)
}
const counts = Array.from(sampleCountByThreadID.entries())
sortBy(counts, c => c[1])
const mainThreadID = lastOf(counts)![0]
samples = samples.filter(s => s.threadID === mainThreadID)
sortBy(counts, c => -c[1])
const threadIDs = counts.map(c => c[0])
return {
name: fileName,
indexToView: 0,
profiles: threadIDs.map(threadID =>
importThreadFromInstrumentsTrace({
threadID,
fileName,
arrays,
addressToFrameMap,
samples,
}),
),
}
}
export function importThreadFromInstrumentsTrace(args: {
fileName: string
addressToFrameMap: Map<number, FrameInfo>
threadID: number
arrays: number[][]
samples: Sample[]
}): Profile {
let {fileName, addressToFrameMap, arrays, threadID, samples} = args
const backtraceIDtoStack = new Map<number, FrameInfo[]>()
samples = samples.filter(s => s.threadID === threadID)
const profile = new StackListProfileBuilder(lastOf(samples)!.timestamp)
profile.setName(`${fileName} - thread ${threadID}`)
function appendRecursive(k: number, stack: FrameInfo[]) {
const frame = addressToFrameMap.get(k)
@@ -510,7 +579,7 @@ export async function importFromInstrumentsTrace(
if (lastTimestamp === null) {
// The first sample is sometimes fairly late in the profile for some reason.
// We'll just say nothing was known to be on the stack in that time.
profile.appendSample([], sample.timestamp)
profile.appendSampleWithWeight([], sample.timestamp)
lastTimestamp = sample.timestamp
}
@@ -518,7 +587,7 @@ export async function importFromInstrumentsTrace(
throw new Error('Timestamps out of order!')
}
profile.appendSample(stackForSample, sample.timestamp - lastTimestamp)
profile.appendSampleWithWeight(stackForSample, sample.timestamp - lastTimestamp)
lastTimestamp = sample.timestamp
}
+22
View File
@@ -0,0 +1,22 @@
import {checkProfileSnapshot} from '../lib/test-utils'
describe('importFromLinuxPerf', async () => {
test('simple.linux-perf.txt', async () => {
await checkProfileSnapshot('./sample/profiles/linux-perf/simple.linux-perf.txt')
})
test('one-sample.linux-perf.txt', async () => {
await checkProfileSnapshot('./sample/profiles/linux-perf/one-sample.linux-perf.txt')
})
test('forks.linux-perf.txt', async () => {
await checkProfileSnapshot('./sample/profiles/linux-perf/forks.linux-perf.txt')
})
test('simple-with-header.linux-perf.txt', async () => {
await checkProfileSnapshot('./sample/profiles/linux-perf/simple-with-header.linux-perf.txt')
})
test('simple-with-pids.linux-perf.txt', async () => {
await checkProfileSnapshot('./sample/profiles/linux-perf/simple-with-pid.linux-perf.txt')
})
test('system-wide.linux-perf.txt', async () => {
await checkProfileSnapshot('./sample/profiles/linux-perf/system-wide.linux-perf.txt')
})
})
+130
View File
@@ -0,0 +1,130 @@
import {StackListProfileBuilder, ProfileGroup} from '../lib/profile'
import {itMap, getOrInsert} from '../lib/utils'
import {TimeFormatter} from '../lib/value-formatters'
// This imports the output of the "perf script" command on linux.
//
// Reference: https://github.com/torvalds/linux/blob/0fbc4aea/tools/perf/builtin-script.c#L1622
// Reference: https://github.com/brendangregg/FlameGraph/blob/18c3dea/stackcollapse-perf.pl#L163
interface PerfStackFrame {
address: string
symbolName: string
file: string
}
interface PerfEvent {
command: string | null
processID: number | null
threadID: number | null
time: number | null
eventType: string
stack: PerfStackFrame[]
}
function parseEvent(rawEvent: string): PerfEvent | null {
const lines = rawEvent.split('\n').filter(l => !/^\s*#/.exec(l))
const event: PerfEvent = {
command: null,
processID: null,
threadID: null,
time: null,
eventType: '',
stack: [],
}
const firstLine = lines.shift()
if (!firstLine) return null
// Note: command name may contain spaces, e.g.
//
// V8 WorkerThread 25607 4794564.109216: cycles:
const eventStartMatch = /^(\S.+?)\s+(\d+)(?:\/?(\d+))?\s+/.exec(firstLine)
if (!eventStartMatch) return null
event.command = eventStartMatch[1]
// default "perf script" output has TID but not PID
if (eventStartMatch[3]) {
event.processID = parseInt(eventStartMatch[2], 10)
event.threadID = parseInt(eventStartMatch[3], 10)
} else {
event.threadID = parseInt(eventStartMatch[2], 10)
}
const timeMatch = /\s+(\d+\.\d+):\s+/.exec(firstLine)
if (timeMatch) {
event.time = parseFloat(timeMatch[1])
}
const evName = /(\S+):\s*$/.exec(firstLine)
if (evName) {
event.eventType = evName[1]
}
for (let line of lines) {
const lineMatch = /^\s*(\w+)\s*(.+) \((\S*)\)/.exec(line)
if (!lineMatch) continue
let [, address, symbolName, file] = lineMatch
// Linux 4.8 included symbol offsets in perf script output by default, eg:
// 7fffb84c9afc cpu_startup_entry+0x800047c022ec ([kernel.kallsyms])
// strip these off:
symbolName = symbolName.replace(/\+0x[\da-f]+$/, '')
event.stack.push({address: `0x${address}`, symbolName, file})
}
event.stack.reverse()
return event
}
export function importFromLinuxPerf(contents: string): ProfileGroup | null {
const profiles = new Map<string, StackListProfileBuilder>()
let eventType: string | null = null
const events = contents.split('\n\n').map(parseEvent)
for (let event of events) {
if (event == null) continue
if (eventType != null && eventType != event.eventType) continue
if (event.time == null) continue
eventType = event.eventType
let profileNameParts = []
if (event.command) profileNameParts.push(event.command)
if (event.processID) profileNameParts.push(`pid: ${event.processID}`)
if (event.threadID) profileNameParts.push(`tid: ${event.threadID}`)
const profileName = profileNameParts.join(' ')
const builderState = getOrInsert(profiles, profileName, () => {
const builder = new StackListProfileBuilder()
builder.setName(profileName)
builder.setValueFormatter(new TimeFormatter('seconds'))
return builder
})
const builder = builderState
builder.appendSampleWithTimestamp(
event.stack.map(({symbolName, file}) => {
return {
key: `${symbolName} (${file})`,
name: symbolName === '[unknown]' ? `??? (${file})` : symbolName,
file: file,
}
}),
event.time!,
)
}
if (profiles.size === 0) {
return null
}
return {
name: profiles.size === 1 ? Array.from(profiles.keys())[0] : '',
indexToView: 0,
profiles: Array.from(itMap(profiles.values(), builder => builder.build())),
}
}
+1 -1
View File
@@ -45,7 +45,7 @@ export function importFromStackprof(stackprofProfile: StackprofProfile): Profile
sampleDuration += raw_timestamp_deltas[sampleIndex++]
}
profile.appendSample(stack, sampleDuration)
profile.appendSampleWithWeight(stack, sampleDuration)
prevStack = stack
}
+1 -1
View File
@@ -173,7 +173,7 @@ export function importFromV8ProfLog(v8log: V8LogProfile): Profile {
}
stack.push(getFrameInfo(id))
}
profile.appendSample(stack, tick.tm - lastTm)
profile.appendSampleWithWeight(stack, tick.tm - lastTm)
lastTm = tick.tm
}
@@ -40,6 +40,7 @@ Object {
"totalWeight": 4,
},
],
"name": "simple.txt",
"stacks": Array [
"a;b;c 2",
"a;b;d 4",
@@ -49,6 +50,10 @@ Object {
}
`;
exports[`importSpeedscopeProfiles 0.0.1 evented profile: indexToView 1`] = `0`;
exports[`importSpeedscopeProfiles 0.0.1 evented profile: profileGroup.name 1`] = `"simple.txt"`;
exports[`importSpeedscopeProfiles 0.1.2 sampled profile 1`] = `
Object {
"frames": Array [
@@ -89,6 +94,7 @@ Object {
"totalWeight": 4,
},
],
"name": "simple.speedscope.json",
"stacks": Array [
"a;b;c 2.00s",
"a;b;d 4.00s",
@@ -97,3 +103,111 @@ Object {
],
}
`;
exports[`importSpeedscopeProfiles 0.1.2 sampled profile: indexToView 1`] = `0`;
exports[`importSpeedscopeProfiles 0.1.2 sampled profile: profileGroup.name 1`] = `"simple.speedscope.json"`;
exports[`importSpeedscopeProfiles 0.6.0 multiple profiles 1`] = `
Object {
"frames": Array [
Frame {
"col": undefined,
"file": undefined,
"key": 0,
"line": undefined,
"name": "a",
"selfWeight": 0,
"totalWeight": 14,
},
Frame {
"col": undefined,
"file": undefined,
"key": 1,
"line": undefined,
"name": "b",
"selfWeight": 5,
"totalWeight": 14,
},
Frame {
"col": undefined,
"file": undefined,
"key": 2,
"line": undefined,
"name": "c",
"selfWeight": 5,
"totalWeight": 5,
},
Frame {
"col": undefined,
"file": undefined,
"key": 3,
"line": undefined,
"name": "d",
"selfWeight": 4,
"totalWeight": 4,
},
],
"name": "one",
"stacks": Array [
"a;b;c 2.00s",
"a;b;d 4.00s",
"a;b;c 3.00s",
"a;b 5.00s",
],
}
`;
exports[`importSpeedscopeProfiles 0.6.0 multiple profiles 2`] = `
Object {
"frames": Array [
Frame {
"col": undefined,
"file": undefined,
"key": 0,
"line": undefined,
"name": "a",
"selfWeight": 0,
"totalWeight": 14,
},
Frame {
"col": undefined,
"file": undefined,
"key": 1,
"line": undefined,
"name": "b",
"selfWeight": 5,
"totalWeight": 14,
},
Frame {
"col": undefined,
"file": undefined,
"key": 2,
"line": undefined,
"name": "c",
"selfWeight": 5,
"totalWeight": 5,
},
Frame {
"col": undefined,
"file": undefined,
"key": 3,
"line": undefined,
"name": "d",
"selfWeight": 4,
"totalWeight": 4,
},
],
"name": "two",
"stacks": Array [
"a;b;c 2.00s",
"a;b;d 4.00s",
"a;b;c 3.00s",
"a;b 5.00s",
],
}
`;
exports[`importSpeedscopeProfiles 0.6.0 multiple profiles: indexToView 1`] = `1`;
exports[`importSpeedscopeProfiles 0.6.0 multiple profiles: profileGroup.name 1`] = `"Two Samples"`;
+25 -1
View File
@@ -4,12 +4,36 @@ export namespace FileFormat {
export type Profile = EventedProfile | SampledProfile
export interface File {
version: string
$schema: 'https://www.speedscope.app/file-format-schema.json'
// Data shared between profiles
shared: {
frames: Frame[]
}
// List of profile definitions
profiles: Profile[]
// The name of the contained profile group. If omitted, will use the name of
// the file itself.
// Added in 0.6.0
name?: string
// The index into the `profiles` array that should be displayed upon file
// load. If omitted, will default to displaying the first profile in the
// file.
//
// Added in 0.6.0
activeProfileIndex?: number
// The name of the the program which exported this profile. This isn't
// consumed but can be helpful for debugging generated data by seeing what
// was generating it! Recommended format is "name@version". e.g. when the
// file was exported by speedscope v0.6.0 itself, it will be
// "speedscope@0.6.0"
//
// Added in 0.6.0
exporter?: string
}
export interface Frame {
+4
View File
@@ -8,4 +8,8 @@ describe('importSpeedscopeProfiles', async () => {
test('0.1.2 sampled profile', async () => {
await checkProfileSnapshot('./sample/profiles/speedscope/0.1.2/simple-sampled.speedscope.json')
})
test('0.6.0 multiple profiles', async () => {
await checkProfileSnapshot('./sample/profiles/speedscope/0.6.0/two-sampled.speedscope.json')
})
})
+39 -26
View File
@@ -5,29 +5,14 @@ import {
CallTreeProfileBuilder,
FrameInfo,
StackListProfileBuilder,
ProfileGroup,
} from './profile'
import {TimeFormatter, ByteFormatter, RawValueFormatter} from './value-formatters'
import {FileFormat} from './file-format-spec'
export function exportProfile(profile: Profile): FileFormat.File {
export function exportProfileGroup(profileGroup: ProfileGroup): FileFormat.File {
const frames: FileFormat.Frame[] = []
const eventedProfile: FileFormat.EventedProfile = {
type: FileFormat.ProfileType.EVENTED,
name: profile.getName(),
unit: profile.getWeightUnit(),
startValue: 0,
endValue: profile.getTotalWeight(),
events: [],
}
const file: FileFormat.File = {
version: require('../../package.json').version,
$schema: 'https://www.speedscope.app/file-format-schema.json',
shared: {frames},
profiles: [eventedProfile],
}
const indexForFrame = new Map<Frame, number>()
function getIndexForFrame(frame: Frame): number {
let index = indexForFrame.get(frame)
@@ -38,7 +23,6 @@ export function exportProfile(profile: Profile): FileFormat.File {
if (frame.file != null) serializedFrame.file = frame.file
if (frame.line != null) serializedFrame.line = frame.line
if (frame.col != null) serializedFrame.col = frame.col
index = frames.length
indexForFrame.set(frame, index)
frames.push(serializedFrame)
@@ -46,6 +30,31 @@ export function exportProfile(profile: Profile): FileFormat.File {
return index
}
const file: FileFormat.File = {
exporter: `speedscope@${require('../../package.json').version}`,
name: profileGroup.name,
activeProfileIndex: profileGroup.indexToView,
$schema: 'https://www.speedscope.app/file-format-schema.json',
shared: {frames},
profiles: [],
}
for (let profile of profileGroup.profiles) {
file.profiles.push(exportProfile(profile, getIndexForFrame))
}
return file
}
function exportProfile(profile: Profile, getIndexForFrame: (frame: Frame) => number) {
const eventedProfile: FileFormat.EventedProfile = {
type: FileFormat.ProfileType.EVENTED,
name: profile.getName(),
unit: profile.getWeightUnit(),
startValue: 0,
endValue: profile.getTotalWeight(),
events: [],
}
const openFrame = (node: CallTreeNode, value: number) => {
eventedProfile.events.push({
type: FileFormat.EventType.OPEN_FRAME,
@@ -61,8 +70,7 @@ export function exportProfile(profile: Profile): FileFormat.File {
})
}
profile.forEachCall(openFrame, closeFrame)
return file
return eventedProfile
}
function importSpeedscopeProfile(
@@ -130,7 +138,7 @@ function importSpeedscopeProfile(
for (let i = 0; i < samples.length; i++) {
const stack = samples[i]
const weight = weights[i]
profile.appendSample(stack.map(n => frameInfos[n]), weight)
profile.appendSampleWithWeight(stack.map(n => frameInfos[n]), weight)
}
return profile.build()
@@ -144,14 +152,19 @@ function importSpeedscopeProfile(
}
}
export function importSpeedscopeProfiles(serialized: FileFormat.File): Profile[] {
return serialized.profiles.map(p => importSpeedscopeProfile(p, serialized.shared.frames))
export function importSpeedscopeProfiles(serialized: FileFormat.File): ProfileGroup {
return {
name: serialized.name || serialized.profiles[0].name || 'profile',
indexToView: serialized.activeProfileIndex || 0,
profiles: serialized.profiles.map(p => importSpeedscopeProfile(p, serialized.shared.frames)),
}
}
export function saveToFile(profile: Profile): void {
const blob = new Blob([JSON.stringify(exportProfile(profile))], {type: 'text/json'})
export function saveToFile(profileGroup: ProfileGroup): void {
const file = exportProfileGroup(profileGroup)
const blob = new Blob([JSON.stringify(file)], {type: 'text/json'})
const nameWithoutExt = profile.getName().split('.')[0]!
const nameWithoutExt = file.name ? file.name.split('.')[0]! : 'profile'
const filename = `${nameWithoutExt.replace(/\W+/g, '_')}.speedscope.json`
console.log('Saving', filename)
+7 -7
View File
@@ -147,9 +147,9 @@ test('StackListProfileBuilder', () => {
]
samples.forEach(stack => {
b.appendSample(stack, 1)
b.appendSampleWithWeight(stack, 1)
})
b.appendSample([], 4)
b.appendSampleWithWeight([], 4)
const profile = b.build()
expect(profile.getTotalWeight()).toBe(samples.length + 4)
@@ -170,9 +170,9 @@ test('StackListProfileBuilder separates non-contiguous', () => {
]
samples.forEach(stack => {
b.appendSample(stack, 1)
b.appendSampleWithWeight(stack, 1)
})
b.appendSample([], 4)
b.appendSampleWithWeight([], 4)
const profile = b.build()
expect(toTreeString(profile, true)).toMatchSnapshot('grouped')
@@ -251,7 +251,7 @@ test('getInvertedProfileForCallersOf', () => {
[fd, fb],
]
samples.forEach(stack => {
b.appendSample(stack, 1)
b.appendSampleWithWeight(stack, 1)
})
const profile = b.build()
@@ -279,7 +279,7 @@ test('getProfileForCalleesOf', () => {
[fd, fb],
]
samples.forEach(stack => {
b.appendSample(stack, 1)
b.appendSampleWithWeight(stack, 1)
})
const profile = b.build()
@@ -305,7 +305,7 @@ test('getProfileWithRecursionFlattened', () => {
[fa, fb, fa],
]
samples.forEach(stack => {
b.appendSample(stack, 1)
b.appendSampleWithWeight(stack, 1)
})
const profile = b.build()
+57 -5
View File
@@ -103,6 +103,12 @@ export class CallTreeNode extends HasWeights {
}
}
export interface ProfileGroup {
name: string
indexToView: number
profiles: Profile[]
}
export class Profile {
protected name: string = ''
@@ -331,7 +337,7 @@ export class Profile {
for (let n: CallTreeNode | null = node; n != null && n.frame !== Frame.root; n = n.parent) {
stack.push(n.frame)
}
builder.appendSample(stack, node.getTotalWeight())
builder.appendSampleWithWeight(stack, node.getTotalWeight())
}
const ret = builder.build()
@@ -349,7 +355,7 @@ export class Profile {
function visit(node: CallTreeNode) {
stack.push(node.frame)
builder.appendSample(stack, node.getSelfWeight())
builder.appendSampleWithWeight(stack, node.getSelfWeight())
for (let child of node.children) {
visit(child)
}
@@ -444,17 +450,63 @@ export class StackListProfileBuilder extends Profile {
frame.addToTotalWeight(weight)
}
this.samples.push(node)
this.weights.push(weight)
if (node === lastOf(this.samples)) {
this.weights[this.weights.length - 1] += weight
} else {
this.samples.push(node)
this.weights.push(weight)
}
}
}
appendSample(stack: FrameInfo[], weight: number) {
appendSampleWithWeight(stack: FrameInfo[], weight: number) {
if (weight === 0) {
// Samples with zero weight have no effect, so let's ignore them
return
}
if (weight < 0) {
throw new Error('Samples must have positive weights')
}
this._appendSample(stack, weight, true)
this._appendSample(stack, weight, false)
}
private pendingSample: {
stack: FrameInfo[]
startTimestamp: number
centralTimestamp: number
} | null = null
appendSampleWithTimestamp(stack: FrameInfo[], timestamp: number) {
if (this.pendingSample) {
if (timestamp < this.pendingSample.centralTimestamp) {
throw new Error('Timestamps received out of order')
}
const endTimestamp = (timestamp + this.pendingSample.centralTimestamp) / 2
this.appendSampleWithWeight(
this.pendingSample.stack,
endTimestamp - this.pendingSample.startTimestamp,
)
this.pendingSample = {stack, startTimestamp: endTimestamp, centralTimestamp: timestamp}
} else {
this.pendingSample = {stack, startTimestamp: timestamp, centralTimestamp: timestamp}
}
}
build(): Profile {
if (this.pendingSample) {
if (this.samples.length > 0) {
this.appendSampleWithWeight(
this.pendingSample.stack,
this.pendingSample.centralTimestamp - this.pendingSample.startTimestamp,
)
} else {
// There is only a single sample. In this case, units will be meaningless,
// so we'll append with a weight of 1 and also clear any value formatter
this.appendSampleWithWeight(this.pendingSample.stack, 1)
this.setValueFormatter(new RawValueFormatter())
}
}
this.totalWeight = Math.max(this.totalWeight, this.weights.reduce((a, b) => a + b, 0))
return this
}
+37 -15
View File
@@ -1,16 +1,18 @@
import * as fs from 'fs'
import * as path from 'path'
import {Profile, CallTreeNode, Frame} from './profile'
import {importProfile} from '../import'
import {exportProfile, importSpeedscopeProfiles} from './file-format'
import {importProfileGroup} from '../import'
import {exportProfileGroup, importSpeedscopeProfiles} from './file-format'
interface DumpedProfile {
name: string
stacks: string[]
frames: Frame[]
}
export function dumpProfile(profile: Profile): any {
const dump: DumpedProfile = {
name: profile.getName(),
stacks: [],
frames: [],
}
@@ -47,30 +49,50 @@ export function dumpProfile(profile: Profile): any {
export async function checkProfileSnapshot(filepath: string) {
const input = fs.readFileSync(filepath, 'utf8')
const profile = await importProfile(path.basename(filepath), input)
if (profile) {
expect(dumpProfile(profile)).toMatchSnapshot()
const profileGroup = await importProfileGroup(path.basename(filepath), input)
if (profileGroup) {
expect(profileGroup.name).toMatchSnapshot('profileGroup.name')
expect(profileGroup.indexToView).toMatchSnapshot('indexToView')
for (let profile of profileGroup.profiles) {
expect(dumpProfile(profile)).toMatchSnapshot()
}
} else {
fail('Failed to extract profile')
return
}
const profileWithoutFilename = await importProfile('unknown', input)
if (profileWithoutFilename) {
profileWithoutFilename.setName(profile.getName())
expect(exportProfile(profileWithoutFilename)).toEqual(exportProfile(profile))
const profilesWithoutFilename = await importProfileGroup('unknown', input)
if (profilesWithoutFilename) {
expect(profilesWithoutFilename.profiles.length).toEqual(profileGroup.profiles.length)
profilesWithoutFilename.name = profileGroup.name
for (let i = 0; i < profileGroup.profiles.length; i++) {
const a = profileGroup.profiles[i]
const b = profilesWithoutFilename.profiles[i]
b.setName(a.getName())
}
expect(exportProfileGroup(profileGroup)).toEqual(exportProfileGroup(profilesWithoutFilename))
} else {
fail('Failed to extract profile when filename was "unknown"')
return
}
const exported = exportProfile(profile)
const reimported = importSpeedscopeProfiles(exported)[0]
const exported = exportProfileGroup(profileGroup)
const reimportedGroup = importSpeedscopeProfiles(exported)
expect(reimported.getName()).toEqual(profile.getName())
expect(reimported.getTotalWeight()).toEqual(profile.getTotalWeight())
expect(dumpProfile(reimported).stacks.join('\n')).toEqual(dumpProfile(profile).stacks.join('\n'))
expect(reimportedGroup.name).toEqual(profileGroup.name)
expect(reimportedGroup.profiles.length).toEqual(profileGroup.profiles.length)
const reexported = exportProfile(reimported)
for (let i = 0; i < profileGroup.profiles.length; i++) {
const profile = profileGroup.profiles[i]
const reimported = reimportedGroup.profiles[i]
expect(reimported.getTotalWeight()).toEqual(profile.getTotalWeight())
expect(dumpProfile(reimported).stacks.join('\n')).toEqual(
dumpProfile(profile).stacks.join('\n'),
)
}
const reexported = exportProfileGroup(reimportedGroup)
expect(exported).toEqual(reexported)
}
+28 -6
View File
@@ -37,6 +37,7 @@ export function actionCreator(type: string) {
}
export type Reducer<T> = (state: T | undefined, action: Action<any>) => T
export type ReducerWithActionType<T, A> = (state: T | undefined, action: Action<A>) => T
export function setter<T>(
setterAction: ActionCreator<T>,
@@ -51,18 +52,30 @@ export function setter<T>(
}
export type Dispatch = redux.Dispatch<Action<any>>
export type WithDispatch<T> = T & {dispatch: Dispatch}
export type WithoutDispatch<T> = Pick<T, Exclude<keyof T, 'dispatch'>>
// We make this into a single function invocation instead of the connect(map, map)(Component)
// syntax to make better use of type inference.
export function createContainer<OwnProps, State, PropsFromState, ComponentType>(
//
// NOTE: To avoid this returning objects which do not compare shallow equal, it's the
// responsibility of the caller to ensure that the props returned by map compare shallow
// equal. This most importantly mean memoizing functions which wrap dispatch to avoid
// all callback props from being regenerated on every call.
export function createContainer<OwnProps, State, ComponentProps, ComponentType>(
component: {
new (props: OwnProps & PropsFromState & {dispatch: Dispatch}): ComponentType
new (props: ComponentProps): ComponentType
},
mapStateToProps: (state: State, ownProps: OwnProps) => PropsFromState,
map: (state: State, dispatch: Dispatch, ownProps: OwnProps) => ComponentProps,
): ComponentConstructor<OwnProps, {}> {
return connect(mapStateToProps, (dispatch: Dispatch) => ({dispatch}))(component)
const mapStateToProps = (state: State) => state
const mapDispatchToProps = (dispatch: Dispatch) => ({dispatch})
const mergeProps = (
stateProps: State,
dispatchProps: {dispatch: Dispatch},
ownProps: OwnProps,
) => {
return map(stateProps, dispatchProps.dispatch, ownProps)
}
return connect(mapStateToProps, mapDispatchToProps, mergeProps)(component)
}
export type VoidState = {
@@ -70,3 +83,12 @@ export type VoidState = {
}
export abstract class StatelessComponent<P> extends Component<P, VoidState> {}
export function bindActionCreator<T>(
dispatch: Dispatch,
actionCreator: (payload: T) => Action<T>,
): (t: T) => void {
return (t: T) => {
dispatch(actionCreator(t))
}
}
+64
View File
@@ -10,6 +10,9 @@ import {
formatPercent,
KeyedSet,
binarySearch,
memoizeByReference,
memoizeByShallowEquality,
objectsHaveShallowEquality,
} from './utils'
test('sortBy', () => {
@@ -109,3 +112,64 @@ test('binarySearch', () => {
expect(lo).toBeLessThan(Math.E)
expect(hi).toBeGreaterThan(Math.E)
})
test('memoizeByReference', () => {
let hitCount = 0
const identity = memoizeByReference((arg: number) => {
hitCount++
return arg
})
expect(identity(3)).toBe(3)
expect(hitCount).toBe(1)
expect(identity(3)).toBe(3)
expect(hitCount).toBe(1)
expect(identity(5)).toBe(5)
expect(hitCount).toBe(2)
expect(identity(3)).toBe(3)
expect(hitCount).toBe(3)
})
test('memoizeByShallowEquality', () => {
let hitCount = 0
const identity = memoizeByShallowEquality((arg: {a: number; b: number}) => {
hitCount++
return arg
})
expect(identity({a: 1, b: 2})).toEqual({a: 1, b: 2})
expect(hitCount).toBe(1)
expect(identity({a: 1, b: 2})).toEqual({a: 1, b: 2})
expect(hitCount).toBe(1)
expect(identity({a: 2, b: 2})).toEqual({a: 2, b: 2})
expect(hitCount).toBe(2)
expect(identity({a: 2, b: 2})).toEqual({a: 2, b: 2})
expect(hitCount).toBe(2)
expect(identity({a: 2, b: 1})).toEqual({a: 2, b: 1})
expect(hitCount).toBe(3)
expect(identity({a: 2, b: 1})).toEqual({a: 2, b: 1})
expect(hitCount).toBe(3)
expect(identity({a: 1, b: 2})).toEqual({a: 1, b: 2})
expect(hitCount).toBe(4)
})
test('objectsHaveShallowEquality', () => {
expect(objectsHaveShallowEquality({}, {})).toBe(true)
expect(objectsHaveShallowEquality({a: 1, b: 2}, {a: 1, b: 2})).toBe(true)
expect(objectsHaveShallowEquality({a: 1, b: 2}, {a: 1, b: 3})).toBe(false)
expect(objectsHaveShallowEquality({a: 1, b: 2}, {a: 2, b: 2})).toBe(false)
expect(objectsHaveShallowEquality({a: 1}, {a: 1, b: 2})).toBe(false)
expect(objectsHaveShallowEquality({a: 1, b: 2}, {b: 2})).toBe(false)
expect(objectsHaveShallowEquality([], [])).toBe(true)
expect(objectsHaveShallowEquality([1, 2], [1, 2])).toBe(true)
expect(objectsHaveShallowEquality([1], [1, 2])).toBe(false)
expect(objectsHaveShallowEquality([1, 2], [1])).toBe(false)
})
+2 -3
View File
@@ -122,7 +122,7 @@ export function binarySearch(
export function noop(...args: any[]) {}
function shallowEquals<T extends object>(a: T, b: T): boolean {
export function objectsHaveShallowEquality<T extends object>(a: T, b: T): boolean {
for (let key in a) {
if (a[key] !== b[key]) return false
}
@@ -132,7 +132,6 @@ function shallowEquals<T extends object>(a: T, b: T): boolean {
return true
}
// TODO(jlfwong): Write tests for this
export function memoizeByShallowEquality<T extends object, U>(cb: (t: T) => U): (t: T) => U {
let last: {args: T; result: U} | null = null
return (args: T) => {
@@ -141,7 +140,7 @@ export function memoizeByShallowEquality<T extends object, U>(cb: (t: T) => U):
result = cb(args)
last = {args, result}
return result
} else if (shallowEquals(last.args, args)) {
} else if (objectsHaveShallowEquality(last.args, args)) {
return last.result
} else {
last.args = args
+2 -5
View File
@@ -1,8 +1,7 @@
import {h, render} from 'preact'
import {createApplicationStore, ApplicationState} from './store'
import {createApplicationStore} from './store'
import {Provider} from 'preact-redux'
import {createContainer} from './lib/typed-redux'
import {Application} from './views/application'
import {ApplicationContainer} from './views/application-container'
console.log(`speedscope v${require('../package.json').version}`)
@@ -19,8 +18,6 @@ const lastStore: any = (window as any)['store']
const store = createApplicationStore(lastStore ? lastStore.getState() : {})
;(window as any)['store'] = store
const ApplicationContainer = createContainer(Application, (state: ApplicationState) => state)
render(
<Provider store={store}>
<ApplicationContainer />
+13 -14
View File
@@ -1,21 +1,18 @@
import {actionCreator} from '../lib/typed-redux'
import {Profile, CallTreeNode, Frame} from '../lib/profile'
import {CallTreeNode, Frame, ProfileGroup} from '../lib/profile'
import {SortMethod} from '../views/profile-table-view'
import {ViewMode} from '.'
import {FlamechartID} from './flamechart-view-state'
import {Rect, Vec2} from '../lib/math'
import {HashParams} from '../lib/hash-params'
import {actionCreatorWithIndex} from './profiles-state'
export namespace actions {
// Set the top-level profile from which other data will be derived
export const setProfile = actionCreator<Profile>('setProfile')
// Set the top-level profile group from which other data will be derived
export const setProfileGroup = actionCreator<ProfileGroup>('setProfileGroup')
// Set the profile currently being viewed
export const setActiveProfile = actionCreator<Profile>('setActiveProfile')
export const setFrameToColorBucket = actionCreator<Map<string | number, number>>(
'setFrameToColorBucket',
)
// Set the index into the profile group to view
export const setProfileIndexToView = actionCreator<number>('setProfileIndexToView')
export const setGLCanvas = actionCreator<HTMLCanvasElement | null>('setGLCanvas')
@@ -43,26 +40,28 @@ export namespace actions {
// Set the table sorting method used for the sandwich view.
export const setTableSortMethod = actionCreator<SortMethod>('sandwichView.setTableSortMethod')
export const setSelectedFrame = actionCreator<Frame | null>('sandwichView.setSelectedFarmr')
export const setSelectedFrame = actionCreatorWithIndex<Frame | null>(
'sandwichView.setSelectedFarmr',
)
}
export namespace flamechart {
export const setHoveredNode = actionCreator<{
export const setHoveredNode = actionCreatorWithIndex<{
id: FlamechartID
hover: {node: CallTreeNode; event: MouseEvent} | null
}>('flamechart.setHoveredNode')
export const setSelectedNode = actionCreator<{
export const setSelectedNode = actionCreatorWithIndex<{
id: FlamechartID
selectedNode: CallTreeNode | null
}>('flamechart.setSelectedNode')
export const setConfigSpaceViewportRect = actionCreator<{
export const setConfigSpaceViewportRect = actionCreatorWithIndex<{
id: FlamechartID
configSpaceViewportRect: Rect
}>('flamechart.setConfigSpaceViewportRect')
export const setLogicalSpaceViewportSize = actionCreator<{
export const setLogicalSpaceViewportSize = actionCreatorWithIndex<{
id: FlamechartID
logicalSpaceViewportSize: Vec2
}>('flamechart.setLogicalSpaceViewportSpace')
+105
View File
@@ -0,0 +1,105 @@
import {storeTest, profileGroupTwoSampled} from './store-test-utils'
import {actions} from './actions'
import {Rect, Vec2} from '../lib/math'
import {FlamechartID} from './flamechart-view-state'
import {ViewMode} from '.'
describe('flamechart view state', () => {
storeTest('setHoveredNode', ({getState, dispatch}) => {
dispatch(actions.setProfileGroup(profileGroupTwoSampled))
expect(getState().profileGroup!.profiles[0].chronoViewState.hover).toEqual(null)
const {profileGroup} = getState()
const hover = {
node: profileGroup!.profiles[0].profile.getAppendOrderCalltreeRoot().children[0],
event: {} as MouseEvent,
}
dispatch(
actions.flamechart.setHoveredNode({
profileIndex: 0,
args: {
id: FlamechartID.CHRONO,
hover,
},
}),
)
expect(getState().profileGroup!.profiles[0].chronoViewState.hover).toEqual(hover)
expect(getState().profileGroup!.profiles[0].leftHeavyViewState.hover).toEqual(null)
expect(getState().profileGroup!.profiles[1].chronoViewState.hover).toEqual(null)
// Changing view mode should clear the hover state
dispatch(actions.setViewMode(ViewMode.LEFT_HEAVY_FLAME_GRAPH))
expect(getState().profileGroup!.profiles[0].chronoViewState.hover).toEqual(null)
})
storeTest('setSelectedNode', ({getState, dispatch}) => {
dispatch(actions.setProfileGroup(profileGroupTwoSampled))
expect(getState().profileGroup!.profiles[0].chronoViewState.selectedNode).toEqual(null)
const {profileGroup} = getState()
const selectedNode = profileGroup!.profiles[0].profile.getAppendOrderCalltreeRoot().children[0]
dispatch(
actions.flamechart.setSelectedNode({
profileIndex: 0,
args: {
id: FlamechartID.CHRONO,
selectedNode,
},
}),
)
expect(getState().profileGroup!.profiles[0].chronoViewState.selectedNode).toEqual(selectedNode)
expect(getState().profileGroup!.profiles[0].leftHeavyViewState.selectedNode).toEqual(null)
expect(getState().profileGroup!.profiles[1].chronoViewState.selectedNode).toEqual(null)
})
storeTest('setLogicalSpaceViewportSize', ({getState, dispatch}) => {
dispatch(actions.setProfileGroup(profileGroupTwoSampled))
expect(getState().profileGroup!.profiles[0].chronoViewState.logicalSpaceViewportSize).toEqual(
Vec2.zero,
)
const logicalSpaceViewportSize = new Vec2(3, 5)
dispatch(
actions.flamechart.setLogicalSpaceViewportSize({
profileIndex: 0,
args: {
id: FlamechartID.CHRONO,
logicalSpaceViewportSize,
},
}),
)
expect(getState().profileGroup!.profiles[0].chronoViewState.logicalSpaceViewportSize).toEqual(
logicalSpaceViewportSize,
)
expect(
getState().profileGroup!.profiles[0].leftHeavyViewState.logicalSpaceViewportSize,
).toEqual(Vec2.zero)
expect(getState().profileGroup!.profiles[1].chronoViewState.logicalSpaceViewportSize).toEqual(
Vec2.zero,
)
})
storeTest('setConfigSpaceViewportRect', ({getState, dispatch}) => {
dispatch(actions.setProfileGroup(profileGroupTwoSampled))
expect(getState().profileGroup!.profiles[0].chronoViewState.configSpaceViewportRect).toEqual(
Rect.empty,
)
dispatch(
actions.flamechart.setConfigSpaceViewportRect({
profileIndex: 0,
args: {
id: FlamechartID.CHRONO,
configSpaceViewportRect: new Rect(Vec2.zero, Vec2.unit),
},
}),
)
expect(getState().profileGroup!.profiles[0].chronoViewState.configSpaceViewportRect).toEqual(
new Rect(Vec2.zero, Vec2.unit),
)
expect(getState().profileGroup!.profiles[0].leftHeavyViewState.configSpaceViewportRect).toEqual(
Rect.empty,
)
expect(getState().profileGroup!.profiles[1].chronoViewState.configSpaceViewportRect).toEqual(
Rect.empty,
)
})
})
+17 -16
View File
@@ -20,37 +20,38 @@ export interface FlamechartViewState {
configSpaceViewportRect: Rect
}
export function createFlamechartViewStateReducer(id: FlamechartID): Reducer<FlamechartViewState> {
export function createFlamechartViewStateReducer(
id: FlamechartID,
profileIndex: number,
): Reducer<FlamechartViewState> {
let initialState: FlamechartViewState = {
hover: null,
selectedNode: null,
configSpaceViewportRect: Rect.empty,
logicalSpaceViewportSize: Vec2.zero,
}
function applies(action: {payload: {profileIndex: number; args: {id: FlamechartID}}}) {
const {payload} = action
return payload.args.id === id && payload.profileIndex === profileIndex
}
return (state = initialState, action) => {
if (actions.flamechart.setHoveredNode.matches(action) && action.payload.id === id) {
const {hover} = action.payload
if (actions.flamechart.setHoveredNode.matches(action) && applies(action)) {
const {hover} = action.payload.args
return {...state, hover}
}
if (actions.flamechart.setSelectedNode.matches(action) && action.payload.id === id) {
const {selectedNode} = action.payload
if (actions.flamechart.setSelectedNode.matches(action) && applies(action)) {
const {selectedNode} = action.payload.args
return {...state, selectedNode}
}
if (actions.flamechart.setConfigSpaceViewportRect.matches(action) && action.payload.id === id) {
const {configSpaceViewportRect} = action.payload
if (actions.flamechart.setConfigSpaceViewportRect.matches(action) && applies(action)) {
const {configSpaceViewportRect} = action.payload.args
return {...state, configSpaceViewportRect}
}
if (
actions.flamechart.setLogicalSpaceViewportSize.matches(action) &&
action.payload.id === id
) {
const {logicalSpaceViewportSize} = action.payload
if (actions.flamechart.setLogicalSpaceViewportSize.matches(action) && applies(action)) {
const {logicalSpaceViewportSize} = action.payload.args
return {...state, logicalSpaceViewportSize}
}
if (actions.setProfile.matches(action)) {
// If the profile changes, we should invalidate all of our state, since none of it still applies
return initialState
}
if (actions.setViewMode.matches(action)) {
// If we switch views, the hover information is no longer relevant
return {...state, hover: null}
+20
View File
@@ -45,3 +45,23 @@ export const getProfileToView = memoizeByShallowEquality(
return flattenRecursion ? profile.getProfileWithRecursionFlattened() : profile
},
)
export const getFrameToColorBucket = memoizeByReference((profile: Profile): Map<
string | number,
number
> => {
const frames: Frame[] = []
profile.forEachFrame(f => frames.push(f))
function key(f: Frame) {
return (f.file || '') + f.name
}
function compare(a: Frame, b: Frame) {
return key(a) > key(b) ? 1 : -1
}
frames.sort(compare)
const frameToColorBucket = new Map<string | number, number>()
for (let i = 0; i < frames.length; i++) {
frameToColorBucket.set(frames[i].key, Math.floor(255 * i / frames.length))
}
return frameToColorBucket
})
+51
View File
@@ -0,0 +1,51 @@
import {ViewMode} from '.'
import {actions} from './actions'
import {storeTest} from './store-test-utils'
import {SortField, SortDirection} from '../views/profile-table-view'
storeTest('flattenRecursion', ({getState, dispatch}) => {
expect(getState().flattenRecursion).toBe(false)
dispatch(actions.setFlattenRecursion(true))
expect(getState().flattenRecursion).toBe(true)
})
storeTest('viewMode', ({getState, dispatch}) => {
expect(getState().viewMode).toBe(ViewMode.CHRONO_FLAME_CHART)
dispatch(actions.setViewMode(ViewMode.SANDWICH_VIEW))
expect(getState().viewMode).toBe(ViewMode.SANDWICH_VIEW)
})
storeTest('dragActive', ({getState, dispatch}) => {
expect(getState().dragActive).toBe(false)
dispatch(actions.setDragActive(true))
expect(getState().dragActive).toBe(true)
})
storeTest('loading', ({getState, dispatch}) => {
expect(getState().loading).toBe(false)
dispatch(actions.setLoading(true))
expect(getState().loading).toBe(true)
})
storeTest('error', ({getState, dispatch}) => {
expect(getState().error).toBe(false)
dispatch(actions.setError(true))
expect(getState().error).toBe(true)
})
storeTest('setTableSortMethod', ({getState, dispatch}) => {
expect(getState().tableSortMethod).toEqual({
field: SortField.SELF,
direction: SortDirection.DESCENDING,
})
dispatch(
actions.sandwichView.setTableSortMethod({
field: SortField.SYMBOL_NAME,
direction: SortDirection.ASCENDING,
}),
)
expect(getState().tableSortMethod).toEqual({
field: SortField.SYMBOL_NAME,
direction: SortDirection.ASCENDING,
})
})
+10 -22
View File
@@ -7,14 +7,9 @@ import {actions} from './actions'
import * as redux from 'redux'
import {setter, Reducer} from '../lib/typed-redux'
import {Profile} from '../lib/profile'
import {
createFlamechartViewStateReducer,
FlamechartID,
FlamechartViewState,
} from './flamechart-view-state'
import {SandwichViewState, sandwichView} from './sandwich-view-state'
import {HashParams, getHashParams} from '../lib/hash-params'
import {ProfileGroupState, profileGroup} from './profiles-state'
import {SortMethod, SortField, SortDirection} from '../views/profile-table-view'
export const enum ViewMode {
CHRONO_FLAME_CHART,
@@ -23,9 +18,6 @@ export const enum ViewMode {
}
export interface ApplicationState {
profile: Profile | null
frameToColorBucket: Map<string | number, number>
hashParams: HashParams
glCanvas: HTMLCanvasElement | null
@@ -37,9 +29,9 @@ export interface ApplicationState {
loading: boolean
error: boolean
chronoView: FlamechartViewState
leftHeavyView: FlamechartViewState
sandwichView: SandwichViewState
tableSortMethod: SortMethod
profileGroup: ProfileGroupState
}
const protocol = window.location.protocol
@@ -57,11 +49,7 @@ export function createApplicationStore(
const loading = canUseXHR && hashParams.profileURL != null
const reducer: Reducer<ApplicationState> = redux.combineReducers({
profile: setter<Profile | null>(actions.setProfile, null),
frameToColorBucket: setter<Map<string | number, number>>(
actions.setFrameToColorBucket,
new Map(),
),
profileGroup,
hashParams: setter<HashParams>(actions.setHashParams, hashParams),
@@ -75,10 +63,10 @@ export function createApplicationStore(
loading: setter<boolean>(actions.setLoading, loading),
error: setter<boolean>(actions.setError, false),
chronoView: createFlamechartViewStateReducer(FlamechartID.CHRONO),
leftHeavyView: createFlamechartViewStateReducer(FlamechartID.LEFT_HEAVY),
sandwichView,
tableSortMethod: setter<SortMethod>(actions.sandwichView.setTableSortMethod, {
field: SortField.SELF,
direction: SortDirection.DESCENDING,
}),
})
return redux.createStore(reducer, initialState)
+36
View File
@@ -0,0 +1,36 @@
import {storeTest, profileGroupTwoSampled} from './store-test-utils'
import {actions} from './actions'
describe('profileGroup', () => {
storeTest('setProfileGroup', ({getState, dispatch}) => {
expect(getState().profileGroup).toBe(null)
dispatch(actions.setProfileGroup(profileGroupTwoSampled))
const {profileGroup} = getState()
expect(profileGroup!.name).toBe(profileGroupTwoSampled.name)
expect(profileGroup!.indexToView).toBe(profileGroupTwoSampled.indexToView)
for (let i = 0; i < profileGroupTwoSampled.profiles.length; i++) {
expect(profileGroup!.profiles[i].profile).toEqual(profileGroupTwoSampled.profiles[i])
}
})
storeTest('setProfileIndexToView', ({getState, dispatch}) => {
dispatch(actions.setProfileGroup(profileGroupTwoSampled))
expect(getState().profileGroup!.indexToView).toBe(1)
dispatch(actions.setProfileIndexToView(0))
expect(getState()!.profileGroup!.indexToView).toBe(0)
dispatch(actions.setProfileIndexToView(-1))
expect(getState()!.profileGroup!.indexToView).toBe(0)
dispatch(actions.setProfileIndexToView(2))
expect(getState().profileGroup!.indexToView).toBe(1)
})
storeTest('preserve state', ({getState, dispatch}) => {
// When an unrelated action occurs, we should not change the identiy of the profileGroup
// property
dispatch(actions.setProfileGroup(profileGroupTwoSampled))
const profileGroup = getState().profileGroup
dispatch(actions.setDragActive(true))
expect(getState().profileGroup).toBe(profileGroup)
})
})
+100
View File
@@ -0,0 +1,100 @@
import {Profile} from '../lib/profile'
import {
FlamechartViewState,
createFlamechartViewStateReducer,
FlamechartID,
} from './flamechart-view-state'
import {SandwichViewState, createSandwichView} from './sandwich-view-state'
import {Reducer, actionCreator, setter} from '../lib/typed-redux'
import {actions} from './actions'
import {clamp} from '../lib/math'
import {objectsHaveShallowEquality} from '../lib/utils'
export type ProfileGroupState = {
name: string
indexToView: number
profiles: ProfileState[]
} | null
export interface ProfileWithIndex {
profile: Profile
index: number
}
export interface ProfileState {
profile: Profile
chronoViewState: FlamechartViewState
leftHeavyViewState: FlamechartViewState
sandwichViewState: SandwichViewState
}
export function actionCreatorWithIndex<T>(name: string) {
return actionCreator<{profileIndex: number; args: T}>(name)
}
function createProfileReducer(profile: Profile, index: number): Reducer<ProfileState> {
const chronoViewStateReducer = createFlamechartViewStateReducer(FlamechartID.CHRONO, index)
const leftHeavyViewStateReducer = createFlamechartViewStateReducer(FlamechartID.LEFT_HEAVY, index)
const sandwichViewStateReducer = createSandwichView(index)
return (state = undefined, action) => {
if (state === undefined) {
return {
profile,
chronoViewState: chronoViewStateReducer(undefined, action),
leftHeavyViewState: leftHeavyViewStateReducer(undefined, action),
sandwichViewState: sandwichViewStateReducer(undefined, action),
}
}
const nextState = {
profile,
chronoViewState: chronoViewStateReducer(state.chronoViewState, action),
leftHeavyViewState: leftHeavyViewStateReducer(state.leftHeavyViewState, action),
sandwichViewState: sandwichViewStateReducer(state.sandwichViewState, action),
}
if (objectsHaveShallowEquality(state, nextState)) {
return state
}
return nextState
}
}
export const profileGroup: Reducer<ProfileGroupState> = (state = null, action) => {
if (actions.setProfileGroup.matches(action)) {
const {indexToView, profiles, name} = action.payload
return {
indexToView,
name,
profiles: profiles.map((p, i) => {
return createProfileReducer(p, i)(undefined, action)
}),
}
}
if (state != null) {
const {indexToView, profiles} = state
const nextIndexToView = clamp(
setter(actions.setProfileIndexToView, 0)(indexToView, action),
0,
profiles.length - 1,
)
const nextProfiles = profiles.map((profileState, profileIndex) => {
return createProfileReducer(profileState.profile, profileIndex)(profileState, action)
})
if (indexToView === nextIndexToView && objectsHaveShallowEquality(profiles, nextProfiles)) {
return state
}
return {
...state,
indexToView: nextIndexToView,
profiles: nextProfiles,
}
}
return state
}
+70
View File
@@ -0,0 +1,70 @@
import {storeTest, profileGroupTwoSampled} from './store-test-utils'
import {actions} from './actions'
import {Vec2} from '../lib/math'
import {FlamechartID} from './flamechart-view-state'
describe('sandwich view state', () => {
storeTest('setSelectedFrame', ({getState, dispatch}) => {
dispatch(actions.setProfileGroup(profileGroupTwoSampled))
expect(getState().profileGroup!.profiles[0].sandwichViewState.callerCallee).toBe(null)
const {profileGroup} = getState()
const selectedFrame = profileGroup!.profiles[0].profile.getAppendOrderCalltreeRoot().children[0]
.frame
dispatch(actions.sandwichView.setSelectedFrame({profileIndex: 0, args: selectedFrame}))
expect(getState().profileGroup!.profiles[0].sandwichViewState.callerCallee!.selectedFrame).toBe(
selectedFrame,
)
// Other profiles selection state should not change
expect(getState().profileGroup!.profiles[1].sandwichViewState.callerCallee).toBe(null)
// Changing selection when something is already selected should work
const selectedFrame2 = profileGroup!.profiles[0].profile.getAppendOrderCalltreeRoot()
.children[0].children[0].frame
dispatch(actions.sandwichView.setSelectedFrame({profileIndex: 0, args: selectedFrame2}))
expect(getState().profileGroup!.profiles[0].sandwichViewState.callerCallee!.selectedFrame).toBe(
selectedFrame2,
)
// Clear selection
dispatch(actions.sandwichView.setSelectedFrame({profileIndex: 0, args: null}))
expect(getState().profileGroup!.profiles[0].sandwichViewState.callerCallee).toBe(null)
})
storeTest('contained flamegraphs receive updates', ({getState, dispatch}) => {
dispatch(actions.setProfileGroup(profileGroupTwoSampled))
const {profileGroup} = getState()
const selectedFrame = profileGroup!.profiles[0].profile.getAppendOrderCalltreeRoot().children[0]
.frame
dispatch(actions.sandwichView.setSelectedFrame({profileIndex: 0, args: selectedFrame}))
expect(
getState().profileGroup!.profiles[0].sandwichViewState.callerCallee!.calleeFlamegraph
.logicalSpaceViewportSize,
).toEqual(Vec2.zero)
dispatch(
actions.flamechart.setLogicalSpaceViewportSize({
profileIndex: 0,
args: {id: FlamechartID.SANDWICH_CALLEES, logicalSpaceViewportSize: Vec2.unit},
}),
)
expect(
getState().profileGroup!.profiles[0].sandwichViewState.callerCallee!.calleeFlamegraph
.logicalSpaceViewportSize,
).toEqual(Vec2.unit)
})
storeTest('preserve identity', ({getState, dispatch}) => {
dispatch(actions.setProfileGroup(profileGroupTwoSampled))
const {profileGroup} = getState()
const selectedFrame = profileGroup!.profiles[0].profile.getAppendOrderCalltreeRoot().children[0]
.frame
dispatch(actions.sandwichView.setSelectedFrame({profileIndex: 0, args: selectedFrame}))
// When an unrelated action is triggered, it should not change the identity of the sandwichViewState
const sandwichViewState = getState().profileGroup!.profiles[0].sandwichViewState
dispatch(actions.setLoading(true))
expect(getState().profileGroup!.profiles[0].sandwichViewState).toBe(sandwichViewState)
})
})
+44 -52
View File
@@ -1,4 +1,3 @@
import {SortMethod, SortField, SortDirection} from '../views/profile-table-view'
import {Frame} from '../lib/profile'
import {
FlamechartViewState,
@@ -9,7 +8,6 @@ import {Reducer} from '../lib/typed-redux'
import {actions} from './actions'
export interface SandwichViewState {
tableSortMethod: SortMethod
callerCallee: CallerCalleeState | null
}
@@ -19,36 +17,52 @@ export interface CallerCalleeState {
calleeFlamegraph: FlamechartViewState
}
const defaultSortMethod = {
field: SortField.SELF,
direction: SortDirection.DESCENDING,
}
const calleesReducer = createFlamechartViewStateReducer(FlamechartID.SANDWICH_CALLEES)
const invertedCallersReducer = createFlamechartViewStateReducer(
FlamechartID.SANDWICH_INVERTED_CALLERS,
)
export const sandwichView: Reducer<SandwichViewState> = (
state = {tableSortMethod: defaultSortMethod, callerCallee: null},
action,
) => {
if (actions.setProfile.matches(action)) {
// When a new profile is dropped in, none of the selection state is going to make
// sense any more.
return {...state, callerCallee: null}
export function createSandwichView(profileIndex: number): Reducer<SandwichViewState> {
const calleesReducer = createFlamechartViewStateReducer(
FlamechartID.SANDWICH_CALLEES,
profileIndex,
)
const invertedCallersReducer = createFlamechartViewStateReducer(
FlamechartID.SANDWICH_INVERTED_CALLERS,
profileIndex,
)
function applies(action: {payload: {profileIndex: number}}) {
const {payload} = action
return payload.profileIndex === profileIndex
}
const {callerCallee} = state
if (callerCallee) {
const {calleeFlamegraph, invertedCallerFlamegraph} = callerCallee
const nextCalleeFlamegraph = calleesReducer(calleeFlamegraph, action)
const nextInvertedCallerFlamegraph = invertedCallersReducer(invertedCallerFlamegraph, action)
return (state = {callerCallee: null}, action) => {
if (actions.sandwichView.setSelectedFrame.matches(action) && applies(action)) {
if (action.payload.args == null) {
return {
...state,
callerCallee: null,
}
} else {
return {
...state,
callerCallee: {
selectedFrame: action.payload.args,
calleeFlamegraph: calleesReducer(undefined, action),
invertedCallerFlamegraph: invertedCallersReducer(undefined, action),
},
}
}
}
const {callerCallee} = state
if (callerCallee) {
const {calleeFlamegraph, invertedCallerFlamegraph} = callerCallee
const nextCalleeFlamegraph = calleesReducer(calleeFlamegraph, action)
const nextInvertedCallerFlamegraph = invertedCallersReducer(invertedCallerFlamegraph, action)
if (
nextCalleeFlamegraph === calleeFlamegraph &&
nextInvertedCallerFlamegraph === invertedCallerFlamegraph
) {
return state
}
if (
nextCalleeFlamegraph !== calleeFlamegraph ||
nextInvertedCallerFlamegraph !== invertedCallerFlamegraph
) {
return {
...state,
callerCallee: {
@@ -58,29 +72,7 @@ export const sandwichView: Reducer<SandwichViewState> = (
},
}
}
}
if (actions.sandwichView.setTableSortMethod.matches(action)) {
return {...state, tableSortMethod: action.payload}
return state
}
if (actions.sandwichView.setSelectedFrame.matches(action)) {
if (action.payload == null) {
return {
...state,
callerCallee: null,
}
} else {
return {
...state,
callerCallee: {
selectedFrame: action.payload,
calleeFlamegraph: calleesReducer(undefined, action),
invertedCallerFlamegraph: invertedCallersReducer(undefined, action),
},
}
}
}
return state
}
+16
View File
@@ -0,0 +1,16 @@
import * as fs from 'fs'
import {Store, AnyAction} from '../../node_modules/redux'
import {ApplicationState, createApplicationStore} from '.'
import {importSpeedscopeProfiles} from '../lib/file-format'
export function storeTest(name: string, cb: (store: Store<ApplicationState, AnyAction>) => void) {
const store = createApplicationStore({})
test(name, () => {
cb(store)
})
}
const filepath = './sample/profiles/speedscope/0.6.0/two-sampled.speedscope.json'
const input = fs.readFileSync(filepath, 'utf8')
export const profileGroupTwoSampled = importSpeedscopeProfiles(JSON.parse(input))
+47
View File
@@ -0,0 +1,47 @@
import {createContainer, Dispatch, bindActionCreator, ActionCreator} from '../lib/typed-redux'
import {Application, ActiveProfileState} from './application'
import {ApplicationState} from '../store'
import {getProfileToView} from '../store/getters'
import {actions} from '../store/actions'
export const ApplicationContainer = createContainer(
Application,
(state: ApplicationState, dispatch: Dispatch) => {
const {flattenRecursion, profileGroup} = state
let activeProfileState: ActiveProfileState | null = null
if (profileGroup) {
if (profileGroup.profiles.length > profileGroup.indexToView) {
const index = profileGroup.indexToView
const profileState = profileGroup.profiles[index]
activeProfileState = {
...profileGroup.profiles[profileGroup.indexToView],
profile: getProfileToView({profile: profileState.profile, flattenRecursion}),
index: profileGroup.indexToView,
}
}
}
function wrapActionCreator<T>(actionCreator: ActionCreator<T>): (t: T) => void {
return bindActionCreator(dispatch, actionCreator)
}
const setters = {
setGLCanvas: wrapActionCreator(actions.setGLCanvas),
setLoading: wrapActionCreator(actions.setLoading),
setError: wrapActionCreator(actions.setError),
setProfileGroup: wrapActionCreator(actions.setProfileGroup),
setDragActive: wrapActionCreator(actions.setDragActive),
setViewMode: wrapActionCreator(actions.setViewMode),
setFlattenRecursion: wrapActionCreator(actions.setFlattenRecursion),
setProfileIndexToView: wrapActionCreator(actions.setProfileIndexToView),
}
return {
activeProfileState,
dispatch,
...setters,
...state,
}
},
)
+234 -134
View File
@@ -2,22 +2,22 @@ import {h, Component} from 'preact'
import {StyleSheet, css} from 'aphrodite'
import {FileSystemDirectoryEntry} from '../import/file-system-entry'
import {Profile, Frame} from '../lib/profile'
import {Profile, ProfileGroup} from '../lib/profile'
import {FontFamily, FontSize, Colors, Sizes, Duration} from './style'
import {importEmscriptenSymbolMap} from '../lib/emscripten'
import {SandwichViewContainer} from './sandwich-view'
import {saveToFile} from '../lib/file-format'
import {ApplicationState, ViewMode, canUseXHR} from '../store'
import {actions} from '../store/actions'
import {Dispatch, StatelessComponent, WithDispatch} from '../lib/typed-redux'
import {StatelessComponent} from '../lib/typed-redux'
import {LeftHeavyFlamechartView, ChronoFlamechartView} from './flamechart-view-container'
import {getProfileToView} from '../store/getters'
import {SandwichViewState} from '../store/sandwich-view-state'
import {FlamechartViewState} from '../store/flamechart-view-state'
const importModule = import('../import')
// Force eager loading of the module
importModule.then(() => {})
async function importProfile(fileName: string, contents: string): Promise<Profile | null> {
return (await importModule).importProfile(fileName, contents)
async function importProfiles(fileName: string, contents: string): Promise<ProfileGroup | null> {
return (await importModule).importProfileGroup(fileName, contents)
}
async function importFromFileSystemDirectoryEntry(entry: FileSystemDirectoryEntry) {
return (await importModule).importFromFileSystemDirectoryEntry(entry)
@@ -26,8 +26,7 @@ async function importFromFileSystemDirectoryEntry(entry: FileSystemDirectoryEntr
declare function require(x: string): any
const exampleProfileURL = require('../../sample/profiles/stackcollapse/perf-vertx-stacks-01-collapsed-all.txt')
interface ToolbarProps extends ApplicationState {
setViewMode(order: ViewMode): void
interface ToolbarProps extends ApplicationProps {
browseForFile(): void
saveFile(): void
}
@@ -45,7 +44,88 @@ export class Toolbar extends StatelessComponent<ToolbarProps> {
this.props.setViewMode(ViewMode.SANDWICH_VIEW)
}
render() {
renderLeftContent() {
if (!this.props.activeProfileState) return null
return (
<div className={css(style.toolbarLeft)}>
<div
className={css(
style.toolbarTab,
this.props.viewMode === ViewMode.CHRONO_FLAME_CHART && style.toolbarTabActive,
)}
onClick={this.setTimeOrder}
>
<span className={css(style.emoji)}>🕰</span>Time Order
</div>
<div
className={css(
style.toolbarTab,
this.props.viewMode === ViewMode.LEFT_HEAVY_FLAME_GRAPH && style.toolbarTabActive,
)}
onClick={this.setLeftHeavyOrder}
>
<span className={css(style.emoji)}></span>Left Heavy
</div>
<div
className={css(
style.toolbarTab,
this.props.viewMode === ViewMode.SANDWICH_VIEW && style.toolbarTabActive,
)}
onClick={this.setSandwichView}
>
<span className={css(style.emoji)}>🥪</span>Sandwich
</div>
</div>
)
}
renderCenterContent() {
const {activeProfileState, profileGroup} = this.props
if (activeProfileState && profileGroup) {
const {index} = activeProfileState
if (profileGroup.profiles.length === 1) {
return activeProfileState.profile.getName()
} else {
function makeNavButton(content: string, disabled: boolean, onClick: () => void) {
return (
<button
disabled={disabled}
onClick={onClick}
className={css(
style.emoji,
style.toolbarProfileNavButton,
disabled && style.toolbarProfileNavButtonDisabled,
)}
>
{content}
</button>
)
}
const prevButton = makeNavButton('⬅️', index === 0, () =>
this.props.setProfileIndexToView(index - 1),
)
const nextButton = makeNavButton('➡️', index >= profileGroup.profiles.length - 1, () =>
this.props.setProfileIndexToView(index + 1),
)
return (
<div className={css(style.toolbarCenter)}>
{prevButton}
{activeProfileState.profile.getName()}{' '}
<span className={css(style.toolbarProfileIndex)}>
({activeProfileState.index + 1}/{profileGroup.profiles.length})
</span>
{nextButton}
</div>
)
}
}
return '🔬speedscope'
}
renderRightContent() {
const importFile = (
<div className={css(style.toolbarTab)} onClick={this.props.browseForFile}>
<span className={css(style.emoji)}></span>Import
@@ -63,63 +143,32 @@ export class Toolbar extends StatelessComponent<ToolbarProps> {
</div>
)
if (!this.props.profile) {
return (
<div className={css(style.toolbar)}>
🔬speedscope
<div className={css(style.toolbarRight)}>
{importFile}
{help}
</div>
</div>
)
}
return (
<div className={css(style.toolbar)}>
<div className={css(style.toolbarLeft)}>
<div
className={css(
style.toolbarTab,
this.props.viewMode === ViewMode.CHRONO_FLAME_CHART && style.toolbarTabActive,
)}
onClick={this.setTimeOrder}
>
<span className={css(style.emoji)}>🕰</span>Time Order
</div>
<div
className={css(
style.toolbarTab,
this.props.viewMode === ViewMode.LEFT_HEAVY_FLAME_GRAPH && style.toolbarTabActive,
)}
onClick={this.setLeftHeavyOrder}
>
<span className={css(style.emoji)}></span>Left Heavy
</div>
<div
className={css(
style.toolbarTab,
this.props.viewMode === ViewMode.SANDWICH_VIEW && style.toolbarTabActive,
)}
onClick={this.setSandwichView}
>
<span className={css(style.emoji)}>🥪</span>Sandwich
</div>
</div>
{this.props.profile.getName()}
<div className={css(style.toolbarRight)}>
<div className={css(style.toolbarRight)}>
{this.props.activeProfileState && (
<div className={css(style.toolbarTab)} onClick={this.props.saveFile}>
<span className={css(style.emoji)}></span>Export
</div>
{importFile}
{help}
</div>
)}
{importFile}
{help}
</div>
)
}
render() {
return (
<div className={css(style.toolbar)}>
{this.renderLeftContent()}
{this.renderCenterContent()}
{this.renderRightContent()}
</div>
)
}
}
interface GLCanvasProps {
dispatch: Dispatch
setGLCanvas: (canvas: HTMLCanvasElement | null) => void
}
export class GLCanvas extends Component<GLCanvasProps, void> {
private canvas: HTMLCanvasElement | null = null
@@ -131,7 +180,7 @@ export class GLCanvas extends Component<GLCanvasProps, void> {
this.canvas = null
}
this.props.dispatch(actions.setGLCanvas(this.canvas))
this.props.setGLCanvas(this.canvas)
}
private maybeResize() {
@@ -168,64 +217,72 @@ export class GLCanvas extends Component<GLCanvasProps, void> {
}
}
export class Application extends StatelessComponent<WithDispatch<ApplicationState>> {
async loadProfile(loader: () => Promise<Profile | null>) {
this.props.dispatch(actions.setLoading(true))
export interface ActiveProfileState {
profile: Profile
index: number
chronoViewState: FlamechartViewState
leftHeavyViewState: FlamechartViewState
sandwichViewState: SandwichViewState
}
export type ApplicationProps = ApplicationState & {
setGLCanvas: (canvas: HTMLCanvasElement | null) => void
setLoading: (loading: boolean) => void
setError: (error: boolean) => void
setProfileGroup: (profileGroup: ProfileGroup) => void
setDragActive: (dragActive: boolean) => void
setViewMode: (viewMode: ViewMode) => void
setFlattenRecursion: (flattenRecursion: boolean) => void
setProfileIndexToView: (profileIndex: number) => void
activeProfileState: ActiveProfileState | null
}
export class Application extends StatelessComponent<ApplicationProps> {
private async loadProfile(loader: () => Promise<ProfileGroup | null>) {
this.props.setLoading(true)
await new Promise(resolve => setTimeout(resolve, 0))
if (!this.props.glCanvas) return
console.time('import')
let profile: Profile | null = null
let profileGroup: ProfileGroup | null = null
try {
profile = await loader()
profileGroup = await loader()
} catch (e) {
console.log('Failed to load format', e)
this.props.dispatch(actions.setError(true))
this.props.setError(true)
return
}
if (profile == null) {
if (profileGroup == null) {
// TODO(jlfwong): Make this a nicer overlay
alert('Unrecognized format! See documentation about supported formats.')
this.props.dispatch(actions.setLoading(false))
this.props.setLoading(false)
return
}
await profile.demangle()
if (this.props.hashParams.title) {
profileGroup = {
name: this.props.hashParams.title,
...profileGroup,
}
}
document.title = `${profileGroup.name} - speedscope`
const title = this.props.hashParams.title || profile.getName()
profile.setName(title)
for (let profile of profileGroup.profiles) {
await profile.demangle()
}
await this.setActiveProfile(profile)
for (let profile of profileGroup.profiles) {
const title = this.props.hashParams.title || profile.getName()
profile.setName(title)
}
console.timeEnd('import')
this.props.dispatch(actions.setProfile(profile))
this.props.dispatch(actions.setLoading(false))
}
async setActiveProfile(profile: Profile) {
if (!this.props.glCanvas) return
document.title = `${profile.getName()} - speedscope`
const frames: Frame[] = []
profile.forEachFrame(f => frames.push(f))
function key(f: Frame) {
return (f.file || '') + f.name
}
function compare(a: Frame, b: Frame) {
return key(a) > key(b) ? 1 : -1
}
frames.sort(compare)
const frameToColorBucket = new Map<string | number, number>()
for (let i = 0; i < frames.length; i++) {
frameToColorBucket.set(frames[i].key, Math.floor(255 * i / frames.length))
}
this.props.dispatch(actions.setActiveProfile(profile))
this.props.dispatch(actions.setFrameToColorBucket(frameToColorBucket))
this.props.setProfileGroup(profileGroup)
this.props.setLoading(false)
}
loadFromFile(file: File) {
@@ -239,25 +296,31 @@ export class Application extends StatelessComponent<WithDispatch<ApplicationStat
throw new Error('Expected ArrayBuffer')
}
const profile = await importProfile(file.name, reader.result)
if (profile) {
if (!profile.getName()) {
profile.setName(file.name)
const profiles = await importProfiles(file.name, reader.result)
if (profiles) {
for (let profile of profiles.profiles) {
if (!profile.getName()) {
profile.setName(file.name)
}
}
return profile
return profiles
}
if (this.props.profile) {
if (this.props.profileGroup && this.props.activeProfileState) {
// If a profile is already loaded, it's possible the file being imported is
// a symbol map. If that's the case, we want to parse it, and apply the symbol
// mapping to the already loaded profile. This can be use to take an opaque
// profile and make it readable.
const map = importEmscriptenSymbolMap(reader.result)
if (map) {
const {profile, index} = this.props.activeProfileState
console.log('Importing as emscripten symbol map')
let profile = this.props.profile
profile.remapNames(name => map.get(name) || name)
return profile
return {
name: this.props.profileGroup.name || 'profile',
indexToView: index,
profiles: [profile],
}
}
}
@@ -269,16 +332,12 @@ export class Application extends StatelessComponent<WithDispatch<ApplicationStat
this.loadProfile(async () => {
const filename = 'perf-vertx-stacks-01-collapsed-all.txt'
const data = await fetch(exampleProfileURL).then(resp => resp.text())
const profile = await importProfile(filename, data)
if (profile && !profile.getName()) {
profile.setName(filename)
}
return profile
return await importProfiles(filename, data)
})
}
onDrop = (ev: DragEvent) => {
this.props.dispatch(actions.setDragActive(false))
this.props.setDragActive(false)
ev.preventDefault()
const firstItem = ev.dataTransfer.items[0]
@@ -288,7 +347,9 @@ export class Application extends StatelessComponent<WithDispatch<ApplicationStat
// Instrument.app file format is actually a directory.
if (webkitEntry.isDirectory && webkitEntry.name.endsWith('.trace')) {
console.log('Importing as Instruments.app .trace file')
this.loadProfile(async () => await importFromFileSystemDirectoryEntry(webkitEntry))
this.loadProfile(async () => {
return await importFromFileSystemDirectoryEntry(webkitEntry)
})
return
}
}
@@ -300,31 +361,47 @@ export class Application extends StatelessComponent<WithDispatch<ApplicationStat
}
onDragOver = (ev: DragEvent) => {
this.props.dispatch(actions.setDragActive(true))
this.props.setDragActive(true)
ev.preventDefault()
}
onDragLeave = (ev: DragEvent) => {
this.props.dispatch(actions.setDragActive(false))
this.props.setDragActive(false)
ev.preventDefault()
}
onWindowKeyPress = async (ev: KeyboardEvent) => {
if (ev.key === '1') {
this.props.dispatch(actions.setViewMode(ViewMode.CHRONO_FLAME_CHART))
this.props.setViewMode(ViewMode.CHRONO_FLAME_CHART)
} else if (ev.key === '2') {
this.props.dispatch(actions.setViewMode(ViewMode.LEFT_HEAVY_FLAME_GRAPH))
this.props.setViewMode(ViewMode.LEFT_HEAVY_FLAME_GRAPH)
} else if (ev.key === '3') {
this.props.dispatch(actions.setViewMode(ViewMode.SANDWICH_VIEW))
this.props.setViewMode(ViewMode.SANDWICH_VIEW)
} else if (ev.key === 'r') {
const {flattenRecursion} = this.props
this.props.dispatch(actions.setFlattenRecursion(!flattenRecursion))
this.props.setFlattenRecursion(!flattenRecursion)
} else if (ev.key === 'n') {
const {activeProfileState} = this.props
if (activeProfileState) {
this.props.setProfileIndexToView(activeProfileState.index + 1)
}
} else if (ev.key === 'p') {
const {activeProfileState} = this.props
if (activeProfileState) {
this.props.setProfileIndexToView(activeProfileState.index - 1)
}
}
}
private saveFile = () => {
if (this.props.profile) {
saveToFile(this.props.profile)
if (this.props.profileGroup) {
const {name, indexToView, profiles} = this.props.profileGroup
const profileGroup: ProfileGroup = {
name,
indexToView,
profiles: profiles.map(p => p.profile),
}
saveToFile(profileGroup)
}
}
@@ -352,7 +429,9 @@ export class Application extends StatelessComponent<WithDispatch<ApplicationStat
ev.stopPropagation()
const pasted = (ev as ClipboardEvent).clipboardData.getData('text')
this.loadProfile(async () => importProfile('From Clipboard', pasted))
this.loadProfile(async () => {
return await importProfiles('From Clipboard', pasted)
})
}
componentDidMount() {
@@ -382,7 +461,7 @@ export class Application extends StatelessComponent<WithDispatch<ApplicationStat
if (filename.includes('/')) {
filename = filename.slice(filename.lastIndexOf('/') + 1)
}
return await importProfile(filename, await response.text())
return await importProfiles(filename, await response.text())
})
} else if (this.props.hashParams.localProfilePath) {
// There isn't good cross-browser support for XHR of local files, even from
@@ -391,7 +470,7 @@ export class Application extends StatelessComponent<WithDispatch<ApplicationStat
;(window as any)['speedscope'] = {
loadFileFromBase64: (filename: string, base64source: string) => {
const source = atob(base64source)
this.loadProfile(() => importProfile(filename, source))
this.loadProfile(() => importProfiles(filename, source))
},
}
@@ -491,12 +570,8 @@ export class Application extends StatelessComponent<WithDispatch<ApplicationStat
return <div className={css(style.loading)} />
}
setViewMode = (viewMode: ViewMode) => {
this.props.dispatch(actions.setViewMode(viewMode))
}
renderContent() {
const {viewMode, flattenRecursion, profile, error, loading, glCanvas} = this.props
const {viewMode, activeProfileState, error, loading, glCanvas} = this.props
if (error) {
return this.renderError()
@@ -506,22 +581,21 @@ export class Application extends StatelessComponent<WithDispatch<ApplicationStat
return this.renderLoadingBar()
}
if (!profile || !glCanvas) {
if (!activeProfileState || !glCanvas) {
return this.renderLanding()
}
const profileToView = getProfileToView({profile, flattenRecursion})
switch (viewMode) {
case ViewMode.CHRONO_FLAME_CHART: {
return <ChronoFlamechartView profile={profileToView} glCanvas={glCanvas} />
return <ChronoFlamechartView activeProfileState={activeProfileState} glCanvas={glCanvas} />
}
case ViewMode.LEFT_HEAVY_FLAME_GRAPH: {
return <LeftHeavyFlamechartView profile={profileToView} glCanvas={glCanvas} />
return (
<LeftHeavyFlamechartView activeProfileState={activeProfileState} glCanvas={glCanvas} />
)
}
case ViewMode.SANDWICH_VIEW: {
if (!this.props.profile) return null
return <SandwichViewContainer />
return <SandwichViewContainer activeProfileState={activeProfileState} glCanvas={glCanvas} />
}
}
}
@@ -534,12 +608,11 @@ export class Application extends StatelessComponent<WithDispatch<ApplicationStat
onDragLeave={this.onDragLeave}
className={css(style.root, this.props.dragActive && style.dragTargetRoot)}
>
<GLCanvas dispatch={this.props.dispatch} />
<GLCanvas setGLCanvas={this.props.setGLCanvas} />
<Toolbar
setViewMode={this.setViewMode}
saveFile={this.saveFile}
browseForFile={this.browseForFile}
{...this.props as ApplicationState}
{...this.props as ApplicationProps}
/>
<div className={css(style.contentContainer)}>{this.renderContent()}</div>
{this.props.dragActive && <div className={css(style.dragTarget)} />}
@@ -671,6 +744,10 @@ const style = StyleSheet.create({
marginRight: 2,
textAlign: 'left',
},
toolbarCenter: {
paddingTop: 1,
height: Sizes.TOOLBAR_HEIGHT,
},
toolbarRight: {
height: Sizes.TOOLBAR_HEIGHT,
overflow: 'hidden',
@@ -680,6 +757,29 @@ const style = StyleSheet.create({
marginRight: 2,
textAlign: 'right',
},
toolbarProfileIndex: {
color: Colors.LIGHT_GRAY,
},
toolbarProfileNavButton: {
opacity: 0.8,
fontSize: FontSize.TITLE,
lineHeight: `${Sizes.TOOLBAR_TAB_HEIGHT}px`,
':hover': {
opacity: 1.0,
},
background: 'none',
border: 'none',
padding: 0,
marginLeft: '0.3em',
marginRight: '0.3em',
transition: `all ${Duration.HOVER_CHANGE} ease-in`,
},
toolbarProfileNavButtonDisabled: {
opacity: 0.5,
':hover': {
opacity: 0.5,
},
},
toolbarTab: {
background: Colors.DARK_GRAY,
marginTop: Sizes.SEPARATOR_HEIGHT,
+16 -6
View File
@@ -1,13 +1,18 @@
import {memoizeByShallowEquality} from '../lib/utils'
import {Profile, Frame} from '../lib/profile'
import {Flamechart} from '../lib/flamechart'
import {createMemoizedFlamechartRenderer} from './flamechart-view-container'
import {createContainer} from '../lib/typed-redux'
import {
createMemoizedFlamechartRenderer,
FlamechartViewContainerProps,
createFlamechartSetters,
} from './flamechart-view-container'
import {createContainer, Dispatch} from '../lib/typed-redux'
import {ApplicationState} from '../store'
import {
getCanvasContext,
createGetColorBucketForFrame,
createGetCSSColorForFrame,
getFrameToColorBucket,
} from '../store/getters'
import {FlamechartID} from '../store/flamechart-view-state'
import {FlamechartWrapper} from './flamechart-wrapper'
@@ -43,14 +48,17 @@ const getCalleeFlamegraphRenderer = createMemoizedFlamechartRenderer()
export const CalleeFlamegraphView = createContainer(
FlamechartWrapper,
(state: ApplicationState) => {
const {profile, flattenRecursion, glCanvas, frameToColorBucket, sandwichView} = state
(state: ApplicationState, dispatch: Dispatch, ownProps: FlamechartViewContainerProps) => {
const {activeProfileState} = ownProps
const {index, profile, sandwichViewState} = activeProfileState
const {flattenRecursion, glCanvas} = state
if (!profile) throw new Error('profile missing')
if (!glCanvas) throw new Error('glCanvas missing')
const {callerCallee} = sandwichView
const {callerCallee} = sandwichViewState
if (!callerCallee) throw new Error('callerCallee missing')
const {selectedFrame} = callerCallee
const frameToColorBucket = getFrameToColorBucket(profile)
const getColorBucketForFrame = createGetColorBucketForFrame(frameToColorBucket)
const getCSSColorForFrame = createGetCSSColorForFrame(frameToColorBucket)
const canvasContext = getCanvasContext(glCanvas)
@@ -62,12 +70,14 @@ export const CalleeFlamegraphView = createContainer(
const flamechartRenderer = getCalleeFlamegraphRenderer({canvasContext, flamechart})
return {
id: FlamechartID.SANDWICH_CALLEES,
renderInverted: false,
flamechart,
flamechartRenderer,
canvasContext,
getCSSColorForFrame,
...createFlamechartSetters(dispatch, FlamechartID.SANDWICH_CALLEES, index),
// This overrides the setSelectedNode specified in createFlamechartSettesr
setSelectedNode: () => {},
...callerCallee.calleeFlamegraph,
}
},
-2
View File
@@ -8,7 +8,6 @@ import {cachedMeasureTextWidth, ELLIPSIS, trimTextMid} from '../lib/text-utils'
import {style} from './flamechart-style'
import {h, Component} from 'preact'
import {css} from 'aphrodite'
import {FlamechartID} from '../store/flamechart-view-state'
interface FlamechartFrameLabel {
configSpaceBounds: Rect
@@ -34,7 +33,6 @@ interface FlamechartFrameLabel {
* canvas primitives.
*/
export interface FlamechartPanZoomViewProps {
id: FlamechartID
flamechart: Flamechart
canvasContext: CanvasContext
flamechartRenderer: FlamechartRenderer
+117 -57
View File
@@ -2,8 +2,8 @@ import {FlamechartID, FlamechartViewState} from '../store/flamechart-view-state'
import {CanvasContext} from '../gl/canvas-context'
import {Flamechart} from '../lib/flamechart'
import {FlamechartRenderer, FlamechartRendererOptions} from '../gl/flamechart-renderer'
import {Dispatch, createContainer, WithoutDispatch} from '../lib/typed-redux'
import {Frame, Profile} from '../lib/profile'
import {Dispatch, createContainer, ActionCreator} from '../lib/typed-redux'
import {Frame, Profile, CallTreeNode} from '../lib/profile'
import {memoizeByShallowEquality} from '../lib/utils'
import {ApplicationState} from '../store'
import {FlamechartView} from './flamechart-view'
@@ -12,17 +12,70 @@ import {
createGetColorBucketForFrame,
getCanvasContext,
createGetCSSColorForFrame,
getFrameToColorBucket,
} from '../store/getters'
import {ActiveProfileState} from './application'
import {Vec2, Rect} from '../lib/math'
import {actions} from '../store/actions'
interface FlamechartSetters {
setLogicalSpaceViewportSize: (logicalSpaceViewportSize: Vec2) => void
setConfigSpaceViewportRect: (configSpaceViewportRect: Rect) => void
setNodeHover: (hover: {node: CallTreeNode; event: MouseEvent} | null) => void
setSelectedNode: (node: CallTreeNode | null) => void
}
interface WithFlamechartContext<T> {
profileIndex: number
args: {
id: FlamechartID
} & T
}
export function createFlamechartSetters(
dispatch: Dispatch,
id: FlamechartID,
profileIndex: number,
): FlamechartSetters {
function wrapActionCreator<T, U>(
actionCreator: ActionCreator<WithFlamechartContext<U>>,
map: (t: T) => U,
): (t: T) => void {
return (t: T) => {
const args = Object.assign({}, map(t), {id})
dispatch(actionCreator({profileIndex, args}))
}
}
const {
setHoveredNode,
setLogicalSpaceViewportSize,
setConfigSpaceViewportRect,
setSelectedNode,
} = actions.flamechart
return {
setNodeHover: wrapActionCreator(setHoveredNode, hover => ({hover})),
setLogicalSpaceViewportSize: wrapActionCreator(
setLogicalSpaceViewportSize,
logicalSpaceViewportSize => ({logicalSpaceViewportSize}),
),
setConfigSpaceViewportRect: wrapActionCreator(
setConfigSpaceViewportRect,
configSpaceViewportRect => ({configSpaceViewportRect}),
),
setSelectedNode: wrapActionCreator(setSelectedNode, selectedNode => ({selectedNode})),
}
}
export type FlamechartViewProps = {
id: FlamechartID
canvasContext: CanvasContext
flamechart: Flamechart
flamechartRenderer: FlamechartRenderer
renderInverted: boolean
dispatch: Dispatch
getCSSColorForFrame: (frame: Frame) => string
} & FlamechartViewState
} & FlamechartSetters &
FlamechartViewState
export const getChronoViewFlamechart = memoizeByShallowEquality(
({
@@ -56,35 +109,39 @@ export const createMemoizedFlamechartRenderer = (options?: FlamechartRendererOpt
const getChronoViewFlamechartRenderer = createMemoizedFlamechartRenderer()
export const ChronoFlamechartView = createContainer<
{profile: Profile; glCanvas: HTMLCanvasElement},
ApplicationState,
WithoutDispatch<FlamechartViewProps>,
FlamechartView
>(FlamechartView, (state, ownProps) => {
const {profile, glCanvas} = ownProps
const {frameToColorBucket, chronoView} = state
export interface FlamechartViewContainerProps {
activeProfileState: ActiveProfileState
glCanvas: HTMLCanvasElement
}
const canvasContext = getCanvasContext(glCanvas)
const getColorBucketForFrame = createGetColorBucketForFrame(frameToColorBucket)
const getCSSColorForFrame = createGetCSSColorForFrame(frameToColorBucket)
export const ChronoFlamechartView = createContainer(
FlamechartView,
(state: ApplicationState, dispatch: Dispatch, ownProps: FlamechartViewContainerProps) => {
const {activeProfileState, glCanvas} = ownProps
const {index, profile, chronoViewState} = activeProfileState
const flamechart = getChronoViewFlamechart({profile, getColorBucketForFrame})
const flamechartRenderer = getChronoViewFlamechartRenderer({
canvasContext,
flamechart,
})
const canvasContext = getCanvasContext(glCanvas)
const frameToColorBucket = getFrameToColorBucket(profile)
const getColorBucketForFrame = createGetColorBucketForFrame(frameToColorBucket)
const getCSSColorForFrame = createGetCSSColorForFrame(frameToColorBucket)
return {
id: FlamechartID.CHRONO,
renderInverted: false,
flamechart,
flamechartRenderer,
canvasContext,
getCSSColorForFrame,
...chronoView,
}
})
const flamechart = getChronoViewFlamechart({profile, getColorBucketForFrame})
const flamechartRenderer = getChronoViewFlamechartRenderer({
canvasContext,
flamechart,
})
return {
renderInverted: false,
flamechart,
flamechartRenderer,
canvasContext,
getCSSColorForFrame,
...createFlamechartSetters(dispatch, FlamechartID.CHRONO, index),
...chronoViewState,
}
},
)
export const getLeftHeavyFlamechart = memoizeByShallowEquality(
({
@@ -105,32 +162,35 @@ export const getLeftHeavyFlamechart = memoizeByShallowEquality(
const getLeftHeavyFlamechartRenderer = createMemoizedFlamechartRenderer()
export const LeftHeavyFlamechartView = createContainer<
{profile: Profile; glCanvas: HTMLCanvasElement},
ApplicationState,
WithoutDispatch<FlamechartViewProps>,
FlamechartView
>(FlamechartView, (state, ownProps) => {
const {profile, glCanvas} = ownProps
const {frameToColorBucket, leftHeavyView} = state
export const LeftHeavyFlamechartView = createContainer(
FlamechartView,
(state: ApplicationState, dispatch: Dispatch, ownProps: FlamechartViewContainerProps) => {
const {activeProfileState, glCanvas} = ownProps
const canvasContext = getCanvasContext(glCanvas)
const getColorBucketForFrame = createGetColorBucketForFrame(frameToColorBucket)
const getCSSColorForFrame = createGetCSSColorForFrame(frameToColorBucket)
const {index, profile, leftHeavyViewState} = activeProfileState
const flamechart = getLeftHeavyFlamechart({profile, getColorBucketForFrame})
const flamechartRenderer = getLeftHeavyFlamechartRenderer({
canvasContext,
flamechart,
})
const canvasContext = getCanvasContext(glCanvas)
const frameToColorBucket = getFrameToColorBucket(profile)
const getColorBucketForFrame = createGetColorBucketForFrame(frameToColorBucket)
const getCSSColorForFrame = createGetCSSColorForFrame(frameToColorBucket)
return {
id: FlamechartID.LEFT_HEAVY,
renderInverted: false,
flamechart,
flamechartRenderer,
canvasContext,
getCSSColorForFrame,
...leftHeavyView,
}
})
const flamechart = getLeftHeavyFlamechart({
profile,
getColorBucketForFrame,
})
const flamechartRenderer = getLeftHeavyFlamechartRenderer({
canvasContext,
flamechart,
})
return {
renderInverted: false,
flamechart,
flamechartRenderer,
canvasContext,
getCSSColorForFrame,
...createFlamechartSetters(dispatch, FlamechartID.LEFT_HEAVY, index),
...leftHeavyViewState,
}
},
)
+5 -19
View File
@@ -12,7 +12,6 @@ import {Sizes, commonStyle} from './style'
import {FlamechartDetailView} from './flamechart-detail-view'
import {FlamechartPanZoomView} from './flamechart-pan-zoom-view'
import {Hovertip} from './hovertip'
import {actions} from '../store/actions'
import {FlamechartViewProps} from './flamechart-view-container'
import {StatelessComponent} from '../lib/typed-redux'
@@ -41,18 +40,11 @@ export class FlamechartView extends StatelessComponent<FlamechartViewProps> {
),
)
this.props.dispatch(
actions.flamechart.setConfigSpaceViewportRect({
id: this.props.id,
configSpaceViewportRect: new Rect(origin, viewportRect.size.withX(width)),
}),
)
this.props.setConfigSpaceViewportRect(new Rect(origin, viewportRect.size.withX(width)))
}
private setLogicalSpaceViewportSize = (logicalSpaceViewportSize: Vec2): void => {
this.props.dispatch(
actions.flamechart.setLogicalSpaceViewportSize({id: this.props.id, logicalSpaceViewportSize}),
)
this.props.setLogicalSpaceViewportSize(logicalSpaceViewportSize)
}
private transformViewport = (transform: AffineTransform): void => {
@@ -60,17 +52,12 @@ export class FlamechartView extends StatelessComponent<FlamechartViewProps> {
this.setConfigSpaceViewportRect(viewportRect)
}
onNodeHover = (hover: {node: CallTreeNode; event: MouseEvent} | null) => {
this.props.dispatch(
actions.flamechart.setHoveredNode({
id: this.props.id,
hover,
}),
)
private onNodeHover = (hover: {node: CallTreeNode; event: MouseEvent} | null) => {
this.props.setNodeHover(hover)
}
onNodeClick = (node: CallTreeNode | null) => {
this.props.dispatch(actions.flamechart.setSelectedNode({id: this.props.id, selectedNode: node}))
this.props.setSelectedNode(node)
}
formatValue(weight: number) {
@@ -116,7 +103,6 @@ export class FlamechartView extends StatelessComponent<FlamechartViewProps> {
/>
<FlamechartPanZoomView
canvasContext={this.props.canvasContext}
id={this.props.id}
flamechart={this.props.flamechart}
flamechartRenderer={this.props.flamechartRenderer}
renderInverted={false}
+3 -12
View File
@@ -6,7 +6,6 @@ import {Rect, AffineTransform, Vec2} from '../lib/math'
import {FlamechartPanZoomView} from './flamechart-pan-zoom-view'
import {noop, formatPercent} from '../lib/utils'
import {Hovertip} from './hovertip'
import {actions} from '../store/actions'
import {FlamechartViewProps} from './flamechart-view-container'
import {StatelessComponent} from '../lib/typed-redux'
@@ -24,17 +23,10 @@ export class FlamechartWrapper extends StatelessComponent<FlamechartViewProps> {
return new Rect(origin, viewportRect.size.withX(width))
}
private setConfigSpaceViewportRect = (configSpaceViewportRect: Rect) => {
this.props.dispatch(
actions.flamechart.setConfigSpaceViewportRect({
id: this.props.id,
configSpaceViewportRect: this.clampViewportToFlamegraph(configSpaceViewportRect),
}),
)
this.props.setConfigSpaceViewportRect(this.clampViewportToFlamegraph(configSpaceViewportRect))
}
private setLogicalSpaceViewportSize = (logicalSpaceViewportSize: Vec2): void => {
this.props.dispatch(
actions.flamechart.setLogicalSpaceViewportSize({id: this.props.id, logicalSpaceViewportSize}),
)
this.props.setLogicalSpaceViewportSize(logicalSpaceViewportSize)
}
private transformViewport = (transform: AffineTransform) => {
@@ -71,7 +63,7 @@ export class FlamechartWrapper extends StatelessComponent<FlamechartViewProps> {
event: MouseEvent
} | null,
) => {
this.props.dispatch(actions.flamechart.setHoveredNode({id: this.props.id, hover}))
this.props.setNodeHover(hover)
}
render() {
return (
@@ -80,7 +72,6 @@ export class FlamechartWrapper extends StatelessComponent<FlamechartViewProps> {
ref={this.containerRef}
>
<FlamechartPanZoomView
id={this.props.id}
selectedNode={null}
onNodeHover={this.setNodeHover}
onNodeSelect={noop}
+16 -6
View File
@@ -1,14 +1,19 @@
import {memoizeByShallowEquality} from '../lib/utils'
import {Profile, Frame} from '../lib/profile'
import {Flamechart} from '../lib/flamechart'
import {createMemoizedFlamechartRenderer} from './flamechart-view-container'
import {createContainer} from '../lib/typed-redux'
import {
createMemoizedFlamechartRenderer,
FlamechartViewContainerProps,
createFlamechartSetters,
} from './flamechart-view-container'
import {createContainer, Dispatch} from '../lib/typed-redux'
import {ApplicationState} from '../store'
import {
getCanvasContext,
createGetColorBucketForFrame,
createGetCSSColorForFrame,
getProfileWithRecursionFlattened,
getFrameToColorBucket,
} from '../store/getters'
import {FlamechartID} from '../store/flamechart-view-state'
import {FlamechartWrapper} from './flamechart-wrapper'
@@ -49,16 +54,19 @@ const getInvertedCallerFlamegraphRenderer = createMemoizedFlamechartRenderer({in
export const InvertedCallerFlamegraphView = createContainer(
FlamechartWrapper,
(state: ApplicationState) => {
let {profile, flattenRecursion, glCanvas, frameToColorBucket, sandwichView} = state
(state: ApplicationState, dispatch: Dispatch, ownProps: FlamechartViewContainerProps) => {
const {activeProfileState} = ownProps
let {profile, sandwichViewState, index} = activeProfileState
let {flattenRecursion, glCanvas} = state
if (!profile) throw new Error('profile missing')
if (!glCanvas) throw new Error('glCanvas missing')
const {callerCallee} = sandwichView
const {callerCallee} = sandwichViewState
if (!callerCallee) throw new Error('callerCallee missing')
const {selectedFrame} = callerCallee
profile = flattenRecursion ? getProfileWithRecursionFlattened(profile) : profile
const frameToColorBucket = getFrameToColorBucket(profile)
const getColorBucketForFrame = createGetColorBucketForFrame(frameToColorBucket)
const getCSSColorForFrame = createGetCSSColorForFrame(frameToColorBucket)
const canvasContext = getCanvasContext(glCanvas)
@@ -74,12 +82,14 @@ export const InvertedCallerFlamegraphView = createContainer(
const flamechartRenderer = getInvertedCallerFlamegraphRenderer({canvasContext, flamechart})
return {
id: FlamechartID.SANDWICH_INVERTED_CALLERS,
renderInverted: true,
flamechart,
flamechartRenderer,
canvasContext,
getCSSColorForFrame,
...createFlamechartSetters(dispatch, FlamechartID.SANDWICH_INVERTED_CALLERS, index),
// This overrides the setSelectedNode specified in createFlamechartSettesr
setSelectedNode: () => {},
...callerCallee.invertedCallerFlamegraph,
}
},
+31 -18
View File
@@ -8,7 +8,8 @@ import {ScrollableListView, ListItem} from './scrollable-list-view'
import {actions} from '../store/actions'
import {Dispatch, createContainer} from '../lib/typed-redux'
import {ApplicationState} from '../store'
import {createGetCSSColorForFrame} from '../store/getters'
import {createGetCSSColorForFrame, getFrameToColorBucket} from '../store/getters'
import {ActiveProfileState} from './application'
export enum SortField {
SYMBOL_NAME,
@@ -68,21 +69,15 @@ class SortIcon extends Component<SortIconProps, {}> {
interface ProfileTableViewProps {
profile: Profile
profileIndex: number
selectedFrame: Frame | null
getCSSColorForFrame: (frame: Frame) => string
sortMethod: SortMethod
dispatch: Dispatch
setSelectedFrame: (frame: Frame | null) => void
setSortMethod: (sortMethod: SortMethod) => void
}
export class ProfileTableView extends Component<ProfileTableViewProps, void> {
setSelectedFrame = (frame: Frame | null) => {
this.props.dispatch(actions.sandwichView.setSelectedFrame(frame))
}
setSortMethod = (method: SortMethod) => {
this.props.dispatch(actions.sandwichView.setTableSortMethod(method))
}
renderRow(frame: Frame, index: number) {
const {profile, selectedFrame} = this.props
@@ -98,7 +93,7 @@ export class ProfileTableView extends Component<ProfileTableViewProps, void> {
return (
<tr
key={`${index}`}
onClick={this.setSelectedFrame.bind(null, frame)}
onClick={this.props.setSelectedFrame.bind(null, frame)}
className={css(
style.tableRow,
index % 2 == 0 && style.tableRowEven,
@@ -128,7 +123,7 @@ export class ProfileTableView extends Component<ProfileTableViewProps, void> {
if (sortMethod.field == field) {
// Toggle
this.setSortMethod({
this.props.setSortMethod({
field,
direction:
sortMethod.direction === SortDirection.ASCENDING
@@ -139,15 +134,15 @@ export class ProfileTableView extends Component<ProfileTableViewProps, void> {
// Set a sane default
switch (field) {
case SortField.SYMBOL_NAME: {
this.setSortMethod({field, direction: SortDirection.ASCENDING})
this.props.setSortMethod({field, direction: SortDirection.ASCENDING})
break
}
case SortField.SELF: {
this.setSortMethod({field, direction: SortDirection.DESCENDING})
this.props.setSortMethod({field, direction: SortDirection.DESCENDING})
break
}
case SortField.TOTAL: {
this.setSortMethod({field, direction: SortDirection.DESCENDING})
this.props.setSortMethod({field, direction: SortDirection.DESCENDING})
break
}
}
@@ -334,20 +329,38 @@ const style = StyleSheet.create({
},
})
interface ProfileTableViewContainerProps {
activeProfileState: ActiveProfileState
}
export const ProfileTableViewContainer = createContainer(
ProfileTableView,
(state: ApplicationState) => {
const {profile, sandwichView, frameToColorBucket} = state
(state: ApplicationState, dispatch: Dispatch, ownProps: ProfileTableViewContainerProps) => {
const {activeProfileState} = ownProps
const {profile, sandwichViewState, index} = activeProfileState
if (!profile) throw new Error('profile missing')
const {tableSortMethod, callerCallee} = sandwichView
const {tableSortMethod} = state
const {callerCallee} = sandwichViewState
const selectedFrame = callerCallee ? callerCallee.selectedFrame : null
const frameToColorBucket = getFrameToColorBucket(profile)
const getCSSColorForFrame = createGetCSSColorForFrame(frameToColorBucket)
const setSelectedFrame = (selectedFrame: Frame | null) => {
dispatch(actions.sandwichView.setSelectedFrame({profileIndex: index, args: selectedFrame}))
}
const setSortMethod = (sortMethod: SortMethod) => {
dispatch(actions.sandwichView.setTableSortMethod(sortMethod))
}
return {
profile,
profileIndex: activeProfileState.index,
selectedFrame,
getCSSColorForFrame,
sortMethod: tableSortMethod,
setSelectedFrame,
setSortMethod,
}
},
)
+45 -9
View File
@@ -8,15 +8,19 @@ import {createContainer, Dispatch, StatelessComponent} from '../lib/typed-redux'
import {ApplicationState} from '../store'
import {InvertedCallerFlamegraphView} from './inverted-caller-flamegraph-view'
import {CalleeFlamegraphView} from './callee-flamegraph-view'
import {ActiveProfileState} from './application'
interface SandwichViewProps {
selectedFrame: Frame | null
dispatch: Dispatch
profileIndex: number
activeProfileState: ActiveProfileState
setSelectedFrame: (selectedFrame: Frame | null) => void
glCanvas: HTMLCanvasElement
}
class SandwichView extends StatelessComponent<SandwichViewProps> {
private setSelectedFrame = (selectedFrame: Frame | null) => {
this.props.dispatch(actions.sandwichView.setSelectedFrame(selectedFrame))
this.props.setSelectedFrame(selectedFrame)
}
onWindowKeyPress = (ev: KeyboardEvent) => {
@@ -43,14 +47,20 @@ class SandwichView extends StatelessComponent<SandwichViewProps> {
<div className={css(style.flamechartLabelParent)}>
<div className={css(style.flamechartLabel)}>Callers</div>
</div>
<InvertedCallerFlamegraphView />
<InvertedCallerFlamegraphView
glCanvas={this.props.glCanvas}
activeProfileState={this.props.activeProfileState}
/>
</div>
<div className={css(style.divider)} />
<div className={css(commonStyle.hbox, style.panZoomViewWraper)}>
<div className={css(style.flamechartLabelParent, style.flamechartLabelParentBottom)}>
<div className={css(style.flamechartLabel, style.flamechartLabelBottom)}>Callees</div>
</div>
<CalleeFlamegraphView />
<CalleeFlamegraphView
glCanvas={this.props.glCanvas}
activeProfileState={this.props.activeProfileState}
/>
</div>
</div>
)
@@ -59,7 +69,7 @@ class SandwichView extends StatelessComponent<SandwichViewProps> {
return (
<div className={css(commonStyle.hbox, commonStyle.fillY)}>
<div className={css(style.tableView)}>
<ProfileTableViewContainer />
<ProfileTableViewContainer activeProfileState={this.props.activeProfileState} />
</div>
{flamegraphViews}
</div>
@@ -107,7 +117,33 @@ const style = StyleSheet.create({
},
})
export const SandwichViewContainer = createContainer(SandwichView, (state: ApplicationState) => {
const {callerCallee} = state.sandwichView
return {selectedFrame: callerCallee ? callerCallee.selectedFrame : null}
})
interface SandwichViewContainerProps {
activeProfileState: ActiveProfileState
glCanvas: HTMLCanvasElement
}
export const SandwichViewContainer = createContainer(
SandwichView,
(state: ApplicationState, dispatch: Dispatch, ownProps: SandwichViewContainerProps) => {
const {activeProfileState, glCanvas} = ownProps
const {sandwichViewState, index} = activeProfileState
const {callerCallee} = sandwichViewState
const setSelectedFrame = (selectedFrame: Frame | null) => {
dispatch(
actions.sandwichView.setSelectedFrame({
profileIndex: index,
args: selectedFrame,
}),
)
}
return {
activeProfileState: activeProfileState,
glCanvas,
setSelectedFrame,
selectedFrame: callerCallee ? callerCallee.selectedFrame : null,
profileIndex: index,
}
},
)