在某些视频游戏中,我发现每次创建新角色时都会使用工厂方法创建一个新的角色
class CharacterEngine
{
public:
static Character* CreateCharacter(string Name, Weapons InitialWeapons)
{
return new Character(Name, InitialWeapons);
}
};
//...
现在,如果我有100000000个字符(非常多,例如模拟粒子),这样的堆分配可能无法在RAM较小的计算机上运行。你对这个问题的解决方案是什么?
修改
您知道哪些其他方法或设计可以更改或替换工厂方法/类?
答案 0 :(得分:4)
你真的有 100K 个字符吗?你是否真的处在一个内存受限且分配失败的环境中?即使Character
是一个惊人的1KB
,你也会看到消耗的100MBs
,即使对于功能手机也不是那么多。
但是也许你担心你可能实际上有多余的内存,但是碎片是如此之高,你无法使用它。这是一个更公平的问题,通常与游戏相关。也许看看object pool模式。另外,考虑到你所说的大量字符,也许flighweight也可能有所帮助!
最后,内存不足与其他程序错误不同,如丢失TCP连接或遇到磁盘错误。如果需要分配100001
个字符并且没有更多内存,则无法分配它,向用户显示错误或稍后再试。如果没有它们,你就无法继续下去。所以不要 - 只是保释程序,也许做任何必要的清理工作,不要失去过多的游戏状态等。也请阅读malloc never fails。
答案 1 :(得分:2)
堆内存显然是有限的,但实际上限制不是那么小(在当前PC上至少是几千兆字节)。
内存消耗并不是游戏中最大的问题。如果你有很多字符,你可能需要处理它们之间的交互,这可能会更困难(例如,确定接近给定字符的字符集可能更具挑战性。)
您应该详细了解memory management,virtual address space,smart pointers,reference counting,RAII,circular reference s,weak reference s,hash consing。
请注意,堆是 global 到您的程序& process(它不是某个特定类或代码块的属性,而是整个程序的属性)。
堆分配例程(与new & delete相关)通常是针对某些operating system原语(通常是system calls)实现的,以增加虚拟地址空间。在Linux上,请参阅mmap(2)。操作系统可以提供一些查询虚拟地址空间的方法(在Linux上,请参阅proc(5)以及pid 1234的进程,/proc/1234/maps
伪文件)。
我建议您在garbage collection上阅读一本好书,例如GC handbook。它教您与C ++编程相关的概念和术语(特别是在游戏中)。从某种意义上说,您可能希望为自己的游戏实现自己的GC。
C ++有一些allocator概念,标准containers知道这一点。
另请阅读一些Introduction to Algorithms。
像这样的堆分配可能无法在RAM较小的计算机上运行。
然后要么改进程序以减少内存使用,要么使用更大的计算机。或许考虑一些distributed computing方法(例如cloud computing),例如MMORG。
您知道哪些其他方法或设计可以更改或替换工厂方法/类?
他们不会改变消耗的内存,因为在您的设计中,每个字符都由其唯一的C ++对象表示。所以无关紧要。
答案 2 :(得分:0)
假设您有足够的本地磁盘空间来存储所有字符的信息,您可以映射一个或多个存储所有字符数据的文件,并仅在需要时从文件中的数据创建一个字符对象。 / p>
如果你没有足够的内存和磁盘空间来存储本地所有字符的数据,那么它就会成为一个更加困难的问题 - 你可能需要为每个字符分配一个URI并从网络加载它...... / p>
编辑:当然,在更新字符数据后,您需要将其写回相应的文件。为了性能起见,您可能希望实现一些缓存机制,因此不需要阅读和使用的常用字符。每次使用时都会回写。