Проведено несколько десятков экспериментов: 1) разные машины,от 486 75 МГц до П-4 3600; 2) разные ОСи - от Вин95 до ХП; 3) разные языки и компиляторы. Измерялось время работы "пустого" программного цикла, при этом: 1) методы измерения - RDTSC, QueryPerformanceCounter, внешний монитор; 2) все посторонние дивайсы (типа сетевух и звуковых) убирались; 3) все посторонние процессы по возможности грохались. Было два сорта экспериментов - для нормал_приорити и для тайм_критикал. Собирались большие статистики - по нескольку миллионов отсчетов (общие продолжительности циклов - от нескольких секунд до минуты). При этом больших буферов не использовалось, чтобы не провоцировать подкачку страниц. Для каждого эксперимента строились гистограммы времени выполнения и (иногда, чтобы понять общую картину) трассы. Примерные картинки оказались одинаковыми - см. в аттаче. Погмогите понять результаты. 1. Что это за пимпочка в районе десятков миллисекунд для нормал приорити? 2. Что это за мусор < 1 mc для нормал приорити? 3. Откуда периодичность, по крайней мере больших выбросов (единицы миллисекунд) для нормал приорити? 4. Куда делись мусор и миллисекундные выбросы для тайм критикал? 5. Почему пимпопчка сильно перехала вправо для тайм критикал? У меня есть свои ответы, но хотелось бы услышать мнение ALL-а. _1934442892__hist.gif
А что ты имеешь в виду под "пустым программным циклом"? Если что-то типа Код (Text): timestamp(); for (int i = 0; i < 1000000; ++i) ; timestamp(); то это не тест а чушь. Весь код (4...5 инструкций) попадают в cache к процессору и исполняются ну просто невероятно быстро - обращений к памяти нету, к железу нету, API calls тоже нету. То есть ты получаешь синтетический максимум производительности который мало что общего имеет с реальностью. P.S. scheduler в виндузах кстати лажёвый, поэтому производительность лучше мерять на линуксе с ядром 2.6.1х в котором куча real time patches.
Ну хоть кто-то откликнулся. s0larian Нет, что-то вроде: Код (Text): for (i=0;i<10000000;i++) { cpuid; timestamp(); } Понятно, что в интервал от одной метки до другой попадают накладные расходы на организацию цикла и на выполнение измерений. Но они меня не интересуют. Меня как раз интересуют эффекты от многозадачности и от обработки посторонних прерываний. Т.е если посмотреть на мои картинки, то с левой стороны - уменьшающаяся экспонента, это и есть накладные расходы. В DOS-программе с замаскированными прерываниями она в точности такая же, но кроме нее больше ничего и нет. А меня интересуют середины и правые части гистограмм, т.е. то, что больше 10-100 мкс, как раз этот самый лажовый вендозный шедулер. Неужели никто не поможет достоверно проинтерпретировать картинки? З.Ы. Зачем надо? Хочу получить более-менее адекватную статистическую картину длительности цикла в Маздаях, чтобы использовать ее в имитационных моделях систем реального времени, сетевых приложений и т.п.
Код (Text): for (i=0;i<10000000;i++) { cpuid; timestamp(); } Так это тоже тест не супер.... cpuid это одна инструкция, а timestamp, если ты используешь QueryPerformanceCounter() на win2k/xp, выливается в системный вызов. То есть в sysenter и переключение в kernel mode. Я к чему клоню - если это сделать в начале и конце теста, то эффект константный и следовательно ничтожный. А так как ты это делаешь в каждом обороте цикла, то тест сводится к "количеству syscalls в единицу времени". Кста, а у тебя есть графики (картинки) повыше качеством с подписанными разграфлёнными осями?
Блин, народ молчит, как рыба об лед. Ладно, попробую по другому вопросы "зададу". 1. Если приоритет тестового потока = нормал, то имеются многочисленные и регулярные задержки в районе сотен микросекунд. Отсюда вопросы: задержки от переключения на другие потоки обязаны быть кратны кванту или нет? Если нет, то неужели все они юзают Sleep(0) и добровольно отдают недоюзанные кванты или есть какой-то другой механизм отъема квантов? 2. Если приоритет тестового потока = нормал, то имеются регулярные задержки длиной типа единиц миллисекунд. Что это - таймерные прерывания, обрабатываемые шедулером? 3. Если приоритет тестового потока = тайм критикал, то все задержки типов (1) и (2) исчезают, зато регулярно проскакивают довольно редкие, но ооочень большие (типа десятых долей секунды)задержки. Впечатление такое, что шедулер долго жмется, терпит, никому не отдает кванты, а потом одним разом в штаны кэээк... Как объяснить? Отдельно скажу: Питреков, Рихтеров и Русиновичей я, естественно, читал. Но только хуже, одному эффекту можно дать несколько разных истолкований. Вот я и прошу помощи - помогите разобраться, что же все-таки на самом деле происходит?
drmad Так бы сразу и "зададал" Ес-но задержки переключения не "обязаны" быть кратны кванту. И ес-но основным механизмом добровольной передачи управления является не Sleep(0), а GetMessage, всевозможные явные и неявные Wait-функции, ну и наконец просто завершение потока. Ес-но если поток завершается или переходит в режим ожидания, то управление передается планировщику, который "недолго думая" запускает очередной готовый поток. Поэтому и задержки твоего переключения в принципе м.б. практически любыми - смотря сколько готовых потоков стоит в очереди и насколько быстро они отработают. А вот прерывания от таймера как раз должны давать небольшие задержки в десятки-сотни микросекунд - ведь квант равен нескольким интервалам таймера, поэтому "быстренько" обработав прерывание в середине кванта, планировщик возобновляет выполнение прерванного потока. В случае обычного time_critical с приоритетом 15 тоже ничего загадочного и необъяснимого нет - рулит динамическое повышение приоритета "обиженных" потоков и когда приоритеты выравниваются, "обиженная" кучка начинает отрабатывать свое время. Просто в случае нормального приоритета их работа размазывается по времени (единицы-десятки мсек), а тут из-за вынужденного простоя они собираются в кучу и уже твоему потоку приходится ждать пока они отработают и вернутся к своему исходному приоритету
Ну и ещё 2 цента: из моего опыта все многопоточные тесты со Wait*/Sleep/GetMessage на windows не показывают точного и повторимого результата т.к. scheduler (и всё ядро) не является real time. В то же время, если провести такие тесты на Integrity или VxWorks, то измерения будут очень точными, т.к. код в этих ядрах обсолютно deterministic и тесты получаются очень чистыми.
leo Спасибо. На 95% у меня была такая же модель происходящего. Единственное, в чем я не был уверен - это во влиянии на картинку планировщика, висящего на таймерном прерывании. Теперь вопрос "исчерепан". s0larian Я еще пытался делать такие тесты на qnx и os-9000.