WICG / frame-timing

Frame Timing API
https://wicg.github.io/frame-timing/
Other
170 stars 18 forks source link

Define idle time. #27

Closed vmpstr closed 9 years ago

vmpstr commented 9 years ago

We reference IDLE time and we should define it.

mpb commented 9 years ago

Should that be defined somewhere like http://www.w3.org/TR/animation-timing/#processingmodel or should there be an in-line or footnote explanation in frame-timing?

vmpstr commented 9 years ago

I'd be OK with an inline, or a footnote. I think the difficulty is getting a concise one-liner that describes it.

mithro commented 9 years ago

I think it's very important that we be explicit about what idle time includes and excludes - even if it means we are more verbose.

My attempt at a definition for idle time is as follows;



Not entirely happy with it, but it was the best I could come up with.

mithro commented 9 years ago

Oh, I also left out the definition of work for this frame which also needs to be defined.

mithro commented 9 years ago

My definition above should match the following Python "pseudo code" (as described in https://github.com/w3c/frame-timing/issues/28#issuecomment-67107134).

You could think of it as being like the following almost Python code;

class RenderTimeCounter:
 def startFrame(self, t):
  self.startTime = t

 def startWork(self, t):
  self.rendering += 1
  # If rendering count is one, we are leaving an idle period and starting to
  # render stuff. Record the start time now.
  if self.rendering == 1:
   self.renderingPeriods.append({'start': t, 'end': None})

 def finishWork(self, t):
  self.rendering -= 1
  assert self.rendering >= 0
  # If nobody is rendering anymore then we are entering an idle period. Record
  # an end of the rendering time.
  if self.rendering == 0:
   assert self.renderingPeriods[-1]["end"] is None
   self.renderingPeriods[-1]["end"] = t

 def nextFrameStarting(self, t):
  assert self.rendering == 0
  assert self.renderingPeriods[-1]["end"] is not None
  self.endTime = t

 def getInfo(self):
  renderingFor = 0
  for work in workPeriods:
    renderingFor += work["end"] - work["start"]
  assert renderingFor < endTime - startTime
  return {"startTime": startTime, "duration": endTime - startTime, "cost": renderingFor}

class WorkerPool:
  class Worker:
    def run(self, stats):
      stats.startWork(Now())
      doStuff()
      stats.finishWork(Now())

  workers = [Worker(), Worker(), Worker()]

  def doFrame(self):
    # Get the frame time - as defined in the raf spec
    raftime = Now()

    # Finish the previous stats and send them to javascript
    self.last_frame_stats.nextFrameStarting(raftime)
    send_stats_to_javascript(self.last_frame_stats.getInfo())
    del self.last_frame_stats

    # Start a new stats
    stats = RenderTimeCounter()
    stats.startFrame(raftime)

    # Do synchronous javascript work
    stats.startWork(t)
    do_raf(raftime)
    stats.finishWork(t)

    # Do some multithreaded painting
    for w in self.workers:
      w.start()
    wait_for_all_to_finish(self.workers)

    # Sleep until we are close to frame deadline
    time.sleep(now - next_frame_time)

    # Do the final fix up rendering work
    stats.startWork(t)
    do_draw_and_swap()
    stats.finishWork(t)

    self.last_frame_stats = stats
igrigorik commented 9 years ago

Closing, summary doc + further discussion: http://lists.w3.org/Archives/Public/public-web-perf/2015Jan/0019.html