Skip to main content
edited tags
Link
G. Sliepen
  • 61.7k
  • 3
  • 61
  • 152
deleted 11 characters in body
Source Link
toolic
  • 6.1k
  • 4
  • 20
  • 73

Thanks!

Thanks!

Source Link
Jnuk
  • 33
  • 2

Simple C++ event loop - static vs dynamic dispatch performance

I have two extremely simple toy implementations of an event loop, and would like to understand the performance differences between them.

First impl - events with a virtual 'handle' method - dynamic dispatch:

#include <memory>
#include <vector>

class Event {
    public:
        virtual bool handle() = 0;
};

class Event1 : public Event {
    public:
        bool handle() override {
            return ++n < 1000000000;
        }

    private:
        int n = 0;
};

class Event2 : public Event {
    public:
        bool handle() override {
            --n;
            return true;
        }
    private:
        int n = 0;
};

class EventLoop {
    public:
        void addEvent(Event& event) {
            events.push_back(&event);
        }

        void run() {
            while (true) {
                for (auto event : events) {
                    if (!event->handle()) {
                        return;
                    }
                }
            }
        }

    private:
        std::vector<Event*> events;
};

int main() {
    EventLoop eventLoop;

    Event1 event1;
    Event2 event2;

    eventLoop.addEvent(event1);
    eventLoop.addEvent(event2);

    eventLoop.run();

    return 0;
}

Second impl - wrap events in a lambda - static dispatch:

#include <vector>
#include <functional>

class Event1 {
    public:
        bool handle() {
            return ++n < 1000000000;
        }

    private:
        int n = 0;
};

class Event2 {
    public:
        bool handle() {
            --n;
            return true;
        }

    private:
        int n = 0;
};

class EventLoop {
    public:
        template<typename T>
            void addEvent(T& event) {
                events.push_back([&event]() { return event.handle(); });
            }

        void run() {
            while (true) {
                for (auto& event : events) {
                    if (!event()) {
                        return;
                    }
                }
            }
        }

    private:
        std::vector<std::function<bool()>> events;
};

int main() {
    EventLoop eventLoop;

    Event1 event1;
    Event2 event2;

    eventLoop.addEvent(event1);
    eventLoop.addEvent(event2);

    eventLoop.run();

    return 0;
}

My naive expectation was that the version using lambdas would be faster (ie 'dynamic dispatch is slow'), but compiling with g++, it was twice as fast to run - 17s compared to 35s on my machine, according to time.

I'd like to understand whether this is likely because with my toy event methods, the compiler was able to optimise the former better (and so in a more realistic scenario with more complex event handlers this would indeed typically be slower), or if there's some overhead associated with the lambdas that I don't understand that will likely always make this the case.

Thanks!