NSUrlConnection в нескольких экземплярах NSOperation в NSOperationQueue

Следующий код добавляет несколько экземпляров NSOperation в NSOperationQueue. Операция просто берет содержимое URL-адреса. Я также предоставляю код php...

Учитывая следующий код...

-(void)requestResponse {

    NSURLRequest *req = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://www.someurl.gr/test.php"] cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:40.0];

    NSDate *dd = [NSDate date];

    NSURLResponse *resp;
    NSData *returnedData = [NSURLConnection sendSynchronousRequest:req returningResponse:&resp error:NULL];

    NSString *ss = [[[NSString alloc] initWithData:returnedData encoding:NSUTF8StringEncoding] autorelease];

    NSLog(@"%@ - %.2f",ss , -[dd timeIntervalSinceNow]);

}


-(NSOperation*)task {
    NSInvocationOperation* theOp = [[[NSInvocationOperation alloc] initWithTarget:self selector:@selector(requestResponse) object:nil] autorelease];
    return theOp;
}


-(IBAction)buttonAction:(id)sender {

    NSOperationQueue *opq = [[NSOperationQueue alloc] init];
    [opq setMaxConcurrentOperationCount:40];

    for(int i=0; i<15;i++) {
        [opq addOperation:[self task]];
        [NSThread sleepForTimeInterval:1.0]; // here is the issue!
    }

    [opq release];
}

Содержимое вызова ведьмы test.php -requestResponse:

<?php
    echo "Through!";
    for($i=0;$i<1000000;$i++) { // don't return too soon
    }
?>

Проблема в том, что когда я использую [NSThread sleepForTimeInterval:1.0] для создания задержки перед каждым добавлением NSOperation в очередь, все запросы выполняются примерно в одно и то же время. Если я прокомментирую эту строку, выполнение большинства запросов будет занимать все больше все больше и больше времени. Вопрос в том, почему?

Я проверил URL-адрес из командной строки (используя curl), и запросы выполняются одинаково для любого количества одновременных вызовов php, поэтому проблема не на стороне сервера.

Вот результат использования localhost в качестве сервера с отключенным sleepForTimeInterval

[s] Through! - 0.22
[s] Through! - 0.23
[s] Through! - 0.25
[s] Through! - 0.26
[s] Through! - 0.26
[s] Through! - 0.28
[s] Through! - 0.43
[s] Through! - 0.46
[s] Through! - 0.49
[s] Through! - 0.50
[s] Through! - 0.52
[s] Through! - 0.51
[s] Through! - 0.60
[s] Through! - 0.62
[s] Through! - 0.63

// конечно, разница намного больше (от 7 до 20 секунд!) с php, выполняющим реальную работу.

и с включенным sleepForTimeInterval

[s] Through! - 0.23
[s] Through! - 0.09
[s] Through! - 0.09
[s] Through! - 0.09
[s] Through! - 0.09
[s] Through! - 0.09
[s] Through! - 0.08
[s] Through! - 0.09
[s] Through! - 0.09
[s] Through! - 0.08
[s] Through! - 0.09
[s] Through! - 0.09
[s] Through! - 0.09
[s] Through! - 0.09
[s] Through! - 0.09

person Vassilis    schedule 15.04.2011    source источник


Ответы (1)


Когда у вас включен sleepForTimeInterval, он приостанавливается на более длительный срок, чем требуется для завершения NSOperation. Следовательно, у вас действительно есть только одна параллельная операция, происходящая за раз.

Когда у вас отключен sleepForTimeInterval, вы предоставляете NSOperationQueue несколько параллельных операций для завершения.

Что у вас установлено [NSoperationQueue setMaxConcurrentOperationCount]? Я бы установил значение 15, чтобы все операции выполнялись параллельно. Я думаю, что, возможно, в данный момент операции стоят в очереди и, следовательно, не все выполняются параллельно.

person Damien    schedule 25.04.2011
comment
Спасибо за Ваш ответ. maxConcurrentOperationCount установлено на 40! Так что проблема не в этом. Я реализовал метод -(void)requestResponseUsingCurl, который использует утилиту командной строки NSTask и curl для выполнения этой работы, и он отлично работает! Все операции выполняются одновременно без дополнительных задержек. Проблема в NSURLConnection sendSynchronousRequest и на самом деле даже в [NSString stringWithContentsOfUrl:], который я тоже пробовал, и у меня была такая же проблема. Это довольно странно, но что-то происходит с использованием класса (за кулисами) для получения содержимого URL. - person Vassilis; 26.04.2011
comment
Круто, тогда я проголосую за свой ответ! Редактировать: только что понял, что вы не можете проголосовать за свой ответ! - person Damien; 26.04.2011
comment
Интересно, есть ли где-то какое-то свойство, для которого не задано неатомарное значение, и поэтому при блокировках объектов образуются очереди? - person Damien; 26.04.2011
comment
xm очень хорошая мысль, но нет, по крайней мере, насколько я могу сказать. Код в точности соответствует опубликованному. - person Vassilis; 26.04.2011
comment
Просто примечание: я опубликовал версию, которая использует NSURLConnection для согласованности. Если вы используете [NSString stringWithContentsOfURL:@"http://www.someurl.gr/test.php"] в -(void)requestResponse, вы получите точно такие же результаты. - person Vassilis; 26.04.2011
comment
Это странно. Что-то где-то должно стоять в очереди! - person Damien; 26.04.2011
comment
Из интереса. Это на OSX или iOS? - person Damien; 26.04.2011
comment
Это на ОСХ. Я попробую это с CGI, отличным от php, на случай, если возникнет какой-то конфликт между php и URLConnection... - person Vassilis; 26.04.2011
comment
Хорошая идея. Может быть, это как-то связано с постоянной обработкой соединения на URLConnection или что-то в этом роде. Но если это так, я ожидаю увидеть это и при последовательном подходе. - person Damien; 26.04.2011