Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d7969ac2b8 | ||
|
|
1b36a2e3f4 |
@@ -0,0 +1,5 @@
|
||||
## [0.3.0] - 2018-07-18
|
||||
|
||||
### Added
|
||||
|
||||
* Support for remapping profiles using a wasm symbol file [#93]
|
||||
+3
-3
@@ -16,7 +16,7 @@ import {SortMethod, SortField, SortDirection} from './profile-table-view'
|
||||
import {triangle} from './utils'
|
||||
import {Color} from './color'
|
||||
import {RowAtlas} from './row-atlas'
|
||||
import {importAsmJsSymbolMap} from './asm-js'
|
||||
import {importEmscriptenSymbolMap} from './emscripten'
|
||||
import {SandwichView} from './sandwich-view'
|
||||
import {saveToFile} from './file-format'
|
||||
|
||||
@@ -384,9 +384,9 @@ export class Application extends ReloadableComponent<{}, ApplicationState> {
|
||||
// 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 = importAsmJsSymbolMap(reader.result)
|
||||
const map = importEmscriptenSymbolMap(reader.result)
|
||||
if (map) {
|
||||
console.log('Importing as asm.js symbol map')
|
||||
console.log('Importing as emscripten symbol map')
|
||||
let profile = this.state.profile
|
||||
profile.remapNames(name => map.get(name) || name)
|
||||
return profile
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
type AsmJsSymbolMap = Map<string, string>
|
||||
|
||||
// This imports symbol maps generated by emscripten using the "--emit-symbol-map" flag.
|
||||
// It allows you to visualize a profile captured in a release build as long as you also
|
||||
// have the associated symbol map. To do this, first drop the profile into speedscope
|
||||
// and then drop the symbol map. After the second drop, the symbols will be remapped to
|
||||
// their original names.
|
||||
export function importAsmJsSymbolMap(contents: string): AsmJsSymbolMap | null {
|
||||
const lines = contents.split('\n')
|
||||
if (!lines.length) return null
|
||||
|
||||
// Remove a trailing blank line if there is one
|
||||
if (lines[lines.length - 1] === '') lines.pop()
|
||||
if (!lines.length) return null
|
||||
|
||||
const map: AsmJsSymbolMap = new Map()
|
||||
const regex = /^([\$\w]+):([\$\w]+)$/
|
||||
|
||||
for (const line of lines) {
|
||||
const match = regex.exec(line)
|
||||
if (!match) return null
|
||||
map.set(match[1], match[2])
|
||||
}
|
||||
|
||||
return map
|
||||
}
|
||||
@@ -1,9 +1,9 @@
|
||||
import {importAsmJsSymbolMap} from './asm-js'
|
||||
import {importEmscriptenSymbolMap} from './emscripten'
|
||||
|
||||
test('importAsmJSSymbolMap', () => {
|
||||
test('importEmscriptenSymbolMap', () => {
|
||||
// Valid symbol map
|
||||
expect(
|
||||
importAsmJsSymbolMap(
|
||||
importEmscriptenSymbolMap(
|
||||
[
|
||||
/* prettier: ignore */
|
||||
'a:A',
|
||||
@@ -15,7 +15,7 @@ test('importAsmJSSymbolMap', () => {
|
||||
|
||||
// Valid symbol map with trailing newline
|
||||
expect(
|
||||
importAsmJsSymbolMap(
|
||||
importEmscriptenSymbolMap(
|
||||
[
|
||||
/* prettier: ignore */
|
||||
'a:A',
|
||||
@@ -27,14 +27,27 @@ test('importAsmJSSymbolMap', () => {
|
||||
).toEqual(new Map([['a', 'A'], ['b', 'B'], ['c', 'C']]))
|
||||
|
||||
// Valid symbol map with non-alpha characters
|
||||
|
||||
expect(importAsmJsSymbolMap('u6:__ZN8tinyxml210XMLCommentD0Ev\n')).toEqual(
|
||||
expect(importEmscriptenSymbolMap('u6:__ZN8tinyxml210XMLCommentD0Ev\n')).toEqual(
|
||||
new Map([['u6', '__ZN8tinyxml210XMLCommentD0Ev']]),
|
||||
)
|
||||
|
||||
// WebAssembly symbol map
|
||||
expect(
|
||||
importEmscriptenSymbolMap(
|
||||
[
|
||||
/* prettier: ignore */
|
||||
'0:A',
|
||||
'1:B',
|
||||
'2:C',
|
||||
].join('\n'),
|
||||
),
|
||||
).toEqual(
|
||||
new Map([['wasm-function[0]', 'A'], ['wasm-function[1]', 'B'], ['wasm-function[2]', 'C']]),
|
||||
)
|
||||
|
||||
// Invalid symbol map
|
||||
expect(
|
||||
importAsmJsSymbolMap(
|
||||
importEmscriptenSymbolMap(
|
||||
[
|
||||
/* prettier: ignore */
|
||||
'a:A',
|
||||
@@ -47,7 +60,7 @@ test('importAsmJSSymbolMap', () => {
|
||||
|
||||
// Collapsed stack format should not be imported as an asm.js symbol map
|
||||
expect(
|
||||
importAsmJsSymbolMap(
|
||||
importEmscriptenSymbolMap(
|
||||
[
|
||||
/* prettier: ignore */
|
||||
'a;b 1',
|
||||
@@ -58,6 +71,6 @@ test('importAsmJSSymbolMap', () => {
|
||||
).toEqual(null)
|
||||
|
||||
// Unrelated files
|
||||
expect(importAsmJsSymbolMap('')).toEqual(null)
|
||||
expect(importAsmJsSymbolMap('\n')).toEqual(null)
|
||||
expect(importEmscriptenSymbolMap('')).toEqual(null)
|
||||
expect(importEmscriptenSymbolMap('\n')).toEqual(null)
|
||||
})
|
||||
@@ -0,0 +1,39 @@
|
||||
type EmscriptenSymbolMap = Map<string, string>
|
||||
|
||||
// This imports symbol maps generated by emscripten using the "--emit-symbol-map" flag.
|
||||
// It allows you to visualize a profile captured in a release build as long as you also
|
||||
// have the associated symbol map. To do this, first drop the profile into speedscope
|
||||
// and then drop the symbol map. After the second drop, the symbols will be remapped to
|
||||
// their original names.
|
||||
export function importEmscriptenSymbolMap(contents: string): EmscriptenSymbolMap | null {
|
||||
const lines = contents.split('\n')
|
||||
if (!lines.length) return null
|
||||
|
||||
// Remove a trailing blank line if there is one
|
||||
if (lines[lines.length - 1] === '') lines.pop()
|
||||
if (!lines.length) return null
|
||||
|
||||
const map: EmscriptenSymbolMap = new Map()
|
||||
const intRegex = /^(\d+):([\$\w]+)$/
|
||||
const idRegex = /^([\$\w]+):([\$\w]+)$/
|
||||
|
||||
for (const line of lines) {
|
||||
// Match lines like "103:__ZN8tinyxml210XMLCommentD0Ev"
|
||||
const intMatch = intRegex.exec(line)
|
||||
if (intMatch) {
|
||||
map.set(`wasm-function[${intMatch[1]}]`, intMatch[2])
|
||||
continue
|
||||
}
|
||||
|
||||
// Match lines like "u6:__ZN8tinyxml210XMLCommentD0Ev"
|
||||
const idMatch = idRegex.exec(line)
|
||||
if (idMatch) {
|
||||
map.set(idMatch[1], idMatch[2])
|
||||
continue
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
return map
|
||||
}
|
||||
Generated
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "speedscope",
|
||||
"version": "0.2.0",
|
||||
"version": "0.3.0",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "speedscope",
|
||||
"version": "0.2.0",
|
||||
"version": "0.3.0",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"bin": {
|
||||
|
||||
Reference in New Issue
Block a user