Files
revng-revng/tests/unit/RecursiveCoroutine.cpp
T
Pietro Fezzardi b58693b8e8 RecursiveCoroutine: enable direct continuation
Before this commit, the execution logic of RecursiveCoroutine used an
underlying std::stack allocated on the heap to hold all the
coroutine_handles. It also manually managed passing return values from
callees to callers.

This commit drops this unnecessary auxiliary stack.
When a RecursiveCoroutine co_awaits another one, the handle of the
awaiter is injected into the awaitee, so that when the awaitee is done
it can directly execute the remaining part of the awaiter as a
continuation.
2021-05-05 17:48:04 +02:00

147 lines
3.1 KiB
C++

//
// This file is distributed under the MIT License. See LICENSE.md for details.
//
#include <chrono>
#include <experimental/coroutine>
#include <functional>
#include <iostream>
#include <vector>
// TODO: increase height up to explosion
// TODO: compare performance and peak memory
#include "revng/ADT/RecursiveCoroutine.h"
#include "revng/Support/Assert.h"
#include "DepthFirstVisit.h"
#include "SimpleRecursiveCoroutine.h"
size_t MaxDepth = 0;
size_t Iterations = 0;
int main(int, char *[]) {
//
// Run a simple recursive coroutine
//
std::vector<MyState> MyStateRCS;
MyStateRCS.emplace_back();
my_coroutine(MyStateRCS, 0);
//
// Visit a simple graph
//
Graph SimpleGraph = createSimpleGraph();
#ifdef ITERATIVE
std::vector<Entry> ThisRCS;
auto *Root = SimpleGraph.root();
auto &Children = Root->children();
ThisRCS.emplace_back(Entry{ Root, true, Children.begin(), Children.end() });
iterativeFindMaxDepth(ThisRCS);
#else
std::vector<Node *> ThisRCS;
// findMaxDepth expects the RCS to already contain the state for the first
// element
ThisRCS.emplace_back(SimpleGraph.root());
// run the coroutine
findMaxDepth(ThisRCS);
#endif
std::cerr << "MaxDepth: " << MaxDepth << std::endl;
std::cerr << "Iterations: " << Iterations << std::endl;
revng_check(MaxDepth == 4);
revng_check(Iterations == 7);
//
// Visit a complex graph
//
Graph G = createRandomGraph();
using namespace std::chrono;
using us = long long;
const us Repeat = 1;
us Average = 0;
for (size_t I = 0; I < Repeat; I++) {
Iterations = 0;
MaxDepth = 0;
auto Start = high_resolution_clock::now();
#ifdef ITERATIVE
std::vector<Entry> Stack;
auto *Root = G.root();
auto &Children = Root->children();
Stack.emplace_back(Entry{ Root, true, Children.begin(), Children.end() });
iterativeFindMaxDepth(Stack);
#else
std::vector<Node *> RCS;
// findMaxDepth expects the RCS to already contain the state for the first
// element
RCS.emplace_back(G.root());
// run the coroutine
findMaxDepth(RCS);
#endif
auto End = high_resolution_clock::now();
if (I != 0) {
Average += (duration_cast<microseconds>(End - Start).count() / Repeat);
}
std::cerr << "MaxDepth: " << MaxDepth << std::endl;
std::cerr << "Iterations: " << Iterations << std::endl;
revng_check(MaxDepth == 31);
revng_check(Iterations == 1227752);
}
std::cout << "Average: " << Average << std::endl;
Average = 0LL;
for (size_t I = 0; I < Repeat; I++) {
Iterations = 0;
MaxDepth = 0;
size_t X = 0ULL;
std::set<Node *> Stack;
auto Start = high_resolution_clock::now();
#ifdef ITERATIVE
X = iterativeFindMaxRet(G.root(), Stack);
#else
X = findMaxDepthRet(G.root(), Stack);
#endif
auto End = high_resolution_clock::now();
if (I != 0) {
Average += (duration_cast<microseconds>(End - Start).count() / Repeat);
}
revng_check(X == 34);
}
std::cout << "Average: " << Average << std::endl;
int Result = 0;
accumulateSums(7, Result);
std::cout << "Result: " << Result << std::endl;
revng_check(Result == 28);
return 0;
}