@@ -27,12 +27,6 @@ import { bindActionCreators } from "redux";
27
27
28
28
import { withShortcut } from "react-keybind" ;
29
29
30
- import { FontAwesomeIcon } from "@fortawesome/react-fontawesome" ;
31
- import {
32
- faIcicles ,
33
- faColumns ,
34
- faBars ,
35
- } from "@fortawesome/free-solid-svg-icons" ;
36
30
import { fetchJSON } from "../redux/actions" ;
37
31
import { buildRenderURL } from "../util/update_requests" ;
38
32
import {
@@ -41,6 +35,8 @@ import {
41
35
DurationFormater ,
42
36
} from "../util/format" ;
43
37
import { colorBasedOnPackageName , colorGreyscale } from "../util/color" ;
38
+ import ProfilerTable from "./ProfilerTable" ;
39
+ import ProfilerHeader from "./ProfilerHeader" ;
44
40
45
41
const PX_PER_LEVEL = 18 ;
46
42
const COLLAPSE_THRESHOLD = 5 ;
@@ -155,13 +151,13 @@ class FlameGraphRenderer extends React.Component {
155
151
} ;
156
152
157
153
// binary search of a block in a stack level
158
- binarySearchLevel ( x , level ) {
154
+ binarySearchLevel ( x , level , tickToX ) {
159
155
let i = 0 ;
160
156
let j = level . length - 4 ;
161
157
while ( i <= j ) {
162
158
const m = 4 * ( ( i / 4 + j / 4 ) >> 1 ) ;
163
- const x0 = this . tickToX ( level [ m ] ) ;
164
- const x1 = this . tickToX ( level [ m ] + level [ m + 1 ] ) ;
159
+ const x0 = tickToX ( level [ m ] ) ;
160
+ const x1 = tickToX ( level [ m ] + level [ m + 1 ] ) ;
165
161
if ( x0 <= x && x1 >= x ) {
166
162
return x1 - x0 > COLLAPSE_THRESHOLD ? m : - 1 ;
167
163
}
@@ -208,7 +204,7 @@ class FlameGraphRenderer extends React.Component {
208
204
xyToBar = ( x , y ) => {
209
205
const i = Math . floor ( y / PX_PER_LEVEL ) + this . topLevel ;
210
206
if ( i >= 0 && i < this . levels . length ) {
211
- const j = this . binarySearchLevel ( x , this . levels [ i ] ) ;
207
+ const j = this . binarySearchLevel ( x , this . levels [ i ] , this . tickToX ) ;
212
208
return { i, j } ;
213
209
}
214
210
return { i : 0 , j : 0 } ;
@@ -420,50 +416,6 @@ class FlameGraphRenderer extends React.Component {
420
416
} ) ;
421
417
} ;
422
418
423
- renderTable = ( ) => {
424
- if ( ! this . props . flamebearer ) {
425
- return [ ] ;
426
- }
427
-
428
- if ( this . props . flamebearer . numTicks == 0 ) {
429
- return [ ] ;
430
- }
431
-
432
- return (
433
- < table className = "flamegraph-table" >
434
- < thead >
435
- < tr >
436
- < th className = "sortable" onClick = { ( ) => this . updateSortBy ( "name" ) } >
437
- Location
438
- < span
439
- className = { clsx ( "sort-arrow" , {
440
- [ this . state . sortByDirection ] : this . state . sortBy == "name" ,
441
- } ) }
442
- />
443
- </ th >
444
- < th className = "sortable" onClick = { ( ) => this . updateSortBy ( "self" ) } >
445
- Self
446
- < span
447
- className = { clsx ( "sort-arrow" , {
448
- [ this . state . sortByDirection ] : this . state . sortBy == "self" ,
449
- } ) }
450
- />
451
- </ th >
452
- < th className = "sortable" onClick = { ( ) => this . updateSortBy ( "total" ) } >
453
- Total
454
- < span
455
- className = { clsx ( "sort-arrow" , {
456
- [ this . state . sortByDirection ] : this . state . sortBy == "total" ,
457
- } ) }
458
- />
459
- </ th >
460
- </ tr >
461
- </ thead >
462
- < tbody > { this . renderTableBody ( ) } </ tbody >
463
- </ table >
464
- ) ;
465
- } ;
466
-
467
419
updateSortBy = ( newSortBy ) => {
468
420
let dir = this . state . sortByDirection ;
469
421
if ( this . state . sortBy == newSortBy ) {
@@ -477,108 +429,27 @@ class FlameGraphRenderer extends React.Component {
477
429
} ) ;
478
430
} ;
479
431
480
- renderTableBody = ( ) => {
481
- const { numTicks, maxSelf, sampleRate, spyName } = this . props . flamebearer ;
482
-
483
- const table = generateTable ( this . props . flamebearer ) . sort (
484
- ( a , b ) => b . total - a . total
485
- ) ;
486
-
487
- const { sortBy, sortByDirection } = this . state ;
488
- const m = sortByDirection == "asc" ? 1 : - 1 ;
489
- let sorted ;
490
- if ( sortBy == "name" ) {
491
- sorted = table . sort ( ( a , b ) => m * a [ sortBy ] . localeCompare ( b [ sortBy ] ) ) ;
492
- } else {
493
- sorted = table . sort ( ( a , b ) => m * ( a [ sortBy ] - b [ sortBy ] ) ) ;
494
- }
495
-
496
- const df = new DurationFormater ( this . numTicks / this . sampleRate ) ;
497
-
498
- return sorted . map ( ( x ) => {
499
- const pn = this . getPackageNameFromStackTrace ( spyName , x . name ) ;
500
- const color = colorBasedOnPackageName ( pn , 1 ) ;
501
- const style = {
502
- backgroundColor : color ,
503
- } ;
504
- return (
505
- < tr key = { x . name } >
506
- < td >
507
- < span className = "color-reference" style = { style } />
508
- < span > { x . name } </ span >
509
- </ td >
510
- < td style = { backgroundImageStyle ( x . self , maxSelf , color ) } >
511
- { /* <span>{ formatPercent(x.self / numTicks) }</span>
512
-
513
- <span>{ shortNumber(x.self) }</span>
514
- */ }
515
- < span title = { df . format ( x . self / sampleRate ) } >
516
- { df . format ( x . self / sampleRate ) }
517
- </ span >
518
- </ td >
519
- < td style = { backgroundImageStyle ( x . total , numTicks , color ) } >
520
- { /* <span>{ formatPercent(x.total / numTicks) }</span>
521
-
522
- <span>{ shortNumber(x.total) }</span>
523
- */ }
524
- < span title = { df . format ( x . total / sampleRate ) } >
525
- { df . format ( x . total / sampleRate ) }
526
- </ span >
527
- </ td >
528
- </ tr >
529
- ) ;
530
- } ) ;
531
- } ;
532
-
533
432
render = ( ) => (
534
433
< div className = "canvas-renderer" >
535
434
< div className = "canvas-container" >
536
- < div className = "navbar-2" >
537
- < input
538
- className = "flamegraph-search"
539
- name = "flamegraph-search"
540
- placeholder = "Search…"
541
- onChange = { this . handleSearchChange }
542
- />
543
-
544
- < button
545
- className = { clsx ( "btn" ) }
546
- style = { this . state . resetStyle }
547
- id = "reset"
548
- onClick = { this . reset }
549
- >
550
- Reset View
551
- </ button >
552
- < div className = "navbar-space-filler" />
553
- < div className = "btn-group viz-switch" >
554
- < button
555
- className = { clsx ( "btn" , { active : this . state . view == "table" } ) }
556
- onClick = { ( ) => this . updateView ( "table" ) }
557
- >
558
- < FontAwesomeIcon icon = { faBars } />
559
-  Table
560
- </ button >
561
- < button
562
- className = { clsx ( "btn" , { active : this . state . view == "both" } ) }
563
- onClick = { ( ) => this . updateView ( "both" ) }
564
- >
565
- < FontAwesomeIcon icon = { faColumns } />
566
-  Both
567
- </ button >
568
- < button
569
- className = { clsx ( "btn" , { active : this . state . view == "icicle" } ) }
570
- onClick = { ( ) => this . updateView ( "icicle" ) }
571
- >
572
- < FontAwesomeIcon icon = { faIcicles } />
573
-  Flamegraph
574
- </ button >
575
- </ div >
576
- </ div >
435
+ < ProfilerHeader
436
+ view = { this . state . view }
437
+ handleSearchChange = { this . handleSearchChange }
438
+ reset = { this . reset }
439
+ updateView = { this . updateView }
440
+ resetStyle = { this . state . resetStyle }
441
+ />
577
442
< div className = "flamegraph-container panes-wrapper" >
578
443
< div
579
444
className = { clsx ( "pane" , { hidden : this . state . view === "icicle" } ) }
580
445
>
581
- { this . renderTable ( ) }
446
+ < ProfilerTable
447
+ flamebearer = { this . props . flamebearer }
448
+ sortByDirection = { this . state . sortByDirection }
449
+ sortBy = { this . state . sortBy }
450
+ updateSortBy = { this . updateSortBy }
451
+ view = { this . state . view }
452
+ />
582
453
</ div >
583
454
< div
584
455
className = { clsx ( "pane" , { hidden : this . state . view === "table" } ) }
@@ -631,42 +502,6 @@ const mapDispatchToProps = (dispatch) => ({
631
502
) ,
632
503
} ) ;
633
504
634
- const backgroundImageStyle = ( a , b , color ) => {
635
- const w = 148 ;
636
- const k = w - ( a / b ) * w ;
637
- const clr = color . alpha ( 1.0 ) ;
638
- return {
639
- // backgroundColor: 'transparent',
640
- backgroundImage : `linear-gradient(${ clr } , ${ clr } )` ,
641
- backgroundPosition : `-${ k } px 0px` ,
642
- backgroundRepeat : "no-repeat" ,
643
- } ;
644
- } ;
645
-
646
- // generates a table from data in flamebearer format
647
- const generateTable = ( data ) => {
648
- const table = [ ] ;
649
- if ( ! data ) {
650
- return table ;
651
- }
652
- const { names, levels } = data ;
653
- const hash = { } ;
654
- for ( let i = 0 ; i < levels . length ; i ++ ) {
655
- for ( let j = 0 ; j < levels [ i ] . length ; j += 4 ) {
656
- const key = levels [ i ] [ j + 3 ] ;
657
- const name = names [ key ] ;
658
- hash [ name ] = hash [ name ] || {
659
- name : name || "<empty>" ,
660
- self : 0 ,
661
- total : 0 ,
662
- } ;
663
- hash [ name ] . total += levels [ i ] [ j + 1 ] ;
664
- hash [ name ] . self += levels [ i ] [ j + 2 ] ;
665
- }
666
- }
667
- return Object . values ( hash ) ;
668
- } ;
669
-
670
505
export default connect (
671
506
mapStateToProps ,
672
507
mapDispatchToProps
0 commit comments