Skip to content

Conversation

ggcrunchy
Copy link
Contributor

This adds some features to profile a running project.

At the moment, it has "Display" and "Render" sections, roughly corresponding to "update stuff" and "draw that stuff".

(Captures and hit events probably could use coverage but present some challenges.)

Basically, in each of those sections, several timestamps are taken—at each "significant" step along the way—and the deltas in microseconds are reported. There is some small sublist support too, allowing event listeners to be included.

The results can be obtained with display.getTimings().


There are some per-frame statistics that Solar itself can already gather. These can be enabled and analyzed via display.enableStatistics() and display.getStatistics().


There is also a display.getSums() function, although it's a no-op.

Sums are similar to the timings described above, but they are meant for code that is hit numerous times, e.g. in a loop over child objects. The time differences are accumulated, and the number of visits recorded. (The counters are reset before rendering.)

These are disabled in normal code (#define ENABLE_SUMMED_TIMINGS 0) exactly because they're in some pretty hot spots, so will further impact code speed. (This was observed.) It would be interesting if some JIT techniques could be applied here. 😄

They're mostly meant as a tool for engine development—whereas the other features are also meant for users—and have already flushed out some performance problems that I'll continue to pursue. The last bit is true of the other functions as well, and where some of these other PRs are coming from.


There are also some details about when these results happen (and therefore when you can query them) since your Lua code obviously occupies a point in time. 😃 I will try to expound on this in a later comment and docs.


Basic example:

local sums, stats, tstack = {}, {}, {}

display.enableStatistics(true)

local function PrintList (name, indent)
  local timings = table.remove(tstack) or {}
  local n = display.getTimings(timings, name)

  indent = indent or " "

  print(indent .. "> " .. name)

  for i = 1, n, 2 do
    local what, time = timings[i], timings[i + 1]

    if time then
      print(indent .. " ", what, time / 1e3)
    else -- sublist?
      PrintList(what, indent .. "  ")
    end
  end

  tstack[#tstack + 1] = timings
end

timer.performWithDelay(1, function()
  PrintList("update")
  
  print("")
  
  PrintList("render")
  
  print("")
  print("Stats")
  
  display.getStatistics(stats)

  for k, v in pairs(stats) do
    print(k, v)
  end
  
  print("")
end, 1000)

Runtime:addEventListener("lateUpdate", function()
  local n = display.getSums(sums)

  for i = 1, n, 3 do
    print(sums[i], sums[i + 1], sums[i + 2])
  end

  if n > 0 then
    print("")
  end  
end)

I added Rtt_Profiling.h and Rtt_Profiling.cpp, so several files are projects with them added. I hope I got them all right. 😄

ggcrunchy and others added 30 commits February 7, 2019 17:09
…nd buffer and assignment logic

Next up, prepare details from graphics.defineEffect()
…from Program

Slight redesign of TimeTransform with caching (to synchronize multiple invocations with a frame) and slightly less heavyweight call site
Err, was calling Modulo for sine method, heh

That said, time transform seems to work in basic test
Fixed error detection for positive number time transform inputs

Relaxed amplitude positivity requirement
Maintenance Revert Test
My mistake adding back changes made
Some fixup in listener handling

Added timing query stuff

Had entirely forgotten to register the Lua functions :D
@ggcrunchy ggcrunchy requested a review from Shchvova as a code owner April 19, 2023 07:50
Copy link
Contributor

@Shchvova Shchvova left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is awesome!
I will merge it after we make a build without it.

@ggcrunchy
Copy link
Contributor Author

Note to self: Was adding files for another PR and saw there was also a Solar2D.project on Linux, that probably also wants the new file.

@Shchvova Shchvova merged commit 6370683 into coronalabs:master Jun 27, 2023
@ananii
Copy link

ananii commented Aug 31, 2023

It looks like these changes broke debugging. Now every error stack traceback points to error function in init.lua :

stack traceback: [C]: in function 'error' ?: in function <?:191>

debug.getinfo returns same path

So, handling "unhandledError" is completely useless now. The only thing that still works is event.errorMessage. Though it doesn't help if you have multiple nested functions.

Looks like it's due to this rewrited part in init.lua

local ok, handled = _pcall( func, event )
if not ok then
	display._endProfile( profile )
	error( handled )
end

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants