| 558 | } |
| 559 | |
| 560 | void RawFrameDataWriter::WriteStats_() |
| 561 | { |
| 562 | auto& stats = *pStatsTracker; |
| 563 | auto& aeStats = *pAnimationErrorTracker; |
| 564 | |
| 565 | std::ofstream statsFile{ *frameStatsPath, std::ios::trunc }; |
| 566 | |
| 567 | // write header |
| 568 | statsFile << |
| 569 | "Duration," |
| 570 | "Total Frames," |
| 571 | "Average FPS," |
| 572 | "Minimum FPS," |
| 573 | "1st Percentile FPS," |
| 574 | "5th Percentile FPS," |
| 575 | "Maximum FPS," |
| 576 | "AnimationErrorPerSecond," |
| 577 | "AnimationErrorPerFrame\n"; |
| 578 | |
| 579 | // lambda to make sure we don't divide by zero |
| 580 | // caps max fps output to 1,000,000 fps |
| 581 | const auto SafeInvert = [](double ft) { |
| 582 | return ft == 0. ? 1'000'000. : 1. / ft; |
| 583 | }; |
| 584 | |
| 585 | if (stats.GetCount() > 0) { |
| 586 | // write data |
| 587 | statsFile << |
| 588 | GetDuration_() << "," << |
| 589 | stats.GetCount() << "," << |
| 590 | SafeInvert(stats.GetMean()) << "," << |
| 591 | SafeInvert(stats.GetMax()) << "," << |
| 592 | SafeInvert(stats.GetPercentile(.99)) << "," << |
| 593 | SafeInvert(stats.GetPercentile(.95)) << "," << |
| 594 | SafeInvert(stats.GetMin()) << ","; |
| 595 | if (aeStats.GetCount() > 0 && GetDuration_() != 0.) { |
| 596 | const double aeSumSecs = aeStats.GetSum() / 1000.; |
| 597 | statsFile << (aeSumSecs / GetDuration_()) << "," << |
| 598 | (aeStats.GetSum() / aeStats.GetCount()) << "\n"; |
| 599 | } |
| 600 | else { |
| 601 | statsFile << 0. << 0. << "\n"; |
| 602 | } |
| 603 | |
| 604 | } |
| 605 | else { |
| 606 | // write null data |
| 607 | statsFile << |
| 608 | 0. << "," << |
| 609 | 0. << "," << |
| 610 | 0. << "," << |
| 611 | 0. << "," << |
| 612 | 0. << "," << |
| 613 | 0. << "," << |
| 614 | 0. << "," << |
| 615 | 0. << "\n"; |
| 616 | } |
| 617 | } |