Compare commits

...
5 Commits
Author SHA1 Message Date
Jamie Wong 81a6f29ad1 1.15.0 2022-10-22 00:18:24 +08:00
Jamie Wong 263f7d513e Update package.json to use upstream version of uint8array-json-parser (#408)
In #385, I introduced a dependency on the `uint8array-json-parser` npm package, but used a fork because of a typescript error. This was resolved in evanw/uint8array-json-parser#1 and published as part of `uint8array-json-parser@0.0.2`. Let's use the upstream.

This also conveniently fixes a new typechecking error that was preventing deployment. The error looked like this:

```
src/import/utils.ts(2,26): error TS2306: File '\''/Users/jlfwong/code/speedscope/node_modules/uint8array-json-parser/uint8array-json-parser.ts'\'' is not a module.'
```

After updating to the upstream, the problem is fixed.
2022-10-22 00:12:45 +08:00
Jamie Wong 1bce806933 Replace fuzzy matching with exact substring matching for finding matching frames (#407)
In #297, I re-used the fuzzy matching logic I implemented in #282 for profile selection. Based on feedback from several people in #352, this is surprising behavior.

Upon reflection, this should have been obvious -- I hijacked the Ctrl/Cmd+F browser behaviour, so I should try to replicate the expected behaviour there as closely as possible. Given more patience, I also would've done some user research :)

This PR updates this logic to try to more closely match browser behaviour. This means case-insensitive, exact-substring matching.

I've left the fuzzy matching alone for profile selection since that doesn't attempt to mimic browser behaviour.

The non-fuzzy matching feels slightly odd to me given the filtering behaviour on the sandwich view, but I think consistency across this find UI is important.

Here are the before & after results when searching for the string "ca" in the example profile.

|Before|After|
|-|-|
|<img width="1791" alt="image" src="https://user-images.githubusercontent.com/150329/197232741-6d1d7a8a-8b8c-4a4f-98e3-2c043fd7efd5.png">|<img width="1789" alt="image" src="https://user-images.githubusercontent.com/150329/197232694-82697b68-ca15-49e7-887b-2606646ee5e9.png">|

Fixes #352 
Supersedes #403
2022-10-21 23:53:46 +08:00
Jamie Wong 6493c5f66f Update deploy script to python3 2022-07-30 23:20:36 -07:00
Evan Wallace 639dae322b Add support for cycle-based Instruments deep copy (#400)
Unlike the Time Profiler, the CPU Profiler in Instruments use `cycles` for units instead of `ms`:

<img width="872" src="https://user-images.githubusercontent.com/406394/175755999-289cb7c0-f29a-44b1-b00e-b55ef17ee303.png">

Currently Speedscope fails to import the data with the following error in the console:

```
Failed to load format Error: Unrecognized units Gc
```

This PR adds support for `cycles` as a unit to the Instruments deep copy importer as well as `Kc`, `Mc`, and `Gc`, which I'm assuming are increasing in multiples of 1000. Hopefully I've added support for this correctly and this PR is helpful.
2022-07-02 22:01:08 -04:00
13 changed files with 490 additions and 24 deletions
+6
View File
@@ -1,3 +1,9 @@
## [1.15.0] - 2022-10-22
### Fixed
- Replace fuzzy matching with exact substring matching for finding matching frames [[#407](https://github.com/jlfwong/speedscope/pull/407)]
## [1.14.0] - 2022-05-19
### Added
+13 -10
View File
@@ -1,11 +1,12 @@
{
"name": "speedscope",
"version": "1.13.0",
"version": "1.15.0",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"version": "1.13.0",
"name": "speedscope",
"version": "1.15.0",
"license": "MIT",
"dependencies": {
"open": "7.2.0"
@@ -38,7 +39,7 @@
"typescript": "4.2.3",
"typescript-json-schema": "0.42.0",
"uglify-es": "3.2.2",
"uint8array-json-parser": "jlfwong/uint8array-json-parser#edce51ce"
"uint8array-json-parser": "0.0.2"
}
},
"node_modules/@babel/code-frame": {
@@ -5843,6 +5844,7 @@
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.11.tgz",
"integrity": "sha512-+ux3lx6peh0BpvY0JebGyZoiR4D+oYzdPZMKJwkZ+sFkNJzpL7tXc/wehS49gUAxg3tmMHPHZkA8JU2rhhgDHw==",
"dev": true,
"hasInstallScript": true,
"optional": true,
"os": [
"darwin"
@@ -14095,10 +14097,10 @@
}
},
"node_modules/uint8array-json-parser": {
"version": "0.0.1",
"resolved": "git+ssh://git@github.com/jlfwong/uint8array-json-parser.git#b4eb100aa3107b5829980171e1dee7d8bf35afe2",
"dev": true,
"license": "MIT"
"version": "0.0.2",
"resolved": "https://registry.npmjs.org/uint8array-json-parser/-/uint8array-json-parser-0.0.2.tgz",
"integrity": "sha512-Cp5ycrI17rzdAkybRfZydr6XdLmOUfhm2jS1i35p3UY2G8TcT7fL+hmFY3zjMGNtoS8uSpdTS7NjiHh+LY/7Bg==",
"dev": true
},
"node_modules/uncss": {
"version": "0.17.3",
@@ -26921,9 +26923,10 @@
}
},
"uint8array-json-parser": {
"version": "git+ssh://git@github.com/jlfwong/uint8array-json-parser.git#b4eb100aa3107b5829980171e1dee7d8bf35afe2",
"dev": true,
"from": "uint8array-json-parser@jlfwong/uint8array-json-parser#edce51ce"
"version": "0.0.2",
"resolved": "https://registry.npmjs.org/uint8array-json-parser/-/uint8array-json-parser-0.0.2.tgz",
"integrity": "sha512-Cp5ycrI17rzdAkybRfZydr6XdLmOUfhm2jS1i35p3UY2G8TcT7fL+hmFY3zjMGNtoS8uSpdTS7NjiHh+LY/7Bg==",
"dev": true
},
"uncss": {
"version": "0.17.3",
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "speedscope",
"version": "1.14.0",
"version": "1.15.0",
"description": "",
"repository": "jlfwong/speedscope",
"main": "index.js",
@@ -54,7 +54,7 @@
"typescript": "4.2.3",
"typescript-json-schema": "0.42.0",
"uglify-es": "3.2.2",
"uint8array-json-parser": "jlfwong/uint8array-json-parser#edce51ce"
"uint8array-json-parser": "0.0.2"
},
"jest": {
"transform": {
@@ -0,0 +1,46 @@
Weight Self Weight Symbol Name
96.08 Gc 100.0% - example_app (40414)
96.08 Gc 100.0% - start
96.08 Gc 100.0% - main
96.08 Gc 100.0% - std::rt::lang_start::hdba6f1ebfd1bdcf8
96.08 Gc 100.0% - std::rt::lang_start_internal::hc453db0ee48af82e
96.08 Gc 100.0% - std::rt::lang_start::_$u7b$$u7b$closure$u7d$$u7d$::hd856f2663871206c
96.08 Gc 100.0% - std::sys_common::backtrace::__rust_begin_short_backtrace::h4869fd82068bc1dc
96.08 Gc 100.0% - core::ops::function::FnOnce::call_once::h06e0c27ee740c6a8
96.08 Gc 100.0% - example_app::main::hddab13ae8d8b6a6e
47.82 Gc 49.7% - example_app::example_a::h622d6879b734496d
46.92 Gc 48.8% 404.75 Mc std::time::Instant::elapsed::h2e3793148fc23529
45.92 Gc 47.7% 45.92 Gc mach_absolute_time
600.78 Mc 0.6% 600.78 Mc std::time::Instant::elapsed::h2e3793148fc23529
1.00 Mc 0.0% 1.00 Mc DYLD-STUB$$mach_absolute_time
634.35 Mc 0.6% 634.35 Mc core::time::Duration::as_millis::hae6ad1b9cf7bb5ec
181.50 Mc 0.1% 181.50 Mc example_app::example_a::h622d6879b734496d
84.45 Mc 0.0% - example_app::example_b::h71b31fcd89b9ffd2
81.45 Mc 0.0% - std::time::Instant::elapsed::h2e3793148fc23529
80.45 Mc 0.0% 80.45 Mc mach_absolute_time
1.00 Mc 0.0% 1.00 Mc std::time::Instant::elapsed::h2e3793148fc23529
1.00 Mc 0.0% - example_app::example_c::h631759c10d7dee93
1.00 Mc 0.0% - alloc::vec::Vec$LT$T$C$A$GT$::push::ha3426502ffc42c8b
1.00 Mc 0.0% - alloc::raw_vec::RawVec$LT$T$C$A$GT$::reserve_for_push::he4a29b8274e35dbb
1.00 Mc 0.0% - alloc::raw_vec::RawVec$LT$T$C$A$GT$::grow_amortized::h78db9ba423623c58
1.00 Mc 0.0% - alloc::raw_vec::finish_grow::h876f5af1c66d74c8
1.00 Mc 0.0% - _$LT$alloc..alloc..Global$u20$as$u20$core..alloc..Allocator$GT$::allocate::hcc733a40a34fbc94
1.00 Mc 0.0% - alloc::alloc::Global::alloc_impl::hc55feba7d6266dfa
1.00 Mc 0.0% - alloc::alloc::alloc::hfac63f3d6850b759
1.00 Mc 0.0% - _malloc_zone_malloc
1.00 Mc 0.0% - nanov2_malloc
1.00 Mc 0.0% - nanov2_allocate
1.00 Mc 0.0% - nanov2_allocate
1.00 Mc 0.0% 1.00 Mc nanov2_find_block_and_allocate
1.00 Mc 0.0% 1.00 Mc example_app::example_b::h71b31fcd89b9ffd2
1.00 Mc 0.0% 1.00 Mc core::time::Duration::as_millis::hae6ad1b9cf7bb5ec
47.45 Gc 49.3% 415.12 Mc std::time::Instant::elapsed::h2e3793148fc23529
46.39 Gc 48.2% 46.39 Gc mach_absolute_time
649.70 Mc 0.6% 649.70 Mc std::time::Instant::elapsed::h2e3793148fc23529
614.22 Mc 0.6% 614.22 Mc core::time::Duration::as_millis::hae6ad1b9cf7bb5ec
190.55 Mc 0.1% 190.55 Mc example_app::main::hddab13ae8d8b6a6e
1.34 Kc 0.0% - std::io::stdio::_print::hdecfefdeb43586ed
1.34 Kc 0.0% - _$LT$$RF$std..io..stdio..Stdout$u20$as$u20$std..io..Write$GT$::write_fmt::h2cb06dcd2b172844
1.34 Kc 0.0% - core::fmt::write::hed96bcfc6342aee5
532 cycles 0.0% - _$LT$std..io..Write..write_fmt..Adapter$LT$T$GT$$u20$as$u20$core..fmt..Write$GT$::write_str::hbe33ec23de24ce2f
532 cycles 0.0% 532 cycles _$LT$std..io..stdio..StdoutLock$u20$as$u20$std..io..Write$GT$::write_all::h22667d0a03b2151b
+1 -1
View File
@@ -58,5 +58,5 @@ echo "Build complete. Starting server on http://localhost:4444/"
echo "Hit Ctrl+C to complete or cancel the release"
echo
echo
python -m SimpleHTTPServer 4444 .
python3 -m http.server 4444
set +x
@@ -99,10 +99,332 @@ Object {
}
`;
exports[`importFromInstrumentsDeepCopy allocations profile 2`] = `
Object {
"frames": Array [
Frame {
"col": undefined,
"file": undefined,
"key": ":example_app (40414)",
"line": undefined,
"name": "example_app (40414)",
"selfWeight": 0,
"totalWeight": 96000000000,
},
Frame {
"col": undefined,
"file": undefined,
"key": ":start",
"line": undefined,
"name": "start",
"selfWeight": 0,
"totalWeight": 96000000000,
},
Frame {
"col": undefined,
"file": undefined,
"key": ":main",
"line": undefined,
"name": "main",
"selfWeight": 0,
"totalWeight": 96000000000,
},
Frame {
"col": undefined,
"file": undefined,
"key": ":std::rt::lang_start::hdba6f1ebfd1bdcf8",
"line": undefined,
"name": "std::rt::lang_start::hdba6f1ebfd1bdcf8",
"selfWeight": 0,
"totalWeight": 96000000000,
},
Frame {
"col": undefined,
"file": undefined,
"key": ":std::rt::lang_start_internal::hc453db0ee48af82e",
"line": undefined,
"name": "std::rt::lang_start_internal::hc453db0ee48af82e",
"selfWeight": 0,
"totalWeight": 96000000000,
},
Frame {
"col": undefined,
"file": undefined,
"key": ":std::rt::lang_start::_$u7b$$u7b$closure$u7d$$u7d$::hd856f2663871206c",
"line": undefined,
"name": "std::rt::lang_start::_$u7b$$u7b$closure$u7d$$u7d$::hd856f2663871206c",
"selfWeight": 0,
"totalWeight": 96000000000,
},
Frame {
"col": undefined,
"file": undefined,
"key": ":std::sys_common::backtrace::__rust_begin_short_backtrace::h4869fd82068bc1dc",
"line": undefined,
"name": "std::sys_common::backtrace::__rust_begin_short_backtrace::h4869fd82068bc1dc",
"selfWeight": 0,
"totalWeight": 96000000000,
},
Frame {
"col": undefined,
"file": undefined,
"key": ":core::ops::function::FnOnce::call_once::h06e0c27ee740c6a8",
"line": undefined,
"name": "core::ops::function::FnOnce::call_once::h06e0c27ee740c6a8",
"selfWeight": 0,
"totalWeight": 96000000000,
},
Frame {
"col": undefined,
"file": undefined,
"key": ":example_app::main::hddab13ae8d8b6a6e",
"line": undefined,
"name": "example_app::main::hddab13ae8d8b6a6e",
"selfWeight": 1385999000,
"totalWeight": 96000000000,
},
Frame {
"col": undefined,
"file": undefined,
"key": ":example_app::example_a::h622d6879b734496d",
"line": undefined,
"name": "example_app::example_a::h622d6879b734496d",
"selfWeight": 282000000,
"totalWeight": 47000000000,
},
Frame {
"col": undefined,
"file": undefined,
"key": ":std::time::Instant::elapsed::h2e3793148fc23529",
"line": undefined,
"name": "std::time::Instant::elapsed::h2e3793148fc23529",
"selfWeight": 2000000000,
"totalWeight": 93081000000,
},
Frame {
"col": undefined,
"file": undefined,
"key": ":mach_absolute_time",
"line": undefined,
"name": "mach_absolute_time",
"selfWeight": 91080000000,
"totalWeight": 91080000000,
},
Frame {
"col": undefined,
"file": undefined,
"key": ":DYLD-STUB$$mach_absolute_time",
"line": undefined,
"name": "DYLD-STUB$$mach_absolute_time",
"selfWeight": 1000000,
"totalWeight": 1000000,
},
Frame {
"col": undefined,
"file": undefined,
"key": ":core::time::Duration::as_millis::hae6ad1b9cf7bb5ec",
"line": undefined,
"name": "core::time::Duration::as_millis::hae6ad1b9cf7bb5ec",
"selfWeight": 1249000000,
"totalWeight": 1249000000,
},
Frame {
"col": undefined,
"file": undefined,
"key": ":example_app::example_b::h71b31fcd89b9ffd2",
"line": undefined,
"name": "example_app::example_b::h71b31fcd89b9ffd2",
"selfWeight": 1000000,
"totalWeight": 84000000,
},
Frame {
"col": undefined,
"file": undefined,
"key": ":example_app::example_c::h631759c10d7dee93",
"line": undefined,
"name": "example_app::example_c::h631759c10d7dee93",
"selfWeight": 0,
"totalWeight": 1000000,
},
Frame {
"col": undefined,
"file": undefined,
"key": ":alloc::vec::Vec$LT$T$C$A$GT$::push::ha3426502ffc42c8b",
"line": undefined,
"name": "alloc::vec::Vec$LT$T$C$A$GT$::push::ha3426502ffc42c8b",
"selfWeight": 0,
"totalWeight": 1000000,
},
Frame {
"col": undefined,
"file": undefined,
"key": ":alloc::raw_vec::RawVec$LT$T$C$A$GT$::reserve_for_push::he4a29b8274e35dbb",
"line": undefined,
"name": "alloc::raw_vec::RawVec$LT$T$C$A$GT$::reserve_for_push::he4a29b8274e35dbb",
"selfWeight": 0,
"totalWeight": 1000000,
},
Frame {
"col": undefined,
"file": undefined,
"key": ":alloc::raw_vec::RawVec$LT$T$C$A$GT$::grow_amortized::h78db9ba423623c58",
"line": undefined,
"name": "alloc::raw_vec::RawVec$LT$T$C$A$GT$::grow_amortized::h78db9ba423623c58",
"selfWeight": 0,
"totalWeight": 1000000,
},
Frame {
"col": undefined,
"file": undefined,
"key": ":alloc::raw_vec::finish_grow::h876f5af1c66d74c8",
"line": undefined,
"name": "alloc::raw_vec::finish_grow::h876f5af1c66d74c8",
"selfWeight": 0,
"totalWeight": 1000000,
},
Frame {
"col": undefined,
"file": undefined,
"key": ":_$LT$alloc..alloc..Global$u20$as$u20$core..alloc..Allocator$GT$::allocate::hcc733a40a34fbc94",
"line": undefined,
"name": "_$LT$alloc..alloc..Global$u20$as$u20$core..alloc..Allocator$GT$::allocate::hcc733a40a34fbc94",
"selfWeight": 0,
"totalWeight": 1000000,
},
Frame {
"col": undefined,
"file": undefined,
"key": ":alloc::alloc::Global::alloc_impl::hc55feba7d6266dfa",
"line": undefined,
"name": "alloc::alloc::Global::alloc_impl::hc55feba7d6266dfa",
"selfWeight": 0,
"totalWeight": 1000000,
},
Frame {
"col": undefined,
"file": undefined,
"key": ":alloc::alloc::alloc::hfac63f3d6850b759",
"line": undefined,
"name": "alloc::alloc::alloc::hfac63f3d6850b759",
"selfWeight": 0,
"totalWeight": 1000000,
},
Frame {
"col": undefined,
"file": undefined,
"key": ":_malloc_zone_malloc",
"line": undefined,
"name": "_malloc_zone_malloc",
"selfWeight": 0,
"totalWeight": 1000000,
},
Frame {
"col": undefined,
"file": undefined,
"key": ":nanov2_malloc",
"line": undefined,
"name": "nanov2_malloc",
"selfWeight": 0,
"totalWeight": 1000000,
},
Frame {
"col": undefined,
"file": undefined,
"key": ":nanov2_allocate",
"line": undefined,
"name": "nanov2_allocate",
"selfWeight": 0,
"totalWeight": 1000000,
},
Frame {
"col": undefined,
"file": undefined,
"key": ":nanov2_find_block_and_allocate",
"line": undefined,
"name": "nanov2_find_block_and_allocate",
"selfWeight": 1000000,
"totalWeight": 1000000,
},
Frame {
"col": undefined,
"file": undefined,
"key": ":std::io::stdio::_print::hdecfefdeb43586ed",
"line": undefined,
"name": "std::io::stdio::_print::hdecfefdeb43586ed",
"selfWeight": 0,
"totalWeight": 1000,
},
Frame {
"col": undefined,
"file": undefined,
"key": ":_$LT$$RF$std..io..stdio..Stdout$u20$as$u20$std..io..Write$GT$::write_fmt::h2cb06dcd2b172844",
"line": undefined,
"name": "_$LT$$RF$std..io..stdio..Stdout$u20$as$u20$std..io..Write$GT$::write_fmt::h2cb06dcd2b172844",
"selfWeight": 0,
"totalWeight": 1000,
},
Frame {
"col": undefined,
"file": undefined,
"key": ":core::fmt::write::hed96bcfc6342aee5",
"line": undefined,
"name": "core::fmt::write::hed96bcfc6342aee5",
"selfWeight": 468,
"totalWeight": 1000,
},
Frame {
"col": undefined,
"file": undefined,
"key": ":_$LT$std..io..Write..write_fmt..Adapter$LT$T$GT$$u20$as$u20$core..fmt..Write$GT$::write_str::hbe33ec23de24ce2f",
"line": undefined,
"name": "_$LT$std..io..Write..write_fmt..Adapter$LT$T$GT$$u20$as$u20$core..fmt..Write$GT$::write_str::hbe33ec23de24ce2f",
"selfWeight": 0,
"totalWeight": 532,
},
Frame {
"col": undefined,
"file": undefined,
"key": ":_$LT$std..io..stdio..StdoutLock$u20$as$u20$std..io..Write$GT$::write_all::h22667d0a03b2151b",
"line": undefined,
"name": "_$LT$std..io..stdio..StdoutLock$u20$as$u20$std..io..Write$GT$::write_all::h22667d0a03b2151b",
"selfWeight": 532,
"totalWeight": 532,
},
],
"name": "cycles-example-deep-copy.txt",
"stacks": Array [
"example_app (40414);start;main;std::rt::lang_start::hdba6f1ebfd1bdcf8;std::rt::lang_start_internal::hc453db0ee48af82e;std::rt::lang_start::_$u7b$$u7b$closure$u7d$$u7d$::hd856f2663871206c;std::sys_common::backtrace::__rust_begin_short_backtrace::h4869fd82068bc1dc;core::ops::function::FnOnce::call_once::h06e0c27ee740c6a8;example_app::main::hddab13ae8d8b6a6e;example_app::example_a::h622d6879b734496d;std::time::Instant::elapsed::h2e3793148fc23529;mach_absolute_time 750000:00",
"example_app (40414);start;main;std::rt::lang_start::hdba6f1ebfd1bdcf8;std::rt::lang_start_internal::hc453db0ee48af82e;std::rt::lang_start::_$u7b$$u7b$closure$u7d$$u7d$::hd856f2663871206c;std::sys_common::backtrace::__rust_begin_short_backtrace::h4869fd82068bc1dc;core::ops::function::FnOnce::call_once::h06e0c27ee740c6a8;example_app::main::hddab13ae8d8b6a6e;example_app::example_a::h622d6879b734496d;std::time::Instant::elapsed::h2e3793148fc23529;std::time::Instant::elapsed::h2e3793148fc23529 10000:00",
"example_app (40414);start;main;std::rt::lang_start::hdba6f1ebfd1bdcf8;std::rt::lang_start_internal::hc453db0ee48af82e;std::rt::lang_start::_$u7b$$u7b$closure$u7d$$u7d$::hd856f2663871206c;std::sys_common::backtrace::__rust_begin_short_backtrace::h4869fd82068bc1dc;core::ops::function::FnOnce::call_once::h06e0c27ee740c6a8;example_app::main::hddab13ae8d8b6a6e;example_app::example_a::h622d6879b734496d;std::time::Instant::elapsed::h2e3793148fc23529;DYLD-STUB$$mach_absolute_time 16:40",
"example_app (40414);start;main;std::rt::lang_start::hdba6f1ebfd1bdcf8;std::rt::lang_start_internal::hc453db0ee48af82e;std::rt::lang_start::_$u7b$$u7b$closure$u7d$$u7d$::hd856f2663871206c;std::sys_common::backtrace::__rust_begin_short_backtrace::h4869fd82068bc1dc;core::ops::function::FnOnce::call_once::h06e0c27ee740c6a8;example_app::main::hddab13ae8d8b6a6e;example_app::example_a::h622d6879b734496d;std::time::Instant::elapsed::h2e3793148fc23529 6650:00",
"example_app (40414);start;main;std::rt::lang_start::hdba6f1ebfd1bdcf8;std::rt::lang_start_internal::hc453db0ee48af82e;std::rt::lang_start::_$u7b$$u7b$closure$u7d$$u7d$::hd856f2663871206c;std::sys_common::backtrace::__rust_begin_short_backtrace::h4869fd82068bc1dc;core::ops::function::FnOnce::call_once::h06e0c27ee740c6a8;example_app::main::hddab13ae8d8b6a6e;example_app::example_a::h622d6879b734496d;core::time::Duration::as_millis::hae6ad1b9cf7bb5ec 10566:40",
"example_app (40414);start;main;std::rt::lang_start::hdba6f1ebfd1bdcf8;std::rt::lang_start_internal::hc453db0ee48af82e;std::rt::lang_start::_$u7b$$u7b$closure$u7d$$u7d$::hd856f2663871206c;std::sys_common::backtrace::__rust_begin_short_backtrace::h4869fd82068bc1dc;core::ops::function::FnOnce::call_once::h06e0c27ee740c6a8;example_app::main::hddab13ae8d8b6a6e;example_app::example_a::h622d6879b734496d;example_app::example_a::h622d6879b734496d 3016:40",
"example_app (40414);start;main;std::rt::lang_start::hdba6f1ebfd1bdcf8;std::rt::lang_start_internal::hc453db0ee48af82e;std::rt::lang_start::_$u7b$$u7b$closure$u7d$$u7d$::hd856f2663871206c;std::sys_common::backtrace::__rust_begin_short_backtrace::h4869fd82068bc1dc;core::ops::function::FnOnce::call_once::h06e0c27ee740c6a8;example_app::main::hddab13ae8d8b6a6e;example_app::example_a::h622d6879b734496d;example_app::example_b::h71b31fcd89b9ffd2;std::time::Instant::elapsed::h2e3793148fc23529;mach_absolute_time 1333:20",
"example_app (40414);start;main;std::rt::lang_start::hdba6f1ebfd1bdcf8;std::rt::lang_start_internal::hc453db0ee48af82e;std::rt::lang_start::_$u7b$$u7b$closure$u7d$$u7d$::hd856f2663871206c;std::sys_common::backtrace::__rust_begin_short_backtrace::h4869fd82068bc1dc;core::ops::function::FnOnce::call_once::h06e0c27ee740c6a8;example_app::main::hddab13ae8d8b6a6e;example_app::example_a::h622d6879b734496d;example_app::example_b::h71b31fcd89b9ffd2;std::time::Instant::elapsed::h2e3793148fc23529;std::time::Instant::elapsed::h2e3793148fc23529 16:40",
"example_app (40414);start;main;std::rt::lang_start::hdba6f1ebfd1bdcf8;std::rt::lang_start_internal::hc453db0ee48af82e;std::rt::lang_start::_$u7b$$u7b$closure$u7d$$u7d$::hd856f2663871206c;std::sys_common::backtrace::__rust_begin_short_backtrace::h4869fd82068bc1dc;core::ops::function::FnOnce::call_once::h06e0c27ee740c6a8;example_app::main::hddab13ae8d8b6a6e;example_app::example_a::h622d6879b734496d;example_app::example_b::h71b31fcd89b9ffd2;example_app::example_c::h631759c10d7dee93;alloc::vec::Vec$LT$T$C$A$GT$::push::ha3426502ffc42c8b;alloc::raw_vec::RawVec$LT$T$C$A$GT$::reserve_for_push::he4a29b8274e35dbb;alloc::raw_vec::RawVec$LT$T$C$A$GT$::grow_amortized::h78db9ba423623c58;alloc::raw_vec::finish_grow::h876f5af1c66d74c8;_$LT$alloc..alloc..Global$u20$as$u20$core..alloc..Allocator$GT$::allocate::hcc733a40a34fbc94;alloc::alloc::Global::alloc_impl::hc55feba7d6266dfa;alloc::alloc::alloc::hfac63f3d6850b759;_malloc_zone_malloc;nanov2_malloc;nanov2_allocate;nanov2_allocate;nanov2_find_block_and_allocate 16:40",
"example_app (40414);start;main;std::rt::lang_start::hdba6f1ebfd1bdcf8;std::rt::lang_start_internal::hc453db0ee48af82e;std::rt::lang_start::_$u7b$$u7b$closure$u7d$$u7d$::hd856f2663871206c;std::sys_common::backtrace::__rust_begin_short_backtrace::h4869fd82068bc1dc;core::ops::function::FnOnce::call_once::h06e0c27ee740c6a8;example_app::main::hddab13ae8d8b6a6e;example_app::example_a::h622d6879b734496d;example_app::example_b::h71b31fcd89b9ffd2;example_app::example_b::h71b31fcd89b9ffd2 16:40",
"example_app (40414);start;main;std::rt::lang_start::hdba6f1ebfd1bdcf8;std::rt::lang_start_internal::hc453db0ee48af82e;std::rt::lang_start::_$u7b$$u7b$closure$u7d$$u7d$::hd856f2663871206c;std::sys_common::backtrace::__rust_begin_short_backtrace::h4869fd82068bc1dc;core::ops::function::FnOnce::call_once::h06e0c27ee740c6a8;example_app::main::hddab13ae8d8b6a6e;example_app::example_a::h622d6879b734496d;example_app::example_b::h71b31fcd89b9ffd2;core::time::Duration::as_millis::hae6ad1b9cf7bb5ec 16:40",
"example_app (40414);start;main;std::rt::lang_start::hdba6f1ebfd1bdcf8;std::rt::lang_start_internal::hc453db0ee48af82e;std::rt::lang_start::_$u7b$$u7b$closure$u7d$$u7d$::hd856f2663871206c;std::sys_common::backtrace::__rust_begin_short_backtrace::h4869fd82068bc1dc;core::ops::function::FnOnce::call_once::h06e0c27ee740c6a8;example_app::main::hddab13ae8d8b6a6e;example_app::example_a::h622d6879b734496d 1683:20",
"example_app (40414);start;main;std::rt::lang_start::hdba6f1ebfd1bdcf8;std::rt::lang_start_internal::hc453db0ee48af82e;std::rt::lang_start::_$u7b$$u7b$closure$u7d$$u7d$::hd856f2663871206c;std::sys_common::backtrace::__rust_begin_short_backtrace::h4869fd82068bc1dc;core::ops::function::FnOnce::call_once::h06e0c27ee740c6a8;example_app::main::hddab13ae8d8b6a6e;std::time::Instant::elapsed::h2e3793148fc23529;mach_absolute_time 766666:40",
"example_app (40414);start;main;std::rt::lang_start::hdba6f1ebfd1bdcf8;std::rt::lang_start_internal::hc453db0ee48af82e;std::rt::lang_start::_$u7b$$u7b$closure$u7d$$u7d$::hd856f2663871206c;std::sys_common::backtrace::__rust_begin_short_backtrace::h4869fd82068bc1dc;core::ops::function::FnOnce::call_once::h06e0c27ee740c6a8;example_app::main::hddab13ae8d8b6a6e;std::time::Instant::elapsed::h2e3793148fc23529;std::time::Instant::elapsed::h2e3793148fc23529 10816:40",
"example_app (40414);start;main;std::rt::lang_start::hdba6f1ebfd1bdcf8;std::rt::lang_start_internal::hc453db0ee48af82e;std::rt::lang_start::_$u7b$$u7b$closure$u7d$$u7d$::hd856f2663871206c;std::sys_common::backtrace::__rust_begin_short_backtrace::h4869fd82068bc1dc;core::ops::function::FnOnce::call_once::h06e0c27ee740c6a8;example_app::main::hddab13ae8d8b6a6e;std::time::Instant::elapsed::h2e3793148fc23529 5850:00",
"example_app (40414);start;main;std::rt::lang_start::hdba6f1ebfd1bdcf8;std::rt::lang_start_internal::hc453db0ee48af82e;std::rt::lang_start::_$u7b$$u7b$closure$u7d$$u7d$::hd856f2663871206c;std::sys_common::backtrace::__rust_begin_short_backtrace::h4869fd82068bc1dc;core::ops::function::FnOnce::call_once::h06e0c27ee740c6a8;example_app::main::hddab13ae8d8b6a6e;core::time::Duration::as_millis::hae6ad1b9cf7bb5ec 10233:20",
"example_app (40414);start;main;std::rt::lang_start::hdba6f1ebfd1bdcf8;std::rt::lang_start_internal::hc453db0ee48af82e;std::rt::lang_start::_$u7b$$u7b$closure$u7d$$u7d$::hd856f2663871206c;std::sys_common::backtrace::__rust_begin_short_backtrace::h4869fd82068bc1dc;core::ops::function::FnOnce::call_once::h06e0c27ee740c6a8;example_app::main::hddab13ae8d8b6a6e;example_app::main::hddab13ae8d8b6a6e 3166:40",
"example_app (40414);start;main;std::rt::lang_start::hdba6f1ebfd1bdcf8;std::rt::lang_start_internal::hc453db0ee48af82e;std::rt::lang_start::_$u7b$$u7b$closure$u7d$$u7d$::hd856f2663871206c;std::sys_common::backtrace::__rust_begin_short_backtrace::h4869fd82068bc1dc;core::ops::function::FnOnce::call_once::h06e0c27ee740c6a8;example_app::main::hddab13ae8d8b6a6e;std::io::stdio::_print::hdecfefdeb43586ed;_$LT$$RF$std..io..stdio..Stdout$u20$as$u20$std..io..Write$GT$::write_fmt::h2cb06dcd2b172844;core::fmt::write::hed96bcfc6342aee5;_$LT$std..io..Write..write_fmt..Adapter$LT$T$GT$$u20$as$u20$core..fmt..Write$GT$::write_str::hbe33ec23de24ce2f;_$LT$std..io..stdio..StdoutLock$u20$as$u20$std..io..Write$GT$::write_all::h22667d0a03b2151b 532.00ms",
"example_app (40414);start;main;std::rt::lang_start::hdba6f1ebfd1bdcf8;std::rt::lang_start_internal::hc453db0ee48af82e;std::rt::lang_start::_$u7b$$u7b$closure$u7d$$u7d$::hd856f2663871206c;std::sys_common::backtrace::__rust_begin_short_backtrace::h4869fd82068bc1dc;core::ops::function::FnOnce::call_once::h06e0c27ee740c6a8;example_app::main::hddab13ae8d8b6a6e;std::io::stdio::_print::hdecfefdeb43586ed;_$LT$$RF$std..io..stdio..Stdout$u20$as$u20$std..io..Write$GT$::write_fmt::h2cb06dcd2b172844;core::fmt::write::hed96bcfc6342aee5 468.00ms",
"example_app (40414);start;main;std::rt::lang_start::hdba6f1ebfd1bdcf8;std::rt::lang_start_internal::hc453db0ee48af82e;std::rt::lang_start::_$u7b$$u7b$closure$u7d$$u7d$::hd856f2663871206c;std::sys_common::backtrace::__rust_begin_short_backtrace::h4869fd82068bc1dc;core::ops::function::FnOnce::call_once::h06e0c27ee740c6a8;example_app::main::hddab13ae8d8b6a6e 19933:19",
],
}
`;
exports[`importFromInstrumentsDeepCopy allocations profile: indexToView 1`] = `0`;
exports[`importFromInstrumentsDeepCopy allocations profile: indexToView 2`] = `0`;
exports[`importFromInstrumentsDeepCopy allocations profile: profileGroup.name 1`] = `"random-allocations-deep-copy.txt"`;
exports[`importFromInstrumentsDeepCopy allocations profile: profileGroup.name 2`] = `"cycles-example-deep-copy.txt"`;
exports[`importFromInstrumentsDeepCopy time profile 1`] = `
Object {
"frames": Array [
+4
View File
@@ -18,6 +18,10 @@ describe('importFromInstrumentsDeepCopy', () => {
'./sample/profiles/Instruments/7.3.1/random-allocations-deep-copy.txt',
)
})
test('allocations profile', async () => {
await checkProfileSnapshot('./sample/profiles/Instruments/13.4/cycles-example-deep-copy.txt')
})
})
class ZipBackedFileSystemEntry implements FileSystemEntry {
+9
View File
@@ -85,7 +85,16 @@ function getWeight(deepCopyRow: any): number {
case 's':
return 1000 * value
case 'min':
return 60 * 1000 * value
case 'cycles':
return value
case 'Kc':
return 1000 * value
case 'Mc':
return 1000 * 1000 * value
case 'Gc':
return 1000 * 1000 * 1000 * value
}
throw new Error(`Unrecognized units ${units}`)
}
+50
View File
@@ -0,0 +1,50 @@
import {exactMatchStrings} from './profile-search'
function assertMatch(text: string, pattern: string, expected: string) {
const match = exactMatchStrings(text, pattern)
let highlighted = ''
let last = 0
for (let range of match) {
highlighted += `${text.slice(last, range[0])}[${text.slice(range[0], range[1])}]`
last = range[1]
}
highlighted += text.slice(last)
expect(highlighted).toEqual(expected)
}
function assertNoMatch(text: string, pattern: string) {
assertMatch(text, pattern, text)
}
describe('exactMatchStrings', () => {
test('no match', () => {
assertNoMatch('a', 'b')
assertNoMatch('aa', 'ab')
assertNoMatch('a', 'aa')
assertNoMatch('ca', 'ac')
})
test('full text match', () => {
assertMatch('hello', 'hello', '[hello]')
assertMatch('multiple words', 'multiple words', '[multiple words]')
})
test('case sensitivity', () => {
assertMatch('HELLO', 'hello', '[HELLO]')
assertMatch('Hello', 'hello', '[Hello]')
assertMatch('hello', 'Hello', '[hello]')
assertMatch('hello', 'HELLO', '[hello]')
})
test('multiple occurrences', () => {
assertMatch('hello hello', 'hello', '[hello] [hello]')
assertMatch('hellohello', 'hello', '[hello][hello]')
})
test('overlapping occurrences', () => {
assertMatch('aaaaa', 'aa', '[aa][aa]a')
assertMatch('abababa', 'aba', '[aba]b[aba]')
})
})
+33 -6
View File
@@ -1,5 +1,4 @@
import {Profile, Frame, CallTreeNode} from './profile'
import {FuzzyMatch, fuzzyMatchStrings} from './fuzzy-find'
import {Flamechart, FlamechartFrame} from './flamechart'
import {Rect, Vec2} from './math'
@@ -8,19 +7,47 @@ export enum FlamechartType {
LEFT_HEAVY_FLAME_GRAPH,
}
// In previous versions of speedscope, searching for strings within the profile
// was done using fuzzy finding. As it turns out, this was surprising behavior
// to most people, so we've switched to a more traditional substring search that
// more closely mimics browser behavior.
//
// This is case insensitive for both the needle & the haystack. This means
// searching for "hello" will match "Hello" and "HELLO", and searching for
// "HELLO" will match both "hello" and "Hello". This matches Chrome's behavior
// as far as I can tell.
//
// See https://github.com/jlfwong/speedscope/issues/352
//
// Return ranges for all matches in order to highlight them.
export function exactMatchStrings(text: string, pattern: string): [number, number][] {
const lowerText = text.toLocaleLowerCase()
const lowerPattern = pattern.toLocaleLowerCase()
let lastIndex = 0
const matchedRanges: Array<[number, number]> = []
while (true) {
let index = lowerText.indexOf(lowerPattern, lastIndex)
if (index === -1) {
return matchedRanges
}
matchedRanges.push([index, index + pattern.length])
lastIndex = index + pattern.length
}
}
// A utility class for storing cached search results to avoid recomputation when
// the search results & profile did not change.
export class ProfileSearchResults {
constructor(readonly profile: Profile, readonly searchQuery: string) {}
private matches: Map<Frame, FuzzyMatch> | null = null
getMatchForFrame(frame: Frame): FuzzyMatch | null {
private matches: Map<Frame, [number, number][] | null> | null = null
getMatchForFrame(frame: Frame): [number, number][] | null {
if (!this.matches) {
this.matches = new Map()
this.profile.forEachFrame(frame => {
const match = fuzzyMatchStrings(frame.name, this.searchQuery)
if (match == null) return
this.matches!.set(frame, match)
const match = exactMatchStrings(frame.name, this.searchQuery)
this.matches!.set(frame, match.length === 0 ? null : match)
})
}
return this.matches.get(frame) || null
+1 -1
View File
@@ -241,7 +241,7 @@ export class FlamechartPanZoomView extends Component<FlamechartPanZoomViewProps,
if (match) {
const rangesToHighlightInTrimmedText = remapRangesToTrimmedText(
trimmedText,
match.matchedRanges,
match
)
// Once we have the character ranges to highlight, we need to
+1 -1
View File
@@ -217,7 +217,7 @@ export const ProfileTableView = memo(
rows.push(
ProfileTableRowView({
frame,
matchedRanges: match == null ? null : match.matchedRanges,
matchedRanges: match == null ? null : match,
index: i,
profile: profile,
selectedFrame: selectedFrame,
+2 -3
View File
@@ -11,7 +11,6 @@ import {SandwichSearchView} from './sandwich-search-view'
import {ActiveProfileState} from '../app-state/active-profile-state'
import {sortBy} from '../lib/utils'
import {ProfileSearchContext} from './search-view'
import {FuzzyMatch} from '../lib/fuzzy-find'
import {Theme, useTheme, withTheme} from './themes/theme'
import {SortField, SortDirection, profileGroupAtom, tableSortMethodAtom} from '../app-state'
import {useAtom} from '../lib/atom'
@@ -141,7 +140,7 @@ interface SandwichViewContextData {
selectedFrame: Frame | null
setSelectedFrame: (frame: Frame | null) => void
getIndexForFrame: (frame: Frame) => number | null
getSearchMatchForFrame: (frame: Frame) => FuzzyMatch | null
getSearchMatchForFrame: (frame: Frame) => [number, number][] | null
}
export const SandwichViewContext = createContext<SandwichViewContextData | null>(null)
@@ -204,7 +203,7 @@ export const SandwichViewContainer = memo((ownProps: SandwichViewContainerProps)
}
}, [rowList])
const getSearchMatchForFrame: (frame: Frame) => FuzzyMatch | null = useMemo(() => {
const getSearchMatchForFrame: (frame: Frame) => [number, number][] | null = useMemo(() => {
return (frame: Frame) => {
if (profileSearchResults == null) return null
return profileSearchResults.getMatchForFrame(frame)