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.