/// Utility function you call before something you want to time, so that the /// recorded times will all be consistent using the viewer's time. void startTiming(osgViewer::Viewer& viewer, const std::string& name) { osg::Timer_t tick = osg::Timer::instance()->tick(); double currentTime = osg::Timer::instance()->delta_s(viewer.getStartTick(), tick); int framenumber = viewer.getFrameStamp()->getFrameNumber(); viewer.getViewerStats()->setAttribute(framenumber, name + " begin", currentTime); }
/// Utility function you call after something you want to time, so that the /// recorded times will all be consistent using the viewer's time. void endTiming(osgViewer::Viewer& viewer, const std::string& name) { osg::Timer_t tick = osg::Timer::instance()->tick(); double currentTime = osg::Timer::instance()->delta_s(viewer.getStartTick(), tick); int framenumber = viewer.getFrameStamp()->getFrameNumber(); viewer.getViewerStats()->setAttribute(framenumber, name + " end", currentTime); double begin = 0.0; double elapsed = 0.0; if (viewer.getViewerStats()->getAttribute(framenumber, name + " begin", begin)) { elapsed = currentTime - begin; } viewer.getViewerStats()->setAttribute(framenumber, name + " time taken", elapsed); }
void updateUserStats(osgViewer::Viewer& viewer) { // Test the custom stats line by just adding up the update and cull // times for the viewer main camera for the previous frame. if (viewer.getViewerStats()->collectStats("update") && viewer.getCamera()->getStats()->collectStats("rendering")) { // First get the frame number. The code below assumes that // updateUserStats() is called after advance(), so the frame number // that will be returned is for the frame that has just started and is // not rendered yet. The previous frame is framenumber-1, but we can't // use that frame's timings because it's probably not finished // rendering yet (in multithreaded viewer modes). So we'll use the // timings for framenumber-2 for this demo. int framenumber = viewer.getFrameStamp()->getFrameNumber(); // Get the update time and the viewer main camera's cull time. We use // getAveragedAttribute() in order to get the actual time elapsed as // calculated by the stats. double update = 0.0, cull = 0.0; viewer.getViewerStats()->getAveragedAttribute("Update traversal time taken", update); viewer.getCamera()->getStats()->getAveragedAttribute("Cull traversal time taken", cull); // Get various begin and end times, note these are not elapsed times // in a frame but rather the simulation time at those moments. double eventBegin = 0.0, updateBegin = 0.0, cullEnd = 0.0, drawEnd = 0.0; viewer.getViewerStats()->getAttribute(framenumber-2, "Event traversal begin time", eventBegin); viewer.getViewerStats()->getAttribute(framenumber-2, "Update traversal begin time", updateBegin); viewer.getCamera()->getStats()->getAttribute(framenumber-2, "Cull traversal end time", cullEnd); viewer.getCamera()->getStats()->getAttribute(framenumber-2, "Draw traversal end time", drawEnd); // This line displays the frame number. It's not averaged, just displayed as is. viewer.getViewerStats()->setAttribute(framenumber, frameNumberName, framenumber); // This line displays the frame time (from beginning of event to end of draw). No bars. viewer.getViewerStats()->setAttribute(framenumber-1, frameTimeName, drawEnd - eventBegin); // This line displays the sum of update and main camera cull times. viewer.getViewerStats()->setAttribute(framenumber-1, customTimeName + " time taken", update+cull); // Since we give begin and end times that correspond to the begin of // the update phase and the end of the cull phase, the bar in the // graph will not correspond to the summed times above if something // happened between update and cull (as in this demo). Also, we need // to translate the updateBegin and cullEnd times by one frame since // we're taking the times for framenumber-2 but using them to display // in the framenumber-1 graph. viewer.getViewerStats()->setAttribute(framenumber-1, customTimeName + " begin", updateBegin + (1.0/60.0)); viewer.getViewerStats()->setAttribute(framenumber-1, customTimeName + " end", cullEnd + (1.0/60.0)); } }
int Metrics::run(osgViewer::Viewer& viewer) { if (Metrics::enabled()) { if (!viewer.isRealized()) { viewer.realize(); } // If Metrics are enabled, enable stats on the Viewer so that it we can report them for the Metrics if (Metrics::enabled()) { osgViewer::ViewerBase::Scenes scenes; viewer.getScenes(scenes); for (osgViewer::ViewerBase::Scenes::iterator itr = scenes.begin(); itr != scenes.end(); ++itr) { osgViewer::Scene* scene = *itr; osgDB::DatabasePager* dp = scene->getDatabasePager(); if (dp && dp->isRunning()) { dp->resetStats(); } } viewer.getViewerStats()->collectStats("frame_rate", true); viewer.getViewerStats()->collectStats("event", true); viewer.getViewerStats()->collectStats("update", true); viewer.getCamera()->getStats()->collectStats("rendering", true); viewer.getCamera()->getStats()->collectStats("gpu", true); } // Report memory and fps every 10 frames. unsigned int reportEvery = 10; while (!viewer.done()) { { METRIC_SCOPED_EX("frame", 1, "number", toString<int>(viewer.getFrameStamp()->getFrameNumber()).c_str()); { METRIC_SCOPED("advance"); viewer.advance(); } { METRIC_SCOPED("event"); viewer.eventTraversal(); } { METRIC_SCOPED("update"); viewer.updateTraversal(); } { METRIC_SCOPED("render"); viewer.renderingTraversals(); } } // Report memory and fps periodically. periodically. if (viewer.getFrameStamp()->getFrameNumber() % reportEvery == 0) { // Only report the metrics if they are enabled to avoid computing the memory. if (Metrics::enabled()) { Metrics::counter("Memory::WorkingSet", "WorkingSet", Memory::getProcessPhysicalUsage() / 1048576); Metrics::counter("Memory::PrivateBytes", "PrivateBytes", Memory::getProcessPrivateUsage() / 1048576); Metrics::counter("Memory::PeakPrivateBytes", "PeakPrivateBytes", Memory::getProcessPeakPrivateUsage() / 1048576); } } double eventTime = 0.0; if (viewer.getViewerStats()->getAttribute(viewer.getViewerStats()->getLatestFrameNumber(), "Event traversal time taken", eventTime)) { Metrics::counter("Viewer::Event", "Event", eventTime * 1000.0); } double updateTime = 0.0; if (viewer.getViewerStats()->getAttribute(viewer.getViewerStats()->getLatestFrameNumber(), "Update traversal time taken", updateTime)) { Metrics::counter("Viewer::Update", "Update", updateTime * 1000.0); } double cullTime = 0.0; if (viewer.getCamera()->getStats()->getAttribute(viewer.getCamera()->getStats()->getLatestFrameNumber(), "Cull traversal time taken", cullTime)) { Metrics::counter("Viewer::Cull", "Cull", cullTime * 1000.0); } double drawTime = 0.0; if (viewer.getCamera()->getStats()->getAttribute(viewer.getCamera()->getStats()->getLatestFrameNumber(), "Draw traversal time taken", drawTime)) { Metrics::counter("Viewer::Draw", "Draw", drawTime * 1000.0); } double gpuTime = 0.0; if (viewer.getCamera()->getStats()->getAttribute(viewer.getCamera()->getStats()->getLatestFrameNumber()-1, "GPU draw time taken", gpuTime)) { Metrics::counter("Viewer::GPU", "GPU", gpuTime * 1000.0); } double frameRate = 0.0; if (viewer.getViewerStats()->getAttribute(viewer.getViewerStats()->getLatestFrameNumber() - 1, "Frame rate", frameRate)) { Metrics::counter("Viewer::FPS", "FPS", frameRate); } } return 0; } else { return viewer.run(); } }