LINUX.ORG.RU

Запаздывание выхода из сна

 , ,


0

2

Поток засыпает на 0.2 сек. В большинстве случаев просыпается вовремя, но раз в несколько минут спит 6-8 сек. Вероятность ошибки повышается если близко по времени засыпает/просыпается больше потоков. При не загруженных ресурсах это не нормально. Как устранить эту проблему? (способ засыпания ни как не влияет, резкое повышение нагрузки тоже)

Ответ на: комментарий от kardapoltsev

Просто поток Запускаю с помощью pthread_create Крутится в цикле, каждый раз засыпая на 0.2 сек в конце цикла Я не проверяю спит он или нет, я проверяю сколько он спит отладочной печатью перед входом в сон и после выхода. Да, он может спать дольше чем положено если просто не хватает ресурсов, но сейчас он крутится в «холостом» режиме (только проверяет что делать нечего и идет спать дальше) и ресурсов более чем достаточно. Тестировал я это три дня и думаю что проблема не в моем коде и не в железе.

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

mihail13
() автор топика

По-моему такое поведение и на каком ядре нельзя считать нормальным. Если б оно спало 0.4 сек вместо 0.2 ещё ладно (хотя тоже плохо), но 6-8 это вообще никак не годится. Ты уверен что у тебя в проге нет багов? Может это отладочные логи и лагают? Попробуй их убрать и просто запоминать время пробуждения и засыпания в какой-нить массив, который выводится на экран/в файл уже другим потоком.

firkax ★★★★★
()
Последнее исправление: firkax (всего исправлений: 1)
Ответ на: комментарий от firkax

Мне и в голову не приходило, что в линуксе такое возможно. Заметил я эту проблему с клиентов для которых общение сервером (эти потоки в демоне на сервере) изредка пропадало на 6-8 сек и они фиксировали разрыв соединения. Я долго искал ошибку в коде клиентов и только потом стал ставить отладки в код демона. То что отладки никак не влияют я выяснил в первый день. Единственное что влияет - количество потоков с очень малой разницей во времени засыпающих/просыпающихся. Время которой должен будет проспать поток значения не имеет. Хоть 0.2 сек, хоть минимально возможное. (не нулевое, если в сон вообще не входить то проблема исчезает, но процу будет жарковато) Загрузка проца 1% или 50% тоже никак не влияла. Я не считаю что это обязательно ошибка ядра, возможно какие-то настройки или параметры указываемые при сборке ядра.

mihail13
() автор топика
Ответ на: комментарий от mihail13

6-8сек задержки на ровном месте в дефолтном конфиге это полюбому баг.

Попробуй просто

#include <sys/time.h>
#include <stdio.h>
#include <unistd.h>

int main(void) {
  struct timeval tv0, tv;
  int delta;
  unsigned long i;
  gettimeofday(&tv0, NULL);
  for(i=0; ; i++) {
    usleep(200000);
    gettimeofday(&tv, NULL);
    delta = (tv.tv_sec-tv0.tv_sec)*1000 + (tv.tv_usec-tv0.tv_usec)/1000;
    if(delta<100 || delta>1000) fprintf(stderr, "wrong delta %d ms at cycle %lu\n", delta, i);
    tv0 = tv;
  }
}
Если тут будут эти ошибки - ищи где баг в системе, если тут нет - ищи баг в своём коде. Ну или ищи баг таки в ядре, провоцируемый какими-то побочными эффектами твоего кода (найди какими). Поставил себе этот код работать, через час посмотрю вывод.

firkax ★★★★★
()
Последнее исправление: firkax (всего исправлений: 1)
Ответ на: комментарий от firkax

А у меня вот такая крысотища…

wrong delta 6178 ms at cycle 5655
wrong delta 2098 ms at cycle 6545
wrong delta 5189 ms at cycle 6640
wrong delta 8648 ms at cycle 7977
wrong delta 6577 ms at cycle 8185
wrong delta 1573 ms at cycle 8418
wrong delta 6782 ms at cycle 8565
wrong delta 4389 ms at cycle 8664
wrong delta 8597 ms at cycle 8682
wrong delta 8163 ms at cycle 9002
wrong delta 8764 ms at cycle 9319
wrong delta 8750 ms at cycle 9756
wrong delta 5583 ms at cycle 9909
wrong delta 8383 ms at cycle 10048
wrong delta 8115 ms at cycle 10788
wrong delta 1890 ms at cycle 11739
wrong delta 7796 ms at cycle 11761
wrong delta 7943 ms at cycle 12678
wrong delta 7137 ms at cycle 13243
wrong delta 8742 ms at cycle 13740
wrong delta 6120 ms at cycle 14430
wrong delta 7033 ms at cycle 15895
wrong delta 3065 ms at cycle 17080
wrong delta 6335 ms at cycle 17649
wrong delta 5430 ms at cycle 22301
wrong delta 6707 ms at cycle 23108
wrong delta 8723 ms at cycle 23785

ядро 3.2.0.4, видимо уже слишком старое чтобы оставаться стабильным, и заменить можно только обновив весь линукс на новый, беда, беда

mihail13
() автор топика
Ответ на: комментарий от slovazap

Не повлияет. В демоне именно CLOCK_MONOTONIC и используется (чтобы коррекция часов не напакостила). Но проверял я все способы и везде проблема есть (и она точно не от коррекции часов).

mihail13
() автор топика

А какой sleep ты юзаешь для засыпания? Вспоминается, что коллега рапортовал недавно, что у него usleep() просыпалось как-то нестабильно. Вот тут даже пишут, что это «фича» такая: https://www.kernel.org/doc/html/latest/timers/timers-howto.html

agentgoblin
()
Ответ на: комментарий от Jetty

Железо хоть и старое но не слабое. 8-ядерный феном. Оперативки достаточно (swap не используется вообще) Тестировалось в основном без нагрузки (1% это нисколько), но и когда дал нагрузку 50% это никак не сказалось. Влияет только количество одновременно засыпающих/просыпающихся потоков (при этом вероятность не проснутся растет существенно)

mihail13
() автор топика
Ответ на: комментарий от pon4ik

Тестировал и на clock_nanosleep, и на poll, и на usleep, и на seleсt - везде один и тот же результат. Только если вообще не засыпать то и не проспит (но крутится в цикле и жарить прой не лучшее решение, при реальной работе ожидаются критические нагрузкии сон там станет куда меньше 0.2 сек, но хоть сколько-то будет). Собственно задача не проспать 0.2 сек, а раз в 0.2сек выполнять задачу (сейчас без нагрузки задачи нет, поэтому можно спать). Сверхточность тоже не нужна, ошибка допустима но не более 0.02 сек. А 8 сек ну никак не приемлимо.

mihail13
() автор топика
Ответ на: комментарий от Jetty

select пробовал, poll пробовал, можно и epoll попробовать (но как я понял разница между ними только в обертке) Сейчас нет нагрузки потому что с демоном пока работает только один клиент на котором я тестирую. При рабочей нагрузке надо держать до 200 000 клиентов. То что проблема наблюдается у меня и не наблюдается на другом сервере было проверено (выше). Врятли стоит колдовать с кодом - виновато либо железо (что маловероятно) либо ядро линукса (что странно). На днях попробую переставить линукс (там немало проблем получу - многое изменилось со времен третьего ядра)

mihail13
() автор топика
Ответ на: комментарий от mihail13

проблема наблюдается у меня и не наблюдается на другом сервере

Сравни через diff с обоих машин /boot/config-${kernel_version}, может в подсистеме таймеров/шедулера что-то накрутил в своё время ради экспериментов и забыл?

agentgoblin
()
Ответ на: комментарий от pathfinder

Ты ещё предложи систему на QNX поменять :)

Но по-теме, тогда и affinity надо выставить на ядро без прерываний и все остальные процессы прогнать с ядра на котором будет эксперимент.

pon4ik ★★★★★
()
Ответ на: комментарий от mihail13

Это всё понятно, но это поможет локализовать проблему.

Например - у тебя стоит кривой драйвер, и так «повезло», что в моменты пауз именно для твоего процесса попадают зависания.

Альтернатива ещё - это поднять «такую же» систему на вирутуалке и погонять там.

pon4ik ★★★★★
()