Observer, Events, Messaging

Started by
2 comments, last by Kylotan 7 years, 8 months ago

(searched forum and google, but nothing answers my questions)

Hey guys,

I am currently starting to prepare writing a game engine ( early stage, yes... )

Anyway, I got myself Game Programming Patterns by Robert Nystrom and Game Engine Architecture second edition by Jason Gregory. (and some C++ skills of course)

In Game Programming Patterns I encountered the observer pattern. The book states that the observer pattern is much faster than an event driven pattern using a queue.

In the observer pattern you register the observers at the subject in order to get notified.

Here my first question:

What exactly is the subject ? As far as I understood it is not the observed engine subsystem but more like a specific event inside the subsystem.

Second question:

When I got the previous right, what is such an engine event ? Is it a specific function that gets called like physicsFalling() ? Or what is it ?

So when you have to register your observers at the subject this is to me pretty much the same like a message queue, just that you reduce the amount of listeners. But why is the observer pattern faster than the events or messaging ? When an event is broadcasted over every subsystem there is in my eyes only a small check whether or not this event should be handled. So this can't be the reason for the perfomance difference. Maybe this check is more performance heavy than I think ?

Third question:

Why is observer significantly faster than events/messaging as stated by Chris Nystrom in Game Programming Patterns ?

Greetings

MAPster7

Advertisement

I don't have the book in front of me, but observer is a general pattern (not specific to games) and I'll explain it from that angle. The subject is the thing being observed, and that can be whatever you want it to be. If the subject was the whole subsystem then things are simpler but observers might get notified a lot about events they don't care about. But if the subsystem contains various subjects, that allows observers to subscribe to more specific things.

The event can be whatever you want or need it to be. Usually the idea is that Thing A may need to do something when Thing B changes. So, Thing A subscribes to Thing B, and Thing B can notify Thing A when it has changed, all without Thing B having to include any code specifically relating to Thing A.

This differs from a message queue in several ways:

1) You're not defining a bunch of message types, or needing to create explicit messages

2) There is no queue object storing those messages

3) It is explicit which events cause which results, because you can follow it on the callstack

4) There is no delay between an event occurring and other objects responding to the event

It's faster than a message queue because you've taken out all the overhead of maintaining that queue, plus there's no time wasted broadcasting an event to things that don't care about it - only observers that have specifically subscribed to an event will ever get notified.

But don't worry about the performance - the difference is minor and irrelevant for 99.9% of cases. What's more important is the code clarity and how well it matches your intent. Sometimes a message queue makes more sense, sometimes an observer does. Sometimes you need both for different things.

Thank you very much, gonna bookmark this as it made many things clear to me I did not get before.

I read on Gamasutra about messaging ( on an engine tut ) and to not care about performance that much, but I am on a point where it makes nearly no difference whether to set up an observer system or a messaging / event system. So I will prefer the performant way as long as there is no other reason to prefer something special. Don't want to hack my engine from event to observer just because I notice I can get significant performance increase from that =D

The big difference is in the semantics. Message systems are great for making systems generic - e.g. a networked game might use a message queue for all processing so that single player and multiplayer have exactly the same logic - it's just that the messages travel across the network in a multiplayer game. But sometimes it's annoying to not know what object created a message or what the state was when the message was created - and you won't have that with an observer, because you can put a breakpoint in the notify function (or whatever the callback is called) and see exactly what has triggered it.

Broadcasting an event is close to being like the observer method, but it requires stronger coupling - every time you add a new system, you have to ensure that your events get broadcast there. You also have to ensure that every system can safely handle all events (even if that just means ignoring them). Eventually you might find that your systems are receiving too many events and even if it doesn't slow performance, it might make debugging annoying.

You can think of the observer pattern as being like event broadcasting, except only sending it to recipients that have explicitly asked to be notified. It's like Pay-per-view instead of normal TV.

This topic is closed to new replies.

Advertisement