Город Мастеров
IPB

Здравствуйте, гость ( Вход | Регистрация )

 Правила этого форума ПРАВИЛА РАЗДЕЛА
 
Ответить в эту темуОткрыть новую тему
> if, &&, || - оптимизация, как быстрее проверки идут?
AliceDiren
сообщение Oct 18 2005, 14:17
Сообщение #1


Level 7
**

Класс: Маг
Характер: True Neutral
Раса: Эльф
NWN: Скриптинг [Sn]



LEX: Все началось с этого:

Neverwinter Script Source
int StartingConditional()
{
object oPC = GetPCSpeaker();

if (GetLocalString(oPC, "victorspoken") == "1") return FALSE;

if (GetGender(oPC) != GENDER_FEMALE) return FALSE;

if (GetRacialType(oPC) != RACIAL_TYPE_DWARF) return FALSE;

if (GetRacialType(oPC) != RACIAL_TYPE_GNOME) return FALSE;

if (GetRacialType(oPC) != RACIAL_TYPE_HALFLING) return FALSE;

return TRUE;
}

--------------------------
Быть может так проще?
Neverwinter Script Source
int StartingConditional()
{
object oPC = GetPCSpeaker();
int bResult = FALSE;

if(GetLocalString(oPC, "victorspoken")=="1")
return FALSE;

bResult = (GetRacialType(oPC) = RACIAL_TYPE_DWARF || GetRacialType(oPC) == RACIAL_TYPE_GNOME || GetRacialType(oPC) == RACIAL_TYPE_HALFLING) && (GetGender(oPC) == GENDER_FEMALE);

return bResult;
}


Я просто к тому, что несколько строк, проверяющих условия рассовой принадлежности, стоит объеденить в одну. Гораздо легче читать

Сообщение отредактировал Lex - Oct 18 2005, 15:58
Вернуться в начало страницы
Скопировать ник в поле быстрого ответа
+Ответить с цитированием данного сообщения
Lex
сообщение Oct 18 2005, 14:23
Сообщение #2


Level 5
Иконки Групп

Класс: Обыватель
Характер: Lawful Neutral
Раса: Человек
NWN: Модмейкер
Проклятие Левора
Порядок Времени



QUOTE (AliceDiren @ Oct 18 2005, 15:17)
Быть может так проще?

:) а мне проще как раз в том стиле, что у химерика. Кстати, так вроде и операций поменьше будет. Но тут я не сильно уверен. (вообще точно вложенные if работают быстрее чем много-условный if. Тут по сути дела так и есть. Женщина И рассы. можно
Neverwinter Script Source
if (female)
{
if (races)
    return
}

а можно
Neverwinter Script Source
if (female)&&(races)
   return

Так вот, первый вроде работает быстрее. :)
По сути тот стиль, что в скрипте Chimeric и есть первый вариант. :) просто чуть по другому написаный - не вложение ифов, а обратные условия и вылет из скрипта (return FALSE)
Вернуться в начало страницы
Скопировать ник в поле быстрого ответа
+Ответить с цитированием данного сообщения
AliceDiren
сообщение Oct 18 2005, 14:28
Сообщение #3


Level 7
**

Класс: Маг
Характер: True Neutral
Раса: Эльф
NWN: Скриптинг [Sn]



:xz: так а там не много-условные, и не вложенные. Я потому и написала :)
Добавлено в 15:33
:angel: а вообще быстрее будет:
Neverwinter Script Source
return (races)&&(female)&&(LocalInt != 1);

имхо

Сообщение отредактировал AliceDiren - Oct 18 2005, 14:33
Вернуться в начало страницы
Скопировать ник в поле быстрого ответа
+Ответить с цитированием данного сообщения
Lex
сообщение Oct 18 2005, 14:36
Сообщение #4


Level 5
Иконки Групп

Класс: Обыватель
Характер: Lawful Neutral
Раса: Человек
NWN: Модмейкер
Проклятие Левора
Порядок Времени



:) где-то читал или кто-то мне говорил, что операция И в нсс сделана малек криво.
не помню подробностей (мб там все условия "И" проверяются, даже если уже 1 было ложно, толи еще какая фигня), но я для себя усвоил то, что эту штуку надо юзать пореже. :)
Вернуться в начало страницы
Скопировать ник в поле быстрого ответа
+Ответить с цитированием данного сообщения
Aiwan
сообщение Oct 18 2005, 15:29
Сообщение #5


Миловидный Бегрюссунг
Иконки Групп

Класс: Воин
Характер: Chaotic Good
Раса: Человек
NWN: Модмейкер
Проклятие Левора
Порядок Времени



Lex давай обсудим этот вопрос со всеми в отдельной теме. Мне тоже интересно как быстрее делать для кода проверки if...
Вернуться в начало страницы
Скопировать ник в поле быстрого ответа
+Ответить с цитированием данного сообщения
dumbo
сообщение Oct 18 2005, 16:27
Сообщение #6


Level 9
Иконки Групп

Класс: Фея
Характер: Chaotic Evil
Раса: Тварь
NWN: Скриптинг [PW]



вскроем правду:

имеем два скрипта:

1. несколько проверок одного условия.
Neverwinter Script Source
void main()
{
  int i;
  if (i == 0x123) return;
  if (i == 0x321) return;
  if (i == 0x111) return;
  if (i == 0x222) return;
  i = 0x666;
}


2. одна проверка с несколькими условиями.
Neverwinter Script Source
void main()
{
  int i;
  if (i == 0x123 || i == 0x321 || i == 0x111 || i == 0x222) return;
  i = 0x666;
}


компилируем-декомпилируем
1.
CODE

00000008 42 000000D3              T 000000D3
0000000D 1E 00 00000008           JSR fn_00000015
00000013 20 00                    RETN
00000015 02 03                    RSADDI
00000017 03 01 FFFFFFFC 0004      CPTOPSP FFFFFFFC, 0004
0000001F 04 03 00000123           CONSTI 00000123
00000025 0B 20                    EQUALII
00000027 1F 00 00000018           JZ off_0000003F
0000002D 1B 00 FFFFFFFC           MOVSP FFFFFFFC
00000033 1D 00 0000009E           JMP off_000000D1
00000039 1D 00 00000006           JMP off_0000003F
0000003F 03 01 FFFFFFFC 0004      CPTOPSP FFFFFFFC, 0004
00000047 04 03 00000321           CONSTI 00000321
0000004D 0B 20                    EQUALII
0000004F 1F 00 00000018           JZ off_00000067
00000055 1B 00 FFFFFFFC           MOVSP FFFFFFFC
0000005B 1D 00 00000076           JMP off_000000D1
00000061 1D 00 00000006           JMP off_00000067
00000067 03 01 FFFFFFFC 0004      CPTOPSP FFFFFFFC, 0004
0000006F 04 03 00000111           CONSTI 00000111
00000075 0B 20                    EQUALII
00000077 1F 00 00000018           JZ off_0000008F
0000007D 1B 00 FFFFFFFC           MOVSP FFFFFFFC
00000083 1D 00 0000004E           JMP off_000000D1
00000089 1D 00 00000006           JMP off_0000008F
0000008F 03 01 FFFFFFFC 0004      CPTOPSP FFFFFFFC, 0004
00000097 04 03 00000222           CONSTI 00000222
0000009D 0B 20                    EQUALII
0000009F 1F 00 00000018           JZ off_000000B7
000000A5 1B 00 FFFFFFFC           MOVSP FFFFFFFC
000000AB 1D 00 00000026           JMP off_000000D1
000000B1 1D 00 00000006           JMP off_000000B7
000000B7 04 03 00000666           CONSTI 00000666
000000BD 01 01 FFFFFFF8 0004      CPDOWNSP FFFFFFF8, 0004
000000C5 1B 00 FFFFFFFC           MOVSP FFFFFFFC
000000CB 1B 00 FFFFFFFC           MOVSP FFFFFFFC
000000D1 20 00                    RETN


2.
CODE

00000008 42 000000E5              T 000000E5
0000000D 1E 00 00000008           JSR fn_00000015
00000013 20 00                    RETN
00000015 02 03                    RSADDI
00000017 03 01 FFFFFFFC 0004      CPTOPSP FFFFFFFC, 0004
0000001F 04 03 00000123           CONSTI 00000123
00000025 0B 20                    EQUALII
00000027 03 01 FFFFFFFC 0004      CPTOPSP FFFFFFFC, 0004
0000002F 1F 00 00000014           JZ off_00000043
00000035 03 01 FFFFFFFC 0004      CPTOPSP FFFFFFFC, 0004
0000003D 1D 00 00000016           JMP off_00000053
00000043 03 01 FFFFFFF8 0004      CPTOPSP FFFFFFF8, 0004
0000004B 04 03 00000321           CONSTI 00000321
00000051 0B 20                    EQUALII
00000053 07 20                    LOGORII
00000055 03 01 FFFFFFFC 0004      CPTOPSP FFFFFFFC, 0004
0000005D 1F 00 00000014           JZ off_00000071
00000063 03 01 FFFFFFFC 0004      CPTOPSP FFFFFFFC, 0004
0000006B 1D 00 00000016           JMP off_00000081
00000071 03 01 FFFFFFF8 0004      CPTOPSP FFFFFFF8, 0004
00000079 04 03 00000111           CONSTI 00000111
0000007F 0B 20                    EQUALII
00000081 07 20                    LOGORII
00000083 03 01 FFFFFFFC 0004      CPTOPSP FFFFFFFC, 0004
0000008B 1F 00 00000014           JZ off_0000009F
00000091 03 01 FFFFFFFC 0004      CPTOPSP FFFFFFFC, 0004
00000099 1D 00 00000016           JMP off_000000AF
0000009F 03 01 FFFFFFF8 0004      CPTOPSP FFFFFFF8, 0004
000000A7 04 03 00000222           CONSTI 00000222
000000AD 0B 20                    EQUALII
000000AF 07 20                    LOGORII
000000B1 1F 00 00000018           JZ off_000000C9
000000B7 1B 00 FFFFFFFC           MOVSP FFFFFFFC
000000BD 1D 00 00000026           JMP off_000000E3
000000C3 1D 00 00000006           JMP off_000000C9
000000C9 04 03 00000666           CONSTI 00000666
000000CF 01 01 FFFFFFF8 0004      CPDOWNSP FFFFFFF8, 0004
000000D7 1B 00 FFFFFFFC           MOVSP FFFFFFFC
000000DD 1B 00 FFFFFFFC           MOVSP FFFFFFFC
000000E3 20 00                    RETN


note: все нижеописанное имеет силу для проверок типа if (xx) return;

суть: при проверке OR нескольких условий, после первого удовлетворяющегося происходит цепочка "холостых" операций пропусков остальных: LOGORxx, уже дающий 1; невыполняющийся переход JZ xxx; JMP на следущий LOGORxx; и пару-тройку операций работы со стеком. в случае нескольких проверок, первая же удовлетворяющаяся приведет к переходу на return.

в остальных случаях (не "if (x) return") выгодней использовать несколько условий OR. в самом деле - не будете же вы копировать блоки, которые под if'ом стоят?! ;)

да, и уж коль скоро речь идет об оптимизации, то не стоит по сто раз вызывать функции - гораздо быстрее(и компактнее) будет занести результат в переменную и уже ее проверять сто раз.

edit: тэги, как всегда, не позакрывал... ;)

Сообщение отредактировал dumbo - Oct 18 2005, 16:30
Вернуться в начало страницы
Скопировать ник в поле быстрого ответа
+Ответить с цитированием данного сообщения
_kaa_
сообщение Oct 18 2005, 18:54
Сообщение #7


Level 9
Иконки Групп

Класс: Волшебник
Характер: Chaotic Good
Раса: Дракон
NWN: Скриптинг [PW]



В итоге :)
1. Если в условии используется функция, особенно "сложная" - всяческие проверки поля зрения, поиск вещей\игроков, операции с itemproperty и прочее - обязательно запомните результат в переменной и с ней работайте.
2. Для условий типа "И" на первое место ставьте то, что скорее всего будет ложным. Как только до него дойдет - проверка прекратится.
3. Для условий типа "ИЛИ" на первом месте наоборот, наиболее вероятное истинное значение, по тем же причинам.

По сути на производительность как-то заметно влияет только первый пункт, 2й и 3й - это просто "правильный" код :)
Вернуться в начало страницы
Скопировать ник в поле быстрого ответа
+Ответить с цитированием данного сообщения
Aiwan
сообщение Oct 18 2005, 22:32
Сообщение #8


Миловидный Бегрюссунг
Иконки Групп

Класс: Воин
Характер: Chaotic Good
Раса: Человек
NWN: Модмейкер
Проклятие Левора
Порядок Времени



Класс. Давно меня это мучало. Но слишком поздно и я не все вкурил что написано. :yes: С утра перечитаю...
Вернуться в начало страницы
Скопировать ник в поле быстрого ответа
+Ответить с цитированием данного сообщения
2_advanced
сообщение Oct 18 2005, 22:46
Сообщение #9


Level 9
Иконки Групп

Класс: Вор
Характер: True Neutral
Раса: Эльф
NWN: Скриптинг [PW]



нужно делать экспорт функций и использовать с++ :D (хочу нечто в нвн2)
Вернуться в начало страницы
Скопировать ник в поле быстрого ответа
+Ответить с цитированием данного сообщения
Nashman
сообщение Oct 18 2005, 23:27
Сообщение #10


Level 8
***

Класс: Тайный Лучник
Характер: Lawful Good
Раса: Эльф



Если уж речь у вас зашла о языках програмирования, то скажите:
- Dll, Delphi....и прочая фигня будет как-то арботать. Если будет, то скажите как. ОК? :this:
Вернуться в начало страницы
Скопировать ник в поле быстрого ответа
+Ответить с цитированием данного сообщения
Lex
сообщение Oct 18 2005, 23:43
Сообщение #11


Level 5
Иконки Групп

Класс: Обыватель
Характер: Lawful Neutral
Раса: Человек
NWN: Модмейкер
Проклятие Левора
Порядок Времени



QUOTE (2_advanced @ Oct 18 2005, 23:46)
нужно делать экспорт функций и использовать с++ :D (хочу нечто в нвн2)

Эй-эй! Не оффтопим. :) Экспорт С++ программ в нсс это ты в другой теме разрабатывай :)
Вернуться в начало страницы
Скопировать ник в поле быстрого ответа
+Ответить с цитированием данного сообщения
Friedrich
сообщение Oct 22 2005, 20:27
Сообщение #12


Level 5
**

Класс: Рейнджер
Характер: Neutral Good
Раса: Человек



QUOTE (dumbo @ Oct 18 2005, 16:27)
несколько проверок одного условия.

void main()
{
  int i;
  if (i == 0x123) return;
  if (i == 0x321) return;
  if (i == 0x111) return;
  if (i == 0x222) return;
  i = 0x666;
}

Пожалуй, так будет эффективнее всего: ;)
Neverwinter Script Source
void main()
{
  int i = 0x333;
  switch( i )
  {
    case 0x111:
    case 0x222:
    case 0x333:
    case 0x444: return;
  }
  i = 0x666;

}

Или нет? Я в этом не особо шарю, но код по крайней мере короче чем в примерах выше. (Значит лучше?)
CODE
00000008 42 000000AB              T 000000AB
0000000D 1E 00 00000008           JSR fn_00000015
00000013 20 00                    RETN
00000015 02 03                    RSADDI
00000017 03 01 FFFFFFFC 0004      CPTOPSP FFFFFFFC, 0004
0000001F 03 01 FFFFFFFC 0004      CPTOPSP FFFFFFFC, 0004
00000027 04 03 00000111           CONSTI 00000111
0000002D 0B 20                    EQUALII
0000002F 25 00 0000004E           JNZ off_0000007D
00000035 03 01 FFFFFFFC 0004      CPTOPSP FFFFFFFC, 0004
0000003D 04 03 00000222           CONSTI 00000222
00000043 0B 20                    EQUALII
00000045 25 00 00000038           JNZ off_0000007D
0000004B 03 01 FFFFFFFC 0004      CPTOPSP FFFFFFFC, 0004
00000053 04 03 00000333           CONSTI 00000333
00000059 0B 20                    EQUALII
0000005B 25 00 00000022           JNZ off_0000007D
00000061 03 01 FFFFFFFC 0004      CPTOPSP FFFFFFFC, 0004
00000069 04 03 00000444           CONSTI 00000444
0000006F 0B 20                    EQUALII
00000071 25 00 0000000C           JNZ off_0000007D
00000077 1D 00 00000012           JMP off_00000089
0000007D 1B 00 FFFFFFF8           MOVSP FFFFFFF8
00000083 1D 00 00000026           JMP off_000000A9
00000089 1B 00 FFFFFFFC           MOVSP FFFFFFFC
0000008F 04 03 00000666           CONSTI 00000666
00000095 01 01 FFFFFFF8 0004      CPDOWNSP FFFFFFF8, 0004
0000009D 1B 00 FFFFFFFC           MOVSP FFFFFFFC
000000A3 1B 00 FFFFFFFC           MOVSP FFFFFFFC
000000A9 20 00                    RETN


И кстати, если условие - функция, то она вызывается только один раз и переменную заводжить не нужно.

Где-то читал, что где там, где это возможно, лучше юзать switch/case, чем много if-ов.
Вернуться в начало страницы
Скопировать ник в поле быстрого ответа
+Ответить с цитированием данного сообщения
Misty Dragon
сообщение Oct 25 2005, 19:08
Сообщение #13


Level 4
Иконки Групп

Класс: Маг
Характер: Lawful Neutral
Раса: Дракон
NWN: Скриптинг [PW]



Как раз-таки кэйсы намного тяжелее обрабатываются, нежели простая проверка условия. Намного проще прописывать if() else конструкцию, ибо , в принципе, с этой конструкцией и так все ясно. А вот с как кейсы обрабатываться будут, во много зависит от разработчиков интерпретаторов-компиляторов. Это так же верно и для скриптов, ибо они все равно транслируются в байт-код(в нормальных скриптовых системах :) ). По поводу использования переменных.
Порой лучше пожертвовать некоторым объемом памяти для скорости. Например GetModule(). В общем, непонятно, как и откуда берется хендл, по этому лучше такой вызов вынести отдельно. Например в событие загрузки модуля: PW_oMod = GetModule()(Это касается так же GetPCSpeaker() и подобных функций). А потом уж использовать PW_oMod. Что касается условий переходов, то следует минимизировать вычисления. Даже логические конструкции можно упростить.
И если уж создаете глобальные переменные, то старайтесь их использовать по максимуму ибо у сервера постоянные лики памяти(одна из причин возникновения лагов). Полезно будет также глянуть и растактовку команд процессора. :)

Сообщение отредактировал Misty Dragon - Oct 25 2005, 19:14
Вернуться в начало страницы
Скопировать ник в поле быстрого ответа
+Ответить с цитированием данного сообщения
dumbo
сообщение Oct 26 2005, 12:04
Сообщение #14


Level 9
Иконки Групп

Класс: Фея
Характер: Chaotic Evil
Раса: Тварь
NWN: Скриптинг [PW]



Misty Dragon, ничего не понял из твоего поста... :xz:

QUOTE (Misty Dragon @ Oct 25 2005, 20:08)
Как раз-таки кэйсы намного тяжелее обрабатываются, нежели простая проверка условия. Намного проще прописывать if() else конструкцию, ибо , в принципе, с этой конструкцией и так все ясно.

о чем идет речь - о простоте восприятия, "прописывания" или о скорости выполнения?
что характерно, сие высказывание неверно в любом случае. ;) если говорить вообще(безотносительно nss), то switch в грамотных реализациях гораздо "легче" выполняется нежели куча if'ов - switch=один безусловный переход, if'ы=сколько if'ов, столько и условных переходов(не будем вдаваться в тонкости, просто отметим, что условный переход хуже безусловного).

QUOTE (Misty Dragon @ Oct 25 2005, 20:08)
А вот с как кейсы обрабатываться будут, во много зависит от разработчиков интерпретаторов-компиляторов

зависит, и не во многом, а во всем ;) бродило мнение, что nss-switch плох, потому что он является по сути множественным if'ом... а вот судя по "декомпиле" Friedrich'а, оказывается, что он действительно раскладывается на много if'ов, но код генерится гораздо более приятный! :crazy:

QUOTE (Misty Dragon @ Oct 25 2005, 20:08)
По поводу использования переменных. Порой лучше пожертвовать некоторым объемом памяти для скорости.

опять не понял(экий непонятливый;)) - о каких переменных идет речь? глобальных переменных в nss нет. максимальный размах - файл скрипта. переменные скрипта лежат в стэке виртуальной машины, который очистится после окончания работы скрипта. если речь идет о "глобальных" переменных, которые получаются путем SetLocalXXX(GetModule(),.., то непонятен смысл занесения в оные самого хэндла модуля...

QUOTE (Misty Dragon @ Oct 25 2005, 20:08)
И если уж создаете глобальные переменные, то старайтесь их использовать по максимуму ибо у сервера постоянные лики памяти(одна из причин возникновения лагов).

вот хоть тресни, а не могу понять, что именно ты хочешь сказать. какая связь между "глобальными переменными" и утечками памяти?

ну и наконец, апофеоз этого поста:
QUOTE (Misty Dragon @ Oct 25 2005, 20:08)
Полезно будет также глянуть и растактовку команд процессора.

НУ ПРИЧЕМ ЗДЕСЬ РАСТАКТОВКА КОМАНД ПРОЦЕССОРА?! 8(
Вернуться в начало страницы
Скопировать ник в поле быстрого ответа
+Ответить с цитированием данного сообщения

Ответить в эту темуОткрыть новую тему
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 



Текстовая версия Сейчас: 28th March 2024 - 19:40