#include #include #include #include #include #include #include #include static bool isJsonFile(const char *filename) { const char *dot = strrchr(filename, '.'); if(!dot || dot == filename) return false; return !strcmp(dot + 1, "json"); } static std::vector jsonFiles(const std::string &dirName) { DIR *d; struct dirent *dir; std::vector result; d = opendir(dirName.c_str()); if (d) { while ((dir = readdir(d)) != NULL) { if (isJsonFile(dir->d_name)) result.push_back(dirName + dir->d_name); } closedir(d); } std::sort(result.begin(), result.end(), [](auto & a, auto &b){return a < b;}); return result; } class Renderer { public: explicit Renderer(const std::string& filename) { _animation = rlottie::Animation::loadFromFile(filename); _frames = _animation->totalFrame(); _buffer = std::make_unique(100 * 100); _surface = rlottie::Surface(_buffer.get(), 100, 100, 100 * 4); } void render() { if (_cur >= _frames) _cur = 0; _animation->renderSync(_cur++, _surface); } void renderAsync() { if (_cur >= _frames) _cur = 0; _future = _animation->render(_cur++, _surface); } void get() { if (_future.valid()) _future.get(); } private: std::unique_ptr _buffer; std::unique_ptr _animation; size_t _frames{0}; size_t _cur{0}; rlottie::Surface _surface; std::future _future; }; class PerfTest { public: explicit PerfTest(size_t resourceCount, size_t iterations): _resourceCount(resourceCount), _iterations(iterations) { _resourceList = jsonFiles(std::string(DEMO_DIR)); } void test(bool async) { setup(); std::cout<<" Test Started : .... \n"; auto start = std::chrono::high_resolution_clock::now(); benchmark(async); std::chrono::duration secs = std::chrono::high_resolution_clock::now() - start; std::chrono::duration millisecs = secs; std::cout<< " Test Finished.\n"; std::cout<< " \nPerformance Report: \n\n"; std::cout<< " \t Resource Rendered per Frame : "<< _resourceCount <<"\n"; std::cout<< " \t Render Buffer Size : (100 X 100) \n"; std::cout<< " \t Render Mode : "<< (async ? "Async" : "Sync")<<"\n"; std::cout<< " \t Total Frames Rendered : "<< _iterations<<"\n"; std::cout<< " \t Total Render Time : "<< secs.count()<<"sec\n"; std::cout<< " \t Avrage Time per Resource : "<< millisecs.count() / (_iterations * _resourceCount)<<"ms\n"; std::cout<< " \t Avrage Time Per Frame : "<< millisecs.count() / _iterations <<"ms\n"; std::cout<< " \t FPS : "<< _iterations / secs.count() <<"fps\n\n"; } private: void setup() { for (auto i = 0u; i < _resourceCount; i++) { auto index = i % _resourceList.size(); _renderers.push_back(std::make_unique(_resourceList[index])); } } void benchmark(bool async) { for (auto i = 0u; i < _iterations; i++) { if (async) { for (const auto &e : _renderers) e->renderAsync(); for (const auto &e : _renderers) e->get(); } else { for (const auto &e : _renderers) e->render(); } } } private: size_t _resourceCount; size_t _iterations; std::vector _resourceList; std::vector> _renderers; }; static int help() { std::cout<<"\nUsage : ./perf [--sync] [-c] [resource count] [-i] [iteration count] \n"; std::cout<<"\nExample : ./perf -c 50 -i 100 \n"; std::cout<<"\n\t runs perf test for 100 iterations. renders 50 resource per iteration\n\n"; return 0; } int main(int argc, char ** argv) { bool async = true; size_t resourceCount = 250; size_t iterations = 500; auto index = 0; while (index < argc) { const char* option = argv[index]; index++; if (!strcmp(option,"--help") || !strcmp(option,"-h")) { return help(); } else if (!strcmp(option,"--sync")) { async = false; } else if (!strcmp(option,"-c")) { resourceCount = (index < argc) ? atoi(argv[index]) : resourceCount; index++; } else if (!strcmp(option,"-i")) { iterations = (index < argc) ? atoi(argv[index]) : iterations; index++; } } PerfTest obj(resourceCount, iterations); obj.test(async); return 0; }