Проблема выделения памяти в Haxe с использованием Enum в качестве типа ключа карты - PullRequest
2 голосов
/ 14 июля 2020

Я слежу за библиотекой 2D-графического процессора и увидел проблему с выделением памяти. Array<Map> перечислений вызывается каждый кадр через setBlendMode, в конечном итоге вызывая Type.enumParameters Haxe каждый раз.

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 создает новый массив каждый раз, когда проверяет значения массива enum из setBlendMode, быстро добавляя десятки тысяч переменных, которые часто запускают G C.

Я не знаком с лучшими практиками Haxe и не знаю, как их реорганизовать. Есть ли более эффективный способ хранения перечислений, который не создает проблем с выделением памяти?

Edit : перечисления GBlendMode не могут быть преобразованы в абстрактные перечисления, потому что они нарушает работу других функций.

Редактировать 2: Было предложено решение: https://github.com/pshtif/Genome2D-ContextFlash/issues/17

1 Ответ

1 голос
/ 14 июля 2020

Я вижу, это похоже на код Genome2D .

Но я не вижу кода для перечисления GBlendMode - и все это зависит от этого кода. Если enum GBlendMode - обычное перечисление, то во время выполнения они являются массивами. Функция получения карты должна вызывать Type.enumParameters для сравнения ключей - я сделал снимок экрана nodejs стек вызовов, чтобы доказать это самому себе:

введите описание изображения здесь

Однако, если GBlendMode является абстрактным перечислением поверх String, например:

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

Тогда ключи являются простыми строками и здесь нет сравнения перечислений и не создаются промежуточные массивы.

...