Skip to content

Commit 0c94e54

Browse files
committed
Revert back the NSOperationQueue, seems has better performance on this cases (may dispatch multiple block but not important, one finished is OK)
1 parent 6e1fee7 commit 0c94e54

File tree

4 files changed

+40
-25
lines changed

4 files changed

+40
-25
lines changed

SDWebImage/Core/SDAnimatedImagePlayer.m

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ - (NSOperationQueue *)fetchQueue {
9090
if (!_fetchQueue) {
9191
_fetchQueue = [[NSOperationQueue alloc] init];
9292
_fetchQueue.maxConcurrentOperationCount = 1;
93+
_fetchQueue.name = @"com.hackemist.SDAnimatedImagePlayer.fetchQueue";
9394
}
9495
return _fetchQueue;
9596
}

SDWebImage/Core/SDImageCache.m

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ - (nonnull instancetype)initWithNamespace:(nonnull NSString *)ns
118118

119119
// Create IO queue
120120
dispatch_queue_attr_t ioQueueAttributes = _config.ioQueueAttributes;
121-
_ioQueue = dispatch_queue_create("com.hackemist.SDImageCache", ioQueueAttributes);
121+
_ioQueue = dispatch_queue_create("com.hackemist.SDImageCache.ioQueue", ioQueueAttributes);
122122
NSAssert(_ioQueue, @"The IO queue should not be nil. Your configured `ioQueueAttributes` may be wrong");
123123

124124
// Init the memory cache

SDWebImage/Core/SDWebImageDownloader.m

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ - (instancetype)initWithConfig:(SDWebImageDownloaderConfig *)config {
116116
[_config addObserver:self forKeyPath:NSStringFromSelector(@selector(maxConcurrentDownloads)) options:0 context:SDWebImageDownloaderContext];
117117
_downloadQueue = [NSOperationQueue new];
118118
_downloadQueue.maxConcurrentOperationCount = _config.maxConcurrentDownloads;
119-
_downloadQueue.name = @"com.hackemist.SDWebImageDownloader";
119+
_downloadQueue.name = @"com.hackemist.SDWebImageDownloader.downloadQueue";
120120
_URLOperations = [NSMutableDictionary new];
121121
NSMutableDictionary<NSString *, NSString *> *headerDictionary = [NSMutableDictionary dictionary];
122122
NSString *userAgent = nil;

SDWebImage/Core/SDWebImageDownloaderOperation.m

Lines changed: 37 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ @interface SDWebImageDownloaderOperation ()
7575

7676
@property (strong, nonatomic, readwrite, nullable) NSURLSessionTaskMetrics *metrics API_AVAILABLE(macosx(10.12), ios(10.0), watchos(3.0), tvos(10.0));
7777

78-
@property (strong, nonatomic, nonnull) dispatch_queue_t coderQueue; // the serial operation queue to do image decoding
78+
@property (strong, nonatomic, nonnull) NSOperationQueue *coderQueue; // the serial operation queue to do image decoding
7979

8080
@property (strong, nonatomic, nonnull) NSMapTable<SDImageCoderOptions *, UIImage *> *imageMap; // each variant of image is weak-referenced to avoid too many re-decode during downloading
8181
#if SD_UIKIT
@@ -112,7 +112,9 @@ - (nonnull instancetype)initWithRequest:(nullable NSURLRequest *)request
112112
_finished = NO;
113113
_expectedSize = 0;
114114
_unownedSession = session;
115-
_coderQueue = dispatch_queue_create("com.hackemist.SDWebImageDownloaderOperation", DISPATCH_QUEUE_SERIAL);
115+
_coderQueue = [[NSOperationQueue alloc] init];
116+
_coderQueue.maxConcurrentOperationCount = 1;
117+
_coderQueue.name = @"com.hackemist.SDWebImageDownloaderOperation.coderQueue";
116118
_imageMap = [[NSMapTable alloc] initWithKeyOptions:NSPointerFunctionsStrongMemory valueOptions:NSPointerFunctionsWeakMemory capacity:1];
117119
#if SD_UIKIT
118120
_backgroundTaskId = UIBackgroundTaskInvalid;
@@ -466,23 +468,26 @@ - (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)data
466468
NSData *imageData = self.imageData;
467469

468470
// keep maximum one progressive decode process during download
469-
@weakify(self);
470-
dispatch_async(self.coderQueue, ^{
471-
@strongify(self);
472-
if (!self) {
473-
return;
474-
}
475-
// When cancelled or transfer finished (`didCompleteWithError`), cancel the progress callback, only completed block is called and enough
476-
if (self.isCancelled || SDWebImageDownloaderOperationGetCompleted(self)) {
477-
return;
478-
}
479-
UIImage *image = SDImageLoaderDecodeProgressiveImageData(imageData, self.request.URL, NO, self, [[self class] imageOptionsFromDownloaderOptions:self.options], self.context);
480-
if (image) {
481-
// We do not keep the progressive decoding image even when `finished`=YES. Because they are for view rendering but not take full function from downloader options. And some coders implementation may not keep consistent between progressive decoding and normal decoding.
482-
483-
[self callCompletionBlocksWithImage:image imageData:nil error:nil finished:NO];
484-
}
485-
});
471+
if (self.coderQueue.operationCount == 0) {
472+
// NSOperation have autoreleasepool, don't need to create extra one
473+
@weakify(self);
474+
[self.coderQueue addOperationWithBlock:^{
475+
@strongify(self);
476+
if (!self) {
477+
return;
478+
}
479+
// When cancelled or transfer finished (`didCompleteWithError`), cancel the progress callback, only completed block is called and enough
480+
if (self.isCancelled || SDWebImageDownloaderOperationGetCompleted(self)) {
481+
return;
482+
}
483+
UIImage *image = SDImageLoaderDecodeProgressiveImageData(imageData, self.request.URL, NO, self, [[self class] imageOptionsFromDownloaderOptions:self.options], self.context);
484+
if (image) {
485+
// We do not keep the progressive decoding image even when `finished`=YES. Because they are for view rendering but not take full function from downloader options. And some coders implementation may not keep consistent between progressive decoding and normal decoding.
486+
487+
[self callCompletionBlocksWithImage:image imageData:nil error:nil finished:NO];
488+
}
489+
}];
490+
}
486491
}
487492

488493
for (SDWebImageDownloaderOperationToken *token in tokens) {
@@ -556,9 +561,11 @@ - (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didComp
556561
[self callCompletionBlocksWithError:self.responseError];
557562
[self done];
558563
} else {
564+
// decode the image in coder queue, cancel all previous decoding process
565+
[self.coderQueue cancelAllOperations];
559566
@weakify(self);
560567
for (SDWebImageDownloaderOperationToken *token in tokens) {
561-
dispatch_async(self.coderQueue, ^{
568+
[self.coderQueue addOperationWithBlock:^{
562569
@strongify(self);
563570
if (!self) {
564571
return;
@@ -596,16 +603,23 @@ - (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didComp
596603
} else {
597604
[self callCompletionBlockWithToken:token image:image imageData:imageData error:nil finished:YES];
598605
}
599-
});
606+
}];
600607
}
601608
// call [self done] after all completed block was dispatched
602-
dispatch_async(self.coderQueue, ^{
609+
dispatch_block_t doneBlock = ^{
603610
@strongify(self);
604611
if (!self) {
605612
return;
606613
}
607614
[self done];
608-
});
615+
};
616+
if (@available(iOS 13, tvOS 13, macOS 10.15, watchOS 6, *)) {
617+
// seems faster than `addOperationWithBlock`
618+
[self.coderQueue addBarrierBlock:doneBlock];
619+
} else {
620+
// serial queue, this does the same effect in semantics
621+
[self.coderQueue addOperationWithBlock:doneBlock];
622+
}
609623
}
610624
} else {
611625
[self callCompletionBlocksWithError:[NSError errorWithDomain:SDWebImageErrorDomain code:SDWebImageErrorBadImageData userInfo:@{NSLocalizedDescriptionKey : @"Image data is nil"}]];

0 commit comments

Comments
 (0)