1

誰も私に答えることができますか、コードの下に来ると、C2D 2.6GHz CPU のコア全体がどのように消費されるのでしょうか? 10MB のチャンクでファイルをダウンロードするだけで、600 個ほどになる可能性がありますが、NSOperationQueue には 6 つの同時タスクの制限があります。

なぜ同じアプリが Windows にあるのか (C# で書かれたものは 80% ではなく 2% しか消費しない!)、それは単純な HTTP 要求です!

for (DownloadFile *downloadFile in [download filesInTheDownload])
            {
                for (DownloadChunk *downloadChunk in [downloadFile chunksInTheFile])
                {
                    NSString *downloadPath = [[NSString stringWithFormat:@"%@/%@", [download downloadFolder], [download escapedTitle]] stringByExpandingTildeInPath];
                    NSString *chunkPath = [downloadPath stringByAppendingFormat:@"/%@.%i", [downloadFile fileName], [downloadChunk chunkId]];

                    NSError *attributesError = nil;

                    NSDictionary *fileAttributes = [[NSFileManager defaultManager] attributesOfItemAtPath:chunkPath error:&attributesError];

                    NSNumber *fileSizeNumber = [fileAttributes objectForKey:NSFileSize];
                    uint64_t fileSize = [fileSizeNumber longLongValue];
                    NSLog(@"Chunk file size: %lli", fileSize);
                    uint64_t expectedSize = ([downloadChunk endingByte] - [downloadChunk startingByte]) + 1;
                    NSLog(@"Chunk expected size: %lli", expectedSize);
                    uint64_t newStartingByte = [downloadChunk startingByte] + fileSize;
                    if (fileSize == expectedSize)
                    {
                        NSLog(@"Chunk complete: %@.%i", [downloadFile fileName], [downloadChunk chunkId]);
                    }
                    else
                    {
                        NSURL *fileURL = [[NSURL alloc] initWithString:[downloadFile filePath]];

                        NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:fileURL];
                        NSLog(@"Normal range: %lli-%lli", [downloadChunk startingByte], [downloadChunk endingByte]);
                        NSString *range = [NSString stringWithFormat:@"bytes=%lli-%lli", newStartingByte, [downloadChunk endingByte]];
                        [request setValue:range forHTTPHeaderField:@"Range"];
                        AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
                        operation.outputStream = [NSOutputStream outputStreamToFileAtPath:chunkPath append:YES];

                        [operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
                            NSLog(@"%@", [NSString stringWithFormat:@"Chunk complete: %@.%i", [downloadFile fileName], [downloadChunk chunkId]]);
                            if (download.downloadedBytes == download.size)
                                [[NSNotificationCenter defaultCenter] postNotificationName:@"downloadFinished" object:download];
                        } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
                            NSLog(@"Error: %@", error);
                        }];

                        [operation setDownloadProgressBlock:^(NSInteger bytesRead, long long totalBytesRead, long long totalBytesExpectedToRead) {
                            download.downloadedBytes += bytesRead;
                        }];

                        [queue addOperation:operation];
                    }
                }
            }

ここにいくつかの時間プロファイラーのスクリーンショットがあります。正しく読むと、すべてが RunLoops のようです。

ここに画像の説明を入力 ここに画像の説明を入力

4

2 に答える 2

0

最後のプログレス ブロックでダウンロードが完了すると仮定すると、四角い穴に丸いペグを押し込むようなものになります。それがあなたのCPU使用率が高い原因かどうかはわかりませんが、私は確かにそれを修正します. AFNetworking には、このためだけの機能があります。ここ[AFHTTPRequestOperation setCompletionBlockWithSuccess:failure:]に文書化されています。返された HTTP ステータス コードに基づいて、正しいブロックが呼び出されます。

つまり、これの代わりに:

    AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
    operation.outputStream = [NSOutputStream outputStreamToFileAtPath:chunkPath append:YES];
    [operation setDownloadProgressBlock:^(NSInteger bytesRead, long long totalBytesRead, long long totalBytesExpectedToRead) {
        download.downloadedBytes += bytesRead;
        if (download.downloadedBytes == download.size)
            [[NSNotificationCenter defaultCenter] postNotificationName:@"downloadFinished" object:download];
    }];

    [queue addOperation:operation];
    chunkId++;

これを使って:

    AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
    operation.outputStream = [NSOutputStream outputStreamToFileAtPath:chunkPath append:YES];
    [output setCompletionBlockWithSuccess: ^(AFHTTPRequestOperation *operation, id responseObject) {
    [[NSNotificationCenter defaultCenter] postNotificationName:@"downloadFinished" object:download];
                                        }
                                  failure: ^(AFHTTPRequestOperation *operation, NSError *error) {
    // you should probably do something here
                                        }];

その後、downloadedBytes が必要になるとは思えません。これにより、最後のアトミック プロパティが削除され、状況が改善されるはずです。

于 2012-08-10T16:40:13.777 に答える
0

ほとんどのプロパティを非アトミックにダウングレードすると、使用率が 80% から 20 ~ 30% に低下するようです。今は DownloadBytes だけがアトミックです。また、改善するにはどうすればよいですか?

于 2012-08-03T15:03:12.667 に答える