Git fork

trace2: Documentation/technical/api-trace2.txt

Created design document for Trace2 feature.

Signed-off-by: Jeff Hostetler <jeffhost@microsoft.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>

authored by

Jeff Hostetler and committed by
Junio C Hamano
e544221d 35ee755a

+1349
+1349
Documentation/technical/api-trace2.txt
··· 1 + = Trace2 API 2 + 3 + The Trace2 API can be used to print debug, performance, and telemetry 4 + information to stderr or a file. The Trace2 feature is inactive unless 5 + explicitly enabled by enabling one or more Trace2 Targets. 6 + 7 + The Trace2 API is intended to replace the existing (Trace1) 8 + printf-style tracing provided by the existing `GIT_TRACE` and 9 + `GIT_TRACE_PERFORMANCE` facilities. During initial implementation, 10 + Trace2 and Trace1 may operate in parallel. 11 + 12 + The Trace2 API defines a set of high-level messages with known fields, 13 + such as (`start`: `argv`) and (`exit`: {`exit-code`, `elapsed-time`}). 14 + 15 + Trace2 instrumentation throughout the Git code base sends Trace2 16 + messages to the enabled Trace2 Targets. Targets transform these 17 + messages content into purpose-specific formats and write events to 18 + their data streams. In this manner, the Trace2 API can drive 19 + many different types of analysis. 20 + 21 + Targets are defined using a VTable allowing easy extension to other 22 + formats in the future. This might be used to define a binary format, 23 + for example. 24 + 25 + == Trace2 Targets 26 + 27 + Trace2 defines the following set of Trace2 Targets. 28 + Format details are given in a later section. 29 + 30 + `GIT_TR2` (NORMAL):: 31 + 32 + a simple printf format like GIT_TRACE. 33 + + 34 + ------------ 35 + $ export GIT_TR2=~/log.normal 36 + $ git version 37 + git version 2.20.1.155.g426c96fcdb 38 + ------------ 39 + + 40 + ------------ 41 + $ cat ~/log.normal 42 + 12:28:42.620009 common-main.c:38 version 2.20.1.155.g426c96fcdb 43 + 12:28:42.620989 common-main.c:39 start git version 44 + 12:28:42.621101 git.c:432 cmd_name version (version) 45 + 12:28:42.621215 git.c:662 exit elapsed:0.001227 code:0 46 + 12:28:42.621250 trace2/tr2_tgt_normal.c:124 atexit elapsed:0.001265 code:0 47 + ------------ 48 + 49 + `GIT_TR2_PERF` (PERF):: 50 + 51 + a column-based format to replace GIT_TRACE_PERFORMANCE suitable for 52 + development and testing, possibly to complement tools like gprof. 53 + + 54 + ------------ 55 + $ export GIT_TR2_PERF=~/log.perf 56 + $ git version 57 + git version 2.20.1.155.g426c96fcdb 58 + ------------ 59 + + 60 + ------------ 61 + $ cat ~/log.perf 62 + 12:28:42.620675 common-main.c:38 | d0 | main | version | | | | | 2.20.1.155.g426c96fcdb 63 + 12:28:42.621001 common-main.c:39 | d0 | main | start | | | | | git version 64 + 12:28:42.621111 git.c:432 | d0 | main | cmd_name | | | | | version (version) 65 + 12:28:42.621225 git.c:662 | d0 | main | exit | | 0.001227 | | | code:0 66 + 12:28:42.621259 trace2/tr2_tgt_perf.c:211 | d0 | main | atexit | | 0.001265 | | | code:0 67 + ------------ 68 + 69 + `GIT_TR2_EVENT` (EVENT):: 70 + 71 + a JSON-based format of event data suitable for telemetry analysis. 72 + + 73 + ------------ 74 + $ export GIT_TR2_EVENT=~/log.event 75 + $ git version 76 + git version 2.20.1.155.g426c96fcdb 77 + ------------ 78 + + 79 + ------------ 80 + $ cat ~/log.event 81 + {"event":"version","sid":"1547659722619736-11614","thread":"main","time":"2019-01-16 17:28:42.620713","file":"common-main.c","line":38,"evt":"1","exe":"2.20.1.155.g426c96fcdb"} 82 + {"event":"start","sid":"1547659722619736-11614","thread":"main","time":"2019-01-16 17:28:42.621027","file":"common-main.c","line":39,"argv":["git","version"]} 83 + {"event":"cmd_name","sid":"1547659722619736-11614","thread":"main","time":"2019-01-16 17:28:42.621122","file":"git.c","line":432,"name":"version","hierarchy":"version"} 84 + {"event":"exit","sid":"1547659722619736-11614","thread":"main","time":"2019-01-16 17:28:42.621236","file":"git.c","line":662,"t_abs":0.001227,"code":0} 85 + {"event":"atexit","sid":"1547659722619736-11614","thread":"main","time":"2019-01-16 17:28:42.621268","file":"trace2/tr2_tgt_event.c","line":163,"t_abs":0.001265,"code":0} 86 + ------------ 87 + 88 + == Enabling a Target 89 + 90 + A Trace2 Target is enabled when the corresponding environment variable 91 + (`GIT_TR2`, `GIT_TR2_PERF`, or `GIT_TR2_EVENT`) is set. The following 92 + values are recognized. 93 + 94 + `0`:: 95 + `false`:: 96 + 97 + Disables the target. 98 + 99 + `1`:: 100 + `true`:: 101 + 102 + Enables the target and writes stream to `STDERR`. 103 + 104 + `[2-9]`:: 105 + 106 + Enables the target and writes to the already opened file descriptor. 107 + 108 + `<absolute-pathname>`:: 109 + 110 + Enables the target, opens and writes to the file in append mode. 111 + 112 + `af_unix:[<socket_type>:]<absolute-pathname>`:: 113 + 114 + Enables the target, opens and writes to a Unix Domain Socket 115 + (on platforms that support them). 116 + + 117 + Socket type can be either `stream` or `dgram`. If the socket type is 118 + omitted, Git will try both. 119 + 120 + == Trace2 API 121 + 122 + All public Trace2 functions and macros are defined in `trace2.h` and 123 + `trace2.c`. All public symbols are prefixed with `trace2_`. 124 + 125 + There are no public Trace2 data structures. 126 + 127 + The Trace2 code also defines a set of private functions and data types 128 + in the `trace2/` directory. These symbols are prefixed with `tr2_` 129 + and should only be used by functions in `trace2.c`. 130 + 131 + == Conventions for Public Functions and Macros 132 + 133 + The functions defined by the Trace2 API are declared and documented 134 + in `trace2.h`. It defines the API functions and wrapper macros for 135 + Trace2. 136 + 137 + Some functions have a `_fl()` suffix to indicate that they take `file` 138 + and `line-number` arguments. 139 + 140 + Some functions have a `_va_fl()` suffix to indicate that they also 141 + take a `va_list` argument. 142 + 143 + Some functions have a `_printf_fl()` suffix to indicate that they also 144 + take a varargs argument. 145 + 146 + There are CPP wrapper macros and ifdefs to hide most of these details. 147 + See `trace2.h` for more details. The following discussion will only 148 + describe the simplified forms. 149 + 150 + == Public API 151 + 152 + All Trace2 API functions send a messsage to all of the active 153 + Trace2 Targets. This section describes the set of available 154 + messages. 155 + 156 + It helps to divide these functions into groups for discussion 157 + purposes. 158 + 159 + === Basic Command Messages 160 + 161 + These are concerned with the lifetime of the overall git process. 162 + 163 + `void trace2_initialize()`:: 164 + 165 + Determines if any Trace2 Targets should be enabled and 166 + initializes the Trace2 facility. This includes starting the 167 + elapsed time clocks and thread local storage (TLS). 168 + + 169 + This function emits a "version" message containing the version of git 170 + and the Trace2 protocol. 171 + + 172 + This function should be called from `main()` as early as possible in 173 + the life of the process. 174 + 175 + `int trace2_is_enabled()`:: 176 + 177 + Returns 1 if Trace2 is enabled (at least one target is 178 + active). 179 + 180 + `void trace2_cmd_start(int argc, const char **argv)`:: 181 + 182 + Emits a "start" message containing the process command line 183 + arguments. 184 + 185 + `int trace2_cmd_exit(int exit_code)`:: 186 + 187 + Emits an "exit" message containing the process exit-code and 188 + elapsed time. 189 + + 190 + Returns the exit-code. 191 + 192 + `void trace2_cmd_error(const char *fmt, va_list ap)`:: 193 + 194 + Emits an "error" message containing a formatted error message. 195 + 196 + `void trace2_cmd_path(const char *pathname)`:: 197 + 198 + Emits a "cmd_path" message with the full pathname of the 199 + current process. 200 + 201 + === Command Detail Messages 202 + 203 + These are concerned with describing the specific Git command 204 + after the command line, config, and environment are inspected. 205 + 206 + `void trace2_cmd_name(const char *name)`:: 207 + 208 + Emits a "cmd_name" message with the canonical name of the 209 + command, for example "status" or "checkout". 210 + 211 + `void trace2_cmd_mode(const char *mode)`:: 212 + 213 + Emits a "cmd_mode" message with a qualifier name to further 214 + describe the current git command. 215 + + 216 + This message is intended to be used with git commands having multiple 217 + major modes. For example, a "checkout" command can checkout a new 218 + branch or it can checkout a single file, so the checkout code could 219 + emit a cmd_mode message of "branch" or "file". 220 + 221 + `void trace2_cmd_alias(const char *alias, const char **argv_expansion)`:: 222 + 223 + Emits an "alias" message containing the alias used and the 224 + argument expansion. 225 + 226 + `void trace2_def_param(const char *parameter, const char *value)`:: 227 + 228 + Emits a "def_param" message containing a key/value pair. 229 + + 230 + This message is intended to report some global aspect of the current 231 + command, such as a configuration setting or command line switch that 232 + significantly affects program performance or behavior, such as 233 + `core.abbrev`, `status.showUntrackedFiles`, or `--no-ahead-behind`. 234 + 235 + `void trace2_cmd_list_config()`:: 236 + 237 + Emits a "def_param" messages for "important" configuration 238 + settings. 239 + + 240 + The environment variable `GIT_TR2_CONFIG_PARAMS` can be set to a 241 + list of patterns of important configuration settings, for example: 242 + `core.*,remote.*.url`. This function will iterate over all config 243 + settings and emit a "def_param" message for each match. 244 + 245 + `void trace2_cmd_set_config(const char *key, const char *value)`:: 246 + 247 + Emits a "def_param" message for a specific configuration 248 + setting IFF it matches the `GIT_TR2_CONFIG_PARAMS` pattern. 249 + + 250 + This is used to hook into `git_config_set()` and catch any 251 + configuration changes and update a value previously reported by 252 + `trace2_cmd_list_config()`. 253 + 254 + `void trace2_def_repo(struct repository *repo)`:: 255 + 256 + Registers a repository with the Trace2 layer. Assigns a 257 + unique "repo-id" to `repo->trace2_repo_id`. 258 + + 259 + Emits a "worktree" messages containing the repo-id and the worktree 260 + pathname. 261 + + 262 + Region and data messages (described later) may refer to this repo-id. 263 + + 264 + The main/top-level repository will have repo-id value 1 (aka "r1"). 265 + + 266 + The repo-id field is in anticipation of future in-proc submodule 267 + repositories. 268 + 269 + === Child Process Messages 270 + 271 + These are concerned with the various spawned child processes, 272 + including shell scripts, git commands, editors, pagers, and hooks. 273 + 274 + `void trace2_child_start(struct child_process *cmd)`:: 275 + 276 + Emits a "child_start" message containing the "child-id", 277 + "child-argv", and "child-classification". 278 + + 279 + Before calling this, set `cmd->trace2_child_class` to a name 280 + describing the type of child process, for example "editor". 281 + + 282 + This function assigns a unique "child-id" to `cmd->trace2_child_id`. 283 + This field is used later during the "child_exit" message to associate 284 + it with the "child_start" message. 285 + + 286 + This function should be called before spawning the child process. 287 + 288 + `void trace2_child_exit(struct child_proess *cmd, int child_exit_code)`:: 289 + 290 + Emits a "child_exit" message containing the "child-id", 291 + the child's elapsed time and exit-code. 292 + + 293 + The reported elapsed time includes the process creation overhead and 294 + time spend waiting for it to exit, so it may be slightly longer than 295 + the time reported by the child itself. 296 + + 297 + This function should be called after reaping the child process. 298 + 299 + `int trace2_exec(const char *exe, const char **argv)`:: 300 + 301 + Emits a "exec" message containing the "exec-id" and the 302 + argv of the new process. 303 + + 304 + This function should be called before calling one of the `exec()` 305 + variants, such as `execvp()`. 306 + + 307 + This function returns a unique "exec-id". This value is used later 308 + if the exec() fails and a "exec-result" message is necessary. 309 + 310 + `void trace2_exec_result(int exec_id, int error_code)`:: 311 + 312 + Emits a "exec_result" message containing the "exec-id" 313 + and the error code. 314 + + 315 + On Unix-based systems, `exec()` does not return if successful. 316 + This message is used to indicate that the `exec()` failed and 317 + that the current program is continuing. 318 + 319 + === Git Thread Messages 320 + 321 + These messages are concerned with Git thread usage. 322 + 323 + `void trace2_thread_start(const char *thread_name)`:: 324 + 325 + Emits a "thread_start" message. 326 + + 327 + The `thread_name` field should be a descriptive name, such as the 328 + unique name of the thread-proc. A unique "thread-id" will be added 329 + to the name to uniquely identify thread instances. 330 + + 331 + Region and data messages (described later) may refer to this thread 332 + name. 333 + + 334 + This function must be called by the thread-proc of the new thread 335 + (so that TLS data is properly initialized) and not by the caller 336 + of `pthread_create()`. 337 + 338 + `void trace2_thread_exit()`:: 339 + 340 + Emits a "thread_exit" message containing the thread name 341 + and the thread elapsed time. 342 + + 343 + This function must be called by the thread-proc before it returns 344 + (so that the coorect TLS data is used and cleaned up. It should 345 + not be called by the caller of `pthread_join()`. 346 + 347 + === Region and Data Messages 348 + 349 + These are concerned with recording performance data 350 + over regions or spans of code. 351 + 352 + `void trace2_region_enter(const char *category, const char *label, const struct repository *repo)`:: 353 + 354 + `void trace2_region_enter_printf(const char *category, const char *label, const struct repository *repo, const char *fmt, ...)`:: 355 + 356 + `void trace2_region_enter_printf_va(const char *category, const char *label, const struct repository *repo, const char *fmt, va_list ap)`:: 357 + 358 + Emits a thread-relative "region_enter" message with optional 359 + printf string. 360 + + 361 + This function pushes a new region nesting stack level on the current 362 + thread and starts a clock for the new stack frame. 363 + + 364 + The `category` field is an arbitrary category name used to classify 365 + regions by feature area, such as "status" or "index". At this time 366 + it is only just printed along with the rest of the message. It may 367 + be used in the future to filter messages. 368 + + 369 + The `label` field is an arbitrary label used to describe the activity 370 + being started, such as "read_recursive" or "do_read_index". 371 + + 372 + The `repo` field, if set, will be used to get the "repo-id", so that 373 + recursive oerations can be attributed to the correct repository. 374 + 375 + `void trace2_region_leave(const char *category, const char *label, const struct repository *repo)`:: 376 + 377 + `void trace2_region_leave_printf(const char *category, const char *label, const struct repository *repo, const char *fmt, ...)`:: 378 + 379 + `void trace2_region_leave_printf_va(const char *category, const char *label, const struct repository *repo, const char *fmt, va_list ap)`:: 380 + 381 + Emits a thread-relative "region_leave" message with optional 382 + printf string. 383 + + 384 + This function pops the region nesting stack on the current thread 385 + and reports the elapsed time of the stack frame. 386 + + 387 + The `category`, `label`, and `repo` fields are the same as above. 388 + The `category` and `label` do not need to match the correpsonding 389 + "region_enter" message, but it makes the data stream easier to 390 + understand. 391 + 392 + `void trace2_data_string(const char *category, const struct repository *repo, const char *key, const char * value)`:: 393 + 394 + `void trace2_data_intmax(const char *category, const struct repository *repo, const char *key, intmax value)`:: 395 + 396 + `void trace2_data_json(const char *category, const struct repository *repo, const char *key, const struct json_writer *jw)`:: 397 + 398 + Emits a region- and thread-relative "data" or "data_json" message. 399 + + 400 + This is a key/value pair message containing information about the 401 + current thread, region stack, and repository. This could be used 402 + to print the number of files in a directory during a multi-threaded 403 + recursive tree walk. 404 + 405 + `void trace2_printf(const char *fmt, ...)`:: 406 + 407 + `void trace2_printf_va(const char *fmt, va_list ap)`:: 408 + 409 + Emits a region- and thread-relative "printf" message. 410 + 411 + == Trace2 Target Formats 412 + 413 + === NORMAL Format 414 + 415 + NORMAL format is enabled when the `GIT_TR2` environment variable is 416 + set. 417 + 418 + Events are written as lines of the form: 419 + 420 + ------------ 421 + [<time> SP <filename>:<line> SP+] <event-name> [[SP] <event-message>] LF 422 + ------------ 423 + 424 + `<event-name>`:: 425 + 426 + is the event name. 427 + 428 + `<event-message>`:: 429 + is a free-form printf message intended for human consumption. 430 + + 431 + Note that this may contain embedded LF or CRLF characters that are 432 + not escaped, so the event may spill across multiple lines. 433 + 434 + If `GIT_TR2_BRIEF` is true, the `time`, `filename`, and `line` fields 435 + are omitted. 436 + 437 + This target is intended to be more of a summary (like GIT_TRACE) and 438 + less detailed than the other targets. It ignores thread, region, and 439 + data messages, for example. 440 + 441 + === PERF Format 442 + 443 + PERF format is enabled when the `GIT_TR2_PERF` environment variable 444 + is set. 445 + 446 + Events are written as lines of the form: 447 + 448 + ------------ 449 + [<time> SP <filename>:<line> SP+ 450 + BAR SP] d<depth> SP 451 + BAR SP <thread-name> SP+ 452 + BAR SP <event-name> SP+ 453 + BAR SP [r<repo-id>] SP+ 454 + BAR SP [<t_abs>] SP+ 455 + BAR SP [<t_rel>] SP+ 456 + BAR SP [<category>] SP+ 457 + BAR SP DOTS* <perf-event-message> 458 + LF 459 + ------------ 460 + 461 + `<depth>`:: 462 + is the git process depth. This is the number of parent 463 + git processes. A top-level git command has depth value "d0". 464 + A child of it has depth value "d1". A second level child 465 + has depth value "d2" and so on. 466 + 467 + `<thread-name>`:: 468 + is a unique name for the thread. The primary thread 469 + is called "main". Other thread names are of the form "th%d:%s" 470 + and include a unique number and the name of the thread-proc. 471 + 472 + `<event-name>`:: 473 + is the event name. 474 + 475 + `<repo-id>`:: 476 + when present, is a number indicating the repository 477 + in use. A `def_repo` event is emitted when a repository is 478 + opened. This defines the repo-id and associated worktree. 479 + Subsequent repo-specific events will reference this repo-id. 480 + + 481 + Currently, this is always "r1" for the main repository. 482 + This field is in anticipation of in-proc submodules in the future. 483 + 484 + `<t_abs>`:: 485 + when present, is the absolute time in seconds since the 486 + program started. 487 + 488 + `<t_rel>`:: 489 + when present, is time in seconds relative to the start of 490 + the current region. For a thread-exit event, it is the elapsed 491 + time of the thread. 492 + 493 + `<category>`:: 494 + is present on region and data events and is used to 495 + indicate a broad category, such as "index" or "status". 496 + 497 + `<perf-event-message>`:: 498 + is a free-form printf message intended for human consumption. 499 + 500 + ------------ 501 + 15:33:33.532712 wt-status.c:2310 | d0 | main | region_enter | r1 | 0.126064 | | status | label:print 502 + 15:33:33.532712 wt-status.c:2331 | d0 | main | region_leave | r1 | 0.127568 | 0.001504 | status | label:print 503 + ------------ 504 + 505 + If `GIT_TR2_PERF_BRIEF` is true, the `time`, `file`, and `line` 506 + fields are omitted. 507 + 508 + ------------ 509 + d0 | main | region_leave | r1 | 0.011717 | 0.009122 | index | label:preload 510 + ------------ 511 + 512 + The PERF target is intended for interactive performance analysis 513 + during development and is quite noisy. 514 + 515 + === EVENT Format 516 + 517 + EVENT format is enabled when the `GIT_TR2_EVENT` environment 518 + variable is set. 519 + 520 + Each event is a JSON-object containing multiple key/value pairs 521 + written as a single line and followed by a LF. 522 + 523 + ------------ 524 + '{' <key> ':' <value> [',' <key> ':' <value>]* '}' LF 525 + ------------ 526 + 527 + Some key/value pairs are common to all events and some are 528 + event-specific. 529 + 530 + ==== Common Key/Value Pairs 531 + 532 + The following key/value pairs are common to all events: 533 + 534 + ------------ 535 + { 536 + "event":"version", 537 + "sid":"1547659722619736-11614", 538 + "thread":"main", 539 + "time":"2019-01-16 17:28:42.620713", 540 + "file":"common-main.c", 541 + "line":38, 542 + ... 543 + } 544 + ------------ 545 + 546 + `"event":<event>`:: 547 + is the event name. 548 + 549 + `"sid":<sid>`:: 550 + is the session-id. This is a unique string to identify the 551 + process instance to allow all events emitted by a process to 552 + be identified. A session-id is used instead of a PID because 553 + PIDs are recycled by the OS. For child git processes, the 554 + session-id is prepended with the session-id of the parent git 555 + process to allow parent-child relationships to be identified 556 + during post-processing. 557 + 558 + `"thread":<thread>`:: 559 + is the thread name. 560 + 561 + `"time":<time>`:: 562 + is the UTC time of the event. 563 + 564 + `"file":<filename>`:: 565 + is source file generating the event. 566 + 567 + `"line":<line-number>`:: 568 + is the integer source line number generating the event. 569 + 570 + `"repo":<repo-id>`:: 571 + when present, is the integer repo-id as described previously. 572 + 573 + If `GIT_TR2_EVENT_BRIEF` is true, the `file` and `line` fields are omitted 574 + from all events and the `time` field is only present on the "start" and 575 + "atexit" events. 576 + 577 + ==== Event-Specific Key/Value Pairs 578 + 579 + `"version"`:: 580 + This event gives the version of the executable and the EVENT format. 581 + + 582 + ------------ 583 + { 584 + "event":"version", 585 + ... 586 + "evt":"1", # EVENT format version 587 + "exe":"2.20.1.155.g426c96fcdb" # git version 588 + } 589 + ------------ 590 + 591 + `"start"`:: 592 + This event contains the complete argv received by main(). 593 + + 594 + ------------ 595 + { 596 + "event":"start", 597 + ... 598 + "argv":["git","version"] 599 + } 600 + ------------ 601 + 602 + `"exit"`:: 603 + This event is emitted when git calls `exit()`. 604 + + 605 + ------------ 606 + { 607 + "event":"exit", 608 + ... 609 + "t_abs":0.001227, # elapsed time in seconds 610 + "code":0 # exit code 611 + } 612 + ------------ 613 + 614 + `"atexit"`:: 615 + This event is emitted by the Trace2 `atexit` routine during 616 + final shutdown. It should be the last event emitted by the 617 + process. 618 + + 619 + (The elapsed time reported here is greater than the time reported in 620 + the "exit" event because it runs after all other atexit tasks have 621 + completed.) 622 + + 623 + ------------ 624 + { 625 + "event":"atexit", 626 + ... 627 + "t_abs":0.001227, # elapsed time in seconds 628 + "code":0 # exit code 629 + } 630 + ------------ 631 + 632 + `"signal"`:: 633 + This event is emitted when the program is terminated by a user 634 + signal. Depending on the platform, the signal event may 635 + prevent the "atexit" event from being generated. 636 + + 637 + ------------ 638 + { 639 + "event":"signal", 640 + ... 641 + "t_abs":0.001227, # elapsed time in seconds 642 + "signal":13 # SIGTERM, SIGINT, etc. 643 + } 644 + ------------ 645 + 646 + `"error"`:: 647 + This event is emitted when one of the `error()`, `die()`, 648 + or `usage()` functions are called. 649 + + 650 + ------------ 651 + { 652 + "event":"error", 653 + ... 654 + "msg":"invalid option: --cahced", # formatted error message 655 + "fmt":"invalid option: %s" # error format string 656 + } 657 + ------------ 658 + + 659 + The error event may be emitted more than once. The format string 660 + allows post-processors to group errors by type without worrying 661 + about specific error arguments. 662 + 663 + `"cmd_path"`:: 664 + This event contains the discovered full path of the git 665 + executable (on platforms that are configured to resolve it). 666 + + 667 + ------------ 668 + { 669 + "event":"cmd_path", 670 + ... 671 + "path":"C:/work/gfw/git.exe" 672 + } 673 + ------------ 674 + 675 + `"cmd_name"`:: 676 + This event contains the command name for this git process 677 + and the hierarchy of commands from parent git processes. 678 + + 679 + ------------ 680 + { 681 + "event":"cmd_name", 682 + ... 683 + "name":"pack-objects", 684 + "hierarchy":"push/pack-objects" 685 + } 686 + ------------ 687 + + 688 + Normally, the "name" field contains the canonical name of the 689 + command. When a canonical name is not available, one of 690 + these special values are used: 691 + + 692 + ------------ 693 + "_query_" # "git --html-path" 694 + "_run_dashed_" # when "git foo" tries to run "git-foo" 695 + "_run_shell_alias_" # alias expansion to a shell command 696 + "_run_git_alias_" # alias expansion to a git command 697 + "_usage_" # usage error 698 + ------------ 699 + 700 + `"cmd_mode"`:: 701 + This event, when present, describes the command variant This 702 + event may be emitted more than once. 703 + + 704 + ------------ 705 + { 706 + "event":"cmd_mode", 707 + ... 708 + "name":"branch" 709 + } 710 + ------------ 711 + + 712 + The "name" field is an arbitrary string to describe the command mode. 713 + For example, checkout can checkout a branch or an individual file. 714 + And these variations typically have different performance 715 + characteristics that are not comparable. 716 + 717 + `"alias"`:: 718 + This event is present when an alias is expanded. 719 + + 720 + ------------ 721 + { 722 + "event":"alias", 723 + ... 724 + "alias":"l", # registered alias 725 + "argv":["log","--graph"] # alias expansion 726 + } 727 + ------------ 728 + 729 + `"child_start"`:: 730 + This event describes a child process that is about to be 731 + spawned. 732 + + 733 + ------------ 734 + { 735 + "event":"child_start", 736 + ... 737 + "child_id":2, 738 + "child_class":"?", 739 + "use_shell":false, 740 + "argv":["git","rev-list","--objects","--stdin","--not","--all","--quiet"] 741 + 742 + "hook_name":"<hook_name>" # present when child_class is "hook" 743 + "cd":"<path>" # present when cd is required 744 + } 745 + ------------ 746 + + 747 + The "child_id" field can be used to match this child_start with the 748 + corresponding child_exit event. 749 + + 750 + The "child_class" field is a rough classification, such as "editor", 751 + "pager", "transport/*", and "hook". Unclassified children are classified 752 + with "?". 753 + 754 + `"child_exit"`:: 755 + This event is generated after the current process has returned 756 + from the waitpid() and collected the exit information from the 757 + child. 758 + + 759 + ------------ 760 + { 761 + "event":"child_exit", 762 + ... 763 + "child_id":2, 764 + "pid":14708, # child PID 765 + "code":0, # child exit-code 766 + "t_rel":0.110605 # observed run-time of child process 767 + } 768 + ------------ 769 + + 770 + Note that the session-id of the child process is not available to 771 + the current/spawning process, so the child's PID is reported here as 772 + a hint for post-processing. (But it is only a hint because the child 773 + proces may be a shell script which doesn't have a session-id.) 774 + + 775 + Note that the `t_rel` field contains the observed run time in seconds 776 + for the child process (starting before the fork/exec/spawn and 777 + stopping after the waitpid() and includes OS process creation overhead). 778 + So this time will be slightly larger than the atexit time reported by 779 + the child process itself. 780 + 781 + `"exec"`:: 782 + This event is generated before git attempts to `exec()` 783 + another command rather than starting a child process. 784 + + 785 + ------------ 786 + { 787 + "event":"exec", 788 + ... 789 + "exec_id":0, 790 + "exe":"git", 791 + "argv":["foo", "bar"] 792 + } 793 + ------------ 794 + + 795 + The "exec_id" field is a command-unique id and is only useful if the 796 + `exec()` fails and a corresponding exec_result event is generated. 797 + 798 + `"exec_result"`:: 799 + This event is generated if the `exec()` fails and control 800 + returns to the current git command. 801 + + 802 + ------------ 803 + { 804 + "event":"exec_result", 805 + ... 806 + "exec_id":0, 807 + "code":1 # error code (errno) from exec() 808 + } 809 + ------------ 810 + 811 + `"thread_start"`:: 812 + This event is generated when a thread is started. It is 813 + generated from *within* the new thread's thread-proc (for TLS 814 + reasons). 815 + + 816 + ------------ 817 + { 818 + "event":"thread_start", 819 + ... 820 + "thread":"th02:preload_thread" # thread name 821 + } 822 + ------------ 823 + 824 + `"thread_exit"`:: 825 + This event is generated when a thread exits. It is generated 826 + from *within* the thread's thread-proc (for TLS reasons). 827 + + 828 + ------------ 829 + { 830 + "event":"thread_exit", 831 + ... 832 + "thread":"th02:preload_thread", # thread name 833 + "t_rel":0.007328 # thread elapsed time 834 + } 835 + ------------ 836 + 837 + `"def_param"`:: 838 + This event is generated to log a global parameter. 839 + + 840 + ------------ 841 + { 842 + "event":"def_param", 843 + ... 844 + "param":"core.abbrev", 845 + "value":"7" 846 + } 847 + ------------ 848 + 849 + `"def_repo"`:: 850 + This event defines a repo-id and associates it with the root 851 + of the worktree. 852 + + 853 + ------------ 854 + { 855 + "event":"def_repo", 856 + ... 857 + "repo":1, 858 + "worktree":"/Users/jeffhost/work/gfw" 859 + } 860 + ------------ 861 + + 862 + As stated earlier, the repo-id is currently always 1, so there will 863 + only be one def_repo event. Later, if in-proc submodules are 864 + supported, a def_repo event should be emitted for each submodule 865 + visited. 866 + 867 + `"region_enter"`:: 868 + This event is generated when entering a region. 869 + + 870 + ------------ 871 + { 872 + "event":"region_enter", 873 + ... 874 + "repo":1, # optional 875 + "nesting":1, # current region stack depth 876 + "category":"index", # optional 877 + "label":"do_read_index", # optional 878 + "msg":".git/index" # optional 879 + } 880 + ------------ 881 + + 882 + The `category` field may be used in a future enhancement to 883 + do category-based filtering. 884 + + 885 + The `GIT_TR2_EVENT_NESTING` environment variable can be used to 886 + filter deeply nested regions and data events. It defaults to "2". 887 + 888 + `"region_leave"`:: 889 + This event is generated when leaving a region. 890 + + 891 + ------------ 892 + { 893 + "event":"region_leave", 894 + ... 895 + "repo":1, # optional 896 + "t_rel":0.002876, # time spent in region in seconds 897 + "nesting":1, # region stack depth 898 + "category":"index", # optional 899 + "label":"do_read_index", # optional 900 + "msg":".git/index" # optional 901 + } 902 + ------------ 903 + 904 + `"data"`:: 905 + This event is generated to log a thread- and region-local 906 + key/value pair. 907 + + 908 + ------------ 909 + { 910 + "event":"data", 911 + ... 912 + "repo":1, # optional 913 + "t_abs":0.024107, # absolute elapsed time 914 + "t_rel":0.001031, # elapsed time in region/thread 915 + "nesting":2, # region stack depth 916 + "category":"index", 917 + "key":"read/cache_nr", 918 + "value":"3552" 919 + } 920 + ------------ 921 + + 922 + The "value" field may be an integer or a string. 923 + 924 + `"data-json"`:: 925 + This event is generated to log a pre-formatted JSON string 926 + containing structured data. 927 + + 928 + ------------ 929 + { 930 + "event":"data_json", 931 + ... 932 + "repo":1, # optional 933 + "t_abs":0.015905, 934 + "t_rel":0.015905, 935 + "nesting":1, 936 + "category":"process", 937 + "key":"windows/ancestry", 938 + "value":["bash.exe","bash.exe"] 939 + } 940 + ------------ 941 + 942 + == Example Trace2 API Usage 943 + 944 + Here is a hypothetical usage of the Trace2 API showing the intended 945 + usage (without worrying about the actual Git details). 946 + 947 + Initialization:: 948 + 949 + Initialization happens in `main()`. Behind the scenes, an 950 + `atexit` and `signal` handler are registered. 951 + + 952 + ---------------- 953 + int main(int argc, const char **argv) 954 + { 955 + int exit_code; 956 + 957 + trace2_initialize(); 958 + trace2_cmd_start(argv); 959 + 960 + exit_code = cmd_main(argc, argv); 961 + 962 + trace2_cmd_exit(exit_code); 963 + 964 + return exit_code; 965 + } 966 + ---------------- 967 + 968 + Command Details:: 969 + 970 + After the basics are established, additional command 971 + information can be sent to Trace2 as it is discovered. 972 + + 973 + ---------------- 974 + int cmd_checkout(int argc, const char **argv) 975 + { 976 + trace2_cmd_name("checkout"); 977 + trace2_cmd_mode("branch"); 978 + trace2_def_repo(the_repository); 979 + 980 + // emit "def_param" messages for "interesting" config settings. 981 + trace2_cmd_list_config(); 982 + 983 + if (do_something()) 984 + trace2_cmd_error("Path '%s': cannot do something", path); 985 + 986 + return 0; 987 + } 988 + ---------------- 989 + 990 + Child Processes:: 991 + 992 + Wrap code spawning child processes. 993 + + 994 + ---------------- 995 + void run_child(...) 996 + { 997 + int child_exit_code; 998 + struct child_process cmd = CHILD_PROCESS_INIT; 999 + ... 1000 + cmd.trace2_child_class = "editor"; 1001 + 1002 + trace2_child_start(&cmd); 1003 + child_exit_code = spawn_child_and_wait_for_it(); 1004 + trace2_child_exit(&cmd, child_exit_code); 1005 + } 1006 + ---------------- 1007 + + 1008 + For example, the following fetch command spawned ssh, index-pack, 1009 + rev-list, and gc. This example also shows that fetch took 1010 + 5.199 seconds and of that 4.932 was in ssh. 1011 + + 1012 + ---------------- 1013 + $ export GIT_TR2_BRIEF=1 1014 + $ export GIT_TR2=~/log.normal 1015 + $ git fetch origin 1016 + ... 1017 + ---------------- 1018 + + 1019 + ---------------- 1020 + $ cat ~/log.normal 1021 + version 2.20.1.vfs.1.1.47.g534dbe1ad1 1022 + start git fetch origin 1023 + worktree /Users/jeffhost/work/gfw 1024 + cmd_name fetch (fetch) 1025 + child_start[0] ssh git@github.com ... 1026 + child_start[1] git index-pack ... 1027 + ... (Trace2 events from child processes omitted) 1028 + child_exit[1] pid:14707 code:0 elapsed:0.076353 1029 + child_exit[0] pid:14706 code:0 elapsed:4.931869 1030 + child_start[2] git rev-list ... 1031 + ... (Trace2 events from child process omitted) 1032 + child_exit[2] pid:14708 code:0 elapsed:0.110605 1033 + child_start[3] git gc --auto 1034 + ... (Trace2 events from child process omitted) 1035 + child_exit[3] pid:14709 code:0 elapsed:0.006240 1036 + exit elapsed:5.198503 code:0 1037 + atexit elapsed:5.198541 code:0 1038 + ---------------- 1039 + + 1040 + When a git process is a (direct or indirect) child of another 1041 + git process, it inherits Trace2 context information. This 1042 + allows the child to print the command hierarchy. This example 1043 + shows gc as child[3] of fetch. When the gc process reports 1044 + its name as "gc", it also reports the hierarchy as "fetch/gc". 1045 + (In this example, trace2 messages from the child process is 1046 + indented for clarity.) 1047 + + 1048 + ---------------- 1049 + $ export GIT_TR2_BRIEF=1 1050 + $ export GIT_TR2=~/log.normal 1051 + $ git fetch origin 1052 + ... 1053 + ---------------- 1054 + + 1055 + ---------------- 1056 + $ cat ~/log.normal 1057 + version 2.20.1.160.g5676107ecd.dirty 1058 + start git fetch official 1059 + worktree /Users/jeffhost/work/gfw 1060 + cmd_name fetch (fetch) 1061 + ... 1062 + child_start[3] git gc --auto 1063 + version 2.20.1.160.g5676107ecd.dirty 1064 + start /Users/jeffhost/work/gfw/git gc --auto 1065 + worktree /Users/jeffhost/work/gfw 1066 + cmd_name gc (fetch/gc) 1067 + exit elapsed:0.001959 code:0 1068 + atexit elapsed:0.001997 code:0 1069 + child_exit[3] pid:20303 code:0 elapsed:0.007564 1070 + exit elapsed:3.868938 code:0 1071 + atexit elapsed:3.868970 code:0 1072 + ---------------- 1073 + 1074 + Regions:: 1075 + 1076 + Regions can be use to time an interesting section of code. 1077 + + 1078 + ---------------- 1079 + void wt_status_collect(struct wt_status *s) 1080 + { 1081 + trace2_region_enter("status", "worktrees", s->repo); 1082 + wt_status_collect_changes_worktree(s); 1083 + trace2_region_leave("status", "worktrees", s->repo); 1084 + 1085 + trace2_region_enter("status", "index", s->repo); 1086 + wt_status_collect_changes_index(s); 1087 + trace2_region_leave("status", "index", s->repo); 1088 + 1089 + trace2_region_enter("status", "untracked", s->repo); 1090 + wt_status_collect_untracked(s); 1091 + trace2_region_leave("status", "untracked", s->repo); 1092 + } 1093 + 1094 + void wt_status_print(struct wt_status *s) 1095 + { 1096 + trace2_region_enter("status", "print", s->repo); 1097 + switch (s->status_format) { 1098 + ... 1099 + } 1100 + trace2_region_leave("status", "print", s->repo); 1101 + } 1102 + ---------------- 1103 + + 1104 + In this example, scanning for untracked files ran from +0.012568 to 1105 + +0.027149 (since the process started) and took 0.014581 seconds. 1106 + + 1107 + ---------------- 1108 + $ export GIT_TR2_PERF_BRIEF=1 1109 + $ export GIT_TR2_PERF=~/log.perf 1110 + $ git status 1111 + ... 1112 + 1113 + $ cat ~/log.perf 1114 + d0 | main | version | | | | | 2.20.1.160.g5676107ecd.dirty 1115 + d0 | main | start | | | | | git status 1116 + d0 | main | def_repo | r1 | | | | worktree:/Users/jeffhost/work/gfw 1117 + d0 | main | cmd_name | | | | | status (status) 1118 + ... 1119 + d0 | main | region_enter | r1 | 0.010988 | | status | label:worktrees 1120 + d0 | main | region_leave | r1 | 0.011236 | 0.000248 | status | label:worktrees 1121 + d0 | main | region_enter | r1 | 0.011260 | | status | label:index 1122 + d0 | main | region_leave | r1 | 0.012542 | 0.001282 | status | label:index 1123 + d0 | main | region_enter | r1 | 0.012568 | | status | label:untracked 1124 + d0 | main | region_leave | r1 | 0.027149 | 0.014581 | status | label:untracked 1125 + d0 | main | region_enter | r1 | 0.027411 | | status | label:print 1126 + d0 | main | region_leave | r1 | 0.028741 | 0.001330 | status | label:print 1127 + d0 | main | exit | | 0.028778 | | | code:0 1128 + d0 | main | atexit | | 0.028809 | | | code:0 1129 + ---------------- 1130 + + 1131 + Regions may be nested. This causes messages to be indented in the 1132 + PERF target, for example. 1133 + Elapsed times are relative to the start of the correpsonding nesting 1134 + level as expected. For example, if we add region message to: 1135 + + 1136 + ---------------- 1137 + static enum path_treatment read_directory_recursive(struct dir_struct *dir, 1138 + struct index_state *istate, const char *base, int baselen, 1139 + struct untracked_cache_dir *untracked, int check_only, 1140 + int stop_at_first_file, const struct pathspec *pathspec) 1141 + { 1142 + enum path_treatment state, subdir_state, dir_state = path_none; 1143 + 1144 + trace2_region_enter_printf("dir", "read_recursive", NULL, "%.*s", baselen, base); 1145 + ... 1146 + trace2_region_leave_printf("dir", "read_recursive", NULL, "%.*s", baselen, base); 1147 + return dir_state; 1148 + } 1149 + ---------------- 1150 + + 1151 + We can further investigate the time spent scanning for untracked files. 1152 + + 1153 + ---------------- 1154 + $ export GIT_TR2_PERF_BRIEF=1 1155 + $ export GIT_TR2_PERF=~/log.perf 1156 + $ git status 1157 + ... 1158 + $ cat ~/log.perf 1159 + d0 | main | version | | | | | 2.20.1.162.gb4ccea44db.dirty 1160 + d0 | main | start | | | | | git status 1161 + d0 | main | def_repo | r1 | | | | worktree:/Users/jeffhost/work/gfw 1162 + d0 | main | cmd_name | | | | | status (status) 1163 + ... 1164 + d0 | main | region_enter | r1 | 0.015047 | | status | label:untracked 1165 + d0 | main | region_enter | | 0.015132 | | dir | ..label:read_recursive 1166 + d0 | main | region_enter | | 0.016341 | | dir | ....label:read_recursive vcs-svn/ 1167 + d0 | main | region_leave | | 0.016422 | 0.000081 | dir | ....label:read_recursive vcs-svn/ 1168 + d0 | main | region_enter | | 0.016446 | | dir | ....label:read_recursive xdiff/ 1169 + d0 | main | region_leave | | 0.016522 | 0.000076 | dir | ....label:read_recursive xdiff/ 1170 + d0 | main | region_enter | | 0.016612 | | dir | ....label:read_recursive git-gui/ 1171 + d0 | main | region_enter | | 0.016698 | | dir | ......label:read_recursive git-gui/po/ 1172 + d0 | main | region_enter | | 0.016810 | | dir | ........label:read_recursive git-gui/po/glossary/ 1173 + d0 | main | region_leave | | 0.016863 | 0.000053 | dir | ........label:read_recursive git-gui/po/glossary/ 1174 + ... 1175 + d0 | main | region_enter | | 0.031876 | | dir | ....label:read_recursive builtin/ 1176 + d0 | main | region_leave | | 0.032270 | 0.000394 | dir | ....label:read_recursive builtin/ 1177 + d0 | main | region_leave | | 0.032414 | 0.017282 | dir | ..label:read_recursive 1178 + d0 | main | region_leave | r1 | 0.032454 | 0.017407 | status | label:untracked 1179 + ... 1180 + d0 | main | exit | | 0.034279 | | | code:0 1181 + d0 | main | atexit | | 0.034322 | | | code:0 1182 + ---------------- 1183 + + 1184 + Trace2 regions are similar to the existing trace_performance_enter() 1185 + and trace_performance_leave() routines, but are thread safe and 1186 + maintain per-thread stacks of timers. 1187 + 1188 + Data Messages:: 1189 + 1190 + Data messages added to a region. 1191 + + 1192 + ---------------- 1193 + int read_index_from(struct index_state *istate, const char *path, 1194 + const char *gitdir) 1195 + { 1196 + trace2_region_enter_printf("index", "do_read_index", the_repository, "%s", path); 1197 + 1198 + ... 1199 + 1200 + trace2_data_intmax("index", the_repository, "read/version", istate->version); 1201 + trace2_data_intmax("index", the_repository, "read/cache_nr", istate->cache_nr); 1202 + 1203 + trace2_region_leave_printf("index", "do_read_index", the_repository, "%s", path); 1204 + } 1205 + ---------------- 1206 + + 1207 + This example shows that the index contained 3552 entries. 1208 + + 1209 + ---------------- 1210 + $ export GIT_TR2_PERF_BRIEF=1 1211 + $ export GIT_TR2_PERF=~/log.perf 1212 + $ git status 1213 + ... 1214 + $ cat ~/log.perf 1215 + d0 | main | version | | | | | 2.20.1.156.gf9916ae094.dirty 1216 + d0 | main | start | | | | | git status 1217 + d0 | main | def_repo | r1 | | | | worktree:/Users/jeffhost/work/gfw 1218 + d0 | main | cmd_name | | | | | status (status) 1219 + d0 | main | region_enter | r1 | 0.001791 | | index | label:do_read_index .git/index 1220 + d0 | main | data | r1 | 0.002494 | 0.000703 | index | ..read/version:2 1221 + d0 | main | data | r1 | 0.002520 | 0.000729 | index | ..read/cache_nr:3552 1222 + d0 | main | region_leave | r1 | 0.002539 | 0.000748 | index | label:do_read_index .git/index 1223 + ... 1224 + ---------------- 1225 + 1226 + Thread Events:: 1227 + 1228 + Thread messages added to a thread-proc. 1229 + + 1230 + For example, the multithreaded preload-index code can be 1231 + instrumented with a region around the thread pool and then 1232 + per-thread start and exit events within the threadproc. 1233 + + 1234 + ---------------- 1235 + static void *preload_thread(void *_data) 1236 + { 1237 + // start the per-thread clock and emit a message. 1238 + trace2_thread_start("preload_thread"); 1239 + 1240 + // report which chunk of the array this thread was assigned. 1241 + trace2_data_intmax("index", the_repository, "offset", p->offset); 1242 + trace2_data_intmax("index", the_repository, "count", nr); 1243 + 1244 + do { 1245 + ... 1246 + } while (--nr > 0); 1247 + ... 1248 + 1249 + // report elapsed time taken by this thread. 1250 + trace2_thread_exit(); 1251 + return NULL; 1252 + } 1253 + 1254 + void preload_index(struct index_state *index, 1255 + const struct pathspec *pathspec, 1256 + unsigned int refresh_flags) 1257 + { 1258 + trace2_region_enter("index", "preload", the_repository); 1259 + 1260 + for (i = 0; i < threads; i++) { 1261 + ... /* create thread */ 1262 + } 1263 + 1264 + for (i = 0; i < threads; i++) { 1265 + ... /* join thread */ 1266 + } 1267 + 1268 + trace2_region_leave("index", "preload", the_repository); 1269 + } 1270 + ---------------- 1271 + + 1272 + In this example preload_index() was executed by the `main` thread 1273 + and started the `preload` region. Seven threads, named 1274 + `th01:preload_thread` through `th07:preload_thread`, were started. 1275 + Events from each thread are atomically appended to the shared target 1276 + stream as they occur so they may appear in random order with respect 1277 + other threads. Finally, the main thread waits for the threads to 1278 + finish and leaves the region. 1279 + + 1280 + Data events are tagged with the active thread name. They are used 1281 + to report the per-thread parameters. 1282 + + 1283 + ---------------- 1284 + $ export GIT_TR2_PERF_BRIEF=1 1285 + $ export GIT_TR2_PERF=~/log.perf 1286 + $ git status 1287 + ... 1288 + $ cat ~/log.perf 1289 + ... 1290 + d0 | main | region_enter | r1 | 0.002595 | | index | label:preload 1291 + d0 | th01:preload_thread | thread_start | | 0.002699 | | | 1292 + d0 | th02:preload_thread | thread_start | | 0.002721 | | | 1293 + d0 | th01:preload_thread | data | r1 | 0.002736 | 0.000037 | index | offset:0 1294 + d0 | th02:preload_thread | data | r1 | 0.002751 | 0.000030 | index | offset:2032 1295 + d0 | th03:preload_thread | thread_start | | 0.002711 | | | 1296 + d0 | th06:preload_thread | thread_start | | 0.002739 | | | 1297 + d0 | th01:preload_thread | data | r1 | 0.002766 | 0.000067 | index | count:508 1298 + d0 | th06:preload_thread | data | r1 | 0.002856 | 0.000117 | index | offset:2540 1299 + d0 | th03:preload_thread | data | r1 | 0.002824 | 0.000113 | index | offset:1016 1300 + d0 | th04:preload_thread | thread_start | | 0.002710 | | | 1301 + d0 | th02:preload_thread | data | r1 | 0.002779 | 0.000058 | index | count:508 1302 + d0 | th06:preload_thread | data | r1 | 0.002966 | 0.000227 | index | count:508 1303 + d0 | th07:preload_thread | thread_start | | 0.002741 | | | 1304 + d0 | th07:preload_thread | data | r1 | 0.003017 | 0.000276 | index | offset:3048 1305 + d0 | th05:preload_thread | thread_start | | 0.002712 | | | 1306 + d0 | th05:preload_thread | data | r1 | 0.003067 | 0.000355 | index | offset:1524 1307 + d0 | th05:preload_thread | data | r1 | 0.003090 | 0.000378 | index | count:508 1308 + d0 | th07:preload_thread | data | r1 | 0.003037 | 0.000296 | index | count:504 1309 + d0 | th03:preload_thread | data | r1 | 0.002971 | 0.000260 | index | count:508 1310 + d0 | th04:preload_thread | data | r1 | 0.002983 | 0.000273 | index | offset:508 1311 + d0 | th04:preload_thread | data | r1 | 0.007311 | 0.004601 | index | count:508 1312 + d0 | th05:preload_thread | thread_exit | | 0.008781 | 0.006069 | | 1313 + d0 | th01:preload_thread | thread_exit | | 0.009561 | 0.006862 | | 1314 + d0 | th03:preload_thread | thread_exit | | 0.009742 | 0.007031 | | 1315 + d0 | th06:preload_thread | thread_exit | | 0.009820 | 0.007081 | | 1316 + d0 | th02:preload_thread | thread_exit | | 0.010274 | 0.007553 | | 1317 + d0 | th07:preload_thread | thread_exit | | 0.010477 | 0.007736 | | 1318 + d0 | th04:preload_thread | thread_exit | | 0.011657 | 0.008947 | | 1319 + d0 | main | region_leave | r1 | 0.011717 | 0.009122 | index | label:preload 1320 + ... 1321 + d0 | main | exit | | 0.029996 | | | code:0 1322 + d0 | main | atexit | | 0.030027 | | | code:0 1323 + ---------------- 1324 + + 1325 + In this example, the preload region took 0.009122 seconds. The 7 threads 1326 + took between 0.006069 and 0.008947 seconds to work on their portion of 1327 + the index. Thread "th01" worked on 508 items at offset 0. Thread "th02" 1328 + worked on 508 items at offset 2032. Thread "th04" worked on 508 itemts 1329 + at offset 508. 1330 + + 1331 + This example also shows that thread names are assigned in a racy manner 1332 + as each thread starts and allocates TLS storage. 1333 + 1334 + == Future Work 1335 + 1336 + === Relationship to the Existing Trace Api (api-trace.txt) 1337 + 1338 + There are a few issues to resolve before we can completely 1339 + switch to Trace2. 1340 + 1341 + * Updating existing tests that assume GIT_TRACE format messages. 1342 + 1343 + * How to best handle custom GIT_TRACE_<key> messages? 1344 + 1345 + ** The GIT_TRACE_<key> mechanism allows each <key> to write to a 1346 + different file (in addition to just stderr). 1347 + 1348 + ** Do we want to maintain that ability or simply write to the existing 1349 + Trace2 targets (and convert <key> to a "category").