├── README.md ├── docs └── cddl1.txt ├── examples ├── http-hello-world.rs ├── http-hello-world.svg ├── loop.rs ├── loop.svg ├── tcp-echo-server.rs └── tcp-echo-server.svg ├── flamegraph.pl ├── stackcollapse-perf.pl └── torch.sh /README.md: -------------------------------------------------------------------------------- 1 | # torch 2 | > A script that glues perf CPU sampling and [Brendan Gregg's visualizer](https://github.com/brendangregg/FlameGraph) to generate FlameGraphs. 3 | 4 | * [Requirements](#requirements) 5 | * [Usage](#usage) 6 | * [Examples](#examples) 7 | * [License](#license) 8 | 9 | ## Requirements 10 | Linux 3.7 and above 11 | 12 | ## Usage 13 | ``` 14 | #./torch.sh -h 15 | Usage: ./torch.sh [options] pid 16 | 17 | Options: 18 | -d, --duration duration of sampling in seconds [default: 10] 19 | -o, --output file to save flamegraph to [default: ./flamegraph.svg] 20 | -h, --help this message 21 | ``` 22 | 23 | ## Examples 24 | ### Click graph to zoom 25 | A loop printing stuff ([source](https://github.com/mrhooray/torch/blob/master/examples/loop.rs)) 26 | [![loop](https://cdn.rawgit.com/mrhooray/torch/master/examples/loop.svg)](https://cdn.rawgit.com/mrhooray/torch/master/examples/loop.svg) 27 | Tcp Echo Server ([source](https://github.com/mrhooray/torch/blob/master/examples/tcp-echo-server.rs)) with [coio-rs](https://github.com/zonyitoo/coio-rs) 28 | [![tcp-echo-server](https://cdn.rawgit.com/mrhooray/torch/master/examples/tcp-echo-server.svg)](https://cdn.rawgit.com/mrhooray/torch/master/examples/tcp-echo-server.svg) 29 | HTTP Hello World ([source](https://github.com/mrhooray/torch/blob/master/examples/http-hello-world.rs)) with [hyper](https://github.com/hyperium/hyper) 30 | [![http-hello-world](https://cdn.rawgit.com/mrhooray/torch/master/examples/http-hello-world.svg)](https://cdn.rawgit.com/mrhooray/torch/master/examples/http-hello-world.svg) 31 | 32 | ## License 33 | MIT 34 | CDDL 35 | -------------------------------------------------------------------------------- /docs/cddl1.txt: -------------------------------------------------------------------------------- 1 | ../flamegraph.pl and ../stackcollapse-perf.pl are released 2 | under the Common Development and Distribution License (CDDL). 3 | 4 | -------------------------------------------------------------------- 5 | 6 | 7 | COMMON DEVELOPMENT AND DISTRIBUTION LICENSE Version 1.0 8 | 9 | 1. Definitions. 10 | 11 | 1.1. "Contributor" means each individual or entity that creates 12 | or contributes to the creation of Modifications. 13 | 14 | 1.2. "Contributor Version" means the combination of the Original 15 | Software, prior Modifications used by a Contributor (if any), 16 | and the Modifications made by that particular Contributor. 17 | 18 | 1.3. "Covered Software" means (a) the Original Software, or (b) 19 | Modifications, or (c) the combination of files containing 20 | Original Software with files containing Modifications, in 21 | each case including portions thereof. 22 | 23 | 1.4. "Executable" means the Covered Software in any form other 24 | than Source Code. 25 | 26 | 1.5. "Initial Developer" means the individual or entity that first 27 | makes Original Software available under this License. 28 | 29 | 1.6. "Larger Work" means a work which combines Covered Software or 30 | portions thereof with code not governed by the terms of this 31 | License. 32 | 33 | 1.7. "License" means this document. 34 | 35 | 1.8. "Licensable" means having the right to grant, to the maximum 36 | extent possible, whether at the time of the initial grant or 37 | subsequently acquired, any and all of the rights conveyed 38 | herein. 39 | 40 | 1.9. "Modifications" means the Source Code and Executable form of 41 | any of the following: 42 | 43 | A. Any file that results from an addition to, deletion from or 44 | modification of the contents of a file containing Original 45 | Software or previous Modifications; 46 | 47 | B. Any new file that contains any part of the Original 48 | Software or previous Modifications; or 49 | 50 | C. Any new file that is contributed or otherwise made 51 | available under the terms of this License. 52 | 53 | 1.10. "Original Software" means the Source Code and Executable 54 | form of computer software code that is originally released 55 | under this License. 56 | 57 | 1.11. "Patent Claims" means any patent claim(s), now owned or 58 | hereafter acquired, including without limitation, method, 59 | process, and apparatus claims, in any patent Licensable by 60 | grantor. 61 | 62 | 1.12. "Source Code" means (a) the common form of computer software 63 | code in which modifications are made and (b) associated 64 | documentation included in or with such code. 65 | 66 | 1.13. "You" (or "Your") means an individual or a legal entity 67 | exercising rights under, and complying with all of the terms 68 | of, this License. For legal entities, "You" includes any 69 | entity which controls, is controlled by, or is under common 70 | control with You. For purposes of this definition, 71 | "control" means (a) the power, direct or indirect, to cause 72 | the direction or management of such entity, whether by 73 | contract or otherwise, or (b) ownership of more than fifty 74 | percent (50%) of the outstanding shares or beneficial 75 | ownership of such entity. 76 | 77 | 2. License Grants. 78 | 79 | 2.1. The Initial Developer Grant. 80 | 81 | Conditioned upon Your compliance with Section 3.1 below and 82 | subject to third party intellectual property claims, the Initial 83 | Developer hereby grants You a world-wide, royalty-free, 84 | non-exclusive license: 85 | 86 | (a) under intellectual property rights (other than patent or 87 | trademark) Licensable by Initial Developer, to use, 88 | reproduce, modify, display, perform, sublicense and 89 | distribute the Original Software (or portions thereof), 90 | with or without Modifications, and/or as part of a Larger 91 | Work; and 92 | 93 | (b) under Patent Claims infringed by the making, using or 94 | selling of Original Software, to make, have made, use, 95 | practice, sell, and offer for sale, and/or otherwise 96 | dispose of the Original Software (or portions thereof). 97 | 98 | (c) The licenses granted in Sections 2.1(a) and (b) are 99 | effective on the date Initial Developer first distributes 100 | or otherwise makes the Original Software available to a 101 | third party under the terms of this License. 102 | 103 | (d) Notwithstanding Section 2.1(b) above, no patent license is 104 | granted: (1) for code that You delete from the Original 105 | Software, or (2) for infringements caused by: (i) the 106 | modification of the Original Software, or (ii) the 107 | combination of the Original Software with other software 108 | or devices. 109 | 110 | 2.2. Contributor Grant. 111 | 112 | Conditioned upon Your compliance with Section 3.1 below and 113 | subject to third party intellectual property claims, each 114 | Contributor hereby grants You a world-wide, royalty-free, 115 | non-exclusive license: 116 | 117 | (a) under intellectual property rights (other than patent or 118 | trademark) Licensable by Contributor to use, reproduce, 119 | modify, display, perform, sublicense and distribute the 120 | Modifications created by such Contributor (or portions 121 | thereof), either on an unmodified basis, with other 122 | Modifications, as Covered Software and/or as part of a 123 | Larger Work; and 124 | 125 | (b) under Patent Claims infringed by the making, using, or 126 | selling of Modifications made by that Contributor either 127 | alone and/or in combination with its Contributor Version 128 | (or portions of such combination), to make, use, sell, 129 | offer for sale, have made, and/or otherwise dispose of: 130 | (1) Modifications made by that Contributor (or portions 131 | thereof); and (2) the combination of Modifications made by 132 | that Contributor with its Contributor Version (or portions 133 | of such combination). 134 | 135 | (c) The licenses granted in Sections 2.2(a) and 2.2(b) are 136 | effective on the date Contributor first distributes or 137 | otherwise makes the Modifications available to a third 138 | party. 139 | 140 | (d) Notwithstanding Section 2.2(b) above, no patent license is 141 | granted: (1) for any code that Contributor has deleted 142 | from the Contributor Version; (2) for infringements caused 143 | by: (i) third party modifications of Contributor Version, 144 | or (ii) the combination of Modifications made by that 145 | Contributor with other software (except as part of the 146 | Contributor Version) or other devices; or (3) under Patent 147 | Claims infringed by Covered Software in the absence of 148 | Modifications made by that Contributor. 149 | 150 | 3. Distribution Obligations. 151 | 152 | 3.1. Availability of Source Code. 153 | 154 | Any Covered Software that You distribute or otherwise make 155 | available in Executable form must also be made available in Source 156 | Code form and that Source Code form must be distributed only under 157 | the terms of this License. You must include a copy of this 158 | License with every copy of the Source Code form of the Covered 159 | Software You distribute or otherwise make available. You must 160 | inform recipients of any such Covered Software in Executable form 161 | as to how they can obtain such Covered Software in Source Code 162 | form in a reasonable manner on or through a medium customarily 163 | used for software exchange. 164 | 165 | 3.2. Modifications. 166 | 167 | The Modifications that You create or to which You contribute are 168 | governed by the terms of this License. You represent that You 169 | believe Your Modifications are Your original creation(s) and/or 170 | You have sufficient rights to grant the rights conveyed by this 171 | License. 172 | 173 | 3.3. Required Notices. 174 | 175 | You must include a notice in each of Your Modifications that 176 | identifies You as the Contributor of the Modification. You may 177 | not remove or alter any copyright, patent or trademark notices 178 | contained within the Covered Software, or any notices of licensing 179 | or any descriptive text giving attribution to any Contributor or 180 | the Initial Developer. 181 | 182 | 3.4. Application of Additional Terms. 183 | 184 | You may not offer or impose any terms on any Covered Software in 185 | Source Code form that alters or restricts the applicable version 186 | of this License or the recipients' rights hereunder. You may 187 | choose to offer, and to charge a fee for, warranty, support, 188 | indemnity or liability obligations to one or more recipients of 189 | Covered Software. However, you may do so only on Your own behalf, 190 | and not on behalf of the Initial Developer or any Contributor. 191 | You must make it absolutely clear that any such warranty, support, 192 | indemnity or liability obligation is offered by You alone, and You 193 | hereby agree to indemnify the Initial Developer and every 194 | Contributor for any liability incurred by the Initial Developer or 195 | such Contributor as a result of warranty, support, indemnity or 196 | liability terms You offer. 197 | 198 | 3.5. Distribution of Executable Versions. 199 | 200 | You may distribute the Executable form of the Covered Software 201 | under the terms of this License or under the terms of a license of 202 | Your choice, which may contain terms different from this License, 203 | provided that You are in compliance with the terms of this License 204 | and that the license for the Executable form does not attempt to 205 | limit or alter the recipient's rights in the Source Code form from 206 | the rights set forth in this License. If You distribute the 207 | Covered Software in Executable form under a different license, You 208 | must make it absolutely clear that any terms which differ from 209 | this License are offered by You alone, not by the Initial 210 | Developer or Contributor. You hereby agree to indemnify the 211 | Initial Developer and every Contributor for any liability incurred 212 | by the Initial Developer or such Contributor as a result of any 213 | such terms You offer. 214 | 215 | 3.6. Larger Works. 216 | 217 | You may create a Larger Work by combining Covered Software with 218 | other code not governed by the terms of this License and 219 | distribute the Larger Work as a single product. In such a case, 220 | You must make sure the requirements of this License are fulfilled 221 | for the Covered Software. 222 | 223 | 4. Versions of the License. 224 | 225 | 4.1. New Versions. 226 | 227 | Sun Microsystems, Inc. is the initial license steward and may 228 | publish revised and/or new versions of this License from time to 229 | time. Each version will be given a distinguishing version number. 230 | Except as provided in Section 4.3, no one other than the license 231 | steward has the right to modify this License. 232 | 233 | 4.2. Effect of New Versions. 234 | 235 | You may always continue to use, distribute or otherwise make the 236 | Covered Software available under the terms of the version of the 237 | License under which You originally received the Covered Software. 238 | If the Initial Developer includes a notice in the Original 239 | Software prohibiting it from being distributed or otherwise made 240 | available under any subsequent version of the License, You must 241 | distribute and make the Covered Software available under the terms 242 | of the version of the License under which You originally received 243 | the Covered Software. Otherwise, You may also choose to use, 244 | distribute or otherwise make the Covered Software available under 245 | the terms of any subsequent version of the License published by 246 | the license steward. 247 | 248 | 4.3. Modified Versions. 249 | 250 | When You are an Initial Developer and You want to create a new 251 | license for Your Original Software, You may create and use a 252 | modified version of this License if You: (a) rename the license 253 | and remove any references to the name of the license steward 254 | (except to note that the license differs from this License); and 255 | (b) otherwise make it clear that the license contains terms which 256 | differ from this License. 257 | 258 | 5. DISCLAIMER OF WARRANTY. 259 | 260 | COVERED SOFTWARE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" 261 | BASIS, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, 262 | INCLUDING, WITHOUT LIMITATION, WARRANTIES THAT THE COVERED 263 | SOFTWARE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR 264 | PURPOSE OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND 265 | PERFORMANCE OF THE COVERED SOFTWARE IS WITH YOU. SHOULD ANY 266 | COVERED SOFTWARE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT THE 267 | INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY 268 | NECESSARY SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF 269 | WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE. NO USE OF 270 | ANY COVERED SOFTWARE IS AUTHORIZED HEREUNDER EXCEPT UNDER THIS 271 | DISCLAIMER. 272 | 273 | 6. TERMINATION. 274 | 275 | 6.1. This License and the rights granted hereunder will terminate 276 | automatically if You fail to comply with terms herein and fail to 277 | cure such breach within 30 days of becoming aware of the breach. 278 | Provisions which, by their nature, must remain in effect beyond 279 | the termination of this License shall survive. 280 | 281 | 6.2. If You assert a patent infringement claim (excluding 282 | declaratory judgment actions) against Initial Developer or a 283 | Contributor (the Initial Developer or Contributor against whom You 284 | assert such claim is referred to as "Participant") alleging that 285 | the Participant Software (meaning the Contributor Version where 286 | the Participant is a Contributor or the Original Software where 287 | the Participant is the Initial Developer) directly or indirectly 288 | infringes any patent, then any and all rights granted directly or 289 | indirectly to You by such Participant, the Initial Developer (if 290 | the Initial Developer is not the Participant) and all Contributors 291 | under Sections 2.1 and/or 2.2 of this License shall, upon 60 days 292 | notice from Participant terminate prospectively and automatically 293 | at the expiration of such 60 day notice period, unless if within 294 | such 60 day period You withdraw Your claim with respect to the 295 | Participant Software against such Participant either unilaterally 296 | or pursuant to a written agreement with Participant. 297 | 298 | 6.3. In the event of termination under Sections 6.1 or 6.2 above, 299 | all end user licenses that have been validly granted by You or any 300 | distributor hereunder prior to termination (excluding licenses 301 | granted to You by any distributor) shall survive termination. 302 | 303 | 7. LIMITATION OF LIABILITY. 304 | 305 | UNDER NO CIRCUMSTANCES AND UNDER NO LEGAL THEORY, WHETHER TORT 306 | (INCLUDING NEGLIGENCE), CONTRACT, OR OTHERWISE, SHALL YOU, THE 307 | INITIAL DEVELOPER, ANY OTHER CONTRIBUTOR, OR ANY DISTRIBUTOR OF 308 | COVERED SOFTWARE, OR ANY SUPPLIER OF ANY OF SUCH PARTIES, BE 309 | LIABLE TO ANY PERSON FOR ANY INDIRECT, SPECIAL, INCIDENTAL, OR 310 | CONSEQUENTIAL DAMAGES OF ANY CHARACTER INCLUDING, WITHOUT 311 | LIMITATION, DAMAGES FOR LOST PROFITS, LOSS OF GOODWILL, WORK 312 | STOPPAGE, COMPUTER FAILURE OR MALFUNCTION, OR ANY AND ALL OTHER 313 | COMMERCIAL DAMAGES OR LOSSES, EVEN IF SUCH PARTY SHALL HAVE BEEN 314 | INFORMED OF THE POSSIBILITY OF SUCH DAMAGES. THIS LIMITATION OF 315 | LIABILITY SHALL NOT APPLY TO LIABILITY FOR DEATH OR PERSONAL 316 | INJURY RESULTING FROM SUCH PARTY'S NEGLIGENCE TO THE EXTENT 317 | APPLICABLE LAW PROHIBITS SUCH LIMITATION. SOME JURISDICTIONS DO 318 | NOT ALLOW THE EXCLUSION OR LIMITATION OF INCIDENTAL OR 319 | CONSEQUENTIAL DAMAGES, SO THIS EXCLUSION AND LIMITATION MAY NOT 320 | APPLY TO YOU. 321 | 322 | 8. U.S. GOVERNMENT END USERS. 323 | 324 | The Covered Software is a "commercial item," as that term is 325 | defined in 48 C.F.R. 2.101 (Oct. 1995), consisting of "commercial 326 | computer software" (as that term is defined at 48 327 | C.F.R. 252.227-7014(a)(1)) and "commercial computer software 328 | documentation" as such terms are used in 48 C.F.R. 12.212 329 | (Sept. 1995). Consistent with 48 C.F.R. 12.212 and 48 330 | C.F.R. 227.7202-1 through 227.7202-4 (June 1995), all 331 | U.S. Government End Users acquire Covered Software with only those 332 | rights set forth herein. This U.S. Government Rights clause is in 333 | lieu of, and supersedes, any other FAR, DFAR, or other clause or 334 | provision that addresses Government rights in computer software 335 | under this License. 336 | 337 | 9. MISCELLANEOUS. 338 | 339 | This License represents the complete agreement concerning subject 340 | matter hereof. If any provision of this License is held to be 341 | unenforceable, such provision shall be reformed only to the extent 342 | necessary to make it enforceable. This License shall be governed 343 | by the law of the jurisdiction specified in a notice contained 344 | within the Original Software (except to the extent applicable law, 345 | if any, provides otherwise), excluding such jurisdiction's 346 | conflict-of-law provisions. Any litigation relating to this 347 | License shall be subject to the jurisdiction of the courts located 348 | in the jurisdiction and venue specified in a notice contained 349 | within the Original Software, with the losing party responsible 350 | for costs, including, without limitation, court costs and 351 | reasonable attorneys' fees and expenses. The application of the 352 | United Nations Convention on Contracts for the International Sale 353 | of Goods is expressly excluded. Any law or regulation which 354 | provides that the language of a contract shall be construed 355 | against the drafter shall not apply to this License. You agree 356 | that You alone are responsible for compliance with the United 357 | States export administration regulations (and the export control 358 | laws and regulation of any other countries) when You use, 359 | distribute or otherwise make available any Covered Software. 360 | 361 | 10. RESPONSIBILITY FOR CLAIMS. 362 | 363 | As between Initial Developer and the Contributors, each party is 364 | responsible for claims and damages arising, directly or 365 | indirectly, out of its utilization of rights under this License 366 | and You agree to work with Initial Developer and Contributors to 367 | distribute such responsibility on an equitable basis. Nothing 368 | herein is intended or shall be deemed to constitute any admission 369 | of liability. 370 | 371 | -------------------------------------------------------------------- 372 | 373 | NOTICE PURSUANT TO SECTION 9 OF THE COMMON DEVELOPMENT AND 374 | DISTRIBUTION LICENSE (CDDL) 375 | 376 | For Covered Software in this distribution, this License shall 377 | be governed by the laws of the State of California (excluding 378 | conflict-of-law provisions). 379 | 380 | Any litigation relating to this License shall be subject to the 381 | jurisdiction of the Federal Courts of the Northern District of 382 | California and the state courts of the State of California, with 383 | venue lying in Santa Clara County, California. 384 | -------------------------------------------------------------------------------- /examples/http-hello-world.rs: -------------------------------------------------------------------------------- 1 | extern crate hyper; 2 | 3 | use std::io::write; 4 | 5 | use hyper::server; 6 | use hyper::server::request; 7 | use hyper::server::response; 8 | use hyper::net::fresh; 9 | 10 | fn hello(_: request, res: response) { 11 | res.send(b"hello world!").unwrap(); 12 | } 13 | 14 | fn main() { 15 | server::http("127.0.0.1:3000").unwrap().handle(hello); 16 | } 17 | -------------------------------------------------------------------------------- /examples/loop.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | loop { 3 | some(); 4 | } 5 | } 6 | 7 | fn some() { 8 | stack() 9 | } 10 | 11 | fn stack() { 12 | trace() 13 | } 14 | 15 | fn trace() { 16 | println!("hello world"); 17 | } 18 | -------------------------------------------------------------------------------- /examples/tcp-echo-server.rs: -------------------------------------------------------------------------------- 1 | extern crate coio; 2 | 3 | use std::io::{Read, Write}; 4 | use std::thread; 5 | 6 | use coio::net::TcpListener; 7 | use coio::{spawn, run}; 8 | 9 | fn main() { 10 | spawn(move|| { 11 | let acceptor = TcpListener::bind("127.0.0.1:3000").unwrap(); 12 | 13 | for stream in acceptor.incoming() { 14 | let mut stream = stream.unwrap(); 15 | 16 | spawn(move|| { 17 | let mut buf = [0; 1024]; 18 | 19 | loop { 20 | match stream.read(&mut buf) { 21 | Ok(0) => { 22 | break; 23 | }, 24 | Ok(len) => { 25 | stream.write_all(&buf[0..len]).unwrap(); 26 | }, 27 | Err(err) => { 28 | break; 29 | } 30 | } 31 | } 32 | 33 | }); 34 | } 35 | }); 36 | 37 | run(4); 38 | } 39 | -------------------------------------------------------------------------------- /examples/tcp-echo-server.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 14 | 333 | 334 | Flame Graph 335 | 336 | Reset Zoom 337 | Search 338 | 339 | 340 | epoll_ctl (24 samples, 1.07%) 341 | 342 | 343 | 344 | dev_hard_start_xmit (1 samples, 0.04%) 345 | 346 | 347 | 348 | system_call_fastpath (2 samples, 0.09%) 349 | 350 | 351 | 352 | __libc_start_main (5 samples, 0.22%) 353 | 354 | 355 | 356 | __blk_run_queue (2 samples, 0.09%) 357 | 358 | 359 | 360 | schedule_hrtimeout_range_clock (1 samples, 0.04%) 361 | 362 | 363 | 364 | system_call_fastpath (23 samples, 1.02%) 365 | 366 | 367 | 368 | ip_rcv (1 samples, 0.04%) 369 | 370 | 371 | 372 | runtime::processor::Processor.Handler::ready::h2f1bfbc0b6dfdba0gnc (1 samples, 0.04%) 373 | 374 | 375 | 376 | rt::unwind::try::try_fn::h17892823590535275744 (46 samples, 2.05%) 377 | r.. 378 | 379 | 380 | call_rwsem_wake (1 samples, 0.04%) 381 | 382 | 383 | 384 | do_notify_resume (1 samples, 0.04%) 385 | 386 | 387 | 388 | ep_poll (23 samples, 1.02%) 389 | 390 | 391 | 392 | sys_epoll_wait (23 samples, 1.02%) 393 | 394 | 395 | 396 | __audit_syscall_exit (1 samples, 0.04%) 397 | 398 | 399 | 400 | __slab_alloc (1 samples, 0.04%) 401 | 402 | 403 | 404 | getnstimeofday (2 samples, 0.09%) 405 | 406 | 407 | 408 | __GI___libc_read (1 samples, 0.04%) 409 | 410 | 411 | 412 | tcp_write_xmit (1 samples, 0.04%) 413 | 414 | 415 | 416 | wake_up_process (2 samples, 0.09%) 417 | 418 | 419 | 420 | ip_local_out_sk (2 samples, 0.09%) 421 | 422 | 423 | 424 | system_call_fastpath (2 samples, 0.09%) 425 | 426 | 427 | 428 | process_timeout (2 samples, 0.09%) 429 | 430 | 431 | 432 | sysret_audit (1 samples, 0.04%) 433 | 434 | 435 | 436 | do_sync_read (1 samples, 0.04%) 437 | 438 | 439 | 440 | scheduler::Scheduler::run::do_work::h4e6b4cf7646026ecJWb (24 samples, 1.07%) 441 | 442 | 443 | 444 | netif_rx (2 samples, 0.09%) 445 | 446 | 447 | 448 | call_softirq (1 samples, 0.04%) 449 | 450 | 451 | 452 | coroutine::coroutine_initialize::h6cffbf94287f60d2Utc (46 samples, 2.05%) 453 | c.. 454 | 455 | 456 | boxed::F.FnBox$LT$A$GT$::call_box::h5823809128534621039 (24 samples, 1.07%) 457 | 458 | 459 | 460 | tcp_v4_do_rcv (9 samples, 0.40%) 461 | 462 | 463 | 464 | ep_remove (1 samples, 0.04%) 465 | 466 | 467 | 468 | rt::unwind::try::inner_try::h9ca0fee771d29e74YCw (46 samples, 2.05%) 469 | r.. 470 | 471 | 472 | scsi_io_completion (2 samples, 0.09%) 473 | 474 | 475 | 476 | _raw_spin_unlock_irqrestore (1 samples, 0.04%) 477 | 478 | 479 | 480 | __tcp_push_pending_frames (1 samples, 0.04%) 481 | 482 | 483 | 484 | tcp_close (1 samples, 0.04%) 485 | 486 | 487 | 488 | je_tcache_alloc_small_hard (1 samples, 0.04%) 489 | 490 | 491 | 492 | loopback_xmit (2 samples, 0.09%) 493 | 494 | 495 | 496 | ip_output (2 samples, 0.09%) 497 | 498 | 499 | 500 | je_arena_ralloc (1 samples, 0.04%) 501 | 502 | 503 | 504 | scsi_run_queue (2 samples, 0.09%) 505 | 506 | 507 | 508 | _raw_spin_unlock_irqrestore (1 samples, 0.04%) 509 | 510 | 511 | 512 | arena_run_split_small (1 samples, 0.04%) 513 | 514 | 515 | 516 | __wake_up_sync_key (8 samples, 0.36%) 517 | 518 | 519 | 520 | do_softirq (11 samples, 0.49%) 521 | 522 | 523 | 524 | __GI___libc_write (1,344 samples, 59.76%) 525 | __GI___libc_write 526 | 527 | 528 | sock_aio_write (2 samples, 0.09%) 529 | 530 | 531 | 532 | loopback_xmit (2 samples, 0.09%) 533 | 534 | 535 | 536 | ip_finish_output (1 samples, 0.04%) 537 | 538 | 539 | 540 | dev_hard_start_xmit (2 samples, 0.09%) 541 | 542 | 543 | 544 | copy_user_generic_string (1 samples, 0.04%) 545 | 546 | 547 | 548 | rt::unwind::try::try_fn::h4502362086795080914 (24 samples, 1.07%) 549 | 550 | 551 | 552 | __do_page_fault (1 samples, 0.04%) 553 | 554 | 555 | 556 | schedule_hrtimeout_range (2 samples, 0.09%) 557 | 558 | 559 | 560 | ktime_get_ts (30 samples, 1.33%) 561 | 562 | 563 | 564 | security_file_permission (1 samples, 0.04%) 565 | 566 | 567 | 568 | sock_close (1 samples, 0.04%) 569 | 570 | 571 | 572 | call_timer_fn (2 samples, 0.09%) 573 | 574 | 575 | 576 | ip_finish_output (1,339 samples, 59.54%) 577 | ip_finish_output 578 | 579 | 580 | sock_aio_write (389 samples, 17.30%) 581 | sock_aio_write 582 | 583 | 584 | sys_write (3 samples, 0.13%) 585 | 586 | 587 | 588 | blk_done_softirq (2 samples, 0.09%) 589 | 590 | 591 | 592 | sk_stream_alloc_skb (3 samples, 0.13%) 593 | 594 | 595 | 596 | kmem_cache_alloc_node (1 samples, 0.04%) 597 | 598 | 599 | 600 | __slab_alloc (2 samples, 0.09%) 601 | 602 | 603 | 604 | finish_task_switch (2 samples, 0.09%) 605 | 606 | 607 | 608 | process_backlog (9 samples, 0.40%) 609 | 610 | 611 | 612 | fput (1 samples, 0.04%) 613 | 614 | 615 | 616 | _raw_spin_unlock_irqrestore (2 samples, 0.09%) 617 | 618 | 619 | 620 | inet_release (1 samples, 0.04%) 621 | 622 | 623 | 624 | sys_epoll_wait (58 samples, 2.58%) 625 | sy.. 626 | 627 | 628 | vfs_write (3 samples, 0.13%) 629 | 630 | 631 | 632 | ip_local_out_sk (3 samples, 0.13%) 633 | 634 | 635 | 636 | je_rallocx (1 samples, 0.04%) 637 | 638 | 639 | 640 | unistd::close::hb62f7b5184e0ab02wzi (1 samples, 0.04%) 641 | 642 | 643 | 644 | dev_queue_xmit (2 samples, 0.09%) 645 | 646 | 647 | 648 | boxed::F.FnBox$LT$A$GT$::call_box::h7419086909832966865 (46 samples, 2.05%) 649 | b.. 650 | 651 | 652 | dev_hard_start_xmit (1,327 samples, 59.00%) 653 | dev_hard_start_xmit 654 | 655 | 656 | ktime_get_ts (12 samples, 0.53%) 657 | 658 | 659 | 660 | tcp_rcv_established (1 samples, 0.04%) 661 | 662 | 663 | 664 | do_softirq (2 samples, 0.09%) 665 | 666 | 667 | 668 | net::tcp::TcpStream.io..Read::read::hccf7394e21be1f838sa (2 samples, 0.09%) 669 | 670 | 671 | 672 | sock_def_readable (8 samples, 0.36%) 673 | 674 | 675 | 676 | scsi_request_fn (2 samples, 0.09%) 677 | 678 | 679 | 680 | __getnstimeofday (383 samples, 17.03%) 681 | __getnstimeofday 682 | 683 | 684 | __GI___libc_write (3 samples, 0.13%) 685 | 686 | 687 | 688 | __schedule (1 samples, 0.04%) 689 | 690 | 691 | 692 | try_to_wake_up (2 samples, 0.09%) 693 | 694 | 695 | 696 | ktime_get_real (1,327 samples, 59.00%) 697 | ktime_get_real 698 | 699 | 700 | sock_aio_read (1 samples, 0.04%) 701 | 702 | 703 | 704 | flush_tlb_mm_range (1 samples, 0.04%) 705 | 706 | 707 | 708 | __getnstimeofday (2 samples, 0.09%) 709 | 710 | 711 | 712 | tcp_v4_rcv (9 samples, 0.40%) 713 | 714 | 715 | 716 | [unknown] (1 samples, 0.04%) 717 | 718 | 719 | 720 | __schedule (2 samples, 0.09%) 721 | 722 | 723 | 724 | read_tsc (1 samples, 0.04%) 725 | 726 | 727 | 728 | rust_swap_registers (5 samples, 0.22%) 729 | 730 | 731 | 732 | __alloc_skb (5 samples, 0.22%) 733 | 734 | 735 | 736 | __kmalloc_node_track_caller (2 samples, 0.09%) 737 | 738 | 739 | 740 | new_slab (3 samples, 0.13%) 741 | 742 | 743 | 744 | getnstimeofday (383 samples, 17.03%) 745 | getnstimeofday 746 | 747 | 748 | native_read_tsc (26 samples, 1.16%) 749 | 750 | 751 | 752 | native_read_tsc (30 samples, 1.33%) 753 | 754 | 755 | 756 | runtime::processor::Processor::wait_event::h18029769354204888263 (1 samples, 0.04%) 757 | 758 | 759 | 760 | start_thread (24 samples, 1.07%) 761 | 762 | 763 | 764 | ep_remove (1 samples, 0.04%) 765 | 766 | 767 | 768 | loopback_xmit (1,327 samples, 59.00%) 769 | loopback_xmit 770 | 771 | 772 | tcp-echo-server (2,249 samples, 100.00%) 773 | tcp-echo-server 774 | 775 | 776 | unmap_region (1 samples, 0.04%) 777 | 778 | 779 | 780 | dev_queue_xmit (1,327 samples, 59.00%) 781 | dev_queue_xmit 782 | 783 | 784 | ip_finish_output (385 samples, 17.12%) 785 | ip_finish_output 786 | 787 | 788 | __kmalloc_reserve.isra.27 (2 samples, 0.09%) 789 | 790 | 791 | 792 | dev_queue_xmit (383 samples, 17.03%) 793 | dev_queue_xmit 794 | 795 | 796 | generic_exec_single (1 samples, 0.04%) 797 | 798 | 799 | 800 | all (2,249 samples, 100%) 801 | 802 | 803 | 804 | net_rx_action (9 samples, 0.40%) 805 | 806 | 807 | 808 | system_call_fastpath (1 samples, 0.04%) 809 | 810 | 811 | 812 | main::h85ff8205cc6450b0naa (5 samples, 0.22%) 813 | 814 | 815 | 816 | tcp_data_queue (1 samples, 0.04%) 817 | 818 | 819 | 820 | __wake_up_sync_key (1 samples, 0.04%) 821 | 822 | 823 | 824 | scsi_softirq_done (2 samples, 0.09%) 825 | 826 | 827 | 828 | system_call_fastpath (24 samples, 1.07%) 829 | 830 | 831 | 832 | native_read_tsc (10 samples, 0.44%) 833 | 834 | 835 | 836 | __slab_alloc (3 samples, 0.13%) 837 | 838 | 839 | 840 | getnstimeofday (1 samples, 0.04%) 841 | 842 | 843 | 844 | __do_softirq (1 samples, 0.04%) 845 | 846 | 847 | 848 | native_read_tsc (12 samples, 0.53%) 849 | 850 | 851 | 852 | read_tsc (26 samples, 1.16%) 853 | 854 | 855 | 856 | ktime_get_real (383 samples, 17.03%) 857 | ktime_get_real 858 | 859 | 860 | task_work_run (1 samples, 0.04%) 861 | 862 | 863 | 864 | [unknown] (496 samples, 22.05%) 865 | [unknown] 866 | 867 | 868 | tcp_transmit_skb (1 samples, 0.04%) 869 | 870 | 871 | 872 | coroutine::Coroutine.Drop::drop::h87e8bce25b2ee7c2Uwc (1 samples, 0.04%) 873 | 874 | 875 | 876 | ____fput (1 samples, 0.04%) 877 | 878 | 879 | 880 | inet_sendmsg (3 samples, 0.13%) 881 | 882 | 883 | 884 | arena_bin_nonfull_run_get (1 samples, 0.04%) 885 | 886 | 887 | 888 | getnstimeofday (1,327 samples, 59.00%) 889 | getnstimeofday 890 | 891 | 892 | scsi_finish_command (2 samples, 0.09%) 893 | 894 | 895 | 896 | netif_rx (1,327 samples, 59.00%) 897 | netif_rx 898 | 899 | 900 | __getnstimeofday (2 samples, 0.09%) 901 | 902 | 903 | 904 | loopback_xmit (383 samples, 17.03%) 905 | loopback_xmit 906 | 907 | 908 | boxed::F.FnBox$LT$A$GT$::call_box::h16325064753305179035 (24 samples, 1.07%) 909 | 910 | 911 | 912 | [unknown] (23 samples, 1.02%) 913 | 914 | 915 | 916 | __GI___libc_write (389 samples, 17.30%) 917 | __GI___libc_write 918 | 919 | 920 | ip_queue_xmit (2 samples, 0.09%) 921 | 922 | 923 | 924 | dev_hard_start_xmit (383 samples, 17.03%) 925 | dev_hard_start_xmit 926 | 927 | 928 | kmem_cache_alloc (21 samples, 0.93%) 929 | 930 | 931 | 932 | do_softirq (1 samples, 0.04%) 933 | 934 | 935 | 936 | vfs_write (389 samples, 17.30%) 937 | vfs_write 938 | 939 | 940 | ip_output (385 samples, 17.12%) 941 | ip_output 942 | 943 | 944 | scsi_dispatch_cmd (2 samples, 0.09%) 945 | 946 | 947 | 948 | __tcp_push_pending_frames (1,339 samples, 59.54%) 949 | __tcp_push_pending_frames 950 | 951 | 952 | int_signal (1 samples, 0.04%) 953 | 954 | 955 | 956 | dev_hard_start_xmit (2 samples, 0.09%) 957 | 958 | 959 | 960 | read_tsc (10 samples, 0.44%) 961 | 962 | 963 | 964 | ip_output (1 samples, 0.04%) 965 | 966 | 967 | 968 | new_slab (2 samples, 0.09%) 969 | 970 | 971 | 972 | rt::unwind::try::try_fn::h12779039427349098015 (5 samples, 0.22%) 973 | 974 | 975 | 976 | do_sync_write (3 samples, 0.13%) 977 | 978 | 979 | 980 | sock_aio_read.part.7 (1 samples, 0.04%) 981 | 982 | 983 | 984 | tcp_transmit_skb (3 samples, 0.13%) 985 | 986 | 987 | 988 | rwsem_wake (1 samples, 0.04%) 989 | 990 | 991 | 992 | ip_output (1,339 samples, 59.54%) 993 | ip_output 994 | 995 | 996 | do_sync_write (389 samples, 17.30%) 997 | do_sync_write 998 | 999 | 1000 | local_bh_enable (11 samples, 0.49%) 1001 | 1002 | 1003 | 1004 | ip_local_deliver_finish (1 samples, 0.04%) 1005 | 1006 | 1007 | 1008 | _start (5 samples, 0.22%) 1009 | 1010 | 1011 | 1012 | coroutine..Coroutine::drop.14425::h1dd92738e0160651 (1 samples, 0.04%) 1013 | 1014 | 1015 | 1016 | ata_scsi_queuecmd (2 samples, 0.09%) 1017 | 1018 | 1019 | 1020 | sys_write (1,344 samples, 59.76%) 1021 | sys_write 1022 | 1023 | 1024 | __netif_receive_skb (9 samples, 0.40%) 1025 | 1026 | 1027 | 1028 | tlb_finish_mmu (1 samples, 0.04%) 1029 | 1030 | 1031 | 1032 | system_call_fastpath (58 samples, 2.58%) 1033 | sy.. 1034 | 1035 | 1036 | system_call_fastpath (1,344 samples, 59.76%) 1037 | system_call_fastpath 1038 | 1039 | 1040 | __getnstimeofday (1,327 samples, 59.00%) 1041 | __getnstimeofday 1042 | 1043 | 1044 | tcp_transmit_skb (2 samples, 0.09%) 1045 | 1046 | 1047 | 1048 | tcp_sendmsg (389 samples, 17.30%) 1049 | tcp_sendmsg 1050 | 1051 | 1052 | flat_send_IPI_mask (1 samples, 0.04%) 1053 | 1054 | 1055 | 1056 | ktime_get_real (1 samples, 0.04%) 1057 | 1058 | 1059 | 1060 | read_tsc (2 samples, 0.09%) 1061 | 1062 | 1063 | 1064 | sys_epoll_ctl (24 samples, 1.07%) 1065 | 1066 | 1067 | 1068 | __GI___libc_write (2 samples, 0.09%) 1069 | 1070 | 1071 | 1072 | vm_munmap (1 samples, 0.04%) 1073 | 1074 | 1075 | 1076 | page_fault (1 samples, 0.04%) 1077 | 1078 | 1079 | 1080 | __rust_try (46 samples, 2.05%) 1081 | _.. 1082 | 1083 | 1084 | ip_rcv_finish (1 samples, 0.04%) 1085 | 1086 | 1087 | 1088 | __tcp_push_pending_frames (3 samples, 0.13%) 1089 | 1090 | 1091 | 1092 | dev_queue_xmit (2 samples, 0.09%) 1093 | 1094 | 1095 | 1096 | netif_rx (1 samples, 0.04%) 1097 | 1098 | 1099 | 1100 | sys_munmap (1 samples, 0.04%) 1101 | 1102 | 1103 | 1104 | __netif_receive_skb_core (1 samples, 0.04%) 1105 | 1106 | 1107 | 1108 | tcp_sendmsg (1,344 samples, 59.76%) 1109 | tcp_sendmsg 1110 | 1111 | 1112 | raw_vec::RawVec$LT$T$GT$::double::h11653863171647985615 (1 samples, 0.04%) 1113 | 1114 | 1115 | 1116 | rt::lang_start::h4313dede6ffdb373Hax (5 samples, 0.22%) 1117 | 1118 | 1119 | 1120 | arena_avail_tree_insert (1 samples, 0.04%) 1121 | 1122 | 1123 | 1124 | stack::StackPool::give_stack::h4f9d42b50852970cmza (1 samples, 0.04%) 1125 | 1126 | 1127 | 1128 | je_arena_tcache_fill_small (1 samples, 0.04%) 1129 | 1130 | 1131 | 1132 | result::Result$LT$T$C$$u20$E$GT$::or_else::h17779492161281178275 (1 samples, 0.04%) 1133 | 1134 | 1135 | 1136 | netif_rx (383 samples, 17.03%) 1137 | netif_rx 1138 | 1139 | 1140 | __kmalloc_node_track_caller (2 samples, 0.09%) 1141 | 1142 | 1143 | 1144 | ip_finish_output (2 samples, 0.09%) 1145 | 1146 | 1147 | 1148 | do_munmap (1 samples, 0.04%) 1149 | 1150 | 1151 | 1152 | sys_write (389 samples, 17.30%) 1153 | sys_write 1154 | 1155 | 1156 | __fput (1 samples, 0.04%) 1157 | 1158 | 1159 | 1160 | ip_output (3 samples, 0.13%) 1161 | 1162 | 1163 | 1164 | __getnstimeofday (1 samples, 0.04%) 1165 | 1166 | 1167 | 1168 | tcp_rcv_established (9 samples, 0.40%) 1169 | 1170 | 1171 | 1172 | sk_stream_alloc_skb (5 samples, 0.22%) 1173 | 1174 | 1175 | 1176 | ip_finish_output (3 samples, 0.13%) 1177 | 1178 | 1179 | 1180 | inet_sendmsg (2 samples, 0.09%) 1181 | 1182 | 1183 | 1184 | ip_queue_xmit (385 samples, 17.12%) 1185 | ip_queue_xmit 1186 | 1187 | 1188 | read_tsc (2 samples, 0.09%) 1189 | 1190 | 1191 | 1192 | ip_local_deliver (9 samples, 0.40%) 1193 | 1194 | 1195 | 1196 | dev_queue_xmit (1 samples, 0.04%) 1197 | 1198 | 1199 | 1200 | tcp_v4_do_rcv (1 samples, 0.04%) 1201 | 1202 | 1203 | 1204 | system_call_fastpath (389 samples, 17.30%) 1205 | system_call_fastpath 1206 | 1207 | 1208 | process_backlog (1 samples, 0.04%) 1209 | 1210 | 1211 | 1212 | ktime_get_ts (10 samples, 0.44%) 1213 | 1214 | 1215 | 1216 | native_read_tsc (2 samples, 0.09%) 1217 | 1218 | 1219 | 1220 | new_slab (21 samples, 0.93%) 1221 | 1222 | 1223 | 1224 | sock_aio_write (1,344 samples, 59.76%) 1225 | sock_aio_write 1226 | 1227 | 1228 | vfs_write (1,344 samples, 59.76%) 1229 | vfs_write 1230 | 1231 | 1232 | tcp_v4_rcv (1 samples, 0.04%) 1233 | 1234 | 1235 | 1236 | net_rx_action (1 samples, 0.04%) 1237 | 1238 | 1239 | 1240 | run_timer_softirq (2 samples, 0.09%) 1241 | 1242 | 1243 | 1244 | loopback_xmit (1 samples, 0.04%) 1245 | 1246 | 1247 | 1248 | scsi_next_command (2 samples, 0.09%) 1249 | 1250 | 1251 | 1252 | __rust_try (5 samples, 0.22%) 1253 | 1254 | 1255 | 1256 | __GI___libc_read (2 samples, 0.09%) 1257 | 1258 | 1259 | 1260 | system_call_fastpath (2 samples, 0.09%) 1261 | 1262 | 1263 | 1264 | sock_aio_write (3 samples, 0.13%) 1265 | 1266 | 1267 | 1268 | ktime_get_real (2 samples, 0.09%) 1269 | 1270 | 1271 | 1272 | __alloc_skb (3 samples, 0.13%) 1273 | 1274 | 1275 | 1276 | call_softirq (11 samples, 0.49%) 1277 | 1278 | 1279 | 1280 | unistd::write::hdc57a188f3c7e2c6DAi (3 samples, 0.13%) 1281 | 1282 | 1283 | 1284 | sys_write (2 samples, 0.09%) 1285 | 1286 | 1287 | 1288 | local_bh_enable (1 samples, 0.04%) 1289 | 1290 | 1291 | 1292 | result::Result$LT$T$C$$u20$E$GT$::or_else::h17779492161281178275 (40 samples, 1.78%) 1293 | 1294 | 1295 | 1296 | read_tsc (1,327 samples, 59.00%) 1297 | read_tsc 1298 | 1299 | 1300 | ip_local_out_sk (385 samples, 17.12%) 1301 | ip_local_out_sk 1302 | 1303 | 1304 | poll::Poll::poll::h44114ce574148be0Oec (1 samples, 0.04%) 1305 | 1306 | 1307 | 1308 | skb_copy_datagram_iovec (1 samples, 0.04%) 1309 | 1310 | 1311 | 1312 | runtime::processor::Processor.Handler::ready::h2f1bfbc0b6dfdba0gnc (22 samples, 0.98%) 1313 | 1314 | 1315 | 1316 | read_tsc (12 samples, 0.53%) 1317 | 1318 | 1319 | 1320 | net::tcp::TcpStream.io..Write::write::h384b64e3856c0349XCa (43 samples, 1.91%) 1321 | n.. 1322 | 1323 | 1324 | __tcp_push_pending_frames (386 samples, 17.16%) 1325 | __tcp_push_pending_frames 1326 | 1327 | 1328 | tcp_transmit_skb (1,339 samples, 59.54%) 1329 | tcp_transmit_skb 1330 | 1331 | 1332 | _raw_spin_unlock_irqrestore (8 samples, 0.36%) 1333 | 1334 | 1335 | 1336 | ip_queue_xmit (1 samples, 0.04%) 1337 | 1338 | 1339 | 1340 | ip_local_deliver (1 samples, 0.04%) 1341 | 1342 | 1343 | 1344 | ip_queue_xmit (3 samples, 0.13%) 1345 | 1346 | 1347 | 1348 | scheduler::Scheduler::run::h3b724faae036f8825Vb (5 samples, 0.22%) 1349 | 1350 | 1351 | 1352 | inet_sendmsg (1,344 samples, 59.76%) 1353 | inet_sendmsg 1354 | 1355 | 1356 | __tcp_push_pending_frames (2 samples, 0.09%) 1357 | 1358 | 1359 | 1360 | local_bh_enable (2 samples, 0.09%) 1361 | 1362 | 1363 | 1364 | finish_task_switch (1 samples, 0.04%) 1365 | 1366 | 1367 | 1368 | tcp_data_queue (8 samples, 0.36%) 1369 | 1370 | 1371 | 1372 | ip_rcv_finish (9 samples, 0.40%) 1373 | 1374 | 1375 | 1376 | do_page_fault (1 samples, 0.04%) 1377 | 1378 | 1379 | 1380 | tcp_send_delayed_ack (1 samples, 0.04%) 1381 | 1382 | 1383 | 1384 | tcp_sendmsg (3 samples, 0.13%) 1385 | 1386 | 1387 | 1388 | new_slab (2 samples, 0.09%) 1389 | 1390 | 1391 | 1392 | ktime_get_ts (26 samples, 1.16%) 1393 | 1394 | 1395 | 1396 | system_call_fastpath (3 samples, 0.13%) 1397 | 1398 | 1399 | 1400 | thread_rng::h90d2df7457948f74oWd (2 samples, 0.09%) 1401 | 1402 | 1403 | 1404 | ip_local_out_sk (1 samples, 0.04%) 1405 | 1406 | 1407 | 1408 | _raw_spin_unlock_irqrestore (2 samples, 0.09%) 1409 | 1410 | 1411 | 1412 | ktime_get_real (2 samples, 0.09%) 1413 | 1414 | 1415 | 1416 | ip_local_deliver_finish (9 samples, 0.40%) 1417 | 1418 | 1419 | 1420 | schedule_hrtimeout_range_clock (2 samples, 0.09%) 1421 | 1422 | 1423 | 1424 | __do_softirq (2 samples, 0.09%) 1425 | 1426 | 1427 | 1428 | dput (1 samples, 0.04%) 1429 | 1430 | 1431 | 1432 | sock_def_readable (1 samples, 0.04%) 1433 | 1434 | 1435 | 1436 | rb_erase (1 samples, 0.04%) 1437 | 1438 | 1439 | 1440 | net::tcp::TcpStream.Write::write::hd82c12ce9ba733b0emb (3 samples, 0.13%) 1441 | 1442 | 1443 | 1444 | sys::thread::Thread::new::thread_start::hda9462d1945ff67eLMv (24 samples, 1.07%) 1445 | 1446 | 1447 | 1448 | call_softirq (2 samples, 0.09%) 1449 | 1450 | 1451 | 1452 | rt::unwind::try::inner_try::h9ca0fee771d29e74YCw (24 samples, 1.07%) 1453 | 1454 | 1455 | 1456 | tcp_write_xmit (2 samples, 0.09%) 1457 | 1458 | 1459 | 1460 | epoll_ctl (2 samples, 0.09%) 1461 | 1462 | 1463 | 1464 | select_estimate_accuracy (12 samples, 0.53%) 1465 | 1466 | 1467 | 1468 | native_send_call_func_single_ipi (1 samples, 0.04%) 1469 | 1470 | 1471 | 1472 | native_read_tsc (1 samples, 0.04%) 1473 | 1474 | 1475 | 1476 | native_read_tsc (383 samples, 17.03%) 1477 | native_read_tsc 1478 | 1479 | 1480 | tcp_write_xmit (386 samples, 17.16%) 1481 | tcp_write_xmit 1482 | 1483 | 1484 | ip_queue_xmit (1,339 samples, 59.54%) 1485 | ip_queue_xmit 1486 | 1487 | 1488 | tcp_transmit_skb (385 samples, 17.12%) 1489 | tcp_transmit_skb 1490 | 1491 | 1492 | __rust_try (24 samples, 1.07%) 1493 | 1494 | 1495 | 1496 | netif_rx (2 samples, 0.09%) 1497 | 1498 | 1499 | 1500 | tcp_write_xmit (1,339 samples, 59.54%) 1501 | tcp_write_xmit 1502 | 1503 | 1504 | tlb_flush_mmu.part.53 (1 samples, 0.04%) 1505 | 1506 | 1507 | 1508 | sys_epoll_ctl (2 samples, 0.09%) 1509 | 1510 | 1511 | 1512 | __do_softirq (11 samples, 0.49%) 1513 | 1514 | 1515 | 1516 | vfs_write (2 samples, 0.09%) 1517 | 1518 | 1519 | 1520 | scheduler::Scheduler::run::do_work::h4e6b4cf7646026ecJWb (5 samples, 0.22%) 1521 | 1522 | 1523 | 1524 | inet_recvmsg (1 samples, 0.04%) 1525 | 1526 | 1527 | 1528 | vfs_read (2 samples, 0.09%) 1529 | 1530 | 1531 | 1532 | __netif_receive_skb_core (9 samples, 0.40%) 1533 | 1534 | 1535 | 1536 | tcp_sendmsg (2 samples, 0.09%) 1537 | 1538 | 1539 | 1540 | sys_read (2 samples, 0.09%) 1541 | 1542 | 1543 | 1544 | do_sync_write (2 samples, 0.09%) 1545 | 1546 | 1547 | 1548 | __slab_alloc (2 samples, 0.09%) 1549 | 1550 | 1551 | 1552 | _raw_spin_unlock_irqrestore (1 samples, 0.04%) 1553 | 1554 | 1555 | 1556 | kmem_cache_alloc_node (3 samples, 0.13%) 1557 | 1558 | 1559 | 1560 | __slab_alloc (21 samples, 0.93%) 1561 | 1562 | 1563 | 1564 | schedule (2 samples, 0.09%) 1565 | 1566 | 1567 | 1568 | tcp_write_xmit (3 samples, 0.13%) 1569 | 1570 | 1571 | 1572 | read_tsc (30 samples, 1.33%) 1573 | 1574 | 1575 | 1576 | ip_local_out_sk (1,339 samples, 59.54%) 1577 | ip_local_out_sk 1578 | 1579 | 1580 | native_flush_tlb_others (1 samples, 0.04%) 1581 | 1582 | 1583 | 1584 | smp_call_function_many (1 samples, 0.04%) 1585 | 1586 | 1587 | 1588 | read_tsc (383 samples, 17.03%) 1589 | read_tsc 1590 | 1591 | 1592 | __GI___libc_close (1 samples, 0.04%) 1593 | 1594 | 1595 | 1596 | do_sync_write (1,344 samples, 59.76%) 1597 | do_sync_write 1598 | 1599 | 1600 | ep_poll (58 samples, 2.58%) 1601 | ep.. 1602 | 1603 | 1604 | inet_sendmsg (389 samples, 17.30%) 1605 | inet_sendmsg 1606 | 1607 | 1608 | selinux_file_permission (1 samples, 0.04%) 1609 | 1610 | 1611 | 1612 | __netif_receive_skb (1 samples, 0.04%) 1613 | 1614 | 1615 | 1616 | sock_release (1 samples, 0.04%) 1617 | 1618 | 1619 | 1620 | tcp_send_fin (1 samples, 0.04%) 1621 | 1622 | 1623 | 1624 | blk_run_queue (2 samples, 0.09%) 1625 | 1626 | 1627 | 1628 | getnstimeofday (2 samples, 0.09%) 1629 | 1630 | 1631 | 1632 | schedule_hrtimeout_range (1 samples, 0.04%) 1633 | 1634 | 1635 | 1636 | smp_call_function_single (1 samples, 0.04%) 1637 | 1638 | 1639 | 1640 | __clone (24 samples, 1.07%) 1641 | 1642 | 1643 | 1644 | new_slab (1 samples, 0.04%) 1645 | 1646 | 1647 | 1648 | __kmalloc_reserve.isra.27 (2 samples, 0.09%) 1649 | 1650 | 1651 | 1652 | tcp_recvmsg (1 samples, 0.04%) 1653 | 1654 | 1655 | 1656 | ip_rcv (9 samples, 0.40%) 1657 | 1658 | 1659 | 1660 | schedule (1 samples, 0.04%) 1661 | 1662 | 1663 | 1664 | Worker$LT$T$GT$::pop::h8298562288461272140 (2 samples, 0.09%) 1665 | 1666 | 1667 | 1668 | rw_verify_area (1 samples, 0.04%) 1669 | 1670 | 1671 | 1672 | native_read_tsc (2 samples, 0.09%) 1673 | 1674 | 1675 | 1676 | mutex_lock (1 samples, 0.04%) 1677 | 1678 | 1679 | 1680 | native_read_tsc (1,327 samples, 59.00%) 1681 | native_read_tsc 1682 | 1683 | 1684 | select_estimate_accuracy (26 samples, 1.16%) 1685 | 1686 | 1687 | 1688 | -------------------------------------------------------------------------------- /flamegraph.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl -w 2 | # 3 | # flamegraph.pl flame stack grapher. 4 | # 5 | # This takes stack samples and renders a call graph, allowing hot functions 6 | # and codepaths to be quickly identified. Stack samples can be generated using 7 | # tools such as DTrace, perf, SystemTap, and Instruments. 8 | # 9 | # USAGE: ./flamegraph.pl [options] input.txt > graph.svg 10 | # 11 | # grep funcA input.txt | ./flamegraph.pl [options] > graph.svg 12 | # 13 | # Then open the resulting .svg in a web browser, for interactivity: mouse-over 14 | # frames for info, click to zoom, and ctrl-F to search. 15 | # 16 | # Options are listed in the usage message (--help). 17 | # 18 | # The input is stack frames and sample counts formatted as single lines. Each 19 | # frame in the stack is semicolon separated, with a space and count at the end 20 | # of the line. These can be generated using DTrace with stackcollapse.pl, 21 | # and other tools using the stackcollapse variants. 22 | # 23 | # An optional extra column of counts can be provided to generate a differential 24 | # flame graph of the counts, colored red for more, and blue for less. This 25 | # can be useful when using flame graphs for non-regression testing. 26 | # See the header comment in the difffolded.pl program for instructions. 27 | # 28 | # The output graph shows relative presence of functions in stack samples. The 29 | # ordering on the x-axis has no meaning; since the data is samples, time order 30 | # of events is not known. The order used sorts function names alphabetically. 31 | # 32 | # While intended to process stack samples, this can also process stack traces. 33 | # For example, tracing stacks for memory allocation, or resource usage. You 34 | # can use --title to set the title to reflect the content, and --countname 35 | # to change "samples" to "bytes" etc. 36 | # 37 | # There are a few different palettes, selectable using --color. By default, 38 | # the colors are selected at random (except for differentials). Functions 39 | # called "-" will be printed gray, which can be used for stack separators (eg, 40 | # between user and kernel stacks). 41 | # 42 | # HISTORY 43 | # 44 | # This was inspired by Neelakanth Nadgir's excellent function_call_graph.rb 45 | # program, which visualized function entry and return trace events. As Neel 46 | # wrote: "The output displayed is inspired by Roch's CallStackAnalyzer which 47 | # was in turn inspired by the work on vftrace by Jan Boerhout". See: 48 | # https://blogs.oracle.com/realneel/entry/visualizing_callstacks_via_dtrace_and 49 | # 50 | # Copyright 2011 Joyent, Inc. All rights reserved. 51 | # Copyright 2011 Brendan Gregg. All rights reserved. 52 | # 53 | # CDDL HEADER START 54 | # 55 | # The contents of this file are subject to the terms of the 56 | # Common Development and Distribution License (the "License"). 57 | # You may not use this file except in compliance with the License. 58 | # 59 | # You can obtain a copy of the license at docs/cddl1.txt or 60 | # http://opensource.org/licenses/CDDL-1.0. 61 | # See the License for the specific language governing permissions 62 | # and limitations under the License. 63 | # 64 | # When distributing Covered Code, include this CDDL HEADER in each 65 | # file and include the License file at docs/cddl1.txt. 66 | # If applicable, add the following below this CDDL HEADER, with the 67 | # fields enclosed by brackets "[]" replaced with your own identifying 68 | # information: Portions Copyright [yyyy] [name of copyright owner] 69 | # 70 | # CDDL HEADER END 71 | # 72 | # 11-Oct-2014 Adrien Mahieux Added zoom. 73 | # 21-Nov-2013 Shawn Sterling Added consistent palette file option 74 | # 17-Mar-2013 Tim Bunce Added options and more tunables. 75 | # 15-Dec-2011 Dave Pacheco Support for frames with whitespace. 76 | # 10-Sep-2011 Brendan Gregg Created this. 77 | 78 | use strict; 79 | 80 | use Getopt::Long; 81 | 82 | # tunables 83 | my $encoding; 84 | my $fonttype = "Verdana"; 85 | my $imagewidth = 1200; # max width, pixels 86 | my $frameheight = 16; # max height is dynamic 87 | my $fontsize = 12; # base text size 88 | my $fontwidth = 0.59; # avg width relative to fontsize 89 | my $minwidth = 0.1; # min function width, pixels 90 | my $nametype = "Function:"; # what are the names in the data? 91 | my $countname = "samples"; # what are the counts in the data? 92 | my $colors = "hot"; # color theme 93 | my $bgcolor1 = "#eeeeee"; # background color gradient start 94 | my $bgcolor2 = "#eeeeb0"; # background color gradient stop 95 | my $nameattrfile; # file holding function attributes 96 | my $timemax; # (override the) sum of the counts 97 | my $factor = 1; # factor to scale counts by 98 | my $hash = 0; # color by function name 99 | my $palette = 0; # if we use consistent palettes (default off) 100 | my %palette_map; # palette map hash 101 | my $pal_file = "palette.map"; # palette map file name 102 | my $stackreverse = 0; # reverse stack order, switching merge end 103 | my $inverted = 0; # icicle graph 104 | my $negate = 0; # switch differential hues 105 | my $titletext = ""; # centered heading 106 | my $titledefault = "Flame Graph"; # overwritten by --title 107 | my $titleinverted = "Icicle Graph"; # " " 108 | my $searchcolor = "rgb(230,0,230)"; # color for search highlighting 109 | my $help = 0; 110 | 111 | sub usage { 112 | die < outfile.svg\n 114 | --title # change title text 115 | --width # width of image (default 1200) 116 | --height # height of each frame (default 16) 117 | --minwidth # omit smaller functions (default 0.1 pixels) 118 | --fonttype # font type (default "Verdana") 119 | --fontsize # font size (default 12) 120 | --countname # count type label (default "samples") 121 | --nametype # name type label (default "Function:") 122 | --colors # set color palette. choices are: hot (default), mem, io, 123 | # java, js, red, green, blue, yellow, purple, orange 124 | --hash # colors are keyed by function name hash 125 | --cp # use consistent palette (palette.map) 126 | --reverse # generate stack-reversed flame graph 127 | --inverted # icicle graph 128 | --negate # switch differential hues (blue<->red) 129 | --help # this message 130 | 131 | eg, 132 | $0 --title="Flame Graph: malloc()" trace.txt > graph.svg 133 | USAGE_END 134 | } 135 | 136 | GetOptions( 137 | 'fonttype=s' => \$fonttype, 138 | 'width=i' => \$imagewidth, 139 | 'height=i' => \$frameheight, 140 | 'encoding=s' => \$encoding, 141 | 'fontsize=f' => \$fontsize, 142 | 'fontwidth=f' => \$fontwidth, 143 | 'minwidth=f' => \$minwidth, 144 | 'title=s' => \$titletext, 145 | 'nametype=s' => \$nametype, 146 | 'countname=s' => \$countname, 147 | 'nameattr=s' => \$nameattrfile, 148 | 'total=s' => \$timemax, 149 | 'factor=f' => \$factor, 150 | 'colors=s' => \$colors, 151 | 'hash' => \$hash, 152 | 'cp' => \$palette, 153 | 'reverse' => \$stackreverse, 154 | 'inverted' => \$inverted, 155 | 'negate' => \$negate, 156 | 'help' => \$help, 157 | ) or usage(); 158 | $help && usage(); 159 | 160 | # internals 161 | my $ypad1 = $fontsize * 4; # pad top, include title 162 | my $ypad2 = $fontsize * 2 + 10; # pad bottom, include labels 163 | my $xpad = 10; # pad lefm and right 164 | my $framepad = 1; # vertical padding for frames 165 | my $depthmax = 0; 166 | my %Events; 167 | my %nameattr; 168 | 169 | if ($titletext eq "") { 170 | unless ($inverted) { 171 | $titletext = $titledefault; 172 | } else { 173 | $titletext = $titleinverted; 174 | } 175 | } 176 | 177 | if ($nameattrfile) { 178 | # The name-attribute file format is a function name followed by a tab then 179 | # a sequence of tab separated name=value pairs. 180 | open my $attrfh, $nameattrfile or die "Can't read $nameattrfile: $!\n"; 181 | while (<$attrfh>) { 182 | chomp; 183 | my ($funcname, $attrstr) = split /\t/, $_, 2; 184 | die "Invalid format in $nameattrfile" unless defined $attrstr; 185 | $nameattr{$funcname} = { map { split /=/, $_, 2 } split /\t/, $attrstr }; 186 | } 187 | } 188 | 189 | if ($colors eq "mem") { $bgcolor1 = "#eeeeee"; $bgcolor2 = "#e0e0ff"; } 190 | if ($colors eq "io") { $bgcolor1 = "#f8f8f8"; $bgcolor2 = "#e8e8e8"; } 191 | 192 | # SVG functions 193 | { package SVG; 194 | sub new { 195 | my $class = shift; 196 | my $self = {}; 197 | bless ($self, $class); 198 | return $self; 199 | } 200 | 201 | sub header { 202 | my ($self, $w, $h) = @_; 203 | my $enc_attr = ''; 204 | if (defined $encoding) { 205 | $enc_attr = qq{ encoding="$encoding"}; 206 | } 207 | $self->{svg} .= < 209 | 210 | 211 | 212 | SVG 213 | } 214 | 215 | sub include { 216 | my ($self, $content) = @_; 217 | $self->{svg} .= $content; 218 | } 219 | 220 | sub colorAllocate { 221 | my ($self, $r, $g, $b) = @_; 222 | return "rgb($r,$g,$b)"; 223 | } 224 | 225 | sub group_start { 226 | my ($self, $attr) = @_; 227 | 228 | my @g_attr = map { 229 | exists $attr->{$_} ? sprintf(qq/$_="%s"/, $attr->{$_}) : () 230 | } qw(class style onmouseover onmouseout onclick); 231 | push @g_attr, $attr->{g_extra} if $attr->{g_extra}; 232 | $self->{svg} .= sprintf qq/\n/, join(' ', @g_attr); 233 | 234 | $self->{svg} .= sprintf qq/%s<\/title>/, $attr->{title} 235 | if $attr->{title}; # should be first element within g container 236 | 237 | if ($attr->{href}) { 238 | my @a_attr; 239 | push @a_attr, sprintf qq/xlink:href="%s"/, $attr->{href} if $attr->{href}; 240 | # default target=_top else links will open within SVG 241 | push @a_attr, sprintf qq/target="%s"/, $attr->{target} || "_top"; 242 | push @a_attr, $attr->{a_extra} if $attr->{a_extra}; 243 | $self->{svg} .= sprintf qq//, join(' ', @a_attr); 244 | } 245 | } 246 | 247 | sub group_end { 248 | my ($self, $attr) = @_; 249 | $self->{svg} .= qq/<\/a>\n/ if $attr->{href}; 250 | $self->{svg} .= qq/<\/g>\n/; 251 | } 252 | 253 | sub filledRectangle { 254 | my ($self, $x1, $y1, $x2, $y2, $fill, $extra) = @_; 255 | $x1 = sprintf "%0.1f", $x1; 256 | $x2 = sprintf "%0.1f", $x2; 257 | my $w = sprintf "%0.1f", $x2 - $x1; 258 | my $h = sprintf "%0.1f", $y2 - $y1; 259 | $extra = defined $extra ? $extra : ""; 260 | $self->{svg} .= qq/\n/; 261 | } 262 | 263 | sub stringTTF { 264 | my ($self, $color, $font, $size, $angle, $x, $y, $str, $loc, $extra) = @_; 265 | $x = sprintf "%0.2f", $x; 266 | $loc = defined $loc ? $loc : "left"; 267 | $extra = defined $extra ? $extra : ""; 268 | $self->{svg} .= qq/$str<\/text>\n/; 269 | } 270 | 271 | sub svg { 272 | my $self = shift; 273 | return "$self->{svg}\n"; 274 | } 275 | 1; 276 | } 277 | 278 | sub namehash { 279 | # Generate a vector hash for the name string, weighting early over 280 | # later characters. We want to pick the same colors for function 281 | # names across different flame graphs. 282 | my $name = shift; 283 | my $vector = 0; 284 | my $weight = 1; 285 | my $max = 1; 286 | my $mod = 10; 287 | # if module name present, trunc to 1st char 288 | $name =~ s/.(.*?)`//; 289 | foreach my $c (split //, $name) { 290 | my $i = (ord $c) % $mod; 291 | $vector += ($i / ($mod++ - 1)) * $weight; 292 | $max += 1 * $weight; 293 | $weight *= 0.70; 294 | last if $mod > 12; 295 | } 296 | return (1 - $vector / $max) 297 | } 298 | 299 | sub color { 300 | my ($type, $hash, $name) = @_; 301 | my ($v1, $v2, $v3); 302 | 303 | if ($hash) { 304 | $v1 = namehash($name); 305 | $v2 = $v3 = namehash(scalar reverse $name); 306 | } else { 307 | $v1 = rand(1); 308 | $v2 = rand(1); 309 | $v3 = rand(1); 310 | } 311 | 312 | # theme palettes 313 | if (defined $type and $type eq "hot") { 314 | my $r = 205 + int(50 * $v3); 315 | my $g = 0 + int(230 * $v1); 316 | my $b = 0 + int(55 * $v2); 317 | return "rgb($r,$g,$b)"; 318 | } 319 | if (defined $type and $type eq "mem") { 320 | my $r = 0; 321 | my $g = 190 + int(50 * $v2); 322 | my $b = 0 + int(210 * $v1); 323 | return "rgb($r,$g,$b)"; 324 | } 325 | if (defined $type and $type eq "io") { 326 | my $r = 80 + int(60 * $v1); 327 | my $g = $r; 328 | my $b = 190 + int(55 * $v2); 329 | return "rgb($r,$g,$b)"; 330 | } 331 | 332 | # multi palettes 333 | if (defined $type and $type eq "java") { 334 | if ($name =~ /::/) { # C++ 335 | $type = "yellow"; 336 | } elsif ($name =~ m:/:) { # Java (match "/" in path) 337 | $type = "green" 338 | } else { # system 339 | $type = "red"; 340 | } 341 | # fall-through to color palettes 342 | } 343 | if (defined $type and $type eq "js") { 344 | if ($name =~ /::/) { # C++ 345 | $type = "yellow"; 346 | } elsif ($name =~ m:/:) { # JavaScript (match "/" in path) 347 | $type = "green" 348 | } elsif ($name =~ m/:/) { # JavaScript (match ":" in builtin) 349 | $type = "aqua" 350 | } elsif ($name =~ m/^ $/) { # Missing symbol 351 | $type = "green" 352 | } else { # system 353 | $type = "red"; 354 | } 355 | # fall-through to color palettes 356 | } 357 | 358 | # color palettes 359 | if (defined $type and $type eq "red") { 360 | my $r = 200 + int(55 * $v1); 361 | my $x = 50 + int(80 * $v1); 362 | return "rgb($r,$x,$x)"; 363 | } 364 | if (defined $type and $type eq "green") { 365 | my $g = 200 + int(55 * $v1); 366 | my $x = 50 + int(60 * $v1); 367 | return "rgb($x,$g,$x)"; 368 | } 369 | if (defined $type and $type eq "blue") { 370 | my $b = 205 + int(50 * $v1); 371 | my $x = 80 + int(60 * $v1); 372 | return "rgb($x,$x,$b)"; 373 | } 374 | if (defined $type and $type eq "yellow") { 375 | my $x = 175 + int(55 * $v1); 376 | my $b = 50 + int(20 * $v1); 377 | return "rgb($x,$x,$b)"; 378 | } 379 | if (defined $type and $type eq "purple") { 380 | my $x = 190 + int(65 * $v1); 381 | my $g = 80 + int(60 * $v1); 382 | return "rgb($x,$g,$x)"; 383 | } 384 | if (defined $type and $type eq "aqua") { 385 | my $r = 50 + int(60 * $v1); 386 | my $g = 165 + int(55 * $v1); 387 | my $b = 165 + int(55 * $v1); 388 | return "rgb($r,$g,$b)"; 389 | } 390 | if (defined $type and $type eq "orange") { 391 | my $r = 190 + int(65 * $v1); 392 | my $g = 90 + int(65 * $v1); 393 | return "rgb($r,$g,0)"; 394 | } 395 | 396 | return "rgb(0,0,0)"; 397 | } 398 | 399 | sub color_scale { 400 | my ($value, $max) = @_; 401 | my ($r, $g, $b) = (255, 255, 255); 402 | $value = -$value if $negate; 403 | if ($value > 0) { 404 | $g = $b = int(210 * ($max - $value) / $max); 405 | } elsif ($value < 0) { 406 | $r = $g = int(210 * ($max + $value) / $max); 407 | } 408 | return "rgb($r,$g,$b)"; 409 | } 410 | 411 | sub color_map { 412 | my ($colors, $func) = @_; 413 | if (exists $palette_map{$func}) { 414 | return $palette_map{$func}; 415 | } else { 416 | $palette_map{$func} = color($colors); 417 | return $palette_map{$func}; 418 | } 419 | } 420 | 421 | sub write_palette { 422 | open(FILE, ">$pal_file"); 423 | foreach my $key (sort keys %palette_map) { 424 | print FILE $key."->".$palette_map{$key}."\n"; 425 | } 426 | close(FILE); 427 | } 428 | 429 | sub read_palette { 430 | if (-e $pal_file) { 431 | open(FILE, $pal_file) or die "can't open file $pal_file: $!"; 432 | while ( my $line = ) { 433 | chomp($line); 434 | (my $key, my $value) = split("->",$line); 435 | $palette_map{$key}=$value; 436 | } 437 | close(FILE) 438 | } 439 | } 440 | 441 | my %Node; # Hash of merged frame data 442 | my %Tmp; 443 | 444 | # flow() merges two stacks, storing the merged frames and value data in %Node. 445 | sub flow { 446 | my ($last, $this, $v, $d) = @_; 447 | 448 | my $len_a = @$last - 1; 449 | my $len_b = @$this - 1; 450 | 451 | my $i = 0; 452 | my $len_same; 453 | for (; $i <= $len_a; $i++) { 454 | last if $i > $len_b; 455 | last if $last->[$i] ne $this->[$i]; 456 | } 457 | $len_same = $i; 458 | 459 | for ($i = $len_a; $i >= $len_same; $i--) { 460 | my $k = "$last->[$i];$i"; 461 | # a unique ID is constructed from "func;depth;etime"; 462 | # func-depth isn't unique, it may be repeated later. 463 | $Node{"$k;$v"}->{stime} = delete $Tmp{$k}->{stime}; 464 | if (defined $Tmp{$k}->{delta}) { 465 | $Node{"$k;$v"}->{delta} = delete $Tmp{$k}->{delta}; 466 | } 467 | delete $Tmp{$k}; 468 | } 469 | 470 | for ($i = $len_same; $i <= $len_b; $i++) { 471 | my $k = "$this->[$i];$i"; 472 | $Tmp{$k}->{stime} = $v; 473 | if (defined $d) { 474 | $Tmp{$k}->{delta} += $i == $len_b ? $d : 0; 475 | } 476 | } 477 | 478 | return $this; 479 | } 480 | 481 | # parse input 482 | my @Data; 483 | my $last = []; 484 | my $time = 0; 485 | my $delta = undef; 486 | my $ignored = 0; 487 | my $line; 488 | my $maxdelta = 1; 489 | 490 | # reverse if needed 491 | foreach (<>) { 492 | chomp; 493 | $line = $_; 494 | if ($stackreverse) { 495 | # there may be an extra samples column for differentials 496 | # XXX todo: redo these REs as one. It's repeated below. 497 | my ($stack, $samples) = (/^(.*)\s+?(\d+(?:\.\d*)?)$/); 498 | my $samples2 = undef; 499 | if ($stack =~ /^(.*)\s+?(\d+(?:\.\d*)?)$/) { 500 | $samples2 = $samples; 501 | ($stack, $samples) = $stack =~ (/^(.*)\s+?(\d+(?:\.\d*)?)$/); 502 | unshift @Data, join(";", reverse split(";", $stack)) . " $samples $samples2"; 503 | } else { 504 | unshift @Data, join(";", reverse split(";", $stack)) . " $samples"; 505 | } 506 | } else { 507 | unshift @Data, $line; 508 | } 509 | } 510 | 511 | # process and merge frames 512 | foreach (sort @Data) { 513 | chomp; 514 | # process: folded_stack count 515 | # eg: func_a;func_b;func_c 31 516 | my ($stack, $samples) = (/^(.*)\s+?(\d+(?:\.\d*)?)$/); 517 | unless (defined $samples and defined $stack) { 518 | ++$ignored; 519 | next; 520 | } 521 | 522 | # there may be an extra samples column for differentials: 523 | my $samples2 = undef; 524 | if ($stack =~ /^(.*)\s+?(\d+(?:\.\d*)?)$/) { 525 | $samples2 = $samples; 526 | ($stack, $samples) = $stack =~ (/^(.*)\s+?(\d+(?:\.\d*)?)$/); 527 | } 528 | $delta = undef; 529 | if (defined $samples2) { 530 | $delta = $samples2 - $samples; 531 | $maxdelta = abs($delta) if abs($delta) > $maxdelta; 532 | } 533 | 534 | $stack =~ tr/<>/()/; 535 | 536 | # merge frames and populate %Node: 537 | $last = flow($last, [ '', split ";", $stack ], $time, $delta); 538 | 539 | if (defined $samples2) { 540 | $time += $samples2; 541 | } else { 542 | $time += $samples; 543 | } 544 | } 545 | flow($last, [], $time, $delta); 546 | 547 | warn "Ignored $ignored lines with invalid format\n" if $ignored; 548 | unless ($time) { 549 | warn "ERROR: No stack counts found\n"; 550 | my $im = SVG->new(); 551 | # emit an error message SVG, for tools automating flamegraph use 552 | my $imageheight = $fontsize * 5; 553 | $im->header($imagewidth, $imageheight); 554 | $im->stringTTF($im->colorAllocate(0, 0, 0), $fonttype, $fontsize + 2, 555 | 0.0, int($imagewidth / 2), $fontsize * 2, 556 | "ERROR: No valid input provided to flamegraph.pl.", "middle"); 557 | print $im->svg; 558 | exit 2; 559 | } 560 | if ($timemax and $timemax < $time) { 561 | warn "Specified --total $timemax is less than actual total $time, so ignored\n" 562 | if $timemax/$time > 0.02; # only warn is significant (e.g., not rounding etc) 563 | undef $timemax; 564 | } 565 | $timemax ||= $time; 566 | 567 | my $widthpertime = ($imagewidth - 2 * $xpad) / $timemax; 568 | my $minwidth_time = $minwidth / $widthpertime; 569 | 570 | # prune blocks that are too narrow and determine max depth 571 | while (my ($id, $node) = each %Node) { 572 | my ($func, $depth, $etime) = split ";", $id; 573 | my $stime = $node->{stime}; 574 | die "missing start for $id" if not defined $stime; 575 | 576 | if (($etime-$stime) < $minwidth_time) { 577 | delete $Node{$id}; 578 | next; 579 | } 580 | $depthmax = $depth if $depth > $depthmax; 581 | } 582 | 583 | # draw canvas, and embed interactive JavaScript program 584 | my $imageheight = ($depthmax * $frameheight) + $ypad1 + $ypad2; 585 | my $im = SVG->new(); 586 | $im->header($imagewidth, $imageheight); 587 | my $inc = < 589 | 590 | 591 | 592 | 593 | 594 | 597 | 916 | INC 917 | $im->include($inc); 918 | $im->filledRectangle(0, 0, $imagewidth, $imageheight, 'url(#background)'); 919 | my ($white, $black, $vvdgrey, $vdgrey) = ( 920 | $im->colorAllocate(255, 255, 255), 921 | $im->colorAllocate(0, 0, 0), 922 | $im->colorAllocate(40, 40, 40), 923 | $im->colorAllocate(160, 160, 160), 924 | ); 925 | $im->stringTTF($black, $fonttype, $fontsize + 5, 0.0, int($imagewidth / 2), $fontsize * 2, $titletext, "middle"); 926 | $im->stringTTF($black, $fonttype, $fontsize, 0.0, $xpad, $imageheight - ($ypad2 / 2), " ", "", 'id="details"'); 927 | $im->stringTTF($black, $fonttype, $fontsize, 0.0, $xpad, $fontsize * 2, 928 | "Reset Zoom", "", 'id="unzoom" onclick="unzoom()" style="opacity:0.0;cursor:pointer"'); 929 | $im->stringTTF($black, $fonttype, $fontsize, 0.0, $imagewidth - $xpad - 100, 930 | $fontsize * 2, "Search", "", 'id="search" onmouseover="searchover()" onmouseout="searchout()" onclick="search_prompt()" style="opacity:0.1;cursor:pointer"'); 931 | $im->stringTTF($black, $fonttype, $fontsize, 0.0, $imagewidth - $xpad - 100, $imageheight - ($ypad2 / 2), " ", "", 'id="matched"'); 932 | 933 | if ($palette) { 934 | read_palette(); 935 | } 936 | 937 | # draw frames 938 | while (my ($id, $node) = each %Node) { 939 | my ($func, $depth, $etime) = split ";", $id; 940 | my $stime = $node->{stime}; 941 | my $delta = $node->{delta}; 942 | 943 | $etime = $timemax if $func eq "" and $depth == 0; 944 | 945 | my $x1 = $xpad + $stime * $widthpertime; 946 | my $x2 = $xpad + $etime * $widthpertime; 947 | my ($y1, $y2); 948 | unless ($inverted) { 949 | $y1 = $imageheight - $ypad2 - ($depth + 1) * $frameheight + $framepad; 950 | $y2 = $imageheight - $ypad2 - $depth * $frameheight; 951 | } else { 952 | $y1 = $ypad1 + $depth * $frameheight; 953 | $y2 = $ypad1 + ($depth + 1) * $frameheight - $framepad; 954 | } 955 | 956 | my $samples = sprintf "%.0f", ($etime - $stime) * $factor; 957 | (my $samples_txt = $samples) # add commas per perlfaq5 958 | =~ s/(^[-+]?\d+?(?=(?>(?:\d{3})+)(?!\d))|\G\d{3}(?=\d))/$1,/g; 959 | 960 | my $info; 961 | if ($func eq "" and $depth == 0) { 962 | $info = "all ($samples_txt $countname, 100%)"; 963 | } else { 964 | my $pct = sprintf "%.2f", ((100 * $samples) / ($timemax * $factor)); 965 | my $escaped_func = $func; 966 | $escaped_func =~ s/&/&/g; 967 | $escaped_func =~ s//>/g; 969 | $escaped_func =~ s/"/"/g; 970 | unless (defined $delta) { 971 | $info = "$escaped_func ($samples_txt $countname, $pct%)"; 972 | } else { 973 | my $d = $negate ? -$delta : $delta; 974 | my $deltapct = sprintf "%.2f", ((100 * $d) / ($timemax * $factor)); 975 | $deltapct = $d > 0 ? "+$deltapct" : $deltapct; 976 | $info = "$escaped_func ($samples_txt $countname, $pct%; $deltapct%)"; 977 | } 978 | } 979 | 980 | my $nameattr = { %{ $nameattr{$func}||{} } }; # shallow clone 981 | $nameattr->{class} ||= "func_g"; 982 | $nameattr->{onmouseover} ||= "s(this)"; 983 | $nameattr->{onmouseout} ||= "c()"; 984 | $nameattr->{onclick} ||= "zoom(this)"; 985 | $nameattr->{title} ||= $info; 986 | $im->group_start($nameattr); 987 | 988 | my $color; 989 | if ($func eq "-") { 990 | $color = $vdgrey; 991 | } elsif (defined $delta) { 992 | $color = color_scale($delta, $maxdelta); 993 | } elsif ($palette) { 994 | $color = color_map($colors, $func); 995 | } else { 996 | $color = color($colors, $hash, $func); 997 | } 998 | $im->filledRectangle($x1, $y1, $x2, $y2, $color, 'rx="2" ry="2"'); 999 | 1000 | my $chars = int( ($x2 - $x1) / ($fontsize * $fontwidth)); 1001 | my $text = ""; 1002 | if ($chars >= 3) { # room for one char plus two dots 1003 | $text = substr $func, 0, $chars; 1004 | substr($text, -2, 2) = ".." if $chars < length $func; 1005 | $text =~ s/&/&/g; 1006 | $text =~ s//>/g; 1008 | } 1009 | $im->stringTTF($black, $fonttype, $fontsize, 0.0, $x1 + 3, 3 + ($y1 + $y2) / 2, $text, ""); 1010 | 1011 | $im->group_end($nameattr); 1012 | } 1013 | 1014 | print $im->svg; 1015 | 1016 | if ($palette) { 1017 | write_palette(); 1018 | } 1019 | 1020 | # vim: ts=8 sts=8 sw=8 noexpandtab 1021 | -------------------------------------------------------------------------------- /stackcollapse-perf.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl -w 2 | # 3 | # stackcolllapse-perf.pl collapse perf samples into single lines. 4 | # 5 | # Parses a list of multiline stacks generated by "perf script", and 6 | # outputs a semicolon separated stack followed by a space and a count. 7 | # If memory addresses (+0xd) are present, they are stripped, and resulting 8 | # identical stacks are colased with their counts summed. 9 | # 10 | # USAGE: ./stackcollapse-perf.pl [options] infile > outfile 11 | # 12 | # Run "./stackcollapse-perf.pl -h" to list options. 13 | # 14 | # Example input: 15 | # 16 | # swapper 0 [000] 158665.570607: cpu-clock: 17 | # ffffffff8103ce3b native_safe_halt ([kernel.kallsyms]) 18 | # ffffffff8101c6a3 default_idle ([kernel.kallsyms]) 19 | # ffffffff81013236 cpu_idle ([kernel.kallsyms]) 20 | # ffffffff815bf03e rest_init ([kernel.kallsyms]) 21 | # ffffffff81aebbfe start_kernel ([kernel.kallsyms].init.text) 22 | # [...] 23 | # 24 | # Example output: 25 | # 26 | # swapper;start_kernel;rest_init;cpu_idle;default_idle;native_safe_halt 1 27 | # 28 | # Input may be created and processed using: 29 | # 30 | # perf record -a -g -F 997 sleep 60 31 | # perf script | ./stackcollapse-perf.pl > out.stacks-folded 32 | # 33 | # The output of "perf script" should include stack traces. If these are missing 34 | # for you, try manually selecting the perf script output; eg: 35 | # 36 | # perf script -f comm,pid,tid,cpu,time,event,ip,sym,dso,trace | ... 37 | # 38 | # This is also required for the --pid or --tid options, so that the output has 39 | # both the PID and TID. 40 | # 41 | # Copyright 2012 Joyent, Inc. All rights reserved. 42 | # Copyright 2012 Brendan Gregg. All rights reserved. 43 | # 44 | # CDDL HEADER START 45 | # 46 | # The contents of this file are subject to the terms of the 47 | # Common Development and Distribution License (the "License"). 48 | # You may not use this file except in compliance with the License. 49 | # 50 | # You can obtain a copy of the license at docs/cddl1.txt or 51 | # http://opensource.org/licenses/CDDL-1.0. 52 | # See the License for the specific language governing permissions 53 | # and limitations under the License. 54 | # 55 | # When distributing Covered Code, include this CDDL HEADER in each 56 | # file and include the License file at docs/cddl1.txt. 57 | # If applicable, add the following below this CDDL HEADER, with the 58 | # fields enclosed by brackets "[]" replaced with your own identifying 59 | # information: Portions Copyright [yyyy] [name of copyright owner] 60 | # 61 | # CDDL HEADER END 62 | # 63 | # 02-Mar-2012 Brendan Gregg Created this. 64 | # 02-Jul-2014 " " Added process name to stacks. 65 | 66 | use strict; 67 | use Getopt::Long; 68 | 69 | my %collapsed; 70 | 71 | sub remember_stack { 72 | my ($stack, $count) = @_; 73 | $collapsed{$stack} += $count; 74 | } 75 | 76 | my $include_pname = 1; # include process names in stacks 77 | my $include_pid = 0; # include process ID with process name 78 | my $include_tid = 0; # include process & thread ID with process name 79 | my $tidy_java = 1; # condense Java signatures 80 | my $tidy_generic = 1; # clean up function names a little 81 | my $target_pname; # target process name from perf invocation 82 | 83 | my $show_inline = 0; 84 | my $show_context = 0; 85 | GetOptions('inline' => \$show_inline, 86 | 'context' => \$show_context, 87 | 'pid' => \$include_pid, 88 | 'tid' => \$include_tid) 89 | or die < outfile\n 91 | --pid # include PID with process names [1] 92 | --tid # include TID and PID with process names [1] 93 | --inline # un-inline using addr2line 94 | --context # include source context from addr2line\n 95 | [1] perf script must emit both PID and TIDs for these to work; eg: 96 | perf script -f comm,pid,tid,cpu,time,event,ip,sym,dso,trace 97 | USAGE_END 98 | 99 | # for the --inline option 100 | sub inline { 101 | my ($pc, $mod) = @_; 102 | 103 | # capture addr2line output 104 | my $a2l_output = `addr2line -a $pc -e $mod -i -f -s -C`; 105 | 106 | # remove first line 107 | $a2l_output =~ s/^(.*\n){1}//; 108 | 109 | my @fullfunc; 110 | my $one_item = ""; 111 | for (split /^/, $a2l_output) { 112 | chomp $_; 113 | 114 | # remove discriminator info if exists 115 | $_ =~ s/ \(discriminator \S+\)//; 116 | 117 | if ($one_item eq "") { 118 | $one_item = $_; 119 | } else { 120 | if ($show_context == 1) { 121 | unshift @fullfunc, $one_item . ":$_"; 122 | } else { 123 | unshift @fullfunc, $one_item; 124 | } 125 | $one_item = ""; 126 | } 127 | } 128 | 129 | return join(";", @fullfunc); 130 | } 131 | 132 | my @stack; 133 | my $pname; 134 | 135 | # 136 | # Main loop 137 | # 138 | foreach (<>) { 139 | 140 | # find the name of the process launched by perf, by stepping backwards 141 | # over the args to find the first non-option (no dash): 142 | if (/^# cmdline/) { 143 | my @args = split ' ', $_; 144 | foreach my $arg (reverse @args) { 145 | if ($arg !~ /^-/) { 146 | $target_pname = $arg; 147 | $target_pname =~ s:.*/::; # strip pathname 148 | last; 149 | } 150 | } 151 | } 152 | 153 | # skip remaining comments 154 | next if m/^#/; 155 | chomp; 156 | 157 | # end of stack. save cached data. 158 | if (m/^$/) { 159 | if ($include_pname) { 160 | if (defined $pname) { 161 | unshift @stack, $pname; 162 | } else { 163 | unshift @stack, ""; 164 | } 165 | } 166 | remember_stack(join(";", @stack), 1) if @stack; 167 | undef @stack; 168 | undef $pname; 169 | next; 170 | } 171 | 172 | # event record start 173 | if (/^(\S+)\s+(\d+)\s/) { 174 | # default "perf script" output has TID but not PID 175 | # eg, "java 25607 4794564.109216: cycles:" 176 | if ($include_tid) { 177 | $pname = "$1-?/$2"; 178 | } elsif ($include_pid) { 179 | $pname = "$1-?"; 180 | } else { 181 | $pname = $1; 182 | } 183 | } elsif (/^(\S+)\s+(\d+)\/(\d+)/) { 184 | # eg, "java 24636/25607 [000] 4794564.109216: cycles:" 185 | if ($include_tid) { 186 | $pname = "$1-$2/$3"; 187 | } elsif ($include_pid) { 188 | $pname = "$1-$2"; 189 | } else { 190 | $pname = $1; 191 | } 192 | 193 | # stack line 194 | } elsif (/^\s*(\w+)\s*(.+) \((\S*)\)/) { 195 | my ($pc, $func, $mod) = ($1, $2, $3); 196 | 197 | if ($show_inline == 1 && index($mod, $target_pname) != -1) { 198 | unshift @stack, inline($pc, $mod); 199 | next; 200 | } 201 | 202 | next if $func =~ /^\(/; # skip process names 203 | 204 | if ($tidy_generic) { 205 | $func =~ s/;/:/g; 206 | $func =~ tr/<>//d; 207 | $func =~ s/\(.*//; 208 | # now tidy this horrible thing: 209 | # 13a80b608e0a RegExp:[&<>\"\'] (/tmp/perf-7539.map) 210 | $func =~ tr/"\'//d; 211 | # fall through to $tidy_java 212 | } 213 | 214 | if ($tidy_java and $pname eq "java") { 215 | # along with $tidy_generic, converts the following: 216 | # Lorg/mozilla/javascript/ContextFactory;.call(Lorg/mozilla/javascript/ContextAction;)Ljava/lang/Object; 217 | # Lorg/mozilla/javascript/ContextFactory;.call(Lorg/mozilla/javascript/C 218 | # Lorg/mozilla/javascript/MemberBox;.(Ljava/lang/reflect/Method;)V 219 | # into: 220 | # org/mozilla/javascript/ContextFactory:.call 221 | # org/mozilla/javascript/ContextFactory:.call 222 | # org/mozilla/javascript/MemberBox:.init 223 | $func =~ s/^L// if $func =~ m:/:; 224 | } 225 | 226 | unshift @stack, $func; 227 | } else { 228 | warn "Unrecognized line: $_"; 229 | } 230 | } 231 | 232 | foreach my $k (sort { $a cmp $b } keys %collapsed) { 233 | print "$k $collapsed{$k}\n"; 234 | } 235 | -------------------------------------------------------------------------------- /torch.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | USAGE="Usage: ./torch.sh [options] pid 3 | 4 | Options: 5 | -d, --duration duration of sampling in seconds [default: 10] 6 | -o, --output file to save flamegraph to [default: ./flamegraph.svg] 7 | -h, --help this message" 8 | 9 | while [[ $# > 0 ]] 10 | do 11 | case "$1" in 12 | -d|--duration) 13 | DURATION="$2" 14 | shift 2 15 | ;; 16 | -o|--output) 17 | OUTPUT="$2" 18 | shift 2 19 | ;; 20 | -h|--help) 21 | echo "$USAGE" 22 | exit 0 23 | ;; 24 | -*) 25 | echo "Error: Unkown Option $1" >&2 26 | echo "$USAGE" >&2 27 | exit 1 28 | ;; 29 | *) 30 | break 31 | ;; 32 | esac 33 | done 34 | 35 | PID=$1 36 | 37 | if [[ -z "$PID" ]] 38 | then 39 | echo "Error: pid is missing" >&2 40 | echo "$USAGE" >&2 41 | exit 1 42 | fi 43 | 44 | if [[ -z "$DURATION" ]] 45 | then 46 | DURATION=10 47 | fi 48 | 49 | if [[ -z "$OUTPUT" ]] 50 | then 51 | OUTPUT=./flamegraph.svg 52 | fi 53 | 54 | if [[ "$OUTPUT" != /* ]] 55 | then 56 | OUTPUT="$(pwd)"/"${OUTPUT#./}" 57 | fi 58 | 59 | function get_temp_file() { 60 | local tmppath=${1:-/tmp} 61 | local tmpfile=$2${2:+-} 62 | tmpfile=$tmppath/$tmpfile$RANDOM$RANDOM.tmp 63 | if [ -e $tmpfile ] 64 | then 65 | tmpfile=$(gettmpfile $1 $2) 66 | fi 67 | echo $tmpfile 68 | } 69 | 70 | TEMP_FILE=$(get_temp_file /tmp torch) 71 | echo "sampling pid $PID for $DURATION seconds" && \ 72 | perf record -o $TEMP_FILE -F 199 -p $PID -a --call-graph dwarf -- sleep $DURATION > /dev/null && \ 73 | echo "saving flame graph to $OUTPUT" && \ 74 | cd "$(dirname "${BASH_SOURCE[0]}")" 75 | perf script -i $TEMP_FILE | ./stackcollapse-perf.pl | ./flamegraph.pl > $OUTPUT && \ 76 | echo "done." 77 | rm -rf $TEMP_FILE 78 | --------------------------------------------------------------------------------