Page 1 of 1

Оптимизация кода

Posted: Fri Jul 13, 2007 9:48 am
by blueboar
Здравствуйте.

Просмотрел тут программы для KOS и ужаснулся.
Абсолютно неоптимизированный код.

Почти всегда MOV EAX, 00000001 вместо PUSH 1 / POP EAX
и так далее.

Вы ведь можете уменьшить Колибри раза в полтора, если
захотите. Я понимаю, у вас есть паковщик, но все равно
программы станут меньше.

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

Posted: Fri Jul 13, 2007 9:55 am
by vectoroc
если бы ты внимательнее читал, то мог бы заметить

Code: Select all

macro mov arg1,arg2
 {
   if (arg1 in __regs) & ((arg2 eqtype 0) | (arg2 eqtype '0'))
      if (arg2) = 0
	 xor arg1,arg1
      else if (arg2) = 1
	 xor arg1,arg1
	 inc arg1
      else if (arg2) = -1
	 or  arg1,-1
      else if (arg2) > -128 & (arg2) < 128
	 push arg2
	 pop  arg1
      else
	 mov  arg1,arg2
      end if
   else
      mov arg1,arg2
   end if
 }
в macros.inc
В общем если интересна оптимизация можешь начать присматриваться с этого файла ;)
Насчёт полтора раза ты помоему перегнул

Posted: Fri Jul 13, 2007 10:58 am
by Serge
blueboar

Оптимизация бывает разная. Есть по размеру а есть по скорости. Кому как нравится.

Posted: Fri Jul 13, 2007 12:29 pm
by diamond
blueboar
Ага, есть неоптимальный код. Но есть и код, близкий к оптимальному. В качестве примера посмотри, например, на приложение end.
Насчёт уменьшения раза в полтора - это вряд ли.
Кстати, следует учитывать, что фактически любой файл занимает целое число секторов...
Если нужно, я готов составить файл со списком программ,
где напишу возможные улучшения для каждого вплоть
до номеров строк.
Мы будем только рады :) Единственное, что не стоит оптимизировать по размеру код, критичный по скорости, но такого довольно мало. Если умеешь работать с svn, попроси mike.dld выделить аккаунт в Колибри-репозитории и работай прямо там; если нет, можешь в качестве альтернативы к выкладыванию файла различий просто послать оптимизированный вариант тому же mike.dld или мне, контакты можно узнать, например, на kolibrios.org.

Posted: Fri Jul 13, 2007 3:45 pm
by Serge
А ещё надо учитывать что в памяти программа занимает целое число страниц и накладные расходы памяти на выполнение программы end раз в сорок больше самой программы

Posted: Fri Jul 13, 2007 5:57 pm
by blueboar
Ну хорошо, насчет MOV EAX, 1 я действительно не заметил. Но вот код, который есть почти в каждой программе

still: ; MAIN PROGRAM CYCLE

mov eax,10 ; wait for event
mcall

cmp eax,1 ; redraw? -
je red ; goto red
cmp eax,2 ; key pressed? -
je key ; goto key
cmp eax,3 ; button pressed? -
je button ; goto button

jmp still ; no more events to process


Почему нельзя было заменить все эти CMP на DEC EAX / JZ?

PS: Посмотрел повнимательнее - действительно, такой код есть примерно в половине программ. В половине (в той же END) он действительно заменен на DEC/JZ. Но что мешало заменить его и во второй половине?

Posted: Fri Jul 13, 2007 6:40 pm
by blueboar
Вот для примера код игры "15". Кое-какие оптимизации могут оказаться неправильными, но хотя бы
появятся вопросы для обсуждения. Про STILL я уже говорил. Кроме того.

Строка 66
mov cl,16
ror eax,cl

--> ror eax, 16

Строка 118
cmp eax,176
jl still
sub eax,176
cmp eax,3
ja still
movzx eax,byte [eax+correct] ; 'delta' value from correct[]
jmp m_check

-->
sub eax,176
jc still
cmp eax,3
ja still
movzx eax,byte [eax+correct] ; 'delta' value from correct[]
jmp m_check

Строка 416
cmp ecx,0
jne no_win

--> or ecx, ecx

Posted: Fri Jul 13, 2007 9:55 pm
by Quantum
blueboar
Кое-какие оптимизации могут оказаться неправильными
Это очень важный момент! В погоне за уменьшением размера/увеличением скорости запросто можно внести кучу новых багов. Оптимизировать нужно крайне осторожно, всегда помечая в контроле версий что, где и зачем было переписано.

Posted: Mon Jul 16, 2007 11:28 am
by ALLiGaToR
А может просто разработчикам программ самим оптимизировать код? + также пересмотреть содержание программ на самой ОС (точнее на дискетке с ОС)?

Posted: Tue Jul 17, 2007 11:52 am
by diamond
Почему нельзя было заменить все эти CMP на DEC EAX / JZ?

PS: Посмотрел повнимательнее - действительно, такой код есть примерно в половине программ. В половине (в той же END) он действительно заменен на DEC/JZ. Но что мешало заменить его и во второй половине?
По историческим соображениям. Изначально много программ были написаны Ville, а многие другие программы - по этому образцу. В результате получился код с cmp. Позже были оптимизации, в частности, временами лично я выбирал программу, занимающую 512*n+epsilon байт и оптимизировал до состояния 512*n-epsilon :) В некоторых программах замену на dec/jz сделал Heavyiron заодно с перерисыванием на использование новых заголовков/системных вызовов.

Posted: Tue Jul 17, 2007 8:17 pm
by bw
Интересно. Как вы отнесетесь к тому коду который начнет выходить из под пера компиляторов высокоуровневых языков :-).

..bw

Posted: Wed Jul 18, 2007 7:26 am
by Mario79
bw
Будем дизассемблировать, и править, править, править...

Posted: Wed Jul 18, 2007 9:58 pm
by mike.dld
Преждевременная оптимизация - сами знаете что такое. А у меня ни одну программу язык не поворачивается назвать хотя бы более-менее законченной. Оптимизация хороша и заметна в критичных алгоритмах, таких как, например, сортировка. А в основном народ пишет код, чтобы его потом понимать и иметь возможность сопровождать, а не чтобы на него смотрели и не понимали, как оно работает и как что-то исправить.

Posted: Sat Jul 28, 2007 1:11 pm
by smb-
To Mario79
Знать бы, что править ;)
Высокоуровневые компиляторы очень хорошо выполняют кучу рутины - типа, выравнивания команд/операндов/переходов по словам и распихивания по регистрам. Да и одних оптимизаций циклов можно штук 5 придумать - кому охота с этим заморачиваться вручную?

Для всяких высокоуровневых конструкций давно известны оптимальные аналоги на ASM.

To Ленин
Грамотно. Согласен.

Posted: Mon Jul 30, 2007 12:45 am
by andrew_programmer
Насчёт оптимизации...

Занимался я как-то портированием TinyC в Колибри. Там вывод сообщений об ошибках производится посредством функции printf(). Я долго не мог понять, почему же не выводятся сообщения от компилятора. Потратил кучу времени и нервов. А оказалось, что компилятор GCC САМОВОЛЬНО подменял функции printf() на puts(). Но так как puts() ещё небыла реализована в menuetlibc, то никаких сообщений от компилятора не поступало. С точки зрения оптимизации эта подмена правильная, с точки зрения нервов программиста и надёжности скомпилированного кода - нет.

Так что доверяйте компиляторам языков высокого уровня, но проверяйте сгенерированный код !