NedoLang: Ускорение
...а также демократизация и гласность
Alone Coder
Были наивные надежды уложить полную са─
мокомпиляцию в одну минуту на Z80@3.5 MHz.
Понятно, что можно перекопилировать каждый
модуль по отдельности (только ассемблиро─
вать вместе), но в TR-DOS нет метки време─
ни, а новую ОС пока писать некогда.
Кстати, метка времени должна быть очень
точной - лично я часто запускаю перекомпи─
ляцию, точности в 2 секунды не хватает. К
тому же,у неё всегда проблемы при переносе
с компьютера на компьютер. А поля "номер
версии файла" я не видел ни в одной файло─
вой системе. Как,кстати,и возможности под─
клеивать символы в начало файла, чтобы при
редактировании файла в среде разработки он
всегда был синхронизирован с файловой сис─
темой (как два куска: до курсора и после).
Причём я не хотел переписывать компиля─
тор на ассемблере,хотя сейчас это уже про─
сто - вручную оптимизировать то, что выда─
ёт компилятор. Но так бы я его не портиро─
вал на ARM.
В первую очередь надо было ускорить по─
иск меток и лексер. Вот что учёные пишут
про скорость лексеров:
"A study by Waite[1373] found 41% of
total translation time was spent in a
handcrafted lexer (with little code
optimization performed by the translator).
An automatically produced lexer, the lex
tool was used, consumed 3 to 5 as much
time."(cbook1_0.pdf, p. 232)
То есть нормальный лексер занимает 41%
времени компиляции,а если он автоматически
сгенерирован из описания синтаксиса, то
вообще труба.
27.03.2017:
- сделал передачу параметра через бей─
сик-переменнуюa$.
Стандарт "Command-line friendly" в
TR-DOS (см. ACEdit ) нельзя использовать с
кодовыми файлами - послеCODE не получает─
ся ввести дополнительные параметры даже с
разделителем, или : (вообще ни с каким),
даже если указать 2 числовых параметра.
Единственный работающий разделитель -
OxOd, но его нельзя ввести с клавиатуры.
Можно RUN "filename blablabla"CODE, но
как отследить адрес дополнительного текс─
та, особенно при вызове из бейсика?
- ускорял компилятор,токенизатор,ассемб─
лер и экспортёр на Speccy, в целом ускоре─
ние в несколько раз:
┌────────────────────────────────────────┐
compile.c (здесь и ниже всегда одна и та
же копия) компилит 151 секунду (no delays)
тогда все модули компилятора будут
151 с * 152k/48k = 478 секунд
оптимизировал поиск меток:
теперь компилирует 44.86 секунд(no delays)
заменил хэш-функцию:
теперь компилирует 43.72 секунд(no delays)
почистил readchar:
42.68 - неточно, т.к. не обнулил FRAMES
убрал waseol:
42.08
оптимизировал сравнение в readcomment:
41.08
инлайн readcomment:
41.08 (т.е. нет выигрыша)
замена _tword[_FIRST] на *(PCHAR)_tword
40.96
упростил логику после readcomment:
40.68
убрал _tword[_FIRST]==_DIERESIS:
40.66
убрал _docomment: 40.34
isnum по таблице: 40.18
isalpha по таблице: 39.86
isalphanum по таблице: 38.18
isalphanum инлайн в readconcattword:
37.56
ускорил strjoin: 36.02
strcopy через асмолибу: 35.5
strpush через strcopy: 34.88
strpop через strcopy: 33.86
убрал терминатор в strjoin: 33.74
заменил где можно strjoin на strcopy:
32.44
в read инлайном strclose: 32.12
в compile инлайном strclose: 32.12
(т.е. нет выигрыша по скорости, только по
размеру)
strjoin через асмолибу: 31.12
ещё ускорил (на 4t в цикле,теперь 67t):
31.08/31.2
ещё ускорил (cpir + ldir):
31/31.08/31.02/31.1/31.16 (чем дольше жмём
NumLock в эмуляторе, тем больше время)
обход логики readcomment: 30.8
ещё ускорил isnum: 30.8
isnum инлайн: 30.78
убрал isalpha,а isalphanum через табли─
цу bool везде инлайн: 30.06
время readfin (bd75) = обычно 450 t
(включая вызов) * 49870 b = 22441500 t =
6.4 с (пусть 7) - ускорил до обычно 95 t
(включая вызов)
время fwrite (62bf) = обычно 243 t
(включая вызов) * 61452 b = 14932836 t =
4.3 с (пусть 5)
итого время файловых операций пусть 12 с
токенизатор асма из экспортёра 52.98 с
(надо ускорить сравнения строк - а) через
хэш, б) разрешить команды только с табом и
проверять пару символов)
после того, как убрал _docomment: 53.26
обход логики readcomment: 53.3
isnum инлайн: 53.08
убрал isalpha, а isalphanum через таб─
лицу bool везде инлайн: 52.58
проверка команд требует _asmspcsize!=0:
44.18
сортируем проверку команд по частоте:
31.32
экспорт на tok.f из экспортёра: 15.38
время работы ассемблера на tok.f из
экспортёра (55424 байта (3715 строк, 578
меток) против 203175 (13015 строк, 1645
меток) у компилятора):
33 секунды на 2 прохода
после оптимизации чтения и записи полу─
чилось 19.86 секунд (3640 строк)
итого 183 строки в секунду
замена хэш-функции в поиске меток: 18.7
└────────────────────────────────────────┘
28.03.2017 - ускорил ещё в раза в пол─
тора:
┌────────────────────────────────────────┐
отсортировал проверки в cast: 29.68
отсортировал проверки в push, pop,
сравнениях, убрал char и bool в сравнениях
больше-меньше (исключил ошибку сравнения
знаковых char): 30
отсортировал проверки в вызовах и лог.
операциях, убрал char и int в лог.
операциях: 30.06/29.86
сделал обход лишних операций в eat_cmd:
29.66
пробовал быстрый выход из eat_expr и
т.п. по ')' - нет выигрыша (убрал)
переделал eat_expr и т.п. в процедуры:
29.68
отсортировал операции в eat_expr и т.п:
29.62
в eat_expr и т.п. вместо && поставил
if..if..if: 29.54
убрал лишнее сравнение в let: 29.4
в eat_sumval,eat_mulval убрал dbl и
сделал if..if: 29.52 (заодно убрал ^^)
ускорил проверку числового формата:
29.34
в readchar сделал if..if: 29.02
в readchar присваивание wasdieresis в
разных местах: 28.64
в readchar присваивание wasescape в
разных местах: 28.36
в readchar сделал сравнения на верхнем
уровне по одному символу: 27.4
в readchar (rdch) быстрый выход: 26.18
(сильно увеличилась память под метки и
вырос размер на 104 байта)
в rdch инлайн stradd: 25.22
убрал noskip: 25
исправил оптимизацию условия в
eat_repeat: 24.66
упростил хэш-функцию: 23.68
поиск меток через strcp (асм),
добавление меток через strcopy: 22.78
вернул _docomment: 22.84
итого 70 строк в секунду (1590 строк)
токенизатор асма из экспортёра 52.98 с
(надо ускорить сравнения строк - а) через
хэш, б) разрешить команды только с табом и
проверять пару символов)
после того, как убрал _docomment: 53.26
обход логики readcomment: 53.3
isnum инлайн: 53.08
убрал isalpha, а isalphanum через
таблицу bool везде инлайн: 52.58
проверка команд требует _asmspcsize!=0:
44.18
сортируем проверку команд по частоте:
31.32
после всех оптимизаций read: 23.62
strcp в асмолибе: 22.4
вернул _docomment: 21.88
итого 160 строк в секунду (3518 строк)
экспорт на tok.f из экспортёра: 15.2
через writestr: 7.38
итого 500 строк в секунду (3518 строк)
время работы ассемблера на tok.f из
экспортёра с новым экспортёром: 18.02
asmwordpopvalue через fwrite: 17.6
asmbytepopvalue через writefout: 17.94
_nvalues как byte: 17.7
инлайн asmpopvalue, без проверки: 17.44
фикс оптимизации условия в eat_repeat:
16.82
упростил хэш-функцию: 15.82
поиск меток через strcp (асм): 14.74
добавление меток через strcopy: 14.24
итого 250 строк в секунду (3518 строк)
└────────────────────────────────────────┘
29.03.2017:
- ещё небольшие ускорения:
компилятор - 82 строки в секунду (было 70)
токенизатор-178 строк в секунду (было 160)
ассемблер - 292 строки в секунду(было 250)
- сделал nedotrd, чтобы мог разрезать
большие файлы по стандарту последователь─
ных файлов TR-DOS (не через расширение, а
через младший байт start), и чтобы 3-сим─
вольное расширение не попадало на диск.
Придумать другой стандарт разрезания,чтобы
не трогал ни расширение, ни start? разве
что имя? Или переключать второй символ
расширения терпимо - поддержать в либе 3-
символьное расширение?
30.03.2017:
- совсем небольшие ускорения:
компилятор - 88 строк в секунду (было 82)
токенизатор-209 строк в секунду (было 178)
31.03.2017:
- автоматизировал автосборку NedoLang на
Speccy: параметры (уже не один) передаются
через REM в Бейсике. Размер Бейсика на
пределе. Ещё для этого пришлось сделать
восстановление после RUN "" CODE (глюк в
TR-DOS,описанный у Федина).
- время самокомпиляции для всего проекта
compile:
comp: 41.68
tok: 46.04 - 45.92
asm: 54.28 - 54.04
итого: 142
это из 4814 строк на недоланге (141447
байт) и 998 строк на ассемблере (16117
байт). То есть общая скорость сборки 41
строка в секунду (1,1 КБ/с).
- для всего проектаasm:
comp: 22.38 (много комментов в fmttg)
tok: 23.68
asm: 37.22
итого: 83.28
- для всего проектаtok:
comp: 28.10 (много комментов в fmttg)
tok: 29.40
asm: 37.66
итого: 95.16
- багфиксыDIVLONG и MULLONG
03.04.2017:
- небольшие ускорения самосборки всей
системы:
для проекта compile - 138 (было 142)
для проекта asm - 79 (было 83.28)
для проекта tok - 93 (было 95.16)
04.04.2017:
;; не работал после строки, которая
оканчивается на; - сбросилwaseols
исправил команду после метки в одной
строке
05.04.2017: написал минидему в Nedo─
Lang. Изометрический движок сначала писал─
ся в C++ Builder, потом перенесён в Nedo─
Lang.
06.04.2017:
- добавил библиотеку ptЗplay и вставил
в минидему (теперь она называется NedoGift
и в ней участвуют ещё несколько человек,
инициатор -Sand/MAYhEM ).
- добавил утилиту nedodefb, пока ассемб─
лер не поддерживаетincbin (include тоже -
он просто ассемблировал цепочку файлов,
заданную в параметрах).
- добавилNEG.
- исправил формат команд_FMTCBCMDIDX.
- исправилI,R.
- исправил рекурсию в выражениях в то─
кенизаторе.
- добавил проверку) в if.
07.04.2017:
- небольшое ускорение самосборки(compile
на 4 секунды, asm на 1 секунду). Встал
вопрос сокращения числа конструкций типа
/*...*/ .Как сделать размер массива объяв─
ленной константой (Си не умеет размер гло─
бального массива из const)? Константы ге─
нерятся с точкой. Как вычислить одну кон─
станту из другой? Даже если поддержать вы─
читывание скобок, то константы генерятся с
точкой.
Проще сделать #define без параметров?
Но тогда надо сделать вreadconcattword
(или толькоreadtword ?)чтение из буферной
строки вместо файла.
08.04.2017:
- небольшое ускорение самосборки(compile
на 7 секунд, asm на 4 секунды).
Если переставить точки с неточками, то
будет пересекаться с метками в либе (хотя
можно их тоже с точками), с метками свитча
(а как к ним приклеить точку?), ещё будет
проблема приклеивать-отклеивать неймспей─
сы, ещё и два раза писать константу - в
#define и вconst !
Проще реализовать#define на уровне ле─
ксера.
09.04.2017:
- добавил в NedoGift анализатор музыки,
параллельно переводил процедуры из Nedo─
Lang в NedoAsm для скорости. До этого я
таким методом писал Billiard в EvoSDK.
А
Б
В
Г
Д
Е
Ж
10.04.2017:
- ещё ускорил самосборку за счёт компи─
ляции констант прямо в команду (сравнения
или сложения) и ускорения адресации масси─
вов (сложение вместо сдвига):
для проекта compile - 122.30 (было 126.62)
для проекта asm - 70.26 (было 74)
для проекта tok - 82.68 (было 93)
Общая скорость сборки получилась 41 строка
в секунду.
Как ускорять дальше:
а)упростить компилятор
б)ускорить или убрать токенизатор
в)сделать однопроходный асм?
г)улучшить кодогенерацию? не факт, что
это ускорит сборку
д)убрать специфические процедуры в
стартап асмом (напр.,rdtword, genautonum)
е)добавить подсказкуREGISTERдля
кодогенератора
11-13.04.2017: доделал NedoGift, потом
13-15.04 вносил последние штрихи от соав─
торов и отправил поздравлянту (тов.LVD ),
потом17-20.04 оформлял релиз с фиксами по
отзывамLVD.
Other articles: