schuler, А должна быть разница в профайле, про шедулер слыхал что такое поточное квантование ? Что за школосходка!?
Ahimov, В Delphi 7 нет встроенного профайлера, замерял через GetTickCount, а надо было через QueryPerformanceCounter ? Какое поточное квантование? с школьным уровнем 9го класса, конечно не слышал. Просто ковырялся в старье начала 2000х годов и нарвался на этот код
schuler, Понятно, сразу бы сказал. Замер профайла бывает двух видов. Первый реализован архитектурно - взводится высокопр. таймер, он вызывает прерывания. Процедура обработки берет адрес останова потока и матем. индексирует счетчик в адресном массиве. Так мы видим где задача, тоесть поток провел больше времени. Мы это называем - обеспечить покрытие кода(cover). Второй тип - замер в цикле. Но тут нужно понимать что есть задача, поток и это дискретно. Система дает квант времени, затем забирает примерно 20ms задача исполняется, затем уходит в сон. Замер в цикле ты увидешь поточное квантование и и расчет производительности будет неверен, матем ошибка без учета планирования. Простой пример - есть решения, это конструкторы, с виксов. Ты на вход даешь код, он формирует граф и пересобирает код назад, обычно мутация еще, но не суть. Так для оптимизации сборки необходим механизм BDO, тут есть моя тема и я нашел решение. Но не суть - использовался примитивный механизм, уменьшаем ветвление и ребилдим весь граф. Был использован профайлер, который показал этот косяк. Наверно много написал, сорян за опечатки я с сенсора
Ты сделал мой день. У индия к сожалению перья не держатся, приходится постоянно втыкать по делу и без.
Если хотите измерить время выполнения блока кода, просто создайте для этого благоприятную среду. Тогда и планировщик может не отобрать 30 мл/сек квант вашего потока. Шедулер передаёт управление только активным потокам в очереди, которые реально исполняются на данный момент. Если у вас открыто хоть 100 окон с разными приложениями, но все они находятся в фоне, планировщик не переключится ни на один из них, а будет постоянно отдавать квант только вашему профайлеру, окно которого висит на переднем плане. Но если в момент тестов у вас параллельно идёт, например, длительное копирование данных, тогда система отберёт ваш квант, и на такое-же время передаст его потоку копирования, после чего опять вернёт его вам. В общем случае нужно: 1. Включить в биосе таймер HPET, чтобы получить от QueryPerfFreq() макс частоту 14 МГц. 2. Закрыть все остальные приложения 3. При помощи SetProcessAffinityMask(-1,1) оставить только 1 ядро ЦП 4. Установить высокий приоритет своему потоку через SetPriorityClass(-1,HIGH_PRIORITY_CLASS), тогда у вас точно не отберут квант. 5. Перед каждым замером очищать конвейер ЦП, например инструкцией lfence или cpuid. 6. Иметь ввиду, что профилирование кода любыми методами не даёт 100% результата - всегда имеется погрешность. Вот небольшое приложение на fasm'e, которое измеряет длительность инструкций rdtsc, lfence, и api Sleep(500). Каждый тест производится не 1, а 5 раз подряд, после чего нужно выбрать наибольшее значение. Код показывает и частоту счётчика QPC - если она меньше 10 Мгц, значит HPET в системе не работает, и нужно включить его через bcd.
Первый адоб фотошоп был написан на паскале. Код (Pascal): {Photoshop version 1.0.1, file: Huffman.pas Computer History Museum, www.computerhistory.org This material is (C)Copyright 1990 Adobe Systems Inc. It may not be distributed to third parties. It is licensed for non-commercial use according to www.computerhistory.org/softwarelicense/photoshop/ } PROGRAM Huffman; TYPE PNode = ^TNode; TNode = RECORD leaf: BOOLEAN; code: INTEGER; entry: INTEGER; branch: ARRAY [0..1] OF PNode END; Str255 = STRING [255]; VAR id: INTEGER; root: PNode; word: Str255; code: INTEGER; entry: INTEGER; PROCEDURE AddCode (node: PNode; code: INTEGER; VAR word: Str255); VAR branch: INTEGER; BEGIN IF LENGTH (word) = 0 THEN BEGIN IF node^.leaf OR (node^.branch [0] <> NIL) OR (node^.branch [1] <> NIL) THEN BEGIN WRITELN ('? Conflict for code ', code:1); EXIT (PROGRAM) END; node^.leaf := TRUE; node^.code := code END ELSE BEGIN IF word [1] = '0' THEN branch := 0 ELSE IF word [1] = '1' THEN branch := 1 ELSE BEGIN WRITELN ('? Invalid word for code ', code:1); EXIT (PROGRAM) END; DELETE (word, 1, 1); IF node^.branch [branch] = NIL THEN BEGIN NEW (node^.branch [branch]); node^.branch [branch]^.leaf := FALSE; node^.branch [branch]^.branch [0] := NIL; node^.branch [branch]^.branch [1] := NIL END; AddCode (node^.branch [branch], code, word) END END; PROCEDURE NumberNode (node: PNode); BEGIN node^.entry := entry; entry := entry + 1; IF node^.branch [0] <> NIL THEN NumberNode (node^.branch [0]); IF node^.branch [1] <> NIL THEN NumberNode (node^.branch [1]) END; PROCEDURE WriteHexDigit (x: INTEGER); BEGIN IF x <= 9 THEN WRITE (x:1) ELSE WRITE (CHR (ORD ('A') + x - 10)) END; PROCEDURE WriteHex (x: INTEGER); BEGIN WriteHexDigit (BAND (BSR (x, 12), $F)); WriteHexDigit (BAND (BSR (x, 8), $F)); WriteHexDigit (BAND (BSR (x, 4), $F)); WriteHexDigit (BAND (x, $F)) END; PROCEDURE WriteNode (node: PNode); BEGIN WRITE (' $"'); IF node^.leaf THEN WriteHex (node^.code) ELSE WriteHex (-1); WRITE (' '); IF node^.branch [0] <> NIL THEN WriteHex (node^.branch [0]^.entry) ELSE WriteHex (-1); WRITE (' '); IF node^.branch [1] <> NIL THEN WriteHex (node^.branch [1]^.entry) ELSE WriteHex (-1); WRITELN ('"'); IF node^.branch [0] <> NIL THEN WriteNode (node^.branch [0]); IF node^.branch [1] <> NIL THEN WriteNode (node^.branch [1]) END; BEGIN NEW (root); root^.leaf := FALSE; root^.branch [0] := NIL; root^.branch [1] := NIL; READLN (id); WHILE NOT EOF DO BEGIN READ (code); READLN (word); WHILE (word [1] = ' ') OR (word [1] = CHR (9)) DO DELETE (word, 1, 1); WHILE (word [LENGTH (word)] = ' ') OR (word [LENGTH (word)] = CHR (9)) DO DELETE (word, LENGTH (word), 1); AddCode (root, code, word) END; entry := 0; NumberNode (root); WRITELN ('data ''HUFF'' (', id:1, ', purgeable)'); WRITELN (' {'); WriteNode (root); WRITELN (' };') END.
Собрал сишный исходник с помощью gcc. Код (Text): @echo off cd C:\Users\Admin\Desktop "C:\Program Files\CodeBlocks\MinGW\bin\gcc.exe" Game_v1.c -o Game.exe -lgdi32 -luser32 -lkernel32 -mwindows -Os -s -ffunction-sections -fdata-sections -Wl,--gc-sections if %errorlevel% == 0 ( echo Success! Running game... Game.exe ) else ( echo Compilation failed! ) pause Выхлоп: 25,5 КБ. Тот же самый код на pascal: 23,5 КБ. --- -- Подозреваю, что есть какие то еще магические способы компиляции, уменьшающие размер .ехе, без танцев с бубном.
Вместо сбора секций можно было LTO обойтись, не? (-flto) Ну и говоря о еще меньшем размере, Цэ/Плюсы то будет попроще без стандартных библиотек собрать, чем Паскали.
Ехе собирался батником который сгенерировал дипсик. Интересно можно ли изменением .bat файла собрать .ехе меньшего размера. Код (Text): @echo off cd C:\Users\Admin\Desktop "C:\Program Files\CodeBlocks\MinGW\bin\gcc.exe" Game_v1.c -o Game.exe -lgdi32 -luser32 -lkernel32 -mwindows -Os -s -ffunction-sections -fdata-sections -Wl,--gc-sections if %errorlevel% == 0 ( echo Success! Running game... Game.exe ) else ( echo Compilation failed! ) pause Какое-то очень всратое впечатление о си. Там где в паскале достаточно в uses указать нужные файлы, в си нужно сразу 10 вещей делать. Нужно гадать с какими параметрами собирать исходник. Это для удобства сделано? --- Сообщение объединено, 13 июн 2026 в 09:45 --- Ехе стал меньше на 0,5 кб. Вместо 25,5 КБ -> 25 КБ. Думал что на си будут какие то радикальные изменения, типа ехе в 7 КБ, но не 25 же.
Tech, Размеры двух яп нельзя сравнить, так си использует импорт системных длл. Например для печати дробных чисел вызывается процедура из ртл, в нэйтив нет возможности печати математики(printf() не полноценна). В паскале это возможно билдится сразу, сравнение не корректно. На счет мин размера есть тема, там выполнен анализ загрузчика. дипсик сломали, из за перегрузки серверов выключили доступ в сети и файлы
Tech, Попробуй распечатать 1/3, поймешь о чем я. Может на счет билда не точно, я не знаю как у дельфи. Можешь проверить. Системная ntdll.Xprintf не поддерживает /e, f
Ты недавно говорил: Просто перепиши это: Чтобы был норм эффект. Для человека который все до инструкций понимает, это вообще не проблема. Просто батник, без всякой умной херни про ядро и драйвера.
Tech, Так ты делаешь чепуху, не рассматривая содержимое файлов, сравниваешь размер. Может там вообще область без ничего в 20кб. Сишное приложение завязано на системные длл, соотв. оно в любом случае меньше размером, тк часть кода уже встроена в систему. Открывай дизом и смотри содержимое. > Просто перепиши это: Это не работает на андроиде, параметры описаны в спецификации. Если лень читать, спроси у бота. Мне за тебя это делать не интересно.
Минимальный размер хеллоу ворлда будет 4кб без объединения секций. --- Сообщение объединено, 13 июн 2026 в 15:34 --- Код (C): #include <windows.h> void EntryPoint() { MessageBoxA(NULL, "Hello World", "Hello World", MB_OK); ExitProcess(0); } Код (Text): x86_64-w64-mingw32-gcc -o ./test.exe -O3 -Os -flto -nostdlib -s ./test.c -eEntryPoint -lkernel32 -luser32 wine ./test.exe Код (Text): > ls -l -rw-r--r-- 1 user user 124 июн 13 15:26 test.c -rwxr-xr-x 1 user user 3584 июн 13 15:31 test.exe -rw-r--r-- 1 user user 101 июн 13 15:30 test.sh
Tech, Сказки дядюшки Римуса о x64 → Глава третья. Как Братец Кролик уменьшал размер программы MessageBox 2560 байт → 298 байт
У него есть исходник. Зачем ему еще открывать дизом? Имхо, он и без тебя школьника знает, что параметры описаны в спецификации.
у вас исходник(не знаю про какой именно вы говорите) проходит линковщик и загрузчик. а возможно и компилятор. поэтому исходик хорошо, но реальность она не всегда в исходнике.