cpu speed - work in progress

Ниже вы увидете пост, работа над которым сейчас ведется. Пожалуйста если вы любите проверенные материалы - не читайте далее пока данный абзац не будет убран.  Пост может содержать недостоверную информацию.

Все остальные - пожалуйста комментируйте -  ваше мнение  важно для меня и ваших коллег. Будьте вежливы, но комментарии все равно модерируются -) Вместе с завершением появится и картинка к этому посту.


 

Исходные материалы:  10 sec of cpu time, пост на sql.ru.

Издалека: зачем нам это нужно ? Мы хотим оптимальным образом настроить CBO на нашу систему, подсказать насколько действительно быстрый у нас процессор. Мы никоим образом не можем  делать выводы насколько плох или хорош другой  процессор, поскольку наши измерения недостаточно хороши для этого.

Основополагающий материал для прочтения. Несколько цитат:

Note how the statistics include the apparent cpuspeed, nominally in MHz. Don't be alarmed if this is nothing like the actual CPU speed of your system – the figure is probably just an internal calibration of a baseline operation that Oracle then uses to produce relative CPU costs of other operations
...
Note how the statistics include the apparent cpuspeed, nominally in MHz
...the 10053 trace file has been modified to show that this speed is, indeed, in “millions of Oracle operations per second”

Итак (формула  отсюда),

Cost = (
#SRds * sreadtim +
#MRds * mreadtim +
#CPUCycles / cpuspeed ) / sreadtim

И наконец
"
Either way, when CPU Costing is enabled, a new code path comes into play that сan improve the performance of some of your queries without changing the execution path,
"

Итак, правильная  системная статистика может  повлиять на оптимальную работу системы.


Читаем MOS, System Statistics: Scaling the System to Improve CBO optimizer [ID 153761.1], видим что системная статистика содержит "cpu speed in mhz".Что это на самом деле - написано выше.

Читаем Tuning Guide, находим определения для cpuspeedNW - Represents noworkload CPU speed. CPU speed is the average number of CPU cycles in each second. cpuspeed - Represents workload CPU speed. CPU speed is the average number of CPU cycles in each second.


Определение CPUCycles встретилось только в описании документации к Oracle 9i.
CPUCycles includes CPU cost of query processing (pure CPU cost) and CPU cost of data retrieval (CPU cost of the buffer cache get).


Noworkload statistics
Noworkload statistics consist of I/O transfer speed, I/O seek time, and CPU speed (cpuspeednw). The major difference between workload statistics and noworkload statistics lies in the gathering method.
Noworkload statistics gather data by submitting random reads against all data files, while workload statistics uses counters updated when database activity occurs.

 По определениям выше, оказывается что нужно собирать workload статистику когда у вас идет нормальная работа, сервер работает в полную мощность но и не перегружен.

Вывод: ясно что всякие turbo mode/turbo boost тут могут "не заиграть" и oracle 'занизит' cpuspeed. Зачем нужно noworkload режим я не понимаю и думаю что его нужно избегать.
 

Workload statistics:
Because the counters are in the buffer cache, they include not only I/O delays, but also waits related to latch contention and task switching. Workload statistics thus depend on the activity the system had during the workload window. If system is I/O bound (both latch contention and I/O throughput), then the statistics reflect this situation and therefore promotes a less I/O-intensive plan after the database uses the statistics

Итак, статистика должна помочь Oracle оценить будущий план чтобы не убить систему. Однако, как вы понимаете, hardware намного сложнее сейчас, и Oracle сильно обманывается.

Сбор статистики лучше делать так:

execute dbms_stats.gather_system_stats('Start');
<нагрузка здесь> 
execute dbms_stats.gather_system_stats('Stop');


Утверждение номер 1. Сбор даже workload статистики не в состоянии отразить действительную ситуацию для современного hardware. Нужно будет поправить все значения вручную.

execute DBMS_STATS.SET_SYSTEM_STATS (pname ='cpuspeed', pvalue = 400);

 Вот что я использовал в качестве нагрузки (Тест взят отсюда)


set timing on
spool latch_test_&1
 
select
    count(*) X
from
    kill_cpu_&1
connect by
    n > prior n
start with
    n = 1
;


Для моего виртуального процессора  (10g R2 under Oracle VM)


PNAME                               PVAL1
------------------------------ ----------
CPUSPEED                             2135
CPUSPEEDNW                     587.115789


Легко убедиться по материалам собранным sql.ru что 2135 это навороченный  последний Xeon и чуть ли не рекорд среди всех процессоров -) Напоминаю, что у меня Intel(R) Core(TM)2 Duo CPU     E6850  @ 3.00GHz, домашний компьютер -). Видим что CPUSPEEDNW в 4 раза меньше и забываем про это число навсегда. 


На моем Power 7 (частотой 3 GHz) данные такие:


CPUSPEED                             1369
CPUSPEEDNW                     738.481093


При этом тест по времени выполняется (в один поток) 17 сек на Power, 50 сек на Intel Core Duo.

Утверждение номер 2.   CPUSPEED не отражает реальную производительность процессора. Т.е. никак.  Его нужно менять -(. И Oracle легко обмануть тут особенно в виртуальных средах.


Тест несколько потоков:   На процессоре Power 7 (3 GHz) Я убрал многопоточность. У меня 2 физических процессора в LPAR и nmon видит также 2 процессора.  Я сделал 8 табличек kill_cpu_[a-h] и запустил тот же тест   в несколько потоков, сначала в 2, а  затем 4 и 8

Потоков       Время(сек):
1             17 
2             17    (2 процесса разошлись на 2 ядра)
4             34    (по два процесса на ядро)
8             70    (по 4 процесса на ядро)


Я вижу хорошую линейную масштабируемость процессора. Я так думаю -)

Мой виртуальный процессор загнулся сразу, уже на двух потоках, хотя за ним и стоит 2 реальных  ядра. Кстати, возможно это и хинт, почему такая бешенная CPUSPEED была рассчитана для него


Я обнаружил что с помощью dbms_stats.gather_system_stats можно легко  получить занимательную статистику для любого запроса (нужно запустить 'Start'  дать запросу отработать, затем select pname, pval1 from sys.aux_stats$ where pname like 'CPU%')  :

(Intel, 10g R2)

PNAME                               PVAL1
------------------------------ ----------
CPUSPEED                             2196
CPUSPEEDNW                     587.115789  
CPUCYCLES                           69720  -- смотри формулу стоимости вверху
CPUTIM                              31222    -- время с начала запроса

 И CPUSPEED = (CPUCYCLES / CPUTIM) * 1000

Порядки этих величин для одного и тоже запроса разные (в 100 раз)  в 11gR2 и 10gR2

(Power 7 и 11gR2)

PNAME                               PVAL1
------------------------------ ----------
CPUSPEED                             1369
CPUSPEEDNW                     738.481093
CPUCYCLES                         1952160
CPUTIM                            1426155


Очередная догадка, смотря на числа выше: 
Power 6 понадобилось в 3 раза меньше CPU циклов, но при этом потратилось всего в 2 раза меньше времени. Из данных выше видно что разница по времени выполнения ~ числу CPU циклов, а не CPUTIM. 

Итак я предполагаю что если вы хотите понять для себя любимого, насколько один процессор лучше другого  нужно взять какой-то эталонный тест, затем:

- проверить процессор на 'сопротивляемость' нескольким потокам теста  на ядро. Хорошие числа тут 4 и 8 потоков на ядро.
- сравнить  параметры  CPUCYCLES. Я ожидаю что производительность все таки должна быть пропорциональная этому параметру.
 

1 комментарий:

  1. Вячеслав Рассказов9/5/11 4:40 PM

    В 11.2.0.2, linux, CPUCYCLES каждые несколько минут увеличиваются на 6972, для них подсчитывается CPUSPEEDNW и добавляется нарастающим итогом. Другие платформы еще не смотрел. Это происходит независимо от того, есть ли в базе какая-либо активность, запускаются ли тесты загружающие CPU и т.д. Когда вызывается dbms_stats.gather_system_stats('Start'), эти значения записываются в sys.aux_stats$, sname='SYSSTATS_TEMP'. Больше они во время сбора статистики никогда не меняются. Поэтому нельзя говорить, что эти статистики можно получить для какого-то конкретного запроса. Это просто итоговые статистики с момента старта инстанса, причем статистики синтетического теста. В Вашем случае как такового сбора статистики не было, т.к. сбор закончился до того, как CPUCYCLES, CPUTIM успели обновиться (не в aux_stats$), собственно поэтому CPUSPEED = (CPUCYCLES / CPUTIM) * 1000 - среднее значение с момента старта. Если собирать статистику дольше, то формула будет другой: CPUSPEED = ((CPUCYCLES текущие - CPUCYCLES из aux_stats$) / (CPUTIM текущие - CPUTIM из aux_stats$)) * 1000. Так что не вижу смысла смотреть на CPUCYCLES, оно щелкает периодически одинаковыми порциями и, наверное, это правильно. Скорость CPU все-таки величина постоянная, в отличие от IO. Также надо понимать, что CPUCYCLES никакого отношения к циклам CPU не имеет, как и #CPUCycles.

    ОтветитьУдалить