class Vernier::Output::FileListing

def samples_by_file

def samples_by_file
  thread = @profile.main_thread
  if Hash === thread
    # live profile
    stack_table = @profile._stack_table
    filename_filter = FilenameFilter.new
  else
    stack_table = thread.stack_table
    filename_filter = ->(x) { x }
  end
  weights = thread[:weights]
  samples = thread[:samples]
  self_samples_by_frame = Hash.new do |h, k|
    h[k] = SamplesByLocation.new
  end
  samples.zip(weights).each do |stack_idx, weight|
    # self time
    top_frame_index = stack_table.stack_frame_idx(stack_idx)
    self_samples_by_frame[top_frame_index].self += weight
    # total time
    while stack_idx
      frame_idx = stack_table.stack_frame_idx(stack_idx)
      self_samples_by_frame[frame_idx].total += weight
      stack_idx = stack_table.stack_parent_idx(stack_idx)
    end
  end
  samples_by_file = Hash.new do |h, k|
    h[k] = Hash.new do |h2, k2|
      h2[k2] = SamplesByLocation.new
    end
  end
  self_samples_by_frame.each do |frame, samples|
    line = stack_table.frame_line_no(frame)
    func_index = stack_table.frame_func_idx(frame)
    filename = stack_table.func_filename(func_index)
    samples_by_file[filename][line] += samples
  end
  samples_by_file.transform_keys! do |filename|
    filename_filter.call(filename)
  end
end