Cross-thread memory indexing in time travel debugging traces
By analyzing and identifying memory unit values earlier than memory value records in time travel tracking, the limitations of time travel debugging technology in presenting memory contents are solved, achieving earlier and more accurate memory content exposure.
Patent Information
- Application Number
- CN202080027948.X
- Authority / Receiving Office
- CN · China
- Patent Type
- Patents(China)
- Current Assignee / Owner
- Priority Date
- 2019-04-17
- Filing Date
- 2020-03-26
- Publication Date
- 2025-03-11
- Estimated Expiration
- 2040-03-26
AI Technical Summary
Time travel debugging technology has limitations in presenting memory content, especially in the case of handling rapid execution and large amounts of tracking data by modern processors, resulting in incomplete redundant data and memory content presentation.
By analyzing time travel tracking, identifying and exposing memory cell values that are recorded at execution time earlier than memory values, indexing data is generated to supplement existing tracking, re-arrange the location of memory values, or generate entirely new tracking to improve early exposure and accuracy of memory content.
Improves early exposure of memory cell values during tracking playback, reduces redundant data, and enhances presentation integrity and accuracy of memory content.
Smart Images

Figure CN113711190B_ABST
Abstract
Description
Background Art
[0001] Tracking down and correcting unexpected software behavior in software code (often referred to as "debugging" code) is a core activity in software development. Unexpected software behavior can include many things, such as execution crashes, runtime exceptions, slow execution performance, incorrect data results, data corruption, etc. Unexpected software behavior can be triggered by a variety of factors, such as data input, user input, race conditions (for example, when accessing shared resources), etc. Given the diversity of triggers, unexpected software behavior can be rare and seemingly random, and extremely difficult to reproduce. As such, it can be very time-consuming and difficult for developers to identify a given unexpected software behavior. Once the unexpected software behavior has been identified, it can be time-consuming and difficult to determine its root cause(s) again.
[0002] One method that developers use to debug code is to use a "live" debugger. Typically, a live debugger attaches to the execution of a live procedure and enables the developer to monitor and direct the forward execution of the procedure. For example, a live debugger may enable the developer to set breakpoints that halt program execution when it reaches a specific instruction, set watchpoints that halt program execution when it accesses a specific memory address, single-step through lines of code as it executes, etc.
[0003] Emerging forms of diagnostic tools support "historical" debugging (also known as "time travel" or "reverse" debugging), in which the execution of at least a portion of a program thread(s) is recorded / traced into one or more trace files (i.e., traces). Using some tracing techniques, the trace can contain very high fidelity "bit-accurate" historical trace data, which enables the recorded portion(s) of the traced thread(s) to be virtually "played back" with extremely high fidelity - even down to the granularity of a single instruction (e.g., machine code instructions, intermediate language code instructions, etc.). Thus, using bit-accurate trace data, "time travel" debuggers enable developers to monitor and direct not only forward simulation of the traced code (e.g., via breakpoints, watchpoints, single-stepping, etc.), but also reverse simulation of the traced code (e.g., via reverse breakpoints, reverse watchpoints, reverse single-stepping, etc.). Thus, developers can monitor and direct the execution of any portion of the program prior to tracing.
[0004] Although providing tremendous benefits over traditional on-site debuggers, time travel debugging techniques still have some limitations. For example, with modern processors that may execute billions of instructions per second, the amount of trace data collected during program execution is likely to be astronomical. Therefore, the tracing mechanisms employed by many time travel debugging techniques emphasize generating a minimum amount of trace data for each instruction executed. For example, recognizing that most processor instructions are deterministic (i.e., they will always produce the same output when given the same input), some time travel debugging techniques rely on representing their values at the time the memory read occurs, as well as the side effects (e.g., outputs) of any non-deterministic instructions. It is worth noting that in order to reduce the overhead of the time travel tracker, the tracker may have a limited ability to record which memory values it has previously recorded. In this way, the tracker may record multiple values for the same memory cell associated with multiple reads from that memory cell, which may add redundant data to the time travel trace.
[0005] Since the field debugger is attached to the field process, it has access to the entire memory space of the process at any time, so any content of any accessible memory unit can be presented at any time. In contrast, when replaying the time travel trace that represents the memory reads as they occur, the time travel debugger may only be able to determine the value of a given memory unit when there is a data packet representing the read from the unit in the trace. This means that, compared to the field debugger, the time travel debugger may be limited to the memory content that can be generated at any given time. For example, although the field debugger may be able to present the entire content of the memory buffer when the buffer is initialized (that is, because the entire memory buffer is in the memory space of the field process and can be used for the field debugger), the time travel debugger may only be able to present the contents of the memory buffer step by step because these contents are read by the trace code when replayed by the emulator. Therefore, although the time travel debugger provides significant benefits over the field debugger, such as being able to analyze code both forward and backward, it may be limited in its ability to present memory contents compared to the field debugger. Summary of the invention
[0006] At least some embodiments described herein analyze a time travel trace to identify memory cell values that may be presented during trace playback at an execution time that is earlier than the execution time corresponding to the event (e.g., a memory read) that caused these memory cell values to be recorded in the trace. For example, an embodiment may divide the trace into fragments - or a continuous sequence of instructions executed on a single thread - and identify in at least one of the fragments a memory cell value corresponding to a read that occurred in the fragment that is compatible with other values of the memory cell in the fragment. The memory cell value may then be exposed earlier in the fragment, such as at the beginning of the fragment. An embodiment may also identify whether the memory cell value is compatible with a previous fragment, and if it is compatible, push the value across the fragments. An embodiment may also use a heuristic to determine whether the memory cell value is compatible with gaps in the trace record between fragments, and if it is compatible, push the value across the gaps. Embodiments may generate index data to supplement an existing trace and identify memory values in the trace that may be present earlier than where they appear in the trace, may rewrite / modify an existing trace to rearrange where memory values appear in the trace, or may generate an entirely new trace that includes the rearranged memory values.
[0007] At least some embodiments described herein analyze a time travel trace to identify and insert memory snapshot data to enable one or more threads to be replayed / queried independently of one or more other threads in the trace while still being able to present a correct view of the memory locations interacted with by these other threads. In particular, a trace may represent the execution of multiple threads of execution. In such an embodiment, the trace data for multiple threads is typically interleaved, and playback typically requires processing data related to all threads. In an embodiment, a trace may use a separate trace data stream to represent the execution of each thread, however, the execution of one thread may modify memory visible to another thread. In some embodiments, one or more of the disclosed solutions may insert memory snapshot data into a data stream associated with a given thread, the memory snapshot data identifying the memory that one or more other (multiple) threads interacted with while they were executed (e.g., concurrently with the given thread, or during a suspension of the given thread). These memory snapshots enable a given thread to be replayed / queried independently of other threads while still being able to present a correct view of the memory locations interacted with by these other threads. When inserting a memory snapshot, these embodiments may view threads individually (i.e., so that individual threads can be replayed / queried independently of other thread(s)) and / or view threads as thread groups (i.e., so that thread groups can be replayed / queried independently of other thread(s)).
[0008] Some embodiments include methods, systems, and computer program products for generating data for causing a memory cell value to be exposed during a trace playback at an execution time that precedes an execution time corresponding to an event that caused the memory cell value to be recorded in the trace. These embodiments include identifying a plurality of trace segments within a trace representing a previous execution of one or more threads. Each trace segment represents an uninterrupted, continuous execution of a plurality of executable instructions on a corresponding thread of the one or more threads. The plurality of trace segments include at least a first trace segment and a second trace segment. These embodiments determine at least a partial ordering of the plurality of trace segments, including determining that a first trace segment may be ordered before a second trace segment. For at least the second trace segment, at a first execution time that precedes a second execution time that corresponds to an event that caused the memory cell value to be recorded in the trace segment during the trace recording, these embodiments determine that the memory cell value may be exposed during the playback of the second trace segment. These embodiments then generate output data indicating that the memory cell value may be exposed at the first execution time during the playback of the second trace segment.
[0009] Other embodiments include methods, systems, and computer program products for modifying a trace to expose memory cell values prior to an execution time corresponding to an event that caused the memory cell values to be recorded in the trace. These embodiments include accessing a trace representing a previous execution of one or more threads, and identifying a plurality of data packets within the trace, the data packets respectively representing corresponding memory cell values read from a particular memory cell. Each data packet in the plurality of data packets corresponds to at least one execution event. These embodiments also include selecting a particular memory cell value represented in one of the plurality of data packets. These embodiments also include modifying the trace by performing at least one of the following: (i) removing all but one of the plurality of data packets from at least one trace segment; or (ii) inserting data into the trace that exposes the selected particular memory cell values during trace playback at an execution time prior to an execution time of an execution event corresponding to the plurality of data packets, and removing the plurality of data packets from the trace.
[0010] Other embodiments include methods, systems, and computer program products for creating memory snapshot data that reduces processing for thread-focused analysis. These embodiments include identifying multiple trace segments within a trace representing a previous execution of multiple threads. Each trace segment represents the uninterrupted continuous execution of multiple executable instructions on a corresponding thread in the multiple threads. The multiple trace segments include a first trace segment and a second trace segment corresponding to a first thread, and a third trace segment corresponding to a second thread. These embodiments also include at least determining a partial ordering among the multiple trace segments, including determining that the first trace segment is orderable before the second trace segment on the first thread, and the third trace segment is orderable between the first trace segment and the second trace segment. These embodiments also include: based on the third trace segment being orderable between the first trace segment and the second trace segment, identifying at least one memory unit that interacts with the execution of one or more executable instructions represented by the third trace segment, and inserting memory snapshot data into the trace data corresponding to the first thread, the memory snapshot data at least identifying the at least one memory unit.
[0011] This Summary is provided to introduce a selection of concepts in a simplified form that are further described below in the Detailed Description. This Summary is not intended to identify key features or essential features of the claimed subject matter, nor is it intended to be used as an aid in determining the scope of the claimed subject matter. BRIEF DESCRIPTION OF THE DRAWINGS
[0012] In order to describe the manner in which the above and other advantages and features of the present invention can be obtained, a more particular description of the invention briefly described above will be drawn by reference to specific embodiments thereof illustrated in the accompanying drawings. Understanding that these drawings depict only typical embodiments of the invention and are not therefore to be considered limiting of its scope, the present invention will be described and explained with additional specificity and detail through the use of the accompanying drawings, in which:
[0013] Figure 1A An example computing environment is illustrated that facilitates exposing a memory cell value prior to an execution time corresponding to an event that causes the memory cell value to be recorded in a trace;
[0014] Figure 1B Pictured Figure 1A Additional details of the memory index component of ;
[0015] Figure 2 The diagram shows Figure 1A An example of a computing environment that is networked with one or more other computer systems;
[0016] Figure 3 illustrates an example of a time travel debug trace;
[0017] Figure 4A illustrates an example timing diagram including a timeline of execution of three threads (including fragments);
[0018] Figure 4B Pictured Figure 4A An example of a potential total ordering of the fragments in ;
[0019] Figure 5A illustrates an example timing diagram including a timeline of execution of three threads (including fragments and gaps);
[0020] Figure 5B Pictured Figure 5A An example of a potential total ordering of fragments and gaps in ;
[0021] Fig. 6A illustrates an example timing diagram corresponding to the execution of a single snippet performing a string copy, including live and time travel debug memory read and write timing;
[0022] Figure 6B illustrates an example timing diagram corresponding to execution of a single segment that performs a string copy, including performing an intra-segment memory move;
[0023] Fig. 7A illustrates an example timing diagram corresponding to the execution of a single snippet performing a string copy, including live and time travel debug memory read and write timing;
[0024] Figure 7B illustrates an example timing diagram corresponding to execution of a single segment that performs a string copy, including performing an intra-segment memory move;
[0025] Fig. 8A illustrates an example timing diagram corresponding to the execution of multiple snippets that split a string into multiple segments based on regular expression matching and which includes a snippet from another thread, including live and time travel debug memory read and write timing;
[0026] Figure 8B illustrates an example timing diagram corresponding to execution of a plurality of snippets that split a string into multiple segments based on regular expression matching and that include a snippet from another thread, including performing an intra-segment memory move;
[0027] Figure 8C An example timing diagram corresponding to the execution of multiple snippets that split a string into multiple segments based on regular expression matching and that include a snippet from another thread, including Figure 8B Performing inter-segment memory movement after the intra-segment memory movement;
[0028] Fig.8D An example timing diagram corresponding to the execution of multiple fragments that split a string into multiple segments based on regular expression matching and that include fragments from another thread is illustrated, and Fig. 8A Overall memory movement compared to;
[0029] Fig. 9A illustrates an example timing diagram corresponding to the execution of multiple snippets that split a string into multiple segments based on regular expression matching and which include gaps, including live and time travel debug memory read and write timing;
[0030] Fig. 9B illustrates an example timing diagram corresponding to execution of a plurality of segments that split a string into segments based on regular expression matching and that include gaps, including performing inter-segment memory moves;
[0031] Fig. 9C illustrates an example timing diagram corresponding to execution of a plurality of segments that split a string into a plurality of segments based on a regular expression match and that include gaps, including performing a memory move across the gaps based on a single line move analysis;
[0032] Fig.9D illustrates an example timing diagram corresponding to execution of a plurality of fragments that split a string into a plurality of segments based on regular expression matching and that include gaps, including performing memory moves across the gaps based on annotation-based analysis;
[0033] Fig.9E illustrates an example timing diagram corresponding to execution of a plurality of segments that split a string into a plurality of segments based on regular expression matching and that include gaps, including performing a memory move across the gaps based on allocation-based analysis;
[0034] Fig.10 illustrates a flow chart of an example method for generating data for exposing a memory cell value during trace playback at an execution time that precedes an execution time corresponding to an event that caused the memory cell value to be recorded in the trace;
[0035] Fig.11 illustrates a flow chart of an example method for modifying a trace to expose a memory cell value prior to an execution time corresponding to an event that caused the memory cell value to be recorded in the trace;
[0036] Fig. 12A An example timing diagram is shown, the timing diagram including timelines of execution of three threads, including fragment execution up to a particular point in one of the timelines;
[0037] Fig. 12BShows Figure 4A An example of a potential total ordering of the fragments in to a particular point.
[0038] Fig. 12C An example timing diagram is shown, which generally corresponds to Fig. 12A , but it shows the insertion of memory snapshot data based on intervening fragments;
[0039] Fig.12D An example timing diagram is shown, which generally corresponds to Fig. 12B but it shows the insertion of memory snapshot data based on intervening fragments;
[0040] Fig.12E An example timing diagram is shown, which generally corresponds to Fig. 12C , but it shows pushing the compatible memory snapshot data to the start of the trace;
[0041] Fig.12F An example timing diagram is shown, which generally corresponds to Fig.12D , but it shows pushing the compatible memory snapshot data to the start of the trace;
[0042] Figure 12G An example timing diagram is shown, which generally corresponds to Fig. 12A , but it shows a memory snapshot in the presence of a focus group;
[0043] Fig.12H An example timing diagram is shown, which generally corresponds to Fig. 12B but showing a memory snapshot in the presence of a focus group; and
[0044] Fig.13 A flow chart of an example method for creating memory snapshot data to reduce processing for thread-focused analysis is shown. DETAILED DESCRIPTION
[0045] At least some embodiments described herein analyze a time travel trace to identify memory cell values that may be presented during trace playback at an execution time that is earlier than the execution time corresponding to the event (e.g., a memory read) that caused these memory cell values to be recorded in the trace. For example, an embodiment may divide the trace into fragments - or a continuous sequence of instructions executed on a single thread - and identify in at least one of the fragments a memory cell value corresponding to a read that occurred in the fragment that is compatible with other values of the memory cell in the fragment. The memory cell value may then be exposed earlier in the fragment, such as at the beginning of the fragment. An embodiment may also identify whether the memory cell value is compatible with a previous fragment, and if it is compatible, push the value across the fragments. An embodiment may also use a heuristic to determine whether the memory cell value is compatible with gaps in the trace record between fragments, and if it is compatible, push the value across the gaps. Embodiments may generate index data to supplement an existing trace and identify memory values in the trace that may have been presented earlier than where they appeared in the trace, may rewrite / modify an existing trace to rearrange where memory values appear in the trace, or may generate an entirely new trace that includes the rearranged memory values.
[0046] At least some embodiments described herein analyze a time travel trace to identify and insert memory snapshot data to enable one or more threads to be replayed / queried independently of one or more other threads in the trace while still being able to present a correct view of the memory locations interacted with by these other threads. In particular, a trace may represent the execution of multiple threads of execution. In such an embodiment, the trace data for multiple threads is typically interleaved, and playback typically requires processing data related to all threads. In an embodiment, a trace may use a separate trace data stream to represent the execution of each thread, however, the execution of one thread may modify memory visible to another thread. In some embodiments, one or more of the disclosed solutions may insert memory snapshot data into a data stream associated with a given thread, the memory snapshot data identifying the memory that one or more other threads interacted with while they were executed (e.g., concurrently with the given thread, or during a suspension of the given thread). These memory snapshots enable a given thread to be replayed / queried independently of other threads while still being able to present a correct view of the memory locations interacted with by these other threads. When inserting a memory snapshot, these embodiments may view threads individually (i.e., so that individual threads can be replayed / queried independently of other thread(s)) and / or view threads as thread groups (i.e., so that thread groups can be replayed / queried independently of other thread(s)).
[0047] Figure 1AAn example computing environment 100a is illustrated that facilitates exposing memory cell values prior to an execution time corresponding to an event that causes the memory cell values to be recorded in a trace, and creating memory snapshot data that reduces processing (e.g., playback / query) for thread-focused analysis. As depicted, computing environment 100a may include or utilize a special purpose or general purpose computer system 101 that includes computer hardware such as, for example, one or more processors 102, system memory 103, persistent storage 104, and / or network device(s) 105 that are communicatively coupled using one or more communication buses 106.
[0048] Embodiments within the scope of the present invention may include physical and other computer-readable media for carrying or storing computer-executable instructions and / or data structures. Such computer-readable media may be any available media that can be accessed by a general-purpose or special-purpose computer system. Computer-readable media that store computer-executable instructions and / or data structures are computer storage media. Computer-readable media that carry computer-executable instructions and / or data structures are transmission media. Thus, by way of example and not limitation, embodiments of the present invention may include at least two distinct computer-readable media: computer storage media and transmission media.
[0049] Computer storage media are physical storage media (e.g., system memory 103 and / or persistent storage 104) that store computer-executable instructions and / or data structures. Physical storage media include computer hardware, such as RAM, ROM, EEPROM, solid-state drives ("SSD"), flash memory, phase-change memory ("PCM"), optical disk storage, magnetic disk storage or other magnetic storage devices, or any other hardware storage device(s), which may be used to store program code in the form of computer-executable instructions or data structures that may be accessed and executed by a general-purpose or special-purpose computer system to implement the disclosed functionality of the present invention.
[0050] Transmission media may include networks and / or data links, which may be used to carry program codes in the form of computer executable instructions or data structures and may be accessed by general or special computer systems."Network" is defined as one or more data links that can transmit electronic data between computer systems and / or modules and / or other electronic devices. When information is transmitted or provided to a computer system through a network or another communication connection (hardwired, wireless, or a combination of hardwired or wireless), the computer system may view the connection as a transmission medium. The above combination should also be included in the scope of computer-readable media.
[0051] Further, upon reaching various computer system components, program code in the form of computer executable instructions or data structures may be automatically transferred from transmission media to computer storage media (or vice versa). For example, computer executable instructions or data structures received over a network or data link may be buffered in RAM within a network interface module (e.g., network device(s) 105) and then ultimately transferred to computer system RAM (e.g., system memory 103) and / or less volatile computer storage media at the computer system (e.g., persistent storage 104). Thus, it should be understood that computer storage media may be included in computer system components that also (or even primarily) utilize transmission media.
[0052] For example, computer executable instructions include instructions and data that, when executed at one or more processors, cause a general purpose computer system, a special purpose computer system, or a special purpose processing device to perform a certain function or group of functions. For example, computer executable instructions may be machine code instructions (e.g., binary), intermediate format instructions (such as assembly language), or even source code.
[0053] Those skilled in the art will appreciate that the present invention can be practiced in a network computing environment using many types of computer system configurations, including personal computers, desktop computers, laptop computers, message processors, handheld devices, multiprocessor systems, based on multiprocessor or programmable consumer electronics, network PCs, minicomputers, mainframe computers, mobile phones, PDAs, tablet computers, pagers, routers, switches, etc. The present invention can also be practiced in a distributed system environment, wherein both local and remote computer systems of a network link (by a hardwired data link, a wireless data link or by a combination of a hardwired and wireless data link) perform tasks. Thus, in a distributed system environment, a computer system can include multiple component computer systems. In a distributed system environment, a program module can be located in both local and remote memory storage devices.
[0054] Those skilled in the art will also appreciate that the present invention can be practiced in a cloud computing environment. A cloud computing environment can be distributed, although this is not required. When distributed, a cloud computing environment can be distributed internationally within an organization and / or have components owned across multiple organizations. In this description and in the following claims, "cloud computing" is defined as a model for enabling on-demand network access to a shared pool of configurable computing resources (e.g., networks, servers, storage devices, applications, and services). The definition of "cloud computing" is not limited to any of the many other advantages that can be obtained from such a model when properly deployed.
[0055] The cloud computing model can consist of various characteristics, such as on-demand self-service, broad network access, resource pooling, rapid elasticity, measured services, etc. The cloud computing model can also appear in the form of various service models, such as, for example, software as a service ("SaaS"), platform as a service ("PaaS"), and infrastructure as a service ("IaaS"). The cloud computing model can also be deployed using different deployment models, such as private cloud, community cloud, public cloud, hybrid cloud, etc.
[0056] Some embodiments (such as, cloud computing environment) may include a system, which includes one or more hosts that are respectively capable of running one or more virtual machines. During operation, the virtual machine emulates an operable computing system, thereby supporting an operating system and possibly one or more other applications. In some embodiments, each host includes a hypervisor that emulates virtual resources for the virtual machine using physical resources abstracted from the virtual machine's view. The hypervisor also provides appropriate isolation between virtual machines. Therefore, from the perspective of any given virtual machine, the hypervisor provides the illusion that the virtual machine is interfacing with physical resources, even if the virtual machine is only interfacing with the appearance of physical resources (e.g., virtual resources). Examples of physical resources include processing power, memory, disk space, network bandwidth, media drives, etc.
[0057] like Figure 1A As shown, each processor 102 may include (among other things) one or more processing units 107 (e.g., processor cores) and one or more caches 108. Each processing unit 107 loads and executes machine code instructions via cache 108. During execution of these machine code instructions at one or more execution units 107b, the instructions may use internal processor registers 107a as temporary storage locations, and may read and write to various locations in system memory 103 via cache 108. Typically, cache 108 temporarily caches portions of system memory 103; for example, cache 108 may include a "code" portion that caches portions of system memory 103 that store application code and a "data" portion that caches portions of system memory 103 that store application runtime data. If a processing unit 107 requires data (e.g., code or application runtime data) that is not already stored in cache 108, then the processing unit 107 may initiate a "cache miss" that causes the required data to be fetched from system memory 103 - while potentially "evicting" some other data from cache 108 back to system memory 103.
[0058] As illustrated, persistent storage 104 may store computer-executable instructions and / or data structures representing executable software components; correspondingly, one or more portions of these computer-executable instructions and / or data structures may be loaded into system memory 103 during execution of the software at processor(s) 102. For example, persistent storage 104 is shown as storing computer-executable instructions and / or data structures corresponding to memory index component 109, tracing component 110, emulation component 111, and application(s) 112. Persistent storage 104 may also store data, such as trace(s) 113 representing one or more executions of one or more of application(s) 112.
[0059] Typically, the memory index component 109 takes one or more of the trace(s) 113 as input, and based on analysis of these trace(s) 113, the memory index component 109 identifies memory cell value(s) that may be exposed during playback of the trace(s) 113 at an execution time prior to the execution time(s) corresponding to the event that caused the memory cell value(s) to be recorded in the trace(s) 113. The memory index component 109 may then generate index data to supplement the trace(s) 113, to generate new trace(s) 113 that contain changes consistent with the index data, and / or to modify or rewrite existing trace(s) 113 that are consistent with the index data. Thus, Figure 1A The memory index component 109 and (multiple) traces 113 are shown loaded into the system memory (i.e., the memory index component 109' and (multiple) traces 113'), and the double-ended arrow between the memory index component 109' and (multiple) traces 113' indicates that the memory index component 109' can read from and possibly write to (multiple) these traces 113'; if data is written to (multiple) traces 113', the data may also be persisted to the (multiple) traces 113 in the persistent storage device 104.
[0060] As mentioned, the memory index component 109 performs analysis on the trace(s) 113. In embodiments, the analysis may include one or both of a static analysis or a dynamic analysis. As used herein, static analysis includes the memory index component 109 performing analysis based solely on data read from the trace(s) 113. On the other hand, dynamic analysis may use data generated / obtained from playback / simulation of the application(s) 112 based on these trace(s) 113. Thus, Figure 1AIt is shown that simulation component 111 may also be loaded into system memory 103 (i.e., simulation component 111'), and application(s) 112 may be simulated by simulation component 111' (i.e., application(s) 112'). The double-ended arrow between memory index component 109' and simulation component 111' indicates that memory index component 109' may request a trace simulation by simulation component 111', and simulation component 111' may provide the results of the trace simulation to memory index component 109'.
[0061] If present, the tracing component 110 may record or "trace" the execution of one or more of the application(s) 112 into the tracing(s) 113. The tracing component 110 may record whether the execution of the application(s) 112 is executed directly on the processor(s) 102 or via a managed runtime on the processor(s) 102. Thus, Figure 1A It is also shown that the tracking component 110 can be loaded into the system memory 103 (i.e., the tracking component 110'). The arrow between the tracking component 110' and the trace(s) 113' indicates that the tracking component 110' can record the tracking data into the trace(s) 113' (which can then be persisted to the persistent storage device 104 as the trace(s) 113).
[0062] Computer system 101 may additionally or alternatively receive one or more of trace(s) 113 from another computer system (e.g., using network device(s) 105). For example, Figure 2 An example computing environment 200 is illustrated, wherein Figure 1A The computer system 101 is connected to one or more other computer systems 202 (i.e., computer systems 202a to 202n) via one or more networks 201. As shown in example 200, each computer system 202 includes a tracing component 110 and (multiple) applications 112. As such, the computer system 101 can receive (multiple) one or more traces 113 of (multiple) previous executions of one or more of the (multiple) applications 112 at (multiple) these computer systems 202 via the network(s) 201.
[0063] It is noted that while the memory index component 109, the tracing component 110, and / or the emulation component 111 may each be a separate component or application, they may alternatively be integrated into the same application (such as a debugging suite), or may be integrated into another software component—such as an operating system component, a hypervisor, a cloud fabric, etc. As such, those skilled in the art will also appreciate that the present invention may be practiced in a cloud computing environment of which the computer system 101 is a part.
[0064] In an embodiment, memory index component 109, tracing component 110, and / or emulation component 111 operate trace(s) 113 that include high fidelity "bit-accurate" trace data that records previous executions of one or more threads of application 112, and where the trace data enables any traced portion(s) of these thread(s) to be emulated (i.e., "played back") by emulation component 111 down to the granularity of a single instruction (e.g., machine code instruction, intermediate language code instruction, etc.). As used herein, a "bit-accurate" trace is a trace that includes sufficient data to enable previously executed code of application 112 (e.g., at computer system 101 and / or at one or more computer systems in computer system 202) to be played back via emulation by emulation component 111, such that emulation component 111 simulates execution of the code in substantially the same manner as it was previously executed. Tracing component 110 can use a variety of methods to record and store bit-accurate traces. Two different families of methods that provide high performance levels and reasonable trace sizes are now briefly summarized, but it is to be understood that embodiments herein create and operate traces recorded using other methods. Additionally, optimizations can be applied to any of these families of methods, which are not described herein for the sake of brevity.
[0065] The first family of methods is based on the recognition that processor instructions (including virtual machine "virtual processor" instructions) generally fall into one of three categories: (1) instructions identified as "non-deterministic", i.e., do not produce predictable output because their output is not completely determined by data in a general purpose register (e.g., register 107a) or a cache (e.g., cache(s) 108), (2) deterministic instructions whose inputs do not depend on memory values (e.g., they depend only on processor register values or values defined in the code itself), and (3) deterministic instructions whose inputs depend on reading values from memory. Thus, in some embodiments, storing sufficient state data to reproduce the execution of instructions can be accomplished by solving the following problems: (1) how to record non-deterministic instructions that produce outputs that are not completely determined by their inputs, (2) how to reproduce the values of input registers to instructions depending on registers, and (3) how to reproduce the values of input memory to instructions depending on memory reads.
[0066] In some embodiments, the first method(s) record the execution of non-deterministic instructions into the trace(s) 113 that produce outputs that are not completely determined by their inputs by storing the side effects of the execution of such instructions into the trace(s) 113. As used herein, "non-deterministic" instructions may include less common instructions that (i) produce non-deterministic outputs each time they are executed (e.g., RDTSC on Intel processors, which writes the number of processor cycles since the last processor reset into a register), (ii) may produce deterministic outputs, but depend on inputs that are not tracked during trace recording (e.g., debug registers, timers, etc.), and / or (iii) produce processor-specific information (e.g., CPUID on Intel processors, which writes processor-specific data to registers). Storing the side effects of the execution of such instructions may include, for example, storing register values and / or memory values that are changed by the execution of the instructions. In some architectures (e.g., from Intel) processor features (e.g., those found in Virtual Machine Extensions (VMX)) may be used to capture instruction traces for recording their side effects into the trace(s) 113.
[0067] Solving how to reproduce the values of the input registers for deterministic instructions (e.g., whose inputs depend only on processor register values) is simple because they are the output of the execution of the previous instruction(s). Therefore, the first method(s) for recording the trace can therefore reduce the recording of the execution of an entire series of processor instructions to store data that can be used to reproduce the register values at the beginning of the series. In an embodiment, the trace(s) 113 may not even need to store records or intermediate register values for the specific instructions executed in the series. This is because the actual instructions are available from the application code itself. Therefore, these instructions can be supplied with the recorded inputs (i.e., the recorded initial register value set) during playback to execute in the same manner as they were during the trace.
[0068] Finally, the first method(s) for recording traces may address how to reproduce the values of input memory for deterministic instructions whose input depends on the memory values consumed (i.e., read) by recording the memory values consumed by these instructions into the trace(s) 113 - regardless of how the values read by the instructions were written to memory. In other words, some trace(s) 113 may record the values of memory reads, but not the values of memory writes. For example, although values may be written to memory by the current thread, another thread (including the kernel, e.g., as part of handling an interrupt), or a hardware device, a complete playback of the instructions of the thread that performed the reads requires only the values read by the thread's instructions. This is because the values read by the thread (not necessarily all the values written to memory) dictate how the thread executes.
[0069] A second family of methods for recording bit-accurate traces is based on the recognition that a processor (e.g., processor 102) forms a semi-closed or quasi-closed system. For example, once the data portion (i.e., code data and runtime application data) for a process is loaded into cache(s) 108, processor 102 can operate on its own - without any input - as a semi-closed or quasi-closed system for time bursts. Specifically, once cache(s) 108 are loaded with data, one or more of processing units 107 use the runtime data stored in the data portion of cache(s) and use registers 107a to execute instructions from the code portion of cache(s) 108. When processing unit 107 needs some information to flow in (e.g., because it is executing, will execute, or may execute instructions that access code or runtime data that is not in cache(s) 108), a "cache miss" occurs, and the information is brought into cache(s) 108 from system memory 103. The processing unit 107 can then continue to execute using the new information in the cache(s) 108 until new information is again brought into the cache(s) 108 (e.g., due to another cache miss or an uncached read). Thus, in the second series of methods, the tracking component 110 can record sufficient data to be able to reproduce the influx of information into the cache(s) 108 as the tracked processing unit executes.
[0070] Figure 3 An example of a trace 300 is illustrated, which may correspond to one or more of the trace(s) 113 of FIG. 1 , and which may be created according to one or more of the aforementioned tracking techniques. Figure 3 In the example of , the trace 300 includes one or more trace data streams 301. Figure 3, three tracing data streams 301 (i.e., tracing data streams 301a to 301c) are illustrated. In an embodiment, each tracing data stream 301 represents the execution of a different thread executed from the code of application 112. For example, tracing data stream 301a may represent the execution of a first thread of application 112, tracing data stream 301b may represent the execution of a second thread of application 112, and tracing data stream 301c may represent the execution of a third thread of application 112. As shown, each tracing data stream 301 includes a plurality of data packets 302 (i.e., data packet 302a for data stream 301a, data packet 302b for data stream 301b, and data packet 302c for data stream 301c). Since the specific data recorded in each data packet 302 may vary, they are shown as having different sizes. Typically, when using time travel debugging techniques, each data packet 302 represents at least the input (e.g., register values, memory values, cache line data, etc.) of one or more executable instructions executed as part of the first thread of the application 112. As shown, the trace data stream 301 may also include one or more key frames 303 (e.g., key frames 303a to 303e), each of which represents sufficient information, such as a snapshot of register and / or memory values, to enable the previous execution of the thread containing the key frame to be replayed by the simulation component 111 starting from the point of the key frame 303 forward. In addition, the trace data stream 301 may include one or more sequencing events, such as Figure 3 9. Although each trace data stream 301 typically tracks a given thread independently, sequencing events represent the occurrence of events that can be ordered across threads. For example, these sequencing events can correspond to events of thread interactions, such as through shared memory, via function calls, etc. While for simplicity, the order of events in the trace data stream 301 rotates through the thread cycle, it is understood that they will generally occur in a less predictable manner.
[0071] In an embodiment, trace 113 may also include the actual code that was executed. Figure 3, each data packet 302 is shown as including a non-shaded data input portion 304 (i.e., data input portion 304a for data packet 302a, data input portion 304b for data packet 302b, and data input portion 304c for data packet 302c) and a shaded code portion 305 (i.e., code portion 305a for data packet 302a, code portion 305b for data packet 302b, and code portion 305c for data packet 302c). In an embodiment, the code portion 305 in the packet 302 may include executable instructions that are executed based on the corresponding data input. However, in other embodiments, the tracking 113 may omit the actual code that is executed, and instead rely on separate access to the code of the application 112 (e.g., from the persistent storage device 104). In these other embodiments, each data packet may, for example, specify the address or offset of the appropriate (multiple) executable instructions. As shown, the trace 113 may include any number of additional data streams 306 (i.e., data streams 306a to 306n), which may store any type of additional trace data. The additional trace data may include, for example, index data, such as occasional memory snapshots, reverse lookup data structures for quickly locating memory addresses / values in the trace data stream 301, etc.
[0072] The disclosure herein relates to inserting data into a trace that exposes a memory cell value at an execution time prior to an execution time corresponding to an event (e.g., a memory read) that caused the memory cell value to be recorded in a trace. Such data may be inserted into a trace file or trace data stream at any location, regardless of where the original memory cell value is recorded in the trace file or trace data stream, as long as such data causes the memory cell value to be exposed prior to the execution time during trace playback, at which the memory cell value would otherwise have been exposed. Thus, when referring to inserting such data, it is to be understood that the time / place where the data is inserted is relative to the execution time, not the location of the data packet in the trace file or trace data stream. Additionally, one of ordinary skill in the art will appreciate that inserting data into a trace that exposes a memory cell value may encompass one or both of the following: (i) inserting the memory cell value directly into the trace, or (ii) inserting a component that restores and / or calculates the memory cell value into the trace (e.g., by inserting a compressed version of the value; by inserting a reference to where the value can be found, such as in another trace data stream; by inserting a reference to how the value can be calculated, etc.).
[0073] Figure 1B The diagram provides Figure 1A Example 100b of additional details of the memory index component 109. Figure 1BThe memory index component 109 depicted in the drawings includes various subcomponents (e.g., trace access 114, trace parsing 115, trace sorting 116, memory analysis 117, output 118, etc.) that represent various functionalities that the memory index component 109 can implement in accordance with various embodiments described herein. It is to be understood that the depicted components - including their identities, subcomponents, and arrangements - are merely presented to aid in describing various embodiments of the memory index component 109, and that these components / subcomponents are not limited to how software and / or hardware can implement various embodiments of the memory index component 109 or its specific functionality.
[0074] Trace access component 114 accesses at least one of trace(s) 113. This may mean accessing trace(s) 113 from persistent storage 104, and / or accessing trace(s) 113 from another computer system (e.g., one or more of computer systems 202). In an embodiment, accessing trace 113 causes the trace to be at least partially loaded into system memory 103 (i.e., as shown as trace(s) 113').
[0075] The trace parsing component 115 parses the accessed trace(s) 113 to identify at least one or more segments in the traced execution. Figure 1B It is shown that the tracking parsing component 115 can include a segment identification component 115a. As used herein, a "segment" is one or more consecutive instructions executed on the same thread without being interrupted by any other thread. In an embodiment, a segment can be defined based on a sequencing event. For example, a segment can be a set of consecutive instructions executed between sequencing events, with a key frame at the beginning of the track acting as a sequencing event.
[0076] For illustration purposes, Figure 4A An example timing diagram 400a is illustrated showing three timelines 401 (ie, timelines 401a through 401c) of execution of three threads, such as traced to Figure 3 401. While for simplicity, the threads in timing diagram 400a are executed in a cyclic manner, it is to be understood that they will typically execute in a less predictable manner. As shown, each of these timelines 401 begins with a key frame 402 (i.e., key frames 402a to 402c), which may correspond to, for example, Figure 3 Each of these timelines 401 also includes three sequencing events 403 (i.e., sequencing events 403a to 403i), such as Figure 3For example, sequencing events 403a, 403d, and 403g on timeline 401a may correspond to sequencing events 1, 4, and 7; sequencing events 403b, 403e, and 403h on timeline 401b may correspond to sequencing events 2, 5, and 8; and sequencing events 403c, 403f, and 403i on timeline 401c may correspond to sequencing events 3, 6, and 9.
[0077] exist Figure 4A Within the context of , the segments on timeline 401a may include a first segment including code executed between key frame 402a and sequencing event 403a (arrow 404a), a second segment including code executed between sequencing event 403a and sequencing event 403d (arrow 404d), and a third segment including code executed between sequencing event 403d and sequencing event 403g (arrow 404g). Similarly, the segments on timeline 401b may include a first segment between key frame 402b and sequencing event 403b (arrow 404b), a second segment between sequencing event 403b and sequencing event 403e (arrow 404e), and a third segment between sequencing event 403e and sequencing event 403h (arrow 404h); the segments on timeline 401c may include a first segment between key frame 402c and sequencing event 403c (arrow 404c), a second segment between sequencing event 403c and sequencing event 403f (arrow 404f), and a third segment between sequencing event 403f and sequencing event 403i (arrow 404i).
[0078] The trace parsing component 115 may also parse the visited trace(s) 113 to identify one or more gaps in the visited trace(s) 113. Figure 1B It is shown that the trace parsing component 115 may include a gap identification component 115b. Generally, a gap is any execution time period where there is a discontinuity or lack of trace data for the trace data of one or more traced threads. In an embodiment, gaps can be in two forms: large gaps and small gaps. In an embodiment, a large gap appears in the trace of the thread when the trace for the thread stops for an unknown period of time. For example, this may be because the recording of the thread is paused for an unknown period of time, or because the recorded thread is terminated and the recording is later resumed on a different thread. In an embodiment, a small gap occurs when the recording of the thread is stopped / paused for a known purpose. For example, a small gap may occur when the thread makes a function call that pauses the execution of the thread to execute a thread that is not being tracked.
[0079] To illustrate these concepts, Figure 5A The diagram shows Figure 4AExample timing diagram 500a is similar to timing diagram 400a of FIG. 500a, but includes examples of large gaps and small gaps. As an example of a large gap caused by recording a thread that is suspended for an unknown period of time, assume that Figure 5A , the thread corresponding to timeline 501b is responsible for drawing / rendering the user interface window 112 for the tracking application. If the tracking component 110 stops recording the thread because the user interface window is closed, the tracking component 110 does not know when the user interface will be opened later (and tracking resumed). In an embodiment, the gap in tracking the thread that occurs between the time the window is closed and the time the window is later opened (and tracking resumed) can be considered a large gap. This large gap is Figure 5A 501a to 501b as a gap between sequencing events 503b and 503e in the line representing timeline 501b. An alternate example (not shown) of a large gap may be a time period during which recording is closed for each of the threads corresponding to timelines 501a to 501a. During this time period, a large gap may exist for each of timelines 501.
[0080] As an example of a small gap, suppose that Figure 5A In FIG. 5 , the thread corresponding to timeline 501 a is responsible for parsing file data. If the thread calls a kernel function to open a file, and the kernel thread that handles the request is not tracked, then in an embodiment, the time period between the tracked thread making the kernel call and the kernel call returning to the tracked thread can be considered a small gap. This small gap is Figure 5A 503a is represented as a dashed line between sequencing events 503d and 503g in timeline 501a.
[0081] Based on the trace parsing component 115 having identified the fragments in the accessed (multiple) traces 113, the trace sorting component 116 can identify the order among these fragments. This is the order in which the fragments can be simulated by the simulation component 111. In an embodiment, this can be a partial order or a total order. In a total order, each instruction represented in the (multiple) traces 113 has a defined order relative to other instructions in the (multiple) traces 113. In a partial order, this restriction can be relaxed. For example, due to the inclusion of key frames, and because two or more fragments do not overlap in their memory accesses, it is possible that these fragments can be simulated in parallel by the simulation component 111. Figure 4B Picture shows Figure 4A Example 400b of a potential total ordering of the fragments in . Although the tracking fragments can be ordered in various ways, example 400b orders the fragments based on the sequence number order. For example, in Figure 4B , the tracking segments are shown as 405a, then 405b, then 405c, and so on to segment 405i. This follows from Figure 4AThe sequence shown by the arrow in FIG. 4 starts from key frame 402a. For example, Figure 4B The fragment 405a in corresponds to Figure 4A The code snippet (arrow 404a) executed between key frame 402a and sequence event 403a in FIG. Figure 4A After the dashed arrow from sequencing event 403a to key frame 402b, Figure 4B The fragment 405b in corresponds to Figure 4A The code snippet (arrow 404b) executed between the key frame 402b and the sequence event 403b in FIG. Figure 4A After the dashed arrow from sequencing event 403b to key frame 402c, Figure 4B The fragment 405c in corresponds to Figure 4A The code snippet (arrow 404c) executed between the key frame 402c and the sequence event 403c in FIG. Figure 4A After the dashed arrow from sequencing event 403c to sequencing event 403a, Figure 4B The fragment 405d in corresponds to Figure 4A The code snippet executed between sequencing event 403a and sequencing event 403d in (arrow 404d). This pattern continues throughout Figure 4A .
[0082] If gaps are identified by the gap identification component 115b, the tracking ordering component 116 may also identify the ordering of these gaps among the ordered segments. Figure 5B Picture shows Figure 5A Example 500b of a potential total ordering of the fragments and gaps in the . Although the tracking fragments and gaps can be ordered in various ways, example 500b also orders the fragments and gaps based on the sequence number order. For example, in Figure 5B , the tracking segments are shown as 505a, then 505b, then 505c, and so on to segment 505i. This includes sorting large gaps (i.e., 505e) and small gaps (i.e., 505g). Similar to Figure 4B , the order is determined by Figure 5A The sequence shown by the arrow in , starts from key frame 502a.
[0083] Using the fragments and gaps (if any) identified by the trace parsing component 115, and using at least a partial ordering of these fragments and gaps (if any) identified by the trace ordering component 116, the memory analysis component 117 can perform one or more of intra-fragment analysis, inter-fragment analysis, or gap analysis to identify memory cell values that may have been present during the trace simulation at a time earlier than the time when these memory cell values appeared in the trace(s) 113. Figure 1BIn FIG. 1 , the memory analysis component 117 includes an intra-fragment analysis component 117a, an inter-fragment analysis component 117b, and a gap analysis component 117c. Additionally or alternatively, the memory analysis component 117 may perform inter-thread analysis to enable efficient thread-centric analysis (e.g., playback, memory query, etc.) while still being able to present a correct view of memory locations that interact with threads that are not part of the thread-centric analysis. Figure 1B In the example embodiment, the memory analysis component 117 includes an inter-thread analysis component 117d.
[0084] The intra-segment analysis component 117a analyzes segments individually to determine whether "compatible" memory cell value(s) can be "pre-fetched" and presented in the segment during playback / simulation of the segment earlier than the point at which these memory cell value(s) appear in the trace data for the segment. In an embodiment, the intra-segment analysis component 117a can identify a given memory cell value as "compatible" with other values in the segment by determining whether the value is consistent with other previously known values of the memory cell in the segment. For example, if the memory cell value is the value of the first read from the memory cell in the segment, the value will obviously be compatible with the previously known value of the memory cell in the segment because there is no previously known value for the memory cell in the segment. On the other hand, if the memory cell value is the value of a subsequent read from the memory cell in the segment, the value is compatible if it matches the previously known value for the memory cell in the segment. The previously known value may be known as a result of reading from or writing to the memory cell. Thus, for example, if (i) the first read in the fragment obtains the value "A" from the cell, (ii) a subsequent write in the fragment writes the value "B" to the cell, and (iii) the subject subsequent read obtains the value "B" from the cell, then the value obtained from the subsequent read will be compatible. However, if the subsequent read obtains anything other than the value "B" from the cell, then the value obtained from the subsequent read will not be compatible because the cell has been modified by something outside the fragment (e.g., another thread, hardware direct memory access (DMA), etc.). Thus, for example, if the subsequent read obtains the value "C" from the cell, then that value will be incompatible with the previous two values.
[0085] It is worth noting that in scenarios where there are multiple reads and / or writes from a memory cell, if these reads / writes are compatible, then it may be possible to "prefetch" by prefetching only the initial value of the memory cell. For example, in the previous example, only the value "A" needs to be prefetched; the write of the value "B" and the read of the value "B" can be reproduced via simulation from instructions after the initial read of the memory cell. In the second example where a subsequent read obtains the value "C", it may be possible to prefetch the value "A" obtained by the first read, but not the value "C" obtained by the subsequent read.
[0086] To demonstrate the concept of prefetching within a fragment, Fig. 6A and 6B An example timing diagram 600a / 600b corresponding to execution of a function that performs string copying is illustrated. Fig. 6A and 6B Assume that the entire function is executed as a single fragment (i.e., there are no other threads interrupting its execution and there are no gaps in its execution). The function consists of the following steps:
[0087] 1. Set up the function stack
[0088] 2. Start the loop
[0089] a. Copy a single character
[0090] b. Compare the character to the null terminator to exit
[0091] 3. End the loop
[0092] 4. Return
[0093] Timing diagram 600a illustrates examples of when - for both in-place debugging and time travel debugging - memory cell values corresponding to an input string are available for reading (i.e., visible), when uninitialized memory cells corresponding to an output string are visible, and when data is written to memory cells corresponding to the output string. For example, timing diagram 600a shows that, during in-place debugging, at step one in the above function (i.e., when the function stack is set up), memory cell values corresponding to the entire input string may be available for reading, and uninitialized memory cells corresponding to the entire output string may be visible. In contrast, timing diagram 600a also shows that, during time travel debugging, memory cell values corresponding to the input string may only gradually become visible as they are read in step 2a of the loop (e.g., when the data packet(s) storing these values appear in the trace), and uninitialized memory cells corresponding to the output string may become visible only in connection with writing these memory cells in step 2a of the loop.
[0094] It is noteworthy that in timing diagram 600a / 600b (and in subsequent timing diagrams), the visibility of uninitialized memory cell values during time travel debugging depends on those values being present in the trace when the first action performed by the code on the memory cell is a write. Therefore, when the trace component 110 captures a write to a previously unrecorded memory cell as a read from the memory cell plus a write to the memory cell (e.g., instead of performing a write without recording anything), these uninitialized values may be available. In this way, the availability of the values of uninitialized memory cells during time travel debugging depends on their being in the trace, but their availability (or lack thereof) does not affect correctness during trace playback. For example, if the values of uninitialized memory cells are not available in the trace, the debugger can display this unknown data as question marks, random values, a defined pattern, etc.
[0095] In an embodiment, the intra-segment analysis component 117a may determine that memory cell values corresponding to the input string read during time travel debugging in step 2a are compatible with other values of those memory cells in the segment, and therefore determine that these memory cell values may be "pre-fetched" and visible at an earlier point in the segment (such as, the beginning of the segment) during simulation / playback. In addition, the intra-segment analysis component 117a may determine that memory cell values corresponding to uninitialized memory are compatible with other values of those memory cells in the segment, and therefore determine that the uninitialized memory may also be visible at an earlier point in the segment (such as, the beginning of the segment) during simulation / playback. Therefore, turning to Figure 6B , timing diagram 600b shows that during time travel debugging (i.e., during step 1 of the function, just as during in-place debugging), these memory cells may be visible at the beginning of the fragment. Specifically, the various dashed arrows and dashed boxes associated with the input string show that the memory cell values corresponding to the reads may be pre-fetched from the natural time location in the trace and visible at the beginning of the fragment (i.e., step 1) during playback / emulation of the fragment; the various arrows and dashed boxes associated with the output string also show that uninitialized memory cell values may also be visible at the beginning of the fragment (i.e., step 1) during playback / emulation of the fragment.
[0096] Fig. 7A and 7B Another example of prefetching values within a segment is provided. Specifically, Fig. 7A and 7B An example timing diagram 700a / 700b is illustrated, which corresponds to the execution of a function that splits a string into segments based on a regular expression (RegEx) match. It is noteworthy that in Fig. 6A and 6B The meanings of the various shadows defined in Fig. 7A and7B .again, Fig. 7A and 7B Assume that the entire function is executed as a single snippet. The function consists of the following steps:
[0097] 1. Set up the function stack
[0098] 2. Allocate memory for the result list
[0099] 3. Call the function to compile the regular expression
[0100] 4. Start the loop
[0101] a. Call the function to find the position of the next RegEx match in the string
[0102] b. Call a function to create a new string from a previously found substring match
[0103] c. Append the string to the result
[0104] 5. End the loop
[0105] 6. Prepare to return to the list
[0106] 7. Return
[0107] Similar to timing diagram 600a, timing diagram 700a illustrates an example of when—for both in-place debugging and time travel debugging—memory cell values corresponding to reads and uninitialized memory may be visible. As with timing diagram 600a, timing diagram 700a shows that, during in-place debugging, memory cell values that will be read by a function (i.e., the input regular expression and input string) and uninitialized memory cells that will be written by the function (i.e., the result list, the compiled regular expression, and the substring) are visible at function entry (i.e., in step 1 above). Also similar to timing diagram 600a, timing diagram 700a also shows that, during time travel debugging, memory cell values corresponding to reads (i.e., the input regular expression and input string) may only become visible gradually as they are read in steps 3 and 4a, and uninitialized memory cells corresponding to writes (i.e., the result list, the compiled regular expression, and the substring) may only become visible in connection with writing those memory cells in steps 2, 3, 4b, and 4c. Go to Figure 7B , timing diagram 700b shows that during time travel debugging (e.g., at the beginning of the snippet) during step 1 of the function - just as during in-place debugging, these memory cells may be able to become visible earlier in the snippet. For example, Figure 7BThe various dashed arrows and dashed boxes in show that the memory cell values corresponding to the reads can be pre-fetched from their natural time locations in the trace and become visible at the beginning of the segment (e.g., in step 1) during playback / simulation of the segment. Figure 7B It is also shown that during playback / simulation of a segment, uninitialized memory cells may also become visible at the beginning of the segment (e.g., in step 1), despite Figure 7B The movement of this uninitialized memory is not explicitly shown via dashed arrows or dashed boxes.
[0108] While the intra-fragment analysis component 117a identifies memory cell values that can be pre-fetched and exposed earlier in a fragment than where they appear in the fragment's trace, the inter-fragment analysis component 117b identifies memory cell values that can be pushed across fragments. In an embodiment, the inter-fragment analysis component 117b can operate on fragments after the intra-fragment analysis component 117a has operated on them, although the inter-fragment analysis component 117b may also operate independently of the intra-fragment analysis component 117a.
[0109] The inter-fragment analysis component 117b operates by determining whether a given memory cell value in one fragment is compatible with one or more previous fragments. While the intra-fragment analysis component 117a determines the intra-fragment compatibility of a given memory cell value with the value of a memory cell previously seen in the same fragment, the inter-fragment analysis component 117b determines the compatibility of a given memory cell value with the memory value seen in one or more previous fragments. Therefore, similar to the intra-fragment compatibility analysis, the inter-fragment compatibility analysis also determines the compatibility of a memory cell value with a value previously seen (in execution time). In an embodiment, the inter-fragment analysis component 117b can identify a memory cell value in a particular fragment as "compatible" with an adjacent previous fragment by determining whether the previous fragment touches the memory cell. If the previous fragment does not touch the memory cell, then the value is compatible with the previous fragment and can be pushed across the previous fragment (for example, it can be exposed at the beginning of the previous fragment). On the other hand, if the previous fragment does touch the memory cell, then the memory cell value is compatible with the previous fragment only if the value of the memory cell at the end of the previous fragment is the same as the value of the memory cell at the beginning of the particular fragment. In an embodiment, the inter-fragment analysis component 117b can determine that a memory cell value is compatible with multiple previous fragments. Thus, it may be possible to push a memory cell value across a series of fragments that are respectively compatible with the memory cell value.
[0110] To demonstrate the concept of pushing memory cell values across fragments, Figures 8A to 8D The diagram shows the combination Fig. 7A and 7BThe example timing diagrams 800a to 800d correspond to the execution of the function discussed (i.e., it splits a string into multiple segments based on regular expression matching). It is worth noting that in Fig. 6A and 6B The meanings of the various shadows defined in Figures 8A to 8D .and Fig. 7A and 7B Different, in Figures 8A to 8D In , the function is not executed as a single fragment. Instead, as shown at step "F", the execution of the function is interrupted by another traced thread that has no overlapping memory access (determined by thread tracing). Therefore, in FIG. 8A to FIG. 8D , there are three fragments - the first fragment includes executing the function until step F (i.e., the second instance of step 1 to step 4b), the second fragment includes step F itself, and the third fragment includes executing the function after step F (i.e., the second instance of step 4c to step 7).
[0111] Timing diagram 800a shows an example of when memory cell values corresponding to read and uninitialized memory may be visible—for both in-place debugging and time travel debugging. Timing diagram 800a is the same as timing diagram 700a, except that there is a fragment in step F. Therefore, the memory visibility in timing diagram 800a is the same for in-place debugging and time travel debugging because those visibilities are combined Fig. 7A Descriptive.
[0112] Go to Figure 8B , timing diagram 800b shows that, for time travel debugging, the intra-segment analysis component 117a can identify compatible memory cell values that can be exposed at the beginning of each segment. For example, Figure 8B The dashed arrows and dashed boxes in show that the memory cell values in the first segment (i.e., corresponding to reads from the input regular expression and input string) can be pre-fetched from natural time locations in the trace and become visible at the beginning of the first segment (e.g., in step 1) during playback / simulation of the first segment. Similarly, Figure 8B The dashed arrows and dashed boxes in also show that the memory cell values in the third segment (i.e., corresponding to reads from the input string) can be pre-fetched from natural time locations in the trace and become visible at the beginning of the third segment (e.g., in the first instance of step 4C in that segment) during playback / simulation of the third segment. Figure 8B The movement of the uninitialized memory is not explicitly shown via dashed arrows or dashed boxes. Figure 8B It is also shown that during playback / simulation of these fragments, uninitialized memory cells may also become visible at the beginning of these fragments (eg, in step 1 for the first fragment and in step 4C of the third fragment).
[0113] Go to Figure 8C , timing diagram 800c shows that for time travel debugging, the inter-fragment analysis component 117b can also determine that the pre-fetched memory cell values at the beginning of the third fragment (i.e., now in step 4c of the third fragment) are compatible with the second fragment (which has no overlapping memory accesses), and therefore can be pushed across the second fragment and exposed before the second fragment. Additionally, timing diagram 800c shows that because these memory cell values are also compatible with the first fragment, they can be pushed to the beginning of the first fragment (i.e., pushed to step 1). Although Figure 8C The movement of the uninitialized memory is not explicitly shown via dashed arrows or dashed boxes. Figure 8C It is also shown that uninitialized memory cells can also be pushed to the beginning of the first segment across the second segment.
[0114] Go to Fig.8D , the dashed arrows and dashed boxes in timing diagram 800d show the overall movement of memory cell values corresponding to the reads from the input regular expression and input string. This includes the intra-segment movement of memory cell values from within the first segment to the beginning of the first segment and the inter-segment movement of memory cell values from the third segment across the second segment to the beginning of the first segment.
[0115] In an embodiment, the trace 113 may include all or part of a memory snapshot. If these exist, the memory analysis component 117 may treat the memory snapshot as just a fragment of a series of reads (i.e., reads from the memory cells that are part of the snapshot). Thus, the inter-fragment analysis component 117b may determine the compatibility of a given memory cell value in the fragment by comparing the fragment after the memory snapshot with the memory cells affected by the memory snapshot. If compatible, the fragment analysis component 117b may determine that the memory cell value may be pushed across the memory snapshot.
[0116] The gap analysis component 117c determines whether a memory cell value can be pushed across a gap in the tracking record. Similar to pushing a memory cell value across segments, this involves the gap analysis component 117c determining whether the memory cell value is compatible with the gap. While this analysis is fairly simple for segments (i.e., because there is tracking data for the segment), the lack of information about what happened during the gap may complicate the analysis. In an embodiment, due to the lack of such information, the gap analysis component 117c performs one or more of the heuristic analyses of the gap to infer what memory the gap may have touched.
[0117] As mentioned, there are two main categories of gaps: large gaps, where tracing for a thread stops without knowing when it will resume again - when tracing stops - and small gaps, where recording of a thread is suspended for a known purpose. In some embodiments, the gap analysis component 117c considers large gaps to be always incompatible, so it does not attempt to push memory cell values across large gaps. However, in other embodiments, the gap analysis component 117c may use "domain-specific" knowledge of non-tracing code executed during large gaps to push memory cell values across large gaps. Examples of such domain-specific knowledge are discussed below. For small gaps, the gap analysis component 117c can perform one or more different types of heuristic analysis. Five example heuristics are provided herein, although the gap analysis component 117c is not limited to using these types of analysis, and does not even need to support each of these types of analysis.
[0118] In the first example heuristic, referred to herein as "single line move analysis", a rather naive heuristic assumes that small gaps do not modify memory, and therefore memory cell values can be pushed across gaps. Since the heuristic makes compatibility decisions for gaps without relying on specific knowledge of the potential behavior of the gap, the heuristic may cause some memory cell values to be incorrectly pushed across gaps. Therefore, during time travel debugging, the value of a memory cell may actually become visible before it is actually valid. However, in many scenarios, this may not cause obvious confusion. For example, the variable that exposes the memory cell may be out of scope and therefore difficult to reach, or the memory cell value may simply replace uninitialized data in advance. It is worth noting that during live debugging, it is quite common to see what looks like valid data in uninitialized memory locations (e.g., in memory locations corresponding to the stack because these memory locations are written by previous function calls); making the uninitialized data available to the user earlier than it should appear.
[0119] In a second example heuristic, referred to herein as "annotation-based analysis," the gap analysis component 117c utilizes metadata associated with the non-tracing code executed during the gap to determine whether the non-tracing touches, or may touch, one or more memory cells that are being analyzed for compatibility. Example metadata includes Source Code Annotation Language (SAL) annotations, protocols, and the like. As a first example, the annotations may indicate which memory buffer(s) are received as input by a function executed during the gap, and which memory buffers are used as outputs of the function. In this case, if the subject memory cell(s) are part of the output buffer, the gap analysis component 117c may determine that those memory cells are incompatible with the gap. Alternatively, if the subject memory cell(s) are not part of the output buffer, the gap analysis component 117c may determine that those memory cells are compatible with the gap. As a second example, a method executed during the gap may be annotated as an invariant method, which, by protocol, will require that memory cell values remain constant. For example, given the following class Foo,
[0120]
[0121] If the call to the non-tracing code during the gap is a call to a member function Bar(), and if the subject memory cell corresponds to AlwaysZero or OtherValue, then the protocol can be used to determine that the subject memory cell value is compatible with the gap. As a third example, a post-condition annotation to a function executed during the gap may require that the buffer corresponding to the subject memory cell have the same value at function exit as at function entry. Thus, the post-condition annotation will be used to determine that the subject memory cell value is compatible with the gap. As a fourth example, the non-tracing code executed during the gap may be annotated as having no side effects (i.e., no externally visible side effects at the API level), and thus the annotation can be used to determine that the subject memory cell value is compatible with the gap when it is determined that the memory cell value is not inside the non-tracing code. In a third example heuristic, referred to herein as "allocation-based analysis," the gap analysis component 117c determines whether the memory cell(s) being analyzed for compatibility are part of some allocated memory buffer (e.g., part of a data structure). If so, the gap analysis component 117c can treat the memory buffer as a single unit and determine the compatibility of the buffer (as a whole) with the gap. For example, assume that there is no specific knowledge whether the first memory cell is compatible with the gap, but there is knowledge whether the second memory cell is compatible with the gap. If the gap analysis component 117c determines that the first memory cell and the second memory cell are part of the same buffer, then the first memory cell can be determined to have the same compatibility with the gap as the second memory cell. Thus, for example, if the gap analysis component 117c determines that the second memory cell is compatible with the gap (e.g., based on another heuristic), it may determine that the first memory cell is also compatible with the gap. Alternatively, if the gap analysis component 117c determines that the second memory cell is not compatible with the gap, it may determine that the first memory cell is also incompatible with the gap. Notably, some embodiments may treat the first occurrence of a pointer to a memory buffer as an allocation if the allocation is not explicitly observed.
[0122] In a fourth example heuristic, referred to herein as "allocation-based analysis as an annotation," if a function executed during a gap takes as a parameter a pointer to an allocated buffer that includes a memory cell, then the gap analysis component 117c determines that the memory cell is incompatible with the gap. More generally, when this fourth heuristic is combined with the third heuristic (i.e., allocation-based analysis), the gap analysis component 117c can determine that the entire buffer is incompatible with the gap. This heuristic is based on the observation that a gap that takes an allocated buffer as a parameter is more likely to modify the buffer than a gap that does not take the allocated buffer as a parameter. Thus, for example, if there are two or more gaps that could have modified a buffer, and one of the gaps takes the buffer as a parameter and the other(s) do not, then it is more likely that the gap that takes the buffer as a parameter modifies the buffer than the other(s) do. Thus, the gap analysis component 117c can determine that the memory cell in the buffer is incompatible with the gap that takes the buffer as a parameter. As an example of the use of this fourth heuristic, assume there are N gaps, N+1 sets of fragments around these gaps (including the sets of fragments before the first gap and after the last gap), and two buffers being analyzed for compatibility with the gaps. Of these buffers, the first buffer is compatible between the first fragment and the last fragment, while the second buffer is not. Because the first buffer is compatible with all fragments, the gap analysis component 117c can determine that it is also compatible with all gaps and can therefore be pushed forward across all gaps (e.g., to the first fragment). For the second buffer, the gap analysis component 117c can determine which (multiple) gaps take the second buffer as a parameter, and if there is only one gap, the gap analysis component 117c can determine that the second buffer is compatible with any gap after the gap, but not with any gap before the gap. Even if the second buffer is not seen in the trace until the last fragment by value, the use of a pointer to the buffer by an intermediate fragment can serve as a clue that the intermediate fragment may have modified the buffer.
[0123] In a fifth example heuristic, referred to herein as "domain-specific knowledge analysis," the gap analysis component 117c uses some other knowledge of the non-tracing code executed during the gap to determine whether the subject memory cell value is compatible with the gap. As mentioned above, this heuristic can also be used to determine compatibility with large gaps. As an example, the memory of the library code tends not to change (e.g., because the code is typically read-only). Therefore, the gap analysis component 117c can determine that the memory cell corresponding to the loaded library code can be allowed to cross the gap (e.g., between library load and unload events). As another example, it is generally understood how the stack behaves on a given processor architecture and operating system. Using this understanding, the gap analysis component 117c can determine that the memory cell below the current stack pointer is incompatible with the gap. As another example, the gap analysis component 117c can determine that the non-tracing code corresponds to the execution of a pure function (i.e., where the return value of the function is the same for the same arguments, and where the evaluation of the function has no side effects), and therefore the subject memory cell value is compatible with the gap. As yet another example, the gap analysis component 117c may determine that the non-traced code executed during the gap uses the common language runtime (CLR) of the .NET Framework, which includes some form of metadata that is append-only. Since the metadata is append-only, any memory cells used by the metadata are typically written only once, and thus the gap analysis component 117c may determine that these memory cells are compatible with the gap (i.e., because their values are typically not changed when initially written).
[0124] To demonstrate the concept of pushing memory cell values across gaps, 9A to 9E Diagram showing the combination of Fig. 7A and 7B The example timing diagrams 900a to 900e correspond to the execution of the function in question (i.e., it splits a string into multiple segments based on regular expression matching). It is worth noting that in Fig. 6A and Figure 6B The meanings of the various shadows defined in 9A to 9E .and FIG. 8A to FIG. 8D Similar, in 9A to 9E In , the function is not executed as a single fragment either. In contrast, in step 3 (i.e., calling the function to compile the regular expression), the called function is not traced - resulting in a trace gap. Therefore, in 9A to 9E In the example, there are two fragments separated by a small gap. These fragments include a first fragment (including the execution of steps 1 and 2) and a second fragment (including the execution of steps 4a to 7). These fragments are separated by a small gap in step 3.
[0125] Timing diagram 900a shows an example of when memory cell values corresponding to read and uninitialized memory may be visible—for both in-place debugging and time travel debugging. Timing diagram 900a is similar to timing diagram 700a, except that there is a gap in step 3. Thus, memory visibility in timing diagram 900a is similar to that in conjunction with Fig. 7A In-place debugging and time travel debugging with those visibilities described, except that the input regular expression cannot be seen during time travel debugging (because it is consumed by the gap), and the compiled regular expression (which is the output of the gap, and is therefore now read rather than written) is fully visible at the first instance of step 4a for in-place debugging, but only becomes visible gradually for time travel debugging (i.e., the first and third instances of step 4a).
[0126] Go to Fig. 9B , timing diagram 900b illustrates that the intra-segment analysis component 117a for time travel debugging can identify compatible memory cell values that can be exposed at the beginning of each segment. For example, Fig. 9B The dashed arrows and dashed box in show that the memory cell values in the second segment (i.e., corresponding to reads from the input string and the compiled regular expression) can be prefetched from their natural time positions in the trace and become visible at the beginning of the second segment (e.g., in the first instance of step 4a) during playback / simulation of the second segment. Fig. 9B It is also shown that during time travel debugging, uninitialized memory cells can also become visible at the beginning of the first and second fragments (e.g., in step 1 for the first fragment for the result list, and in the first instance of step 4A for the second fragment for the substring), despite Fig. 9B The movement of the uninitialized memory is not explicitly shown via dashed arrows or dashed boxes.
[0127] Fig. 9C A timing diagram 900c is illustrated which demonstrates a gap crossing following timing diagram 900b based on a single line move analysis (ie, the first heuristic above). Using this analysis, it is simply inferred that the memory cell value is compatible with the gap in step 3. Therefore, Fig. 9CThe dashed arrows and dashed boxes in show that the memory cell values in the second segment (i.e., corresponding to reads from the input string and the compiled regular expression) can cross the gap so as to be visible at the beginning of the first segment (e.g., in step 1) during playback / simulation of the first segment. It is worth noting that this means that the compiled regular expression should actually be visible before the function that generated the compiled regular expression is called. However, there is no harm in doing so because there is no symbol after the gap that can read the value. Therefore, although the user can see the value when viewing the original memory, there will be no symbol describing the variable / memory. Fig. 9C It is also shown that during time travel debugging, uninitialized memory cells may also become visible at the beginning of the first fragment (e.g., in step 1), despite Fig. 9C The movement of this uninitialized memory is not explicitly shown via dashed arrows or dashed boxes.
[0128] Fig.9D A timing diagram 900d is illustrated that demonstrates a gap crossing following timing diagram 900b based on annotation-based analysis (i.e., the second heuristic above). Here, the gap analysis component 117c can utilize SAL annotations, protocols, etc. to determine that the gap will be written to the buffer allocated for the compiled regular expression. Therefore, the memory cell values in the buffer are incompatible with the gap. However, the memory cell values associated with the input string are compatible. Therefore, Fig.9D The dashed arrows and dashed boxes in show that during playback / simulation of the first segment, the memory cell values in the second segment corresponding to the input string can cross the gap and thus be visible at the beginning of the first segment (e.g., in step 1). Note, however, that the memory cell values in the second segment corresponding to the compiled regular expression cannot. Fig.9D It is also shown that during time travel debugging, uninitialized memory cells corresponding to substrings may also be compatible with gaps and become visible at the beginning of the first fragment (e.g., in step 1), despite Fig. 9C The movement of this uninitialized memory is not explicitly shown via dashed arrows or dashed boxes.
[0129] Fig.9E A timing diagram 900e is illustrated, which shows a gap crossing after timing diagram 900b based on allocation-based analysis (i.e., the third heuristic above). Here, the gap analysis component 117c may observe that the buffer for the compiled regular expression and the buffer for the input string are allocated before the gap, and therefore identify the two buffers as compatible with the gap as a whole. Therefore, Fig.9EThe dashed arrows and dashed boxes in show that during playback / simulation of the first segment, the memory cell values in the second segment corresponding to the compiled regular expression and input string can cross the gap and thus be visible at the beginning of the first segment (e.g., in step 1). Fig.9E It is also shown that, during time travel debugging, uninitialized memory cells corresponding to substrings may be incompatible with the gap (ie, because they are allocated after the gap), so they do not span the gap.
[0130] Back to Figure 1B , the output component 118 generates data output based on the analysis of the memory analysis component 117. This may include, for example, generating index data (e.g., as one or more of the data streams 306) that supplement the accessed trace(s) 113 to indicate which memory values may be exposed earlier than the data packet representing the memory read, rewriting one or more of the accessed trace(s) 113 to relocate memory cell values in the trace, and / or writing an entirely new trace 113 that includes the relocated memory cell values. Thus, in Figure 1B , the output component 118 is shown as potentially including an index data generation component 118a, a trace modification / rewrite component 118b, and / or a trace generation component 118c.
[0131] With particular focus on the trace modification / rewrite component 118b and the trace generation component 118c, it is noted that a rewritten or newly generated trace including relocated memory values can take up less storage space than the original access trace 113. For example, assume that within a given fragment, there are multiple reads from a given memory cell. This in turn may mean that there are multiple data packets representing one or more values for the memory cell. If these values are compatible within a fragment, the initial value of the memory cell may be recorded at the beginning of the fragment, and other data packets may be able to be discarded. The same applies across fragments. For example, if there is a series of fragments that are compatible with the memory cell value, the memory cell value may be pushed to the beginning for the series of fragments, and the data packets corresponding to the reads from the memory cell may be able to be discarded from the fragment. Therefore, the trace modification / rewrite component 118b and / or the trace generation component 118c can result in a smaller trace, which in turn may be able to be simulated more efficiently.
[0132] Fig.10 A flow chart of an example method 1000 for generating data for exposing a memory cell value during trace playback at an execution time prior to an execution time corresponding to an event that caused the memory cell value to be recorded in the trace is illustrated. The method 1000 is now FIG. 1A to FIG. 9E and its corresponding description within the context of the description.
[0133] As shown, method 1000 includes an act 1001 of accessing a trace. In some implementations, act 1001 includes accessing a trace representing a previous execution of one or more threads. For example, referring to Figure 1A and Figure 1B , the trace access component 114 can access one or more traces in the trace(s) 113 , which represent previous executions of one or more applications in the application(s) 112 . Figure 3 An example of a trace 300 is illustrated that includes a plurality of trace data streams 301 , each representing a thread of execution.
[0134] Method 1000 also includes an act 1002 of identifying recorded trace segments. In some implementations, act 1002 includes identifying a plurality of trace segments within a trace representing a previous execution of one or more threads, each trace segment representing an uninterrupted continuous execution of a plurality of executable instructions on a corresponding thread of the one or more threads, the plurality of trace segments including at least a first trace segment and a second trace segment. For example, segment identification component 115a may identify segments in accessed trace(s) 113. For example, Figure 3 and 4A Pictured Figure 3 The trace 300 can be divided into fragments based on the sequence number.
[0135] Method 1000 may also include an act 1003 of identifying a gap. In some implementations, act 1003 includes identifying a gap in the trace record caused by a call to non-tracing code by the first trace snippet. Thus, the first trace snippet represents an execution of a first executable instruction of the first thread, and the second trace snippet represents an execution of a second executable instruction of the first thread, and wherein the first trace snippet and the second trace snippet are separated by a gap. For example, gap identification component 115b may identify a gap in access trace(s) 113. For example, Figure 5A Two types of gaps are shown - a large gap at arrow 504e where tracking for the second thread is stopped for an unknown period of time, and a small gap at arrow 504g where recording of the first thread is paused for a known purpose.
[0136] As shown, actions 1002 and 1003 may be performed in parallel. However, in implementation, they may alternatively be performed serially (in either order).
[0137] Method 1000 also includes an act 1004 of sorting the traces. In some implementations, act 1004 includes determining at least a partial ordering among the plurality of trace segments, including determining that a first trace segment can be sorted before a second trace segment. For example, trace sorting component 116 can identify a complete or partial ordering of the segments and gaps (if any) identified in acts 1002 and 1003. For example, Figure 4B Shows Figure 4A The trace fragments in can be sorted based on sequencing events, and Figure 5B Shows Figure 5A The tracking segments and gaps in the sequence may be ordered based on sequencing events. Thus, in act 1004, a first tracking segment may be constrained by a first sequencing event, and a second tracking segment may be constrained by a second sequencing event, and determining that the first tracking segment may be ordered before the second tracking segment may be based on determining that the first sequencing event occurs before the second sequencing event.
[0138] Method 1000 also includes an act 1005 of identifying memory values to push forward in the trace. For example, memory analysis component 117 can use one or more types of analysis to identify memory values that can be exposed earlier than they appear in the trace.
[0139] As shown, action 1005 may include one or more sub-actions, including action 1005a of pre-fetching a value within a segment. In some implementations, action 1005a includes, at a first execution time prior to a second execution time corresponding to an event that caused a memory cell value to be recorded into a trace during trace recording, determining that the memory cell value may be exposed during playback of a second trace segment. For example, this may include determining that the corresponding event is a read from a memory cell that is a first (i.e., initial) represented read from the memory cell in the segment. Alternatively, this may include determining that the memory cell value is compatible with one or more other memory accesses to the memory cell within the second trace segment. For example, the intra-segment analysis component 117a may perform a memory compatibility analysis within the segment. This may include the intra-segment analysis component 117a determining that the memory cell value is compatible with the one or more other memory accesses based on determining at least one of: (i) the read from the memory cell is a first read from the memory cell within the second trace segment; or (ii) the read from the memory cell is a subsequent memory access to the memory cell within the second trace segment, and the memory cell value matches a previously known value of the memory cell within the second trace segment. Example combination of compatibility / movement of memory values within a fragment FIG. 6A to FIG. 7B Discussion. Therefore, the second tracking segment may correspond to Fig. 6A and 6B The fragment shown or Fig. 7A and7B The snippet shown. Additional examples of memory value compatibility / movement within a snippet are shown in Figure 8B and 9B shown.
[0140] Sub-actions of action 1005 may also include action 1005b of pushing a value across fragments. In some implementations, when a first trace fragment represents execution of a first executable instruction of a first thread and a second trace fragment represents execution of a second executable instruction of a second thread, and when the first trace fragment is sequenced before the second trace fragment, action 1005b operates and may include determining that a memory cell value from the second trace fragment may be exposed before the first trace fragment during trace playback. This may include determining that the memory cell value is compatible with the first fragment. For example, the inter-fragment analysis component 117b may perform a memory compatibility analysis across fragments. This may include the inter-fragment analysis component 117b determining that the memory cell value is compatible with the first fragment based on determining at least one of the following: (i) the first trace fragment has no memory accesses to the memory cell; or (ii) the first trace fragment has one or more memory accesses to the memory cell, and a first value of the memory cell at the end of the first trace fragment matches a second value of the memory cell at the beginning of the second trace fragment. Example Combination of Inter-Fragment Memory Value Compatibility / Movement FIG. 8A to FIG. 8D Thus, the first tracking segment discussed in conjunction with this action may correspond to covering FIG. 8A to FIG. 8D The fragment of the step before step F in , and the second tracking fragment discussed in conjunction with this action may correspond to covering FIG. 8A to FIG. 8D The snippet of the steps after step F in .
[0141] As mentioned, the memory snapshot may be considered a segment for performing read operations, and thus action 1005b may push values across the memory snapshot. For example, if a first trace segment and a second trace segment are separated by a memory snapshot, action 1005b may include determining that a memory cell value from the second trace segment may be exposed prior to the memory snapshot during trace playback. To determine whether a memory cell value from the second trace segment may be exposed prior to the memory snapshot during trace playback, the segment analysis component 117b may determine one of: (i) the memory snapshot lacks snapshot information for the memory cell, or (ii) the memory snapshot stores a first value for the memory cell that matches a second value for the memory cell at the beginning of the second trace segment.
[0142] Sub-actions of action 1005 may also include an action 1005c to push a value across a gap. If there is a small gap between the first segment and the second segment as discussed in conjunction with method 1000, in some implementations, action 1005c includes determining that a memory cell value from the second trace segment may be exposed before the gap during trace playback. This may include determining that the memory cell value is compatible with the gap. For example, the gap analysis component 117c may use one or more heuristics to determine compatibility of the memory cell with the gap. These heuristics may include, for example, single line move analysis (i.e., assuming that the memory cell is compatible), annotation-based analysis (i.e., determining whether a parameter annotation of a function call indicates that the called function may write to the memory cell), allocation-based analysis (i.e., whether the memory cell is part of a memory buffer that includes another memory cell that is or may be exposed before the gap), and / or allocation-based analysis as annotations (i.e., determining whether a function takes a memory cell or a pointer to a memory cell as a parameter).
[0143] Although not in Fig.10 , but one or more of actions 1005a to 1005c are parallelizable (e.g., to improve performance / responsiveness). For example, some implementations may analyze each individual fragment in action 1005a independently of other fragments, and therefore may analyze each individual fragment in parallel. Other implementations may analyze each memory unit (or buffer) independently. Other implementations may perform intra-fragment analysis independently for each fragment, but then move to each buffer analysis for inter-fragment and gap intersection stages. As will be appreciated by those of ordinary skill in the art, these tasks may be organized in a variety of ways to achieve their parallelization. However, in an embodiment, actions 1005a to 1005c may alternatively be executed serially (in various orders). For example, some embodiments may execute actions 1005a to 1005c serially in the order of 1005a, then 1005b, then 1005c.
[0144] The method 1000 also includes an act 1006 of generating output data. In some implementations, act 1006 includes generating output data indicating that a memory cell value may be exposed at the first execution time during playback of the second trace segment. For example, the output component 118 may generate trace index data using an index data generation component 118a that supplements the trace of the access(es) and indicates that the memory cell value may be exposed at an earlier execution time point than the data packet represents the memory read determined by the memory analysis component 117, may modify an existing trace using a trace modification / rewrite component 118b to move / reorder trace data determined by the memory analysis component 117, and / or may generate an entirely new trace representing the memory value determined by the memory analysis component 117 using a trace generation component 118c. Thus, in act 1006, generating the output data may include at least one of supplementing the trace with index data based on the generated output data, rewriting the trace based on the generated output data, or generating a new trace based on the generated output data. This may additionally or alternatively include modifying a tracked previous memory snapshot to include the memory cell value based on the generated output data, inserting a memory snapshot including the memory cell value based on the generated output data, and the like.
[0145] Regardless of the form of the output data, the data can include generating trace output data indicating that a memory cell value can be exposed at the beginning of a second trace segment during playback of the second trace segment (i.e., an intra-segment move); generating output data indicating that a memory cell value can be exposed prior to a first trace segment during trace playback (i.e., an inter-segment move); generating trace output indicating that a memory cell value can be exposed prior to a gap during trace playback (i.e., across a gap); and / or generating trace output indicating that a memory cell value can be exposed prior to a memory snapshot during trace playback (i.e., across a memory snapshot).
[0146] As mentioned, generating output data may include rewriting traces. To illustrate this concept, Fig.11 A flow chart of an example method 1100 for modifying a trace to expose a memory cell value prior to an execution time corresponding to an event that causes the memory cell value to be recorded in the trace is illustrated. The method 1100 is currently in FIG. 1A to FIG. 9E and its corresponding description within the context of the description.
[0147] As shown, method 1100 includes an act 1101 of accessing a trace. In some implementations, act 1101 includes accessing a trace representing a previous execution of one or more threads. For example, referring to Figure 1A and Figure 1B, the trace access component 114 can access one or more traces in the trace(s) 113 , which represent previous executions of one or more applications in the application(s) 112 . Figure 3 An example of a trace 300 is illustrated that includes a plurality of trace data streams 301 , each of which represents a thread of execution.
[0148] The method 1100 also includes an act 1102 of identifying a data packet recording a value of a memory cell. In some implementations, the act 1102 includes identifying, within the trace, a plurality of data packets that respectively represent corresponding memory cell values read from a particular memory cell, each data packet in the plurality of data packets corresponding to at least one execution event. The method 1100 also includes an act 1103 of selecting a particular memory cell value. In some implementations, the act 1103 includes selecting a particular memory cell value recorded in one of the plurality of data packets. For example, the memory index component 109 can identify a plurality of compatible accesses to a memory cell in the trace, and determine that at least one of the memory cell values can be pushed earlier in the trace.
[0149] As discussed, the memory index component 109 can employ a variety of methods to determine memory compatibility. For example, the memory index component 109 can initially identify segments in a trace (i.e., using the trace parsing component 115). As such, the method 1100 can include parsing the trace to identify a plurality of trace segments, including a first trace segment and a second trace segment, wherein each trace segment represents uninterrupted continuous execution of a plurality of executable instructions on a corresponding thread in one or more threads. In this scenario, a plurality of data groups can correspond to the second trace segment. Additionally, the memory index component 109 can identify at least a partial ordering among those segments (i.e., using the trace sorting component 116). For example, the method 1100 can also include determining at least a partial ordering among the plurality of trace segments, including determining that a first trace segment is sortable before a second trace segment.
[0150] After identifying the fragments and the ordering among the at least two fragments, the memory index component 109 can use the memory analysis component 117 to identify multiple compatible accesses to the memory cells in the trace and determine that at least one of the memory cell values can be pushed earlier in the trace. This can include, for example, intra-fragment analysis (i.e., intra-fragment analysis component 117a), inter-fragment analysis (i.e., inter-fragment analysis component 117b), and / or gap analysis (i.e., gap analysis component 117c).
[0151] Method 1100 also includes an action 1104 of modifying the trace. The specific actions taken to modify / rewrite the trace may vary. For example, Fig.11It is shown that action 1104 may include action 1104a of removing all data packets except one data packet from the trace segment. In some embodiments, action 1104a includes removing all data packets except one data packet from the plurality of data packets from at least one trace segment. For example, the trace modification / rewrite component 118b may discard all data packets except the first data packet in the trace segment. Considering the intra-segment level, the trace modification / rewrite component 118b may even discard all data packets except the first data packet in the trace. Alternatively, action 1104 may include action 1104b of inserting data exposing a specific memory cell value at an execution time prior to the execution time corresponding to the data packet and action 1105 of discarding the data packet. In some implementations, actions 1104b and 1104c include inserting data into the trace that exposes the selected specific memory cell value at an execution time prior to the execution time of the execution event corresponding to the plurality of data packets, during the trace playback, and removing the plurality of data packets from the trace. For example, the trace modification / rewrite component 118b may insert data into the trace that exposes a particular memory cell value earlier than the execution time of the execution event corresponding to the plurality of data packets, such as at (or near) the beginning of the second segment, in the first segment, or even in an earlier segment. This may also include interleaving gaps and / or memory snapshots. The trace modification / rewrite component 118b may also discard data packets corresponding to subsequent memory accesses because they may be obtained via the inserted memory cell values and / or via trace playback based on the inserted memory cell values.
[0152] As an example, method 1100 may operate to move a memory value within a segment. In this embodiment, the intra-segment analysis component 117a may determine that the selected specific memory cell value is compatible within a second segment. Then, when data is inserted into a trace exposing the selected specific memory cell value at an execution time prior to an execution time of an execution event corresponding to a plurality of data packets during trace playback, action 1104 may include inserting data into the trace exposing the selected specific memory cell value at the beginning of the second trace segment.
[0153] As another example, method 1100 may operate to move memory value inter-segments. In this example, the inter-segment analysis component 117b may determine that the selected specific memory cell value is compatible within a first trace segment. Then, when data is inserted into a trace exposing the selected specific memory cell value at an execution time prior to the execution time of an execution event corresponding to a plurality of data packets during trace playback, action 1104 may include inserting data into the trace exposing the selected specific memory cell value in the first trace segment. In an embodiment, when it is determined that the selected specific memory cell value is compatible with the first trace segment, the inter-segment analysis component 117b may determine at least one of the following: (i) the first trace segment does not have a memory access to the specific memory cell, or (ii) the first trace segment has one or more memory accesses to the specific memory cell, and the value of the specific memory cell at the end of the first trace segment matches the second value of the specific memory cell at the beginning of the second trace segment.
[0154] As yet another example, method 1100 may operate to move a memory value across a memory snapshot. In this example, a first trace segment and a second trace segment may be separated by a memory snapshot, and the inter-segment analysis component 117b may determine that a selected specific memory cell value is compatible with the memory snapshot. Then, when data is inserted into a trace exposing the selected specific memory cell value at an execution time prior to an execution time of an execution event corresponding to a plurality of data packets during trace playback, action 1104 may include inserting data into the trace exposing the selected specific memory cell value in the first trace segment and prior to the memory snapshot. In an embodiment, when determining that the selected specific memory cell value is compatible with the memory snapshot, the inter-segment analysis component 117b may determine at least one of the following: (i) the memory snapshot lacks snapshot information for the specific memory cell, or (ii) the memory snapshot stores a first value for the specific memory cell that matches a second value for the specific memory cell at the beginning of the second trace segment.
[0155] As yet another example, method 1100 may operate to move a memory value across a gap. In this example, a first trace segment and a second trace segment may be separated by a small gap in the trace record, and gap analysis component 117c may determine that the selected specific memory cell value is compatible with the small gap. Then, when data is inserted into a trace exposing the selected specific memory cell value at an execution time prior to an execution time of an execution event corresponding to a plurality of data packets during trace playback, action 1104 may include inserting data into the trace exposing the selected specific memory cell value in the first trace segment and prior to the small gap. In an embodiment, when determining that the selected specific memory cell value is compatible with the first trace segment, gap analysis component 117c may determine at least one of: (i) whether a parameter annotation of a function call indicates that the called function can write to the specific memory cell, (ii) whether the specific memory cell is part of a memory buffer that includes another memory cell that is exposed or can be exposed prior to the gap, (iii) or whether the function takes a specific memory cell or a pointer to a specific memory cell as a parameter.
[0156] As mentioned in conjunction with the tracking ordering component 116, embodiments may identify full ordering among fragments or partial ordering between fragments. For example, if all memory cell values at the beginning and end of two (or more) tracking fragments are compatible, then regardless of the ordering of the (multiple) fragments, the tracking ordering component 116 may not enforce a full ordering between them, but rather enable these tracking fragments to be partially ordered. In an embodiment, partially ordered fragments may provide some opportunities for improved compatibility analysis. For example, suppose there are four fragments A, B, C, and D - due to the shared compatibility of fragments A, B, and C - ordered so that fragment A is in front and fragment D is behind, but fragments B and C can appear in any order. In this scenario, memory cell values can be pushed directly from fragment C to fragment A without considering fragment B. In addition, when considering the compatibility of specific memory cell values in fragment D with fragments A, B, and C (not fully compatible with other fragments), this compatibility can be performed in parallel (e.g., split using mapreduce on fragments A, B, and C).
[0157] As previously described, the memory analysis component 117 may include an inter-thread analysis component 117d that performs inter-thread analysis to enable efficient thread-focused analysis. In particular, the memory analysis component 117 inserts memory snapshot data into one or more (multiple) thread (multiple) traces, which enables these (multiple) threads to be played back independently of other threads while still presenting a correct view of the memory locations that interact with these other threads. Those of ordinary skill in the art will understand that when debugging multi-threaded applications, software developers typically analyze program execution one thread at a time, rather than analyzing all threads of the program together. Thus, for example, when analyzing a time travel trace, a developer may query to analyze memory addresses and / or observed memory values touched by a selected, traced thread. As in conjunction with Figure 3 As discussed, the trace 300 may include a different trace data stream 301 for each thread. Although these data streams 301 may be recorded independently, memory is a global resource, and therefore one thread may make changes to memory locations visible to another thread (even though it may not be used by the other thread). Therefore, when replaying a single thread, and / or when processing queries focused on a single thread, the debugger may need to consider which memory one or more other threads interact with in order to provide a correct memory view. This typically includes replaying (i.e., emulating component 111) portions of these (multiple) other threads - this consumes additional processing and memory resources, and increases the amount of time required to replay the threads and / or process and respond to queries. To address this inefficiency, the inter-thread analysis component 117d may perform inter-thread analysis on the traced trace threads, which the output component 118 may use to generate memory snapshot data and insert it into the trace, thereby enabling one or more threads to be replayed and / or queried independently of the threads tracked by other traces, while still being able to present a correct view of the memory locations that interact with the threads tracked by these other traces.
[0158] Now combine FIG. 12A to FIG. 12H to describe these concepts. Fig. 12A Shows something like Figure 4A The example timing diagram 1200a of the timing diagram 400a is shown in FIG. 1200a, and similar elements are labeled similarly. For example, Fig. 12A Three timelines 1201 (i.e., timelines 1201-1201c, similar to timeline 401) of execution of three threads are shown, where key frames 1202 (i.e., key frames 1202a-1202c, similar to key frame 402) and / or sequencing events 1203 (i.e., sequencing events 1203a-1203i, similar to sequencing event 403) can be used to divide these timelines 1201 into segments. Similarly, Fig. 12B The sequence of event 1203 is shown. Fig. 12A An example of a potential total ordering of the fragments in 1200b is very similar to Figure 4B Example 400b.
[0159] Fig. 12A and 12B It shows how to play back or query the thread corresponding to timeline 1201b. In particular, Fig. 12A and 12B includes arrows 1206 pointing to specific points in the timeline 1201b (ie, Fig. 12A Arrow 1206a and Fig. 12B 1206b), which in segment 1205e corresponds to arrow 1204e between sequencing events 1203b and 1203e. These arrows 1206 indicate points in the execution of a thread that need to be reached as part of thread playback and / or in order to process a query focused on the thread. Referring to timeline 1201b, there is a tracking segment 1205b (i.e., corresponding to arrow 1204b) before tracking segment 1205e on the timeline. However, as Fig. 12B As shown, when following the total ordering of the illustrated tracking segments, there are two intervening segments from other threads (i.e., between segments 1205b and 1205e): segment 1205c on timeline 1201c (i.e., corresponding to arrow 1204c) and segment 1205d on timeline 1201a (i.e., corresponding to arrow 1204d). Both of these intervening segments are shown with cross-hatching along timelines 1201a and 1201c. Between segments 1205b and 1205e, intervening segment 1205c and / or intervening segment 1205d may change the value(s) of one or more memory cells visible to segment 1205b and / or segment 1205e.
[0160] Using conventional techniques, analysis of timeline 1201b from the beginning of timeline 1201b (i.e., key frame 1202b) until the execution point at arrow 1206 may include playback of portions of timelines 1201a and 1201c, in addition to the portion of timeline 1201b. For example, simulation component 111 may start at key frame 1202a and playback each of segments 1205a through 1205d (i.e., as shown in FIG. 1 ). Fig. 12B1205e) and then plays back a portion of segment 1205e to reach the execution point at arrow 1206. Thus, even though the focus of the analysis may be on timeline 1201b, simulation component 111 plays back segments 1205a and 1205d from timeline 1201a and plays back segment 1204c from timeline 1201c. If additional keyframes are present, some of the playback may be mitigated. For example, if a keyframe exists at sequencing event 1203a, analysis of timeline 1201b starting at keyframe 1202b may exclude playback of segment 1205a; however, it will still include playback of intervening segments 1205c and 1205d. Note that while keyframes can exist at segment boundaries (as shown), this is not always the case - they can exist in the middle of a segment, and they may not exist at a segment boundary at all.
[0161] To alleviate the need to replay intervening segments from threads that are not the focus of the analysis, the inter-thread analysis component 117d can analyze these intervening segments to determine which memory units they interact with. Based on this analysis, the output component 118 can generate a memory snapshot that can identify these interactions with the memory units. For example, Fig. 12C and Fig.12D Example timing diagrams 1200c and 1200d are shown, which correspond to timing diagrams 1200a and 1200b, but include arrows 1207 pointing from segments 1205c / 1205d to sequencing event 1203b. For example, arrows 1207a and 1207c point from segment 1205c to sequencing event 1203b, and arrows 1207b and 1207d point from segment 1205d to sequencing event 1203b. These arrows 1207 represent the insertion of memory snapshot data at sequencing event 1203b. In an embodiment, the memory snapshot can be part of a key frame that enables playback to start at sequencing event 1203b, although this is not necessarily the case.
[0162] As used herein, the terms "memory snapshot", "memory snapshot data", etc. should be broadly interpreted to include any data that at least identifies one or more memory cells, or any data that can be used to identify one or more memory cells. In an embodiment, the memory snapshot data identifies one or more memory cells that interact with fragment 1205c and / or fragment 1205d. For example, the memory snapshot data may include the address(es) of these memory cell(s), the address range(s) covering these memory cell(s), the value(s) of these memory cells (e.g., the value(s) of these memory cell(s) at the end of fragment 1205d), etc. It is worth noting that the memory snapshot data may identify the memory cells, but not the values. The memory snapshot data may even identify the cells that are related to the cells that fragment 1205c / 1205d interacts with, but which do not actually interact with fragment 1205c / 1205d. For example, if the interacting memory cells are part of a memory buffer, the memory snapshot data may identify the entire memory buffer (e.g., by address ranges of memory cells in the buffer, by pointers to the buffer, etc.), and may even include actual memory cell values within the buffer. In another example, if the interacting memory cells store pointers, the memory snapshot data may identify one or more memory cells accessible using the pointers, and may even include memory cell values within those pointed-to memory cells. Notably, the relevant memory cells may be identified using the techniques described above in conjunction with the gap analysis component 117c (e.g., allocated buffers, SAL annotations, protocols, etc.). In an embodiment, if the memory snapshot includes only memory address information, a debugger querying on a given thread (e.g., timeline 1201b) may replay intervening segments (e.g., segment 1250d) to obtain values only if the query actually accesses the address memory referenced in the snapshot.
[0163] Although the inter-thread analysis component 117d may identify memory snapshot data for insertion at (or near) sequencing event 1203b (i.e., between segments 1205b and 1205e, with intervening segments 1205c and / or 1205d identifying interacting memory units and / or values), the inter-thread analysis component 117d may additionally or alternatively identify memory snapshot data for insertion prior to segment 1205b. For example, Fig.12E and 12F Example timing diagrams 1200e and 1200f are shown, which correspond to timing diagrams 1200c and 1200d, but now include arrows 1208 pointing from sequencing event 1203b to key frame 1202b (ie, Fig.12E Arrow 1208a and Fig.12F 1208b). These arrows 1208 represent the insertion of memory snapshot data at key frame 1202b in addition to or in lieu of the memory snapshot data inserted at sequencing event 1203b. For example, inter-thread analysis component 117d may initially identify memory snapshot data that may be inserted at sequencing event 1203b, and then perform inter-segment compatibility analysis to determine that it may be pushed to the beginning of timeline 1201b. Thus, in an embodiment, inter-thread analysis component 117d may push the memory snapshot forward to the beginning of the trace data stream if memory value compatibility permits.
[0164] Although the foregoing description of the inter-thread analysis component 117d primarily relates to enabling individual threads to be replayed / queried independently, it should be understood that the inter-thread analysis component 117d can also enable groups of threads to be replayed / queried independently of threads outside the group. For example, when analyzing a time travel trace, a developer can query to analyze selected "focus groups" of related threads (e.g., threads operating on the same data structure) together. For example, a service host process in a Microsoft Windows operating system can contain multiple services within it, and the threads for each of these services can be part of a different focus group. To illustrate the focus groups, Figure 12G and 12H Example timing diagrams 1200g and 1200h are shown, which correspond to timing diagrams 1200a and 1200b, but show that timelines 1201a and 1201b correspond to threads that are parties to focus group 1209. Thus, inter-thread analysis component 117d can perform analysis to enable timelines 1201a and 1201b to be replayed / analyzed independently of timeline 1201c. Because timelines 1201a and 1201b are now part of the focus group, tracking segment 1205c no longer intervenes in the playback of these threads. Thus, in Figure 12G and 12H , only segment 1205d is shown with cross-hatching as the intervening segment of the playback of timelines 1201a and 1201b until the point at arrow 1206. As also shown, only this segment is now used to generate memory snapshot data for insertion at (or near) sequencing event 1203b (and / or pushed to an earlier point in timelines 1201a and / or 1201b, if compatible).
[0165] In view of the foregoing description of the inter-thread analysis component 117d, Fig.13 A flow chart of an example method 1300 for creating memory snapshot data to reduce processing for thread-intensive analysis (eg, playback / query) is shown. Figures 1A to 12H Method 1300 is described in the context of and its corresponding description.
[0166] As shown, method 1300 includes an act 1301 of identifying trace segments. In some implementations, act 1301 includes identifying a plurality of trace segments within a trace representing a previous execution of a plurality of threads, each trace segment representing an uninterrupted continuous execution of a plurality of executable instructions on a corresponding thread of the plurality of threads, the plurality of trace segments including a first trace segment corresponding to a first thread and a second trace segment, and a third trace segment corresponding to a second thread. For example, based on trace access component 114 accessing trace 113, segment identification component 115a may at least identify FIG. 12A to FIG. 12H . These identified tracking segments may include, for example, tracking segments 1204b and 1204e (e.g., a first tracking segment and a second tracking segment corresponding to a first thread) and tracking segment 1204c (e.g., a third tracking segment corresponding to a second thread) from thread / timeline 1201b.
[0167] Method 1300 also includes an act 1302 of sorting the tracking segments across at least two threads. In some implementations, act 1302 includes determining at least a partial ordering between the plurality of tracking segments, including determining that a first tracking segment is sortable before a second tracking segment on a first thread, and a third tracking segment is sortable between the first tracking segment and the second tracking segment. For example, tracking sorting component 116 may identify a possible ordering among the tracking segments identified in act 1301. According to the ordering, tracking sorting component 116 may determine that segment 1205b is sortable before segment 1205c, and segment 1205c is sortable before segment 1205e. Based on the ordering, this means that segment 1205b is sortable before segment 1205e on timeline 1201b.
[0168] Method 1300 also includes act 1303 of, for the first thread, identifying memory effects from intervening trace segments from the second thread. In some implementations, act 1303 includes identifying at least one memory unit that interacts with the execution of one or more executable instructions recorded by the third trace segment based on the third trace segment being sortable between the first trace segment and the second trace segment. For example, intra-thread analysis component 117d may determine that intervening segment 1205c, which may be sortable between segments 1205b and 1205e, interacts with the one or more memory units.
[0169] The method 1300 also includes an act 1304 of inserting memory snapshot data identifying the memory effect into the first thread. In some implementations, act 1304 includes inserting the memory snapshot data into the trace data corresponding to the first thread, the memory snapshot data at least identifying at least one memory unit. For example, based on the analysis performed by the intra-thread analysis component 117d in act 1303, the output component 118 can insert the memory snapshot data identifying the at least one memory unit into the trace data stream corresponding to the thread / timeline 1201. Inserting the memory snapshot data can include modifying the trace data stream itself (e.g., the trace data stream 301b), or supplementing the trace with additional index data (e.g., a data structure in one of the data streams 306). Therefore, in act 1304, inserting the memory snapshot data identifying the at least one memory unit into the trace data corresponding to the first thread can include at least one of the following: (i) inserting the memory snapshot data into the trace data stream representing the execution of the first thread, or (ii) inserting the memory snapshot data as index data that supplements the trace data stream for the first thread.
[0170] As discussed, the specific data inserted by the output component 118 can vary. For example, it can identify a memory cell by an address and / or an address range. Thus, in act 1304, the memory snapshot data identifying at least one memory cell can include at least one of: (i) the address of at least one memory cell, or (ii) an address range including at least one memory cell. In addition to address information, the data inserted by the output component 118 can also include value information. Thus, in act 1304, the memory snapshot data identifying at least one memory cell can include the value of at least one memory cell after execution of the third tracking segment (i.e., segment 1205c). In an embodiment, in addition to or in lieu of (multiple) interacting memory cells, the output component 118 can identify related memory cells. Thus, in act 1304, the at least one memory cell can be a first memory cell, and the memory snapshot data can also at least identify a second memory cell related to the first memory cell. In an embodiment, the second memory cell may be related to the first memory cell based on at least one of: (i) the first memory cell and the second memory cell are part of a memory buffer, or (ii) the second memory cell is reachable based on a value of the first memory cell (e.g., when the first memory cell stores a pointer).
[0171] In action 1304, the memory snapshot data may be inserted into various locations in the first thread. Fig. 12C and Fig.12DAs described above, it may be inserted at sequencing event 1203b. In this case, in action 1304, inserting the memory snapshot data identifying at least one memory unit into the tracking data corresponding to the first thread may include: inserting the memory snapshot on the first thread at the end of the first tracking segment, at the beginning of the second tracking segment, or between the first tracking segment and the second tracking segment. Additionally or alternatively, as combined with Fig.12E and Fig.12F As described, the memory snapshot data may be inserted at an earlier point in the trace (such as, at the beginning of the trace). In this case, in act 1304, inserting the memory snapshot data identifying at least one memory cell into the trace data corresponding to the first thread may include: inserting the memory snapshot on the first thread at the beginning of the first trace segment or before the first trace segment. In an embodiment, the memory snapshot data may be pushed forward in the trace if memory compatibility permits. Therefore, even if some memory snapshot data can be pushed to the beginning of the trace, some incompatible data may need to be inserted at the sequencing event 1203b. Therefore, in act 1304, based on the second value of at least one memory cell after execution of the third trace segment being incompatible with the first value of at least one memory cell in the previous memory snapshot on the first thread, the memory snapshot may be inserted at the beginning of the second trace segment. In an embodiment, the memory snapshot data inserted in act 1304 may be a complete memory snapshot, a partial memory snapshot, or a differential memory snapshot (i.e., relative to one or more previous memory snapshots). Inserting memory snapshot data may include modifying the trace data stream itself (eg, trace data stream 301b), or supplementing the trace with additional index data (eg, a data structure in one of data streams 306).
[0172] In view of the combination Figure 12G and 12HAs disclosed herein, it should be understood that method 1300 may be operable to generate and insert memory snapshot data to enable a thread group to be replayed / queried independently of other threads. Thus, action 1301 may also include identifying a fourth segment (e.g., segment 1205d) corresponding to a third thread (e.g., thread / timeline 1201a). Additionally, action 1302 may include determining that the fourth trace segment may also be ordered between the first trace segment and the second trace segment. Then, based on the first thread and the third thread being part of a thread focus group (e.g., group 1209), action 1303 may include determining, based on the first thread and the third thread being part of the thread focus group, that any memory cells whose values interact with their execution of one or more executable instructions represented by the fourth trace segment do not need to be inserted as memory snapshot data into the trace data corresponding to the first thread. For example, even though trace segment 1205d is interposed between trace segments 1205b and 1205e, memory snapshot data relating to memory changed by trace segment 1205d need not be inserted into the trace for thread / timeline 1201b, since threads / timelines 1201a and 1201b will be replayed / queried together.
[0173] It will be appreciated that the embodiments disclosed herein may provide a variety of valuable technical benefits. From a debugging perspective, presenting memory values at an earlier execution time than in a trace recording provides more valuable debug information, including memory information that is more closely aligned with memory information available during live debugging. From a tracing perspective, the ability to expose memory values earlier during trace playback may enable trace size to be reduced by discarding data packets that store the same memory value or derivatives of that memory value, rather than memory values that may be obtained via trace playback - resulting in a smaller and more efficiently replayed trace.
[0174] Although the subject matter has been described in language specific to structural features and / or methodological acts, it is to be understood that the subject matter defined in the appended claims is not necessarily limited to the described features or the acts described above or the order of the acts described above. Rather, the described features and acts are disclosed as example forms of implementing the claims.
[0175] The present invention can be implemented in other specific forms without departing from its spirit or essential characteristics. The described embodiments are considered to be illustrative in all respects only, and not restrictive. Therefore, the scope of the present invention is indicated by the appended claims, rather than by the foregoing description. All changes falling within the equivalent meanings and scopes of the claims will be included within their scope. When introducing elements in the appended claims, the articles "a", "an", "the" and "said" are intended to indicate the presence of one or more elements. The terms "comprise", "include" and "have" are intended to be inclusive and indicate that there may be additional elements different from the listed elements.
Claims
1. A method implemented in a computer system including at least one processor for creating memory snapshot data that reduces processing for thread-focused analysis, the method comprising: identifying a plurality of trace segments within a trace representing previous execution of a plurality of threads, each trace segment representing uninterrupted continuous execution of a plurality of executable instructions on a corresponding thread of the plurality of threads, the plurality of trace segments comprising a first trace segment and a second trace segment corresponding to the first thread, and a third trace segment corresponding to the second thread; determining at least a partial ordering of the plurality of tracing segments, including determining that the first tracing segment can be ordered before the second tracing segment on the first thread, and the third tracing segment can be ordered between the first tracing segment and the second tracing segment; identifying at least one memory unit interacting with one or more executable instructions, execution of the one or more executable instructions represented by the third trace segment, based on the third trace segment being orderable between the first trace segment and the second trace segment; as well as Memory snapshot data is inserted into the trace data corresponding to the first thread, the memory snapshot data identifying at least the at least one memory unit.
2. The method of claim 1, wherein the memory snapshot data identifying the at least one memory unit comprises at least one of: (i) an address of the at least one memory unit, (ii) an address range including the at least one memory unit. 3 . The method of claim 1 , wherein the memory snapshot data identifying the at least one memory cell comprises a value of the at least one memory cell after execution of the third tracing snippet. 4 . The method of claim 1 , wherein the at least one memory unit is a first memory unit, and wherein the memory snapshot data further identifies at least a second memory unit related to the first memory unit.
5. The method of claim 4, wherein the second memory cell is related to the first memory cell based on at least one of: (i) the first memory cell and the second memory cell are part of a memory buffer, and (ii) the second memory cell is reachable based on a value of the first memory cell.
6. The method of claim 1 , wherein inserting the memory snapshot data identifying the at least one memory unit into the trace data corresponding to the first thread comprises at least one of: (i) inserting the memory snapshot data into a trace data stream representing execution of the first thread, (ii) inserting the memory snapshot data as index data, the index data supplementing the trace data stream for the first thread.
7. The method of claim 1 , wherein inserting the memory snapshot data identifying the at least one memory unit into the trace data corresponding to the first thread comprises: The memory snapshot on the first thread is inserted at the end of the first tracing segment, at the beginning of the second tracing segment, or between the first tracing segment and the second tracing segment.
8. The method of claim 7 , wherein the memory snapshot is inserted at the end of the first tracing segment, at the beginning of the second tracing segment, or between the first tracing segment and the second tracing segment based on the second value of the at least one memory unit after execution of the third tracing segment being incompatible with the first value of the at least one memory unit in a previous memory snapshot on the first thread.
9. The method of claim 1 , wherein inserting the memory snapshot data identifying the at least one memory unit into the trace data corresponding to the first thread comprises: The memory snapshot on the first thread is inserted at the beginning of the first tracing segment or before the first tracing segment.
10. The method of claim 1, wherein the plurality of trace segments further includes a fourth trace segment corresponding to a third thread, wherein the fourth trace segment is also sequenceable between the first trace segment and the second trace segment, and wherein the first thread and the third thread are part of a thread focus group, the method further comprising: Based on the first thread and the third thread being part of the thread focus group, determining that any memory cell whose value interacts with its execution of one or more executable instructions represented by the fourth trace snippet does not need to be inserted as memory snapshot data into the trace data corresponding to the first thread.
11. A computer system comprising: at least one processor; as well as At least one computer-readable medium having computer-executable instructions stored thereon, the computer-executable instructions executable by the at least one processor to create memory snapshot data that reduces processing for thread-focused analysis, the computer-executable instructions comprising instructions executable by the at least one processor to at least: identifying a plurality of trace segments within a trace representing previous execution of a plurality of threads, each trace segment representing uninterrupted continuous execution of a plurality of executable instructions on a corresponding thread of the plurality of threads, the plurality of trace segments comprising a first trace segment and a second trace segment corresponding to the first thread, and a third trace segment corresponding to the second thread; determining at least a partial ordering of the plurality of tracing segments, including determining that the first tracing segment can be ordered before the second tracing segment on the first thread, and the third tracing segment can be ordered between the first tracing segment and the second tracing segment; identifying at least one memory unit interacting with one or more executable instructions, execution of the one or more executable instructions represented by the third trace segment, based on the third trace segment being orderable between the first trace segment and the second trace segment; as well as Memory snapshot data is inserted into the trace data corresponding to the first thread, the memory snapshot data identifying at least the at least one memory unit.
12. The computer system of claim 11, wherein the memory snapshot data identifying the at least one memory unit comprises at least one of the following: (i) an address of the at least one memory unit, (ii) an address range including the at least one memory unit. 13 . The computer system of claim 11 , wherein the memory snapshot data identifying the at least one memory unit comprises a value of the at least one memory unit after execution of the third tracking segment.
14. The computer system of claim 11, wherein the at least one memory unit is a first memory unit, and wherein the memory snapshot data further identifies at least a second memory unit related to the first memory unit.
15. The computer system of claim 11 , wherein inserting the memory snapshot data identifying the at least one memory unit into the tracing data corresponding to the first thread comprises at least one of: (i) inserting the memory snapshot data into a tracing data stream representing execution of the first thread, (ii) inserting the memory snapshot data as index data, the index data supplementing the tracing data stream for the first thread.
16. The computer system of claim 11, wherein inserting the memory snapshot data identifying the at least one memory unit into the trace data corresponding to the first thread comprises: The memory snapshot on the first thread is inserted at the beginning of the second trace segment.
17. The computer system of claim 16, wherein the memory snapshot is inserted at the beginning of the second tracing segment based on a second value of the at least one memory unit after execution of the third tracing segment being incompatible with a first value of the at least one memory unit in a previous memory snapshot on the first thread.
18. The computer system of claim 11, wherein inserting the memory snapshot data identifying the at least one memory unit into the trace data corresponding to the first thread comprises: The memory snapshot on the first thread is inserted at the beginning of the first tracing segment or before the first tracing segment.
19. The computer system of claim 11, wherein the plurality of trace segments further comprises a fourth trace segment corresponding to a third thread, wherein the fourth trace segment is also sequenceable between the first trace segment and the second trace segment, and wherein the first thread and the third thread are part of a thread focus group, the computer-executable instructions further comprising instructions executable by the at least one processor to: Based on the first thread and the third thread being part of the thread focus group, determining that any memory cell whose value interacts with its execution of one or more executable instructions represented by the fourth trace snippet does not need to be inserted as memory snapshot data into the trace data corresponding to the first thread.
20. A computer program product comprising at least one hardware storage device having computer executable instructions stored thereon, the computer executable instructions executable by at least one processor to cause a computer system to create memory snapshot data that reduces processing for thread-focused analysis, the computer executable instructions comprising instructions executable by the at least one processor to at least: identifying a plurality of trace segments within a trace representing previous execution of a plurality of threads, each trace segment representing uninterrupted continuous execution of a plurality of executable instructions on a corresponding thread of the plurality of threads, the plurality of trace segments comprising a first trace segment and a second trace segment corresponding to the first thread, and a third trace segment corresponding to the second thread; determining at least a partial ordering of the plurality of tracing segments, including determining that the first tracing segment can be ordered before the second tracing segment on the first thread, and the third tracing segment can be ordered between the first tracing segment and the second tracing segment; identifying at least one memory unit interacting with one or more executable instructions, execution of the one or more executable instructions represented by the third trace segment, based on the third trace segment being orderable between the first trace segment and the second trace segment; as well as Memory snapshot data is inserted into the trace data corresponding to the first thread, the memory snapshot data identifying at least the at least one memory unit.
Citation Information
Patent Citations
Multi-threading embedded system-based parallel program tracking and playback method
CN104216764A
Apparatus and method for debugging computer program
CN1959653A