XGM Forum
Сайт - Статьи - Проекты - Ресурсы - Блоги

Форуме в режиме ТОЛЬКО ЧТЕНИЕ. Вы можете задать вопросы в Q/A на сайте, либо создать свой проект или ресурс.
Вернуться   XGM Forum > Warcraft> Академия: форум для вопросов> Jass
Ник
Пароль
Войти через VK в один клик
Сайт использует только имя.

Закрытая тема
 
YellowStar
poon
offline
Опыт: 15,144
Активность:
Полезность struct
Короче, количество создаваемого мусора struct - невероятно. Помниться тут, кто-то выкладывал зае----- методы allocate - deallocate.
Дело в том, что для своего маленького проекта, катаю сейчас множество спеллов, и почти на каждый прикручиваю практически одинаковый
struct spell
unit cast
unit targ
real time
............
endstruct
Ну и в принципе, я могу избежать этой порочной конструкции, ВООБЩЕ. Ну в плане, вообще - вообще. (считайте уже есть 120 спеллов, создано 120 alloc, dealloc). В принципе как вариант, можно переписать все на одну структуру, но это трах, с модами по типу -wtf -с максимальным кд, считаю быстро наполнит стак, учитывая что есть долгосрочные спеллы, в том числе и по 20 секунд (ну я набивал в соло 1000 спеллов, на одном герое, проверя возможности скорости вк)
Короче. Принимаю в дар куски кода. alloc/dealloc - принимаю также в дар, самый шустрый метод collision (текущий метод меня не устраивает, вообще ForGroup - оказался настолько медленным, что я решил написать матом, но кто-то отредактировал пост)

Отредактировано Doc, 08.08.2012 в 14:10.
Старый 08.08.2012, 13:54
ScorpioT1000
Работаем
offline
Опыт: отключен
самый шустрый метод collision
xgm.ru/p/wc3/xdestr там ищи
ScorpioT1000 добавил:
ну тоесть фича в том, чтобы не брать все из массивов, т.к. это медленно, а юзать максимум локалок (но не много) + глобалки =)
ScorpioT1000 добавил:
кароче говноваркрафт, что ещё можно сказать
ScorpioT1000 добавил:
почти на каждый прикручиваю практически одинаковый
там вроде наследование есть и работает годно ?
Старый 08.08.2012, 14:07
Doc

offline
Опыт: 63,163
Активность:
ScorpioT1000, да есть и вполне возможно все решить одной структурой с stub методами.
Старый 08.08.2012, 14:10
YellowStar
poon
offline
Опыт: 15,144
Активность:
ScorpioT1000:
xgm.ru/p/wc3/xdestr там ищи
Уже задрачиваю.
Есть вариант, все перенести на одну единственную Hash таблицу, но тогда опять таки, будет бесить меня, в том, что аргументы это таблицы могут быть заняты (хотя если взять общий COUNT)
по типу saveTYPE(hash,count,StringHash("DataName"),data)
Но опять таки, насколько быстр будет метод. Смогу ли я шустро юзать его в таймерах 0.0225?
Старый 08.08.2012, 15:30
ScorpioT1000
Работаем
offline
Опыт: отключен
обычно первый ключ юзается для номера инстанса "структуры", а второй для объявления в ней n переменных одного типа
я думаю, это может полностью заменить структуры
Старый 08.08.2012, 15:36
Faion
Noblesse Oblige
offline
Опыт: 30,395
Активность:
StringHash("DataName"),
/o\
И вообще. Пишем обычный UserData для хт. Пишем параллельные массивы, типа Caster, Target, Dummy, Damage и тд и тп. Вешаем индекс на объект, запихиваем в эти массивы, не то что ваше говно в виде структур. Существенно быстрее.
Для общих массивов пишем общий Flush. И да, не будьте ногоголовыми, при освобождении индексов и вашей UserData, записывайте их в отдельный массив свободных. Если все сурово и нагрузка большая, то распределяй по нескольким хт, ибо адресация последовательная, чем больше даты, тем меньше. На маленьких объемах все ок.
Старый 08.08.2012, 15:42
ScorpioT1000
Работаем
offline
Опыт: отключен
я представляю это как-то так

scope Myspellname_Struct

#define Myspellname = int

integer g_Myspellname_count = 0

// struct members
#define Myspellname_UNIT_OWNER = 0
#define Myspellname_UNIT_DUMMY = 1
#define Myspellname_INT_PARAM1 = 0
// ...

function Myspellname_New takes unit owner, integer param1, ... returns Myspellname 
	local integer id = g_Myspellname_count
	local unit dummy = CreateUnit ...
	set g_Myspellname_count = g_Myspellname_count + 1
	SaveUnitHandle(g_hash, g_Myspellname_count, Myspellname_UNIT_OWNER, owner)
	SaveUnitHandle(g_hash, g_Myspellname_count, Myspellname_UNIT_DUMMY, dummy)
	SaveInteger(g_hash, g_Myspellname_count, Myspellname_INT_PARAM1, param1)
	// ...
endfunction

function Myspellname_SetOwner takes Myspellname instanceId, unit owner returns boolean
	return SaveUnitHandle(g_hash, instanceId, Myspellname_UNIT_OWNER, owner)
endfunction

function Myspellname_GetOwner takes Myspellname instanceId returns unit
	return LoadUnitHandle(g_hash, instanceId, Myspellname_UNIT_OWNER)
endfunction

endscope


// ........

local Myspellname spellInst = Myspellname_New(unit1, 100500)
call Myspellname_SetOwner(spellInst, unit2)

Отредактировано ScorpioT1000, 08.08.2012 в 15:55.
Старый 08.08.2012, 15:49
16GB
GhostOne User
offline
Опыт: 59,317
Активность:
Faion:
Если все сурово и нагрузка большая, то распределяй по нескольким хт, ибо адресация последовательная, чем больше даты, тем меньше. На маленьких объемах все ок.
это 100% проверено? просто у меня например всё в одной и если переписывать то хотелось бы удостоверится
Старый 08.08.2012, 15:52
Faion
Noblesse Oblige
offline
Опыт: 30,395
Активность:
16GB:
это 100% проверено?
Что именно, скорость? Или вообще работоспособность?
Старый 08.08.2012, 16:05
16GB
GhostOne User
offline
Опыт: 59,317
Активность:
Faion,
ну плане повышения производительности
Старый 08.08.2012, 16:18
Faion
Noblesse Oblige
offline
Опыт: 30,395
Активность:
код чисто для примера, все либы не стал дергать, лень.
» UserData
library UserData 
{

    hashtable HashTable = InitHashtable()
    private int count = 0
    private int slot_count = 0
    private int array buff_slots

    void SetUserData(handle h, int val)
    {
        SaveInteger(HashTable,GetHandleId(h),0,val)
        SaveBoolean(HashTable,GetHandleId(h),1,false)
    }
    
    void SetStaticUserData(handle h, int val)
    {
        SaveInteger(HashTable,GetHandleId(h),0,val)
        SaveBoolean(HashTable,GetHandleId(h),1,true)
        count++;
    }

    int GetUserData(handle h)
    {
        return LoadInteger(HashTable,GetHandleId(h),0)
    }    
    
    void FlushUserData(handle h)
    {
        #if Debug 
            LogAdd("FlushUserData func использовано: " + I2S(slot_count))
        #endif
        if (LoadBoolean(HashTable,GetHandleId(h),1) == false)
        {
            slot_count++
            buff_slots[slot_count] = GetUserData(h)
            FlushChildHashtable(HashTable,GetHandleId(h))
        }
    }
    
    void RemoveUnitEx(unit u)
    {
        RemoveUnit(u)
        FlushUserData(u)
    }
    
    int GetNewIndex()
    {
        if slot_count > 0
        {
            slot_count--
            return buff_slots[slot_count+1]
        }
        else
        {
            count++
            return count
        }
        return 0
    }
    
    int GetIndex(handle u)
    {
        if GetUserData(u) == 0
        {
            if slot_count > 0
            {
                if slot_count > 8000
                {
                    BJDebugMsg("Внимание! Скоро всему будет пиздец!!!")
                }
                SetUserData(u,buff_slots[slot_count])
                slot_count--
            }
            else
            {
                count++
                SetUserData(u,count)
            }
        }
        return GetUserData(u)
    }    
}

» Темплейт
library MoveDummyToCoord uses UserData
{        
    #define private TimerAction(onPeriod, onEnd) = 
    {
        vblock
        {
            timer t = GetExpiredTimer();
            int index = GetUserData(t);
            unit TriggerUnit = PandoraDB_Dummy[index];
            float TriggerX = GetUnitX(TriggerUnit);
            float TriggerY = GetUnitY(TriggerUnit);
            
            if (PandoraDB_Distance[index] > 0.0)
            {
                // сокращаем дистанцию
                PandoraDB_Distance[index]-=PandoraDB_Speed[index];
                TriggerX=TriggerX+PandoraDB_CSpeed[index];
                TriggerY=TriggerY+PandoraDB_SSpeed[index];
                SetUnitX(TriggerUnit,TriggerX);
                SetUnitY(TriggerUnit,TriggerY);
                
                #if (!onPeriod)
                    onPeriod
                #endif
            }
            else
            {
                #if (!onEnd)
                    onEnd
                #endif
                PandoraDB_Dummy[index] = null;
                PandoraDB_Speed[index] = 0.0;
                PandoraDB_CSpeed[index] = 0.0;
                PandoraDB_SSpeed[index] = 0.0;
                PandoraDB_Distance[index] = 0.0;
                FlushUserData(t);
                DestroyTimer(t);
            }
            t=null;
            TriggerUnit=null;
        }
    }
        
    #define TMoveDummyToCoord(spellDummy, xCoord, yCoord, speed, onPeriod, onEnd) = 
    {
        vblock
        {
            timer t = CreateTimer();
            int index = GetIndex(t);
            float spellDummyX = GetUnitX(spellDummy);
            float spellDummyY = GetUnitY(spellDummy);
            PandoraDB_Dummy[index] = spellDummy;
            float angle = (57.295827 * Atan2(yCoord-spellDummyY,xCoord-spellDummyX));
            SetUnitFacing(PandoraDB_Dummy[index],angle);
            PandoraDB_Speed[index] = speed;
            PandoraDB_CSpeed[index] = speed*Cos(angle*0.0175);
            PandoraDB_SSpeed[index] = speed*Sin(angle*0.0175);
            PandoraDB_Distance[index] = SquareRoot((xCoord-spellDummyX)*(xCoord-spellDummyX)+(yCoord-spellDummyY)*(yCoord-spellDummyY));
            TimerStart(t,.04,true,lambda void(){TimerAction(onPeriod, onEnd)});
            t=null;
        }
    }
}
» Сампл
scope KunaiBomb

#define
{
    private abilCode = 'A009';
    private abilRang = E;
    private abilType = TAI;
    private exploisonDamage = 300.0;
    private exploisonRange = 300.0;
    private dummyModelPath = "NoteKunai.mdx";
    private dummyModelSize = 0.5;
    private dummySpeed = 40.0
    private effectModelPath = "SFX\\NewGroundEX.mdx"
    private effectModelSize = 1.5;
    private effectModelAngle1 = 0.0;
    private effectModelAngle2 = 0.0;
    private effectModelTime = 0.5;
}

callback onUnitSpellEffect(abilCode) 
{

    unit caster = GetTriggerUnit();
    float spellTargetX = GetSpellTargetX();
    float spellTargetY = GetSpellTargetY();
    unit dummy = Dummy_CreateDummy(caster, dummyModelPath, dummyModelSize,0.0) ;
    
    TMoveDummyToCoord(\
        dummy,\
        spellTargetX,\
        spellTargetY,\
        dummySpeed,\
        EmptyAction,\
        CreateDummySfx(effectModelPath, TriggerX, TriggerY, effectModelAngle1, effectModelAngle2, effectModelSize, effectModelTime);\
        TDamageEnemyArea(TriggerUnit, exploisonRange, exploisonDamage, abilType);\
        Dummy_RemoveDummy(TriggerUnit););
    caster = null;
    dummy = null;
}

endscope
» Темплейт заюзаный в сампле
library Damage uses GroupPick,ElementalSys
{
    public void DamageEnemyArea(unit u, float range, float abilDamage, int abilType)
    {
        group EnumUnits = GetUnitEnemyInRange(u, range)
        loop
        {
            unit TargetUnit = FirstOfGroup(EnumUnits)
            exitwhen TargetUnit == null
            CauseDamageUnitX(u,TargetUnit,abilDamage,abilType)
            GroupRemoveUnit(EnumUnits,TargetUnit)
            TargetUnit = null
        }
        DestroyGroup(EnumUnits)
        EnumUnits = null
    }
    
    #define TDamageEnemyArea(TriggerUnit, range, abilDamage, abilType) = 
    {
        Damage_DamageEnemyArea(TriggerUnit, range, abilDamage, abilType)
    }
}
» Глобалки
library PandoraDB
{
    public unit array Caster
    // дамми
    public unit array Dummy
    // цель
    public unit array Target
    // скорость
    public float array Speed
    // косинус*угол скорости
    public float array CSpeed
    // синус*угол скорости
    public float array SSpeed
    // угол
    //public float array Angle
    // дистанция
    public float array Distance

}
Faion добавил:
16GB:
Faion,
ну плане повышения производительности
Кэп говорит что нативный перебор в хт ключей, быстрее чем велосипеды для перебора массива объектов которые обычно юзают в структурах.
Faion добавил:
16GB:
ну плане повышения производительности
Ну если серьезно, то скорость доступа к ХТ примерно на 1\3 ниже чем скорость доступа к массиву(ибо там прямая адресация).
А теперь внимание вопрос, что быстрее, 1 запрос который медленнее всего лишь на 1\3 или возьмем по минимуму, к примеру 10 запросов во время стандартного перебора. Ответ очевиден, не правда ли?
Ну а далее идет прямая адресация по массивам. Параллельные массивы, выполняют функцию схожую структурам. Лучше завести под весь проект единую БД и юзать для всех спеллов. Быстрее организовать обмен данными не выйдет никак.
Старый 08.08.2012, 16:25
Nerevar
I'll be back!
offline
Опыт: 18,352
Активность:
Faion, он имел ввиду почему несколько быстрее одной как бы._.
Старый 08.08.2012, 16:28
Faion
Noblesse Oblige
offline
Опыт: 30,395
Активность:
Nerevar:
Faion, он имел ввиду почему несколько быстрее одной как бы._.
Омфг, да потому что там не прямая адресация, а последовательная. неужели еще кто то об этом не знает. Вопрос уже поднимался 100500 раз.
Старый 08.08.2012, 16:33
Nerevar
I'll be back!
offline
Опыт: 18,352
Активность:
Faion, и почему-то внезапно на каждом углу в рожок не трубят о том что лучше юзать 100500 таблиц вместо одной
почему же? и где же цифры при превышении скольких значений в одной хт лучше создать дополнительные? и как отразится на скорости
Старый 08.08.2012, 16:51
ScorpioT1000
Работаем
offline
Опыт: отключен
хештейбл на то и сделан, что в нём в 95% случаев прямая адресация и скорость работы не зависит от числа элементов в нём, кроме коллизий (1 коллизия - всеголишь + 1 такт при обращении к конкретному элементу, остальные работают так же моментально)
Старый 08.08.2012, 17:00
Faion
Noblesse Oblige
offline
Опыт: 30,395
Активность:
Nerevar:
Faion, и почему-то внезапно на каждом углу в рожок не трубят о том что лучше юзать 100500 таблиц вместо одной
почему же?
Это ж на сколько нужно быть упоротым, что б не понять, что размерность влияет при последовательной адресации?
Старый 08.08.2012, 17:02
ScorpioT1000
Работаем
offline
Опыт: отключен
Ну, например, в данной таблице при появлении 65536-го элемента появляется 1 коллизия (в теории офк), которая, допустим, добавится "сзади" какогото рандомного элемента, скажем, 3000-го. Теперь при обращении к 65536-му или 3000-му элементу, выполнится 2 сравнения вместо одного. При обращении к остальным элементам возврат выполняется моментально, так же, как к таблице с всего одним элементом.
Старый 08.08.2012, 17:09
Faion
Noblesse Oblige
offline
Опыт: 30,395
Активность:
ScorpioT1000:
хештейбл на то и сделан, что в нём в 95% случаев прямая адресация и скорость работы не зависит от числа элементов в нём
В массиве H хранятся сами пары ключ-значение. Алгоритм вставки элемента проверяет ячейки массива H в некотором порядке до тех пор, пока не будет найдена первая свободная ячейка, в которую и будет записан новый элемент. Этот порядок вычисляется на лету, что позволяет сэкономить на памяти для указателей, требующихся в хеш-таблицах с цепочками.
Последовательность, в которой просматриваются ячейки хеш-таблицы, называется последовательностью проб. В общем случае, она зависит только от ключа элемента, то есть это последовательность h0(x), h1(x), …, hn — 1(x), где x — ключ элемента, а hi(x) — произвольные функции, сопоставляющие каждому ключу ячейку в хеш-таблице. Первый элемент в последовательности, как правило, равен значению некоторой хеш-функции от ключа, а остальные считаются от него одним из приведённых ниже способов. Для успешной работы алгоритмов поиска последовательность проб должна быть такой, чтобы все ячейки хеш-таблицы оказались просмотренными ровно по одному разу.
Алгоритм поиска просматривает ячейки хеш-таблицы в том же самом порядке, что и при вставке, до тех пор, пока не найдется либо элемент с искомым ключом, либо свободная ячейка (что означает отсутствие элемента в хеш-таблице).
Удаление элементов в такой схеме несколько затруднено. Обычно поступают так: заводят булевый флаг для каждой ячейки, помечающий, удален ли элемент в ней или нет. Тогда удаление элемента состоит в установке этого флага для соответствующей ячейки хеш-таблицы, но при этом необходимо модифицировать процедуру поиска существующего элемента так, чтобы она считала удалённые ячейки занятыми, а процедуру добавления — чтобы она их считала свободными и сбрасывала значение флага при добавлении.
Старый 08.08.2012, 17:14
ScorpioT1000
Работаем
offline
Опыт: отключен
"Алгоритм поиска просматривает ячейки хеш-таблицы в том же самом порядке, что и при вставке, до тех пор, пока не найдется либо элемент с искомым ключом"
он просматривает только при коллизиях, обычно при первой же проверке появляется нужное значение
Старый 08.08.2012, 17:19
Hate
конь вакуумный
offline
Опыт: 43,117
Активность:
да какая разница в 2012 год то? у кого то еще слабые компьютеры остались что байтосчитанием так занимаются?
Старый 08.08.2012, 17:19
Закрытая тема

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск

Ваши права в разделе
Вы не можете создавать темы
Вы не можете отвечать на сообщения
Вы не можете прикреплять файлы
Вы можете скачивать файлы

BB-коды Вкл.
[IMG] код Вкл.
HTML код Выкл.
Быстрый переход



Часовой пояс GMT +3, время: 02:03.