docs: def callgrind(self, out, filename=None, commandline=None, relative_path=False):
          """
          Dump statistics in callgrind format.
          Contains:
          - per-line hit count, time and time-per-hit
          - call associations (call tree)
            Note: hit count is not inclusive, in that it is not the sum of all
            hits inside that call.
          Time unit: microsecond (1e-6 second).
          out (file-ish opened for writing)
              Destination of callgrind profiling data.
          filename (str, collection of str)
              If provided, dump stats for given source file(s) only.
              By default, list for all known files.
          commandline (anything with __str__)
              If provided, will be output as the command line used to generate
              this profiling data.
          relative_path (bool)
              When True, absolute elements are stripped from path. Useful when
              maintaining several copies of source trees with their own
              profiling result, so kcachegrind does not look in system-wide
              files which may not match with profiled code.
          """
          print(u'# callgrind format', file=out)
          print(u'version: 1', file=out)
          print(u'creator: pprofile', file=out)
          print(u'event: usphit :microseconds/hit', file=out)
          print(u'events: hits microseconds usphit', file=out)
          if commandline is not None:
              print(u'cmd:', commandline, file=out)
          file_dict = self._mergeFileTiming()
          if relative_path:
              convertPath = _relpath
          else:
              convertPath = lambda x: x
          if os.path.sep != "/":
              # qCacheGrind (windows build) needs at least one UNIX separator
              # in path to find the file. Adapt here even if this is probably
              # more of a qCacheGrind issue...
              convertPath = lambda x, cascade=convertPath: cascade(
                  '/'.join(x.split(os.path.sep))
              )
          code_to_name_dict = {}
          homonym_counter = {}
          def getCodeName(filename, code):
              # Tracks code objects globally, because callee information needs
              # to be consistent accross files.
              # Inside a file, grants unique names to each code object.
              try:
                  return code_to_name_dict[code]
              except KeyError:
                  name = code.co_name + ':%i' % code.co_firstlineno
                  key = (filename, name)
                  homonym_count = homonym_counter.get(key, 0)
                  if homonym_count:
                      name += '_%i' % homonym_count
                  homonym_counter[key] = homonym_count + 1
                  code_to_name_dict[code] = name
                  return name
          for current_file in self._getFileNameList(filename, may_sort=False):
              file_timing = file_dict[current_file]
              print(u'fl=%s' % convertPath(current_file), file=out)
              # When a local callable is created an immediately executed, this
              # loop would start a new "fn=" section but would not end it before
              # emitting "cfn=" lines, making the callee appear as not being
              # called by interrupted "fn=" section.
              # So dispatch all functions in a first pass, and build
              # uninterrupted sections in a second pass.
              # Note: cost line is a list just to be mutable. A single item is
              # expected.
              func_dict = defaultdict(lambda: defaultdict(lambda: ([], [])))
              for lineno, code, hits, duration in file_timing.iterHits():
                  func_dict[getCodeName(current_file, code)][lineno][0].append(
                      (hits, int(duration * 1000000)),
                  )
              for (
                  lineno,
                  caller,
                  call_hits, call_duration,
                  callee_file, callee,
              ) in file_timing.iterCalls():
                  call_ticks = int(call_duration * 1000000)
                  func_call_list = func_dict[
                      getCodeName(current_file, caller)
                  ][lineno][1]
                  append = func_call_list.append
                  append(u'cfl=' + convertPath(callee_file))
                  append(u'cfn=' + getCodeName(callee_file, callee))
                  append(u'calls=%i %i' % (call_hits, callee.co_firstlineno))
                  append(u'%i %i %i %i' % (lineno, call_hits, call_ticks, call_ticks // call_hits))
              for func_name, line_dict in func_dict.iteritems():
                  print(u'fn=%s' % func_name, file=out)
                  for lineno, (func_hit_list, func_call_list) in sorted(line_dict.iteritems()):
                      if func_hit_list:
                          # Multiple function objects may "reside" on the same
                          # line of the same file (same global dict).
                          # Sum these up and produce a single cachegrind event.
                          hits = sum(x for x, _ in func_hit_list)
                          ticks = sum(x for _, x in func_hit_list)
                          print(
                              u'%i %i %i %i' % (
                                  lineno,
                                  hits,
                                  ticks,
                                  ticks // hits,
                              ),
                              file=out,
                          )
                      for line in func_call_list:
                          print(line, file=out)