首页 > 解决方案 > Haxe 中使用 Enum 作为 Map 键类型的内存分配问题

问题描述

我关注了一个 2D GPU 库,发现有人在内存分配方面遇到了问题。枚举的Array<Map>每帧通过setBlendMode调用,最终每次调用 Haxe Type.enumParameters

class GBlendModeFunc
{
    private static var blendFactors:Array<Map<GBlendMode,Array<Context3DBlendFactor>>> = [
        [
            GBlendMode.NONE => [Context3DBlendFactor.ONE, Context3DBlendFactor.ZERO],
            GBlendMode.NORMAL => [Context3DBlendFactor.SOURCE_ALPHA, Context3DBlendFactor.ONE_MINUS_SOURCE_ALPHA],
            GBlendMode.ADD => [Context3DBlendFactor.SOURCE_ALPHA, Context3DBlendFactor.DESTINATION_ALPHA],
            GBlendMode.MULTIPLY => [Context3DBlendFactor.DESTINATION_COLOR, Context3DBlendFactor.ONE_MINUS_SOURCE_ALPHA],
            GBlendMode.SCREEN => [Context3DBlendFactor.SOURCE_ALPHA, Context3DBlendFactor.ONE],
            GBlendMode.ERASE => [Context3DBlendFactor.ZERO, Context3DBlendFactor.ONE_MINUS_SOURCE_ALPHA],
        ],
        [
            GBlendMode.NONE => [Context3DBlendFactor.ONE, Context3DBlendFactor.ZERO],
            GBlendMode.NORMAL => [Context3DBlendFactor.ONE, Context3DBlendFactor.ONE_MINUS_SOURCE_ALPHA],
            GBlendMode.ADD => [Context3DBlendFactor.ONE, Context3DBlendFactor.ONE],
            GBlendMode.MULTIPLY => [Context3DBlendFactor.DESTINATION_COLOR, Context3DBlendFactor.ONE_MINUS_SOURCE_ALPHA],
            GBlendMode.SCREEN => [Context3DBlendFactor.ONE, Context3DBlendFactor.ONE_MINUS_SOURCE_COLOR],
            GBlendMode.ERASE => [Context3DBlendFactor.ZERO, Context3DBlendFactor.ONE_MINUS_SOURCE_ALPHA],
        ]
    ];
    
    static public function setBlendMode(p_context:Context3D, p_mode:GBlendMode, p_premultiplied:Bool):Void {
        var p:Int = (p_premultiplied) ? 1 : 0;
        p_context.setBlendFactors(blendFactors[p][p_mode][0], blendFactors[p][p_mode][1]);
    }
}

这里的问题是Type.enumParameters每次检查枚举数组 from 的值时都会创建一个新数组setBlendMode,快速添加数万个频繁触发 GC 的变量。

我不熟悉最佳 Haxe 实践,也不知道如何重组。是否有更高效的方式来存储不会产生分配问题的枚举?

编辑GBlendMode 枚举不能转换为抽象枚举,因为它破坏了其他功能。

编辑2:提出了一个解决方案:https ://github.com/pshtif/Genome2D-ContextFlash/issues/17

标签: haxestage3d

解决方案


我看到这看起来像Genome2D 代码

但是我没有看到GBlendMode枚举的任何代码——这整个事情都取决于该代码。如果enum GBlendMode是普通枚举,那么在运行时它们是数组。必须调用 map getter 函数Type.enumParameters来比较键——我截屏了一个 nodejs 调用堆栈来向自己证明这一点:

在此处输入图像描述

但是, ifGBlendMode是一个抽象枚举 over String,如下所示:

enum abstract GBlendMode(String) {
  var NONE;
  var NORMAL;
  var ADD;
  var MULTIPLY;
  var SCREEN;
  var ERASE;
}

然后键是简单的字符串,没有枚举比较,也没有创建中间数组。


推荐阅读