io_getevents возвращает меньшее количество заданий, чем запрошено, за время, меньшее времени ожидания

Я читаю SSD и запрашиваю 20 асинхронных заданий. io_getevents вернул значение 7, указывающее, что время истекло. Тайм-аут установлен на 10 секунд, как показано ниже. истекшее время разговора действительно составляет 4,89e-05 секунд, например, осталось почти все 10 секунд. Вопрос: У кого-нибудь был такой инцидент? Если вы это сделали, то нашли ли вы решение?

Вот часть кода:

struct timespec ts = { 10, 0 } ; /* ten seconds delay */
const long ec = io_getevents( ctx, num_jobs, num_jobs, &events[ 0 ], &ts ) ;

Когда ес возвращается 7, ts.tv_sec = 10, ts.tv_nsec = 0

Ядро Linux:

Linux VTL80-G-1J4-823-21 2.6.18-274.18.1.el5 #1 SMP Thu Feb 9 12:20:03 EST 2012 x86_64 x86_64 x86_64 GNU/Linux

Ваша помощь очень ценится! КСТАТИ. Я не смогу проверить почту раньше, чем через несколько часов.

1 ответ

Решение

Путем дополнительных шагов и отладки выходных данных мы выясняем, что есть проблема с драйвером aio в нашем linux (5.3 Carthage, 2.6.18-128.el5)

Решение, которое мы применили (я добавляю его на случай, если кто-то столкнется с той же проблемой), таково:
(Мы считаем прошедшие секунды для вызова сами.)

1) Если мы увидим ошибку, возвращенную из io_getevents() мы сообщаем об этом. СДЕЛАННЫЙ.

2) Если мы видим, что 0 заданий завершено и истекли секунды, мы считаем себя выше ожидаемого и сообщаем об ошибке. СДЕЛАННЫЙ. В противном случае мы продолжаем (мы не меняем тайм-аут на io_getevents())

3) Если некоторые работы завершены, мы анализируем их res для ошибки (отрицательное значение), и если была какая-либо неудачная работа, мы сообщаем об этом. СДЕЛАННЫЙ.

4) Если осталось несколько заданий, мы сбрасываем таймер (да, мы снова будем ждать "ожидаемое" время) и продолжаем.

С помощью этого метода мы сообщим об ошибке, если io_getevents() сообщил об ошибке или любой из заданий сообщил об ошибке. В худшем случае, когда каждое задание возвращается нормально после всего времени ожидания T-epsilon, весь процесс займет N * T времени для завершения.

Я надеюсь, что кто-то найдет это полезным.
Благословения,
Грег.

Пример:

struct timespec       tmCountStart ;
unsigned              seconds_delay = SECONDS_DELAY ;

clock_gettime( CLOCK_REALTIME, &tmCountStart ) ;
while ( num_remaining_jobs > 0 )
{
    struct timespec ts = { seconds_delay, 0 } ;
    struct io_event events[ num_remaining_jobs ] ;
    long ec ;

    do
    {
        ec = io_getevents( ctx, num_remaining_jobs, num_remaining_jobs, &events[ 0 ], &ts ) ;
    }
    while( ec == -EINTR ) ;

    if ( ec < 0 )
        throw exception reporting error ec. cancel all remaining jobs
    else if ( ec == 0 )
    {
        const double elapsed = count elapsed seconds from tmCountStart
        seconds_delay = SECONDS_DELAY - static_cast< unsigned >( elapsed ) ;
        if ( seconds_delay > SECONDS_DELAY ) 
            throw exception reporting timeout. cancel all remaining jobs
    }
    else // we got some jobs back. may not all of them
    {
        for ( int i = 0 ; i < ec ; i++ )
            if (( int64_t )events[ i ].res < 0 )
                throw exception reporting failing job. cancel all remaining jobs.

        num_remaining_jobs -= ec ;
        if ( num_remaining_jobs > 0 )
        {
            clock_gettime( CLOCK_REALTIME, &tmCountStart ) ; // reset timer.
            seconds_delay = SECONDS_DELAY ;
        }
    }
}
Другие вопросы по тегам