Длина переменной не влияет на скорость никак - это очередной тупой миф
Написал для теста код, что упорядочивает массив используя сортировку пузырьком.
функция сортировки
function s__NormalArray_sort takes nothing returns nothing
local boolean swapped
local integer temp
local integer i
loop
set swapped = false
set i = 0
loop
exitwhen not (i < JASS_MAX_ARRAY_SIZE-1)
if items[i] > items[i+1] then
set temp = items[i]
set items[i] = items[i+1]
set items[i+1] = temp
set swapped = true
endif
set i = i + 1
endloop
exitwhen not swapped
endloop
endfunction
native GetTickCount takes nothing returns integer
native SetOperationLimitEnabled takes boolean state returns nothing
native IsOperationLimitEnabled takes nothing returns boolean
library benchmark initializer init uses Caller {
#include "cj_types_priv.j"
define ITEMS_COUNT = JASS_MAX_ARRAY_SIZE
define MAKE_SORTABLE_ARRAY(TYPE_NAME, items, swapped, temp, i) = {
integer items[]
struct TYPE_NAME {
static void fill() {
for (int i = 0; i < ITEMS_COUNT; i++) {
items[i] = ITEMS_COUNT - 1 - i
}
}
static void sort() {
bool swapped
int temp
int i;
loop {
swapped = false
for (i = 0; i < ITEMS_COUNT-1; i++) {
if items[i] > items[i+1] {
temp = items[i]
items[i] = items[i+1]
items[i+1] = temp
swapped = true
}
}
exitwhen not swapped
}
BJDebugMsg("Sorting finished.")
}
static bool check() {
for (int i = 0; i < ITEMS_COUNT-1; i++) {
if items[i] > items[i+1] {
return false
}
}
for (int i = 0; i < ITEMS_COUNT; i++) {
if items[i] != i {
return false
}
}
return true
}
static void benchmark() {
fill()
int start_time = GetTickCount()
CallFunction(function thistype.sort)
int end_time = GetTickCount()
int difference = end_time - start_time
if !check() {
BJDebugMsg("Sorting failed.")
}
else {
BJDebugMsg("Time elapsed: " + I2S(difference) + " ms.")
}
}
}
}
MAKE_SORTABLE_ARRAY(FastArray, a, b, c, d)
MAKE_SORTABLE_ARRAY(NormalArray, items, swapped, temp, i)
MAKE_SORTABLE_ARRAY(SlowArray,aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa,bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb,ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc,ddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd)
MAKE_SORTABLE_ARRAY(VerySlowArray,aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa,bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb,cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc,dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd)
void start() {
bool old_state = IsOperationLimitEnabled()
SetOperationLimitEnabled(false)
CallFunction(function FastArray.benchmark)
CallFunction(function NormalArray.benchmark)
CallFunction(function SlowArray.benchmark)
CallFunction(function VerySlowArray.benchmark)
SetOperationLimitEnabled(old_state)
}
void init() {
trigger t = CreateTrigger()
TriggerAddAction(t, function start)
TriggerRegisterPlayerChatEvent(t, Player(0), "-start", true)
}
}
Другие языки
На Pascal'е сортировка заняла 85 мс, что почти в тысячу раз быстрее.
А при использовании статических массивов время снизилось до 72 мс.
Тот же результат выдала и моя asm реализация независимо от типа массива.
pascal
unit Unit1;
{$mode objfpc}{$H+}
interface
uses
Windows,
Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls;
type
{ TForm1 }
TForm1 = class(TForm)
StartButton: TButton;
Log: TMemo;
procedure StartButtonClick(Sender: TObject);
private
public
end;
//{$define STATIC_ARRAY}
const
TEST_ARRAY_SIZE = 8192;
type
TIntegerArray = array {$ifdef STATIC_ARRAY}[0..TEST_ARRAY_SIZE-1]{$endif} of Integer;
TSortFunction = procedure (var Items: TIntegerArray);
var
Form1: TForm1;
implementation
{$R *.lfm}
procedure FillArray({$ifdef STATIC_ARRAY}out{$endif} Items: TIntegerArray);
var
i: Integer;
begin
for i:= 0 to High(Items) do begin
Items[i]:= High(Items) - i;
end;
end;
procedure BubbleSort({$ifdef STATIC_ARRAY}var{$endif} Items: TIntegerArray);
var
i: Integer;
Temp: Integer;
Swapped: Boolean;
begin
repeat
Swapped:= False;
for i:= 0 to High(Items) - 1 do begin
if Items[i] > Items[i+1] then begin
Temp:= Items[i];
Items[i]:= Items[i+1];
Items[i+1]:= Temp;
Swapped:= True;
end;
end;
until not Swapped;
end;
procedure BubbleSortASM(Items: PInteger; Count: Integer); cdecl;
begin
asm
pushad
mov edx, Items
mov ebx, Count
dec ebx
@repeat:
mov eax, False
xor ecx, ecx
@loop:
lea ebp, [edx+ecx*4]
mov esi, [ebp]
mov edi, [ebp+4]
cmp esi, edi
jle @skip
mov [ebp], edi
mov [ebp+4], esi
mov eax, True
@skip:
inc ecx
cmp ecx, ebx
jl @loop
test eax, eax
jnz @repeat
popad
end;
end;
function IsArraySorted({$ifdef STATIC_ARRAY}const{$endif} Items: TIntegerArray): Boolean;
var
i: Integer;
begin
Result:= True;
for i:= 0 to High(Items) - 1 do begin
if Items[i] > Items[i+1] then
Result:= False;
end;
for i:= 0 to High(Items) do begin
if Items[i] <> i then
Result:= False;
end;
end;
procedure StartTest(TestFunction: TSortFunction);
var
Items: TIntegerArray = nil;
Frequency: Qword;
StartTime, EndTime, ElapsedTime: Qword;
begin
QueryPerformanceFrequency(@Frequency);
{$ifndef STATIC_ARRAY}SetLength(Items, TEST_ARRAY_SIZE);{$endif}
FillArray(Items);
QueryPerformanceCounter(@StartTime);
TestFunction(Items);
QueryPerformanceCounter(@EndTime);
ElapsedTime:= EndTime - StartTime;
if IsArraySorted(Items) then
Form1.Log.Lines.Add('Time elapsed: %d ms.', [ElapsedTime div (Frequency div 1000)])
else
Form1.Log.Lines.Add('Sorting failed.');
end;
procedure BubbleSortBenchmark(var Items: TIntegerArray);
begin
BubbleSort(Items);
end;
procedure BubbleSortASMBenchmark(var Items: TIntegerArray);
begin
BubbleSortASM(@Items[0], Length(Items));
end;
{ TForm1 }
procedure TForm1.StartButtonClick(Sender: TObject);
begin
StartTest(@BubbleSortBenchmark);
StartTest(@BubbleSortASMBenchmark);
end;
end.
SJ Cyber Droeed, да, такая возможность не помешает, если появятся время и желание - сделаю, а пока советую поискать обычные мапхаки, которые умеют показывать кд предметов и не крашатся в реплее.
Для доступа к ячейке хэштаблицы jass'а нужно пройти через 3 словаря.
Ключ для первого - номер хэштаблицы, для остальных двух - parentKey и childKey.
Игра использует собственные коллекции.
Вот как выглядит поиск в их словаре:
code
type
generic TSHashTable<TKey, TValue, TKeyManager> = object
public type
PValue = ^TValue;
TItems = specialize TSLinkedList<TValue>;
PItems = ^TItems;
TPages = specialize TSGrowableArray<TItems>;
public
vtable: Pointer;
Items: TItems;
Counter: Dword;
Pages: TPages;
HashMask: Dword;
end;
function TSHashTable.Find(const AKey: TKey): PValue;
var
Hash: Dword;
Index: Integer;
Page: PItems;
Item: PValue;
begin
Result:= nil;
if HashMask = Dword(-1) then exit;
Hash:= TKeyManager.GetKeyHash(AKey);
Index:= Hash and HashMask;
Page:= Pages.ItemPointers[Index];
for Item in Page do begin
if (Item^.HashKeyData.Hash = Hash) and
TKeyManager.IsKeysEqual(Item^.HashKeyData.Key, AKey)
then begin
Result:= Item;
break;
end;
end;
end;
У строк есть своя отдельная таблица, как и у агентов, в которой ведется подсчет ссылок.
Но, даже если обнулять все строковые переменные, количество ссылок никогда не опустится до нуля.
Происходит это из-за ошибки, допущенной разработчиками в коде игры, поэтому строки копятся и не удаляются.
Steal nerves, сомневаюсь, что такое может происходить из-за скрипта.
Другие карты не глючат?
Локальные файлы включены?
Попробуй запустить напрямую через игру. Может быть, твой редактор при сохранении ломает что-то.
При создании юнита и первом получении его хендла, количество ссылок равно единице.
Каждая ссылающаяся на handle переменная, добавляет к счетчику единицу.
Уничтожение юнита уменьшает счетчик на единицу.
По достижению нуля ссылок, handle освобождается и может быть переиспользован.
А значит, пока есть переменная, которая держит ссылку на юнита, его handle не будет использован для других объектов, даже после его уничтожения.
При объявлении скаляра ему не присваивается начальное значение его типа. Инициализировать его нужно отдельно, при этом, если его не инициализировать, выполнение программы остановится при чтении неинициализированного скаляра.
Массивная переменная - несколько скаляров, расположенных в памяти друг за другом. Эти скаляры называются элементами массива, а их количество называется размером массива.
Каждому элементу массива присваивается начальное значение его типа, то есть элементы массива в отличие от скаляров инициализируются при объявлении массива.
то есть он приобретет false по умолчанию только в случае, если это элемент массива, а не самостоятельная переменная?
Да.
Что касается обычной переменной, думаю, в памяти игры у неё значение 0 (false), но это не важно, так как игра не даст его прочитать.
Поэтому, необходимо явно задавать их значение перед использованием.
avuremybe, при обращении к неинициализированной переменной, поток выполнения обрывается.
Исключение — массивы, элементы которых имеют значения по-умолчанию.
Скачай карту и скопируй все триггеры, кроме тех, что находятся в папке demo.
Из ресурса тоже можно взять код, но он здесь для тех, кому лень качать или у кого нет редактора.
Был вопрос, в котором хотели спрятать тень предмета. Не знаю зачем, но раз спросили, значит нужно. Ответ на тот вопрос, собственно, и сподвиг меня проверить: как это работает и на что оно еще способно.
JaBeN_Симфер, очевидно, что нет. Она лишь позволяет добавлять нативки перед компиляцией скрипта.
С такими потребностями, тебе следует зайти в тему мемхака. Возможно, там есть сетевые функции.
» WarCraft 3 / Что предпочтительней и почему Lua или Jass?
Вторая карта (benchmark-packed.w3m) уже укомплектована DLL с нативками и готова к запуску.
» WarCraft 3 / Что предпочтительней и почему Lua или Jass?
Результаты теста
Исходники JASS скрипта
Другие языки
А при использовании статических массивов время снизилось до 72 мс.
Тот же результат выдала и моя asm реализация независимо от типа массива.
» WarCraft 3 / MapHack для реплея
» WarCraft 3 / Сценарий на любом языке
Разве в этом есть какой-либо толк?
Как бы то ни было, у моей системы не должно быть проблем с их загрузкой.
» WarCraft 3 / Memory Hack: Загрузчик native функций
Ред. IceFog
» WarCraft 3 / MapHack для реплея
» WarCraft 3 / Сценарий на любом языке
» WarCraft 3 / MapHack для реплея
» WarCraft 3 / MapHack для реплея
» WarCraft 3 / Сценарий на любом языке
» WarCraft 3 / Сценарий на любом языке
» WarCraft 3 / Telemetry.txt
» WarCraft 3 / Выделение памяти в хеш-таблице
Ключ для первого - номер хэштаблицы, для остальных двух - parentKey и childKey.
Вот как выглядит поиск в их словаре:
» WarCraft 3 / Опять утечка, может ли утекать переменная типа строка?
Но, даже если обнулять все строковые переменные, количество ссылок никогда не опустится до нуля.
Происходит это из-за ошибки, допущенной разработчиками в коде игры, поэтому строки копятся и не удаляются.
» WarCraft 3 / Манипуляции с кругом выделения и не только
Другие карты не глючат?
Локальные файлы включены?
Попробуй запустить напрямую через игру. Может быть, твой редактор при сохранении ломает что-то.
Ред. IceFog
» WarCraft 3 / Передача аргументов в функции callback'ов
Каждый её вызов создает абсолютно новую функцию.
» WarCraft 3 / Утечка или не утечка.
Каждая ссылающаяся на handle переменная, добавляет к счетчику единицу.
Уничтожение юнита уменьшает счетчик на единицу.
По достижению нуля ссылок, handle освобождается и может быть переиспользован.
» WarCraft 3 / Синхронизация строк
» WarCraft 3 / JASS: Курс молодого бойца
Ред. IceFog
» WarCraft 3 / JASS: Курс молодого бойца
Поэтому, необходимо явно задавать их значение перед использованием.
» WarCraft 3 / JASS: Курс молодого бойца
Исключение — массивы, элементы которых имеют значения по-умолчанию.
» WarCraft 3 / Манипуляции с кругом выделения и не только
Из ресурса тоже можно взять код, но он здесь для тех, кому лень качать или у кого нет редактора.
» WarCraft 3 / Манипуляции с кругом выделения и не только
» WarCraft 3 / убрать круг выбора
» WarCraft 3 / Memory Hack: Загрузчик native функций
С такими потребностями, тебе следует зайти в тему мемхака. Возможно, там есть сетевые функции.