TaskTracer: Difference between revisions

4,248 bytes added ,  13 March 2017
/* Labels
No edit summary
(/* Labels)
 
(17 intermediate revisions by 5 users not shown)
Line 1: Line 1:
== Introduction ==
== Introduction ==
TaskTracer aims at the '''correlation''' between Tasks and Runnables, across threads and processes.
TaskTracer remembers the '''correlation''' between Tasks and Runnables, across threads and processes.


By looking at a task, TaskTracer tells you:
By looking at a task, TaskTracer tells you:
* The “source events” of this task.
* The “source events” of this task.
** IO events: touch events, key events, wifi daemon signal
** IO events: touch events, key events, wifi daemon signal
* Where it is dispatched from.
* Who, the other task, does create a task.
* The timing a task was dispatched, run, and stopped.
== Get log files ==


== How to use Task Tracer ==
Compile Gecko or Firefox with following line in mozconfig.
=== mozilla-central ===
1. Build and flash (built-in)


cd B2G
  ac_add_options --enable-tasktracer
export MOZ_TASK_TRACER=1; ./build.sh gecko
./flash.sh gecko


2. Start profiling
Start logging with Gecko Profiler Addon.  There is an option in the
control panel of the addon to enable TaskTracer.


./profile.sh start -f tasktracer
Attach gdb to Firefox process, the chrome process, and run following
command in gdb.


3. Get result
  (gdb) call profiler_save_profile_to_file_async(0.0, "/abs/to/logfile")
  (gdb) continue


3.1. Capture current result
Waiting for a couple seconds, the file would be created.


./profile.sh capture
== Dump log ==
Get [https://bitbucket.org/thinker/tttools tttools]
  python dumplog.py /path/to/logfile


3.2. Get Task Tracer Converter
== Task ==


  git clone https://github.com/ginayeh/task-tracer-converter -b v2.0
A task is dispatched to a task queue at the time (in ms) given by
|dispatchTime| attribute of the |Task| object. It is an array because
of a runnable can be dispatched and ran for several times.


3.3. Convert result
|begin| is the time that the runnable/task was started to run. |end|
is the time where the task finish it's work.


mv profile_*.txt task-tracer-converter/log/
  {'begin': [u'1472463888021'],
cd task-tracer-converter/
  'dispatchTime': [u'1472463888021'],
./tasktracer.sh get_mmaps
  'end': [u'1472463888021'],
./task_tracer_converter.py -sp $B2G/objdir/dist/bin/libxul.so \
  'label': [],
                            -np $B2G/prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6/x86_64-linux/bin/nm
  'parent': u'0',
  'process': 22525,
  'sourceEventId': u'0',
  'sourceEventType': u'0',
  'taskId': u'96744138362318',
  'thread': 22525,
  'timeDuration': 0,
  'vptr': '??'},


=== v1.3T ===
1. Get the source code of Task Tracer.


git clone https://github.com/shellylin/gecko-dev/tree/tt-1.3t
== Load log in python ==
  import tttools
  profileobject = tttools.loadRawProfile('/abs/to/logfile')


2. Build and flash to a real device.
== Parent tasks ==


  cd B2G
Parent task of a task is the one create and dispatch the task. You
export MOZ_TASK_TRACER=1; ./build.sh gecko
can find the parent task, parent's parent, ... and all ancestors with
./flash.sh gecko
the following Python instructions.


3. Get the source code of data retriever and data converter.
  taskIdsOfAncestors = profileobject.findAncestors(GivenTaskId)
  import pprint
  pprint.pprint(profileobject.findTasks(taskIdsOfAncestors))


git clone https://github.com/ginayeh/task-tracer-converter
== Followers ==


4. Start profiling.
Followers of a task are tasks that is created by the given task or
it's followers.


cd task-tracer-converter
  taskIdsOfFollowers = profileobject.findFollowers(GivenTaskId)
./tasktracer.sh start
  import pprint
  pprint.pprint(profileobject.findTasks(taskIdsOfFollowers))


5. Stop profiling.
== Blocker tasks ==


  ./tasktracer.sh stop
You can find what tasks are blocked by the different in time of
|dispatchTime| and |begin|.


The raw log is written into ''task_tracer_data.logcat''.
  tasks = profileobject.findTasks(profileobject.findAncestors(GivenTaskId))
  for task in tasks:
    queuingTIme = long(task.begin[0]) - long(task.dispatchTime[0])
    print 'task: %s, thread: %d, queuingTime: %d' % (task.taskId,
                                                    task.thread,
    queuingTime)


6. Get memory maps from the real device.
The more time a task staying in the queue, the more time the task is
blocked by other tasks. You can find what other tasks blocked a task
with following instructions.


mkdir mmaps
  task = profileobject.findTask(BlockedTaskId)
./tasktracer.sh get_mmaps
  blockerIds =
    profileobject.findTasksStartInTimeThread(int(task.dispatchTime[0]),
                                            int(task.begin[0]),
    task.thread)
  blockers = profileobject.findTasks(blockerIds)
  pprint.pprint(blockers)


The memory maps pulled out from the real device are put under mmaps directory automatically.
== Labels ==


7. Prepare data for extracting class/task name.
You may need to attach some information or strings on tasks and to see
strings in the log to help you to identify specific tasks. Following
C++ code in Gecko would add a label, i.e. a string, on the current
running task of this thread.


./prepare-data.sh mmaps ''$objdir''
  #ifdef MOZ_TASK_TRACER
  #include "GeckoTaskTracer.h"
  #endif
  ...
  #ifdef MOZ_TASK_TRACER
  mozilla::tasktracer::AddLabel("Event [%s] ...", str...);
  #endif


Two intermediate files are generated for later use: ''mem_offset'', ''symbol''.
Javascript adds labels with a special prefix.


8. Convert raw log to JSON format.
  console.log("#tt# Log message"); // #tt# is the prefix.


python task_tracer_converter.py -i task_tracer_data.logcat [-o task_tracer_data.json] [-w]
For the case of labeling at begin and end of a scope, |AutoScopedLabel| is a helper class to do that.


Default output filename: ''task_tracer_data.json''.
  {
  #ifdef MOZ_TASK_TRACER
    AutoScopedLabel label("Event [%s] ...", str...);  // label "Begin Event [...]..."
  #endif
    // do something ....
  } // label "End Event [...]..."


== How to read the profile using Nephthys ==
The "Begin ..." label would be added when the instance of |AutoScopedLabel| was created.  And, "End ..." label would be added when the instance was destroyed.


Import the json file to Nephthys, http://alivedise.github.io/nephthys/
== DESIGN ==


== Reference links ==
TaskTracer has 5 types of logs in its log files,
* {{bug|995058}} - [Meta] TaskTracer and Nephthys
DISPATCH, BEGIN, END, VTABLE, and LABEL.
* {{bug|908995}} - [B2G] Task tracer
They are used to remember
** https://github.com/shellylin/gecko-dev/tree/tt-v4
* {{bug|916409}} - Data retriever for task tracer
* {{bug|916410}} - Show data generated by Task Tracer in Cleopatra
* {{bug|956620}} - [B2G] Task tracer converter
** https://github.com/ginayeh/task-tracer-converter
* {{bug|992454}} - [B2G] Integrate Task tracer&Nephthys with GeckoProfiler&Cleopatra
* Nephthys
** http://alivedise.github.io/nephthys/
** https://github.com/alivedise/nephthys/tree/gh-pages
* FoxGuide
** https://addons.mozilla.org/en-US/firefox/addon/foxguide/


== TODO ==
- what the task created and dispatched a new task to
* Integrate with built-in profiler
  a target thread,
** Timestamp
- the time a task was started to run at the target thread,
** Start/Stop
- the time a task had done its works,
* Thread pool
- the type (vtalbe of the class) of the runnable of a given task, and
* CpuTime
- labels that denote what was happened in a task.
* Integrate with Cleopatra
 
* Nested loop
=== TASK ID ===
* Ruler
 
Each type of logs has a time stamp to denote when it was happened, and
a task ID to uniquely identify a tasks.  To make the running code
knowning which task is running at a thread, the ID of the running task
is stored in the TLS, e.q. thread local storage, when the event loop
of the thread starts to run it.  That means when a new task was
created and dispatched, TaskTracer got the task ID of the running task
of current thread from TLS, and denote it as the creator/parent of the
new one.
 
The IDs of a task and its parent task (from TLS) were recorded in a
DISPATCH log when it was dispatched to correlates a task and its
parent task.
 
When an IPC message was sent, a new task was created and dispatched at
receiving side to handle the message.  TaskTracer stores the task ID
of the sender of a message in its header, and uses that ID as the
parent task ID of the task handling the message at receiving site.
With this, TaskTracer correlates tasks over processes.
 
=== SOURCE EVENT ID AND TYPE ===
 
Not all tasks are always created by another task.  For example, a
mouse event would create and dispatch a task to handle it, but the
mouse event itself is no task.  TaskTracer calls mouse events or other
events from the kernel as source events.  Every source event has an
unique ID to identify it, and assign a type to identify whether it is
a mouse event, keyboard event, ..., or network event.  They are source
event IDs and source event types.
 
The tasks created by source events have no parent task ID, the value of
its parent task ID is identical to its task ID.  With this rule, users
know a task was created for handling a source event if its task ID is
identical to its parent task ID.
 
Source event ID and type would be stored in TLS of threads.  They are
also retrieved from TLS and stored in the new runnable of a new task
when the new task is created/dispatched.  When a new task was started
to run, the source event ID and type stored on it will be retrieved
and stored to TLS too.  That means source event ID and type would
passing along all tasks created for the source event directly or
indirectly.  That means they are also dispatched along IPC messages.
 
=== VTABLE ===
 
For C++, every virtual class, that means a class having at least one
virtual method, has a vtab to store entry points of its virtual
methods.  A VTABLE log contains the address of vtab of the concrete
class of an instance of Runnable (a task).  With the address of the
vtab of a task, TaskTracer can get the concrete class name of the task
by symbolicating.  People can understand the purpose of a task by its
name.
Confirmed users
398

edits