Методика тестирования

Тема в разделе "WASM.A&O", создана пользователем AndrewKir, 3 июл 2006.

  1. AndrewKir

    AndrewKir New Member

    Публикаций:
    0
    Регистрация:
    3 июл 2006
    Сообщения:
    9
    Народ, подскажите, кто знает. Давно волнует вот какой вопрос. Предположим, читаем в цикле строку, замеряем время и результат выводим в файл. Первый результат стабильно больше остальных. Второй и следующие - практически одинаковые. Эффекты кэш-памяти L1-L2, понимаю. Но если буфер 8 Мб?!

    Первое время - 27х10**6 тактов, остальные - 15х10**6.

    Припоминаю, что есть какие-то структуры на уровне ОС, кэширующие доступ к страницам (TLB). Это причина? Или есть что-то еще?
     
  2. leo

    leo Active Member

    Публикаций:
    0
    Регистрация:
    4 авг 2004
    Сообщения:
    2.542
    Адрес:
    Russia
    Первый результат всегда стабильно больше остальных, но вот насколько больше зависит от конкретной программы. Разницу в миллионы тактов, может дать подкачка кода и данных с диска - если происходит обращение к незагруженной странице секции инициализированных данных или MMF, или вызов процедуры из незагруженной страницы кода. Отказы страниц при обращении к неинициализированным данным (из секции data? или VirtualAlloc) обычно дают задержки на несколько порядков меньше - тысячи-десятки тысяч тактов, если конечно достаточно физ.памяти и винда не сбрасывает модифицированные страницы на диск. Ну а загрузка кода и данных в кэш (в т.ч. и TLB) соответсвенно еще меньше (зависит от размера)
     
  3. AndrewKir

    AndrewKir New Member

    Публикаций:
    0
    Регистрация:
    3 июл 2006
    Сообщения:
    9
    Хмм, подкачка страницы... В принципе логично, ведь 12 млн.тактов на машине 1.6 ГГц = 7.5 мс. Но вот чего я не понимаю. Ведь после первого обращения страница уже в оперативной памяти. Все приложения, кроме этого, закрыты. Памяти достаточно. Запускаю несколько раз подряд, внутри цикл из 10 вызовов. Стабильная разница те же 12 млн. Почему? Разве страница была выгружена?
     
  4. bogrus

    bogrus Active Member

    Публикаций:
    0
    Регистрация:
    24 окт 2003
    Сообщения:
    1.338
    Адрес:
    ukraine
    В физической памяти страница может и осталась, но данные из L1 и L2 полюбому были замещены, ведь 8Mb это много для них, по-этому каждый раз цепочка RAM-->L2-->L1 выполняется заново, а при первом проходе ещё добавлялся винт (HDD-->RAM-->L2-->L1), вообще без конкретного примера точно сказать сложно
     
  5. bogrus

    bogrus Active Member

    Публикаций:
    0
    Регистрация:
    24 окт 2003
    Сообщения:
    1.338
    Адрес:
    ukraine
    И цифры у тебя вообще бешеные, непонятно что ты замеряешь (время записи в файл тоже?), как leo уже сказал - чтение строки 8Мб будет измерятся тысячами тактов, а не миллионами
     
  6. AndrewKir

    AndrewKir New Member

    Публикаций:
    0
    Регистрация:
    3 июл 2006
    Сообщения:
    9
    Цифры бешеные? 15 млн.тактов на 8 млн.байт получается ~2 такта/байт. leo говорил о задержке, вызванной, например отсутствием страницы в памяти. Тогда она подгружается с диска, но неужели это делается при _каждом_ старте программы, ведь страница должна была сохраниться, если ее никто не выгружал?
     
  7. rmn

    rmn Well-Known Member

    Публикаций:
    0
    Регистрация:
    23 ноя 2004
    Сообщения:
    2.348
    а разве страницы не освобождаются при завершении процесса?
     
  8. bogrus

    bogrus Active Member

    Публикаций:
    0
    Регистрация:
    24 окт 2003
    Сообщения:
    1.338
    Адрес:
    ukraine
    да, с цифрами бешеными я стормозил (писал 8Mb, а сам думал о 8Кб)

    У тебя екзешник 8Mb или ты их выделяешь в процессе?
     
  9. leo

    leo Active Member

    Публикаций:
    0
    Регистрация:
    4 авг 2004
    Сообщения:
    2.542
    Адрес:
    Russia
    AndrewKir
    Ты бы пояснил, что делает твой тестируемый код. В частности что это за 8Мб ?
    В простом тесте, когда мы не гоняем большие объемы данных, а просто например читаем один dword из секции data у меня получается такая картина:
    - при первом запуске проги первый проход ес-но дает миллионы тиков - идет подкачка
    - при последующих запусках проги уже получается полтора десятка тысяч тиков, т.е. данные остались в файловом кэше и осталась только обработка отказа страницы
    - если не просто читать данные, а модифицировать их, то задержка при повторных запусках возрастает раза в два-три, т.е. исходные данные все равно берутся из ОЗУ (видимо copy-on-write рулит)

    Почему у тебя данные не остаются в файловом кэше сказать не берусь - поясни конкретнее насчет 8Мб, может они у тебя в data сидят ?
     
  10. leo

    leo Active Member

    Публикаций:
    0
    Регистрация:
    4 авг 2004
    Сообщения:
    2.542
    Адрес:
    Russia
    А вообще-то если учесть цифры, то все просто объясняется отказами страниц. Действительно 8Мб = 2000 страниц по 4Кб. Разница в тиках составляет 12 млн.тактов, т.е. по 6 тыс. тактов на одну страницу - вполне нормальная величина
     
  11. AndrewKir

    AndrewKir New Member

    Публикаций:
    0
    Регистрация:
    3 июл 2006
    Сообщения:
    9
    Хе, интересный вопрос. Они, несомненно, освобождаются, но ведь остаются в оперативной памяти, разве не так? Неужели их снова надо подгружать при [немедленном] повторном старте?

    Буфер 8 Мб, выделяется, например, через механизм memory-mapped file, можно через VirtualAlloc или new. Насколько понимаю, они все равно на низком уровне сведутся к одним и тем же механизмам. Резервируется адресное пространство. Доступ к адресу, отсутствующему в памяти. Страница подгружается.
     
  12. leo

    leo Active Member

    Публикаций:
    0
    Регистрация:
    4 авг 2004
    Сообщения:
    2.542
    Адрес:
    Russia
    AndrewKir
    А вот насчет "одних и тех же механизмов" ты не совсем прав, т.к. одно дело data и MMF - тут при отказе страницы данные действительно подгружается с диска (в случае промаха быстрого чтения из файлового кэша), и другое дело VirtualAlloc и иже с ним - тут винда при наличии свободной физ.памяти просто подсовывает нам свободную обнуленную страницу, ничего не "подгружая"
     
  13. AndrewKir

    AndrewKir New Member

    Публикаций:
    0
    Регистрация:
    3 июл 2006
    Сообщения:
    9
    leo, это очень простая чисто тестовая программа. Такие ситуации складывались неоднократно, но обычно текучка заедает. Остается ощущение недопонимания, и хочется знать детальный ответ. Модельная программа такова:

    1. Выделяем блок памяти, обычно через memory-mapped file, просто я так привык. Те же эффекты получаются, когда, скажем, функция получает для обработки буфер, выделенный VirtualAlloc.

    2. Запускаем цикл такого рода:

    for (int i=0; i<CYCLE_QUANT; i++){
    GetProcClocksFull(&i64Time);

    Тестируемая_функция();

    GetProcClocksFull(&i64Time2);
    DWORD dwDeltaTime = (DWORD)((i64Time2 / 1000) - (i64Time / 1000));
    ToLog(REPORT_FILE,"%u\n",dwDeltaTime);
    }

    3. Сама тестируемая функция:

    MainCycle:
    mov esi, DWORD PTR[edi]
    add edi, 4
    sub ecx, 1
    jnz short MainCycle

    8 млн.байт выделяется потому, что этот буфер заведомо "промоет" оба кэша (Pentium 4), но и заведомо уместится в оперативной памяти.

    Согласен, основная версия, просто по цифрам. Но вот почему эти отказы случаются при каждом запуске, разве страницы уже не в памяти?
    P.S. Маленькое уточнение. Самый первый тест после перезагрузки дает 400 млн.тактов. Вот тут явно подкачка с диска.
     
  14. AndrewKir

    AndrewKir New Member

    Публикаций:
    0
    Регистрация:
    3 июл 2006
    Сообщения:
    9
    Ну да, конечно, но это уже другая модель. Что читать из этой обнуленной страницы? Я имел в виду чем-то заполненный буфер.
     
  15. bogrus

    bogrus Active Member

    Публикаций:
    0
    Регистрация:
    24 окт 2003
    Сообщения:
    1.338
    Адрес:
    ukraine
    может они и оставались в RAM, но процесс то уже другой ... как их связать обратно?

    я как раз такой пример приготовил

    в аттаче такой тест, перезагрузка не нужна, только перекомпилить exe - в результате дисковые страницы станут инвалидны относительно RAM и все 8Мб exe системе прийдется загружать в оперативу заново (дает ~400 млн.тактов) , чего не произойдет при последующих запусках (там разница первый-остальные проходы останется ~12 млн.тактов), пока exe не будет снова перекомпилен
     
  16. leo

    leo Active Member

    Публикаций:
    0
    Регистрация:
    4 авг 2004
    Сообщения:
    2.542
    Адрес:
    Russia
    AndrewKir
    rmn
    Не путайте физические страницы с виртуальными страницами процесса.
    Виртуальные адреса транслируются в физические через каталог страниц (PD) и таблицы страниц (PT). При создании образа проги или при VirtualAlloc или MapView винда лишь создает и подготавливает соответствующие записи PDE и PTE, занося в них информацию о том где брать данные. Но эти PTE для процессора остаются недействительными (флаг present не установлен), поэтому при обращении по этому адресу возникает исключение. Тут винда решает где взять данные - с диска или из списка обнуленных страниц. Если с диска, то делается запрос на чтение данных, который первым делом проверяет - а нет ли соответсвующей страницы в файловом кэше, если есть, то ОК - имеем FastIO, если нет - то читаем с диска.
    Соответсвенно при завершении процесса его таблицы страниц уничтожаются и при новом запуске проги все повторяется. Т.е. данные физически могут сохраняться в файловом кэше, но связь физ.страниц с виртуальными ес-но нарушается и ее нужно восстанавливать заново с теми же отказами. Ну а содержимое страниц, не связанных с реальными файлами (т.е. выделенных VirtualAlloc'ом и не записывавшихся ни в какой в файл) после закрытия процесса - теряется "безвозвратно", т.е. данные могут какое-то время сохраняться в ОЗУ, но перед новым выделением этих страниц винда их обязательно обнулит => по любому VirtualAlloc это не совсем "то же самое", что data и MMF - хотя все они основаны на предоставлении данных "по требованию" через механизм отказа страниц
     
  17. AndrewKir

    AndrewKir New Member

    Публикаций:
    0
    Регистрация:
    3 июл 2006
    Сообщения:
    9
    Да, действительно, этих деталей я не учитывал.

    Хочу уточнить (сорри, не лезть же сейчас в книги), чем отличается обращение к незагруженной странице от отказа страницы.
     
  18. leo

    leo Active Member

    Публикаций:
    0
    Регистрация:
    4 авг 2004
    Сообщения:
    2.542
    Адрес:
    Russia
    Отказ страницы возникает всякий раз, когда процессор при трансляции адреса натыкается на недействительную запись PTE (или PDE). Причины могут быть разные, в том числе и инвалидный адрес. Но в данном случае мы говорим о валидной выделенной (переданной commited) памяти, но не инициализированной, т.е. данный PTE ссылается либо на файл подкачки или объект раздел, связанный с файлом (код, данные, MMF), либо имеет признак страницы обнуляемой по требованию (VirtualAlloc или первое обращение к секции data?). Т.е. отказ страницы возникает в обоих случаях, но в первом случае может потребоваться загрузка страницы с диска, а во втором страница всегда берется из ОЗУ из списка обнуленных или свободных страниц без обращения к диску

    PS: секции, состоящие из одних нулей (такие как .bss или .data?), а также обнуленные "хвосты" других секций (например неинизиализированные данные в конце секции .data) в исполняемый файл не записываются и соответственно с диска не подгружаются. В этом смысле эти страницы при первом обращении ведут себя также как и страницы, выделенные VirtualAlloc'ом - происходит отказ страницы и винда мапит виртуальную страницу в обнуленную страницу физ.памяти.
     
  19. AndrewKir

    AndrewKir New Member

    Публикаций:
    0
    Регистрация:
    3 июл 2006
    Сообщения:
    9
    То есть в примере с MMF те дополнительные 12 млн.тактов/2000 страниц тратятся на создание действительных записей PTE/PDE?
     
  20. leo

    leo Active Member

    Публикаций:
    0
    Регистрация:
    4 авг 2004
    Сообщения:
    2.542
    Адрес:
    Russia
    Точнее сказать на обработку аппаратных исключений #PF (отказ страницы), в результате которой (помимо прочих действий) создаются действительные записи PTE. А в винде на обработку любого исключения уходит не менее нескольких тысяч тактов, поэтому сказать каков тут вклад собственно операций с физ.страницами и PTE - сказать трудно