Jump to content
  • Advertisement
Sign in to follow this  
mike3

Messages and dynamic memory

This topic is 1007 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi.

I am wondering about this. Is there a good way to do event messages between two large-scale loose-coupled parts of a game program without having to dynamically allocate and deallocate the messages? Messages may need to be queued, and there can be different types of messages, which suggests an inheritance hierarchy and that's where the dynamic memory stuff comes from, at least when using C++ as I'd be in this case. Thanks.

Share this post


Link to post
Share on other sites
Advertisement

Well you can send different size messages if theyre prefixed with a size or type.

 

Like serialize size followed by data (probably the raw memory) in a queue of bytes, and on the other end read the object into contiguous memory (since std::queue is not contiguous) and interpret the address as a Base*.

 

But unless you actually need something like that for performance reasons, I wouldnt do it because it seems a bit prone to bugs. Maybe if you do proper serialization instead of raw memcpy (or use POD types + switch instead of inheritance) its safer... (does c++ even allow raw memory copy of objects with virtuals?)

Share this post


Link to post
Share on other sites

Well you can send different size messages if theyre prefixed with a size or type.

 

Like serialize size followed by data (probably the raw memory) in a queue of bytes, and on the other end read the object into contiguous memory (since std::queue is not contiguous) and interpret the address as a Base*.

 

But unless you actually need something like that for performance reasons, I wouldnt do it because it seems a bit prone to bugs. Maybe if you do proper serialization instead of raw memcpy (or use POD types + switch instead of inheritance) its safer... (does c++ even allow raw memory copy of objects with virtuals?)

 

Why would we serialize messages? This is about internal communication within the program.

Share this post


Link to post
Share on other sites

Assuming there's a fairly limited number of different message classes with a high number of instances over time, object pooling might be a good choice. Allocate once, and instead of deallocating, free them to a pool from which you later get them once needed. It will never run out of messages and never allocate more money than needed.

Share this post


Link to post
Share on other sites


Why would we serialize messages? This is about internal communication within the program.

 

Because it provides one solution to your problem. You can allocate a single block of memory and messages and write themselves into the buffer, etc...

 

First, I'd make sure you really need a messaging system anyway. Ideally you could replace them with method calls, and that would make the dependencies more clear.

 

If you really do need some sort of message-like design though (for instance, to be able to queue up messages and process them later), then ask yourself if dynamic allocation will really be a problem (I assume you're worried about performance of dynamic allocation).

Share this post


Link to post
Share on other sites

Are you developing for mobile? As Phil said, I dont think the overhead of alloc/dealloc will be significant unless you literally create/destroy thousands of messages each frame and have a limited processing power. Don't over-optimize before you have to.

 

That being said, pooling is probably your first step solution for any alloc/dealloc optimizations. You can also stick to simple strings/enum/cachec const vars instead of a messaging class and pass the params as (templeted) function parameters rather than in the message object itself. 

Share this post


Link to post
Share on other sites

 


Why would we serialize messages? This is about internal communication within the program.

 

Because it provides one solution to your problem. You can allocate a single block of memory and messages and write themselves into the buffer, etc...

 

First, I'd make sure you really need a messaging system anyway. Ideally you could replace them with method calls, and that would make the dependencies more clear.

 

If you really do need some sort of message-like design though (for instance, to be able to queue up messages and process them later), then ask yourself if dynamic allocation will really be a problem (I assume you're worried about performance of dynamic allocation).

 

 

Yes, I suppose that you could just use method calls, e.g. inherit from some kind of interface class which is kept suitably loose that implementation details don't leak, but then you can't defer processing until later, which was the purpose of the messaging system.

Share this post


Link to post
Share on other sites

I am wondering about this. Is there a good way to do event messages between two large-scale loose-coupled parts of a game program without having to dynamically allocate and deallocate the messages? Messages may need to be queued, and there can be different types of messages, which suggests an inheritance hierarchy and that's where the dynamic memory stuff comes from, at least when using C++ as I'd be in this case. Thanks.

Big bloated generic "event" systems are overkill. Write something specific.
e.g. Producer and Consumer are decoupled, but an application wants one to forward an event to the other:
class Producer
{
public:
  Producer( const std::function<void(int)>& onFrobnicate )
    : onFrobnicate(onFrobnicate)
    , foo() {}

  void Frobnicate()
  {
    onFrobnicate(foo++);
  }
private:
  std::function<void(int)> onFrobnicate;
  int foo;
};
class Consumer
{
public:
  Consumer() : foo() {}
  void Foo( int x )
  {
    foo += x;
  }
private:
  int foo;
};
class Application1
{
public:
  Application1()
    : producer(std::bind( &Consumer::Foo, consumer, _1 ))
  { 
    for( int i=0; i!=10; ++i )
      producer.Frobnicate(); // calls consumer.Foo 10 times
  }
private:
  Consumer consumer;
  Producer producer;
}
Or if the application wants to buffer the events:
class Application2
{
public:
  Application2()
    : producer([&](int x){events.push_back(x);})
  { 
    //we expect to buffer 10 events, so let's pre-allocate that much memory as an optimization:
    events.reserve(10);

    for( int i=0; i!=10; ++i )
      producer.Frobnicate(); // pushes 10 results into 'events'

    //now send the buffered events to the consumer:
    for(auto i: events)
      consumer.Foo(i);
    events.clear();
  }
private:
  Consumer consumer;
  Producer producer;
  std::vector<int> events;
}
Isn't that easier than using some big inheritance-based messaging framework? C++ has tools for this already smile.png

To answer the other question -- if you did need to dynamically create a big stack of temporary messages, I'd use a pool allocator, or even better, a stack allocator. Stack allocators are the cheapest possible allocation of any algorithm, and are built around bulk destruction (freeing every allocation made at the same time).
In the above code, the vector acts like a stack allocator, which is a good start, and could be optimized further by replacing it with a hand-coded/optimized stack allocator.

Share this post


Link to post
Share on other sites

Seconding Hodgman, I honestly consider "big hub" message exchange architectures lack of proper design. I don't recall a single case which, on closer scrutiny really required the arbitrary mappings.

 

While I support the notion above I would rather stay away from std::bind. To be honest I would go with an explicit 'onIntGenerated' callback or 'onIntListener' interface.

Edited by Krohm

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!