2015-01-30 9 views
15

मैं अपने आईओएस ऐप में लगभग 1700+ फ़ाइलों को डाउनलोड करने के लिए cURL का उपयोग कर रहा हूं - जो लगभग ~ 2 9 0 एमबी तक है। cURL का उपयोग करके उन सभी को डाउनलोड करने में मेरे इंटरनेट कनेक्शन पर लगभग 5-7 मिनट लगते हैं। लेकिन चूंकि सभी के पास तेज़ इंटरनेट कनेक्शन नहीं है (विशेष रूप से जब चलते हैं), मैंने पृष्ठभूमि में फ़ाइलों को डाउनलोड करने की अनुमति देने का निर्णय लिया है, ताकि उपयोगकर्ता डाउनलोड समाप्त होने की प्रतीक्षा करते समय अन्य चीजें कर सकें। यह जहां NSURLSession में आता है।NSRLSession कई फ़ाइलों को डाउनलोड करते समय curl से धीमा क्यों है?

का उपयोग NSURLSession, यह मेरे इंटरनेट कनेक्शन पर 20 मिनट का समय लगता है, जबकि एप्लिकेशन को अग्रभूमि में है उन्हें के सभी डाउनलोड करने के लिए। ऐप पृष्ठभूमि में होने पर धीमा होने पर मुझे कोई फर्क नहीं पड़ता, क्योंकि मैं समझता हूं कि डाउनलोड को शेड्यूल करने के लिए ओएस पर निर्भर है। लेकिन यह एक समस्या है जब यह अग्रभूमि में होने पर भी धीमी है। क्या यह अपेक्षित व्यवहार है? क्या यह फाइलों की मात्रा के कारण है?

मामले में मैं NSURLSession सही ढंग से उपयोग नहीं कर रहा हूँ, यहाँ मैं इसे कैसे उपयोग कर रहा हूँ का एक टुकड़ा है:

// Initialization 

NSURLSessionConfiguration *sessionConfiguration = [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier:@"<my-identifier>"]; 
sessionConfiguration.HTTPMaximumConnectionsPerHost = 40; 

backgroundSession = [NSURLSession sessionWithConfiguration:sessionConfiguration 
                delegate:self 
              delegateQueue:nil]; 

// ... 

// Creating the tasks and starting the download 
for (int i = 0; i < 20 && queuedRequests.count > 0; i++) { 
    NSDictionary *requestInfo = [queuedRequests lastObject]; 
    NSURLSessionDownloadTask *downloadTask = [backgroundSession downloadTaskWithURL:[NSURL URLWithString:requestInfo[@"url"]]]; 
    ongoingRequests[@(downloadTask.taskIdentifier)] = requestInfo; 
    [downloadTask resume]; 
    [queuedRequests removeLastObject]; 
    NSLog(@"Begin download file %d/%d: %@", allRequests.count - queuedRequests.count, allRequests.count, requestInfo[@"url"]); 
} 

// ... 

// Somewhere in (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location 

// After each download task is completed, grab a file to download from 
// queuedRequests, and create another task 

if (queuedRequests.count > 0) { 
    requestInfo = [queuedRequests lastObject]; 
    NSURLSessionDownloadTask *newDownloadTask = [backgroundSession downloadTaskWithURL:[NSURL URLWithString:requestInfo[@"url"]]]; 
    ongoingRequests[@(newDownloadTask.taskIdentifier)] = requestInfo; 

    [newDownloadTask resume]; 
    [queuedRequests removeLastObject]; 
    NSLog(@"Begin download file %d/%d: %@", allRequests.count - queuedRequests.count, allRequests.count, requestInfo[@"url"]); 
} 

मैं भी कई NSURLSession का उपयोग कर की कोशिश की है, लेकिन यह अभी भी धीमी है। कारण मैंने कोशिश की है क्योंकि cURL का उपयोग करते समय, मैं एकाधिक धागे (लगभग 20) बना देता हूं, और प्रत्येक थ्रेड एक समय में एक ही फ़ाइल डाउनलोड करेगा।

मेरे लिए ज़िप करके फ़ाइलों की संख्या को कम करना भी संभव नहीं है, क्योंकि मुझे ऐप को व्यक्तिगत फ़ाइलों को डाउनलोड करने में सक्षम होने की आवश्यकता है क्योंकि मैं उन्हें समय-समय पर अपडेट कर दूंगा। असल में, जब ऐप शुरू होता है, तो यह जांच करेगा कि क्या कोई भी फाइल अपडेट की गई है, और केवल उन फ़ाइलों को डाउनलोड करें। चूंकि फ़ाइलों को S3 में संग्रहीत किया जाता है, और S3 में ज़िप सेवा नहीं है, इसलिए मैं उन्हें फ्लाई पर एक फ़ाइल में ज़िप नहीं कर सका।

+1

'backgroundSessionConfigurationWithIdentifier को बदलने का प्रयास करें:' डिफ़ॉल्ट सत्र कॉन्फ़िगरेशन' के साथ और परिणामों की तुलना करें। मुझे नहीं लगता कि आईओएस वास्तव में परवाह करता है कि आपका ऐप चल रहा है या नहीं, पृष्ठभूमि डाउनलोड के लिए कॉन्फ़िगर किए गए सत्र पर डाउनलोड करते समय। यह हमेशा उन डाउनलोडों को एक अलग प्रक्रिया पर करेगा जो गति को थ्रॉटल करता है। –

+1

1. मैं फिलिप से सहमत हूं: अस्थायी रूप से गैर-पृष्ठभूमि सत्र का उपयोग करने का प्रयास करें और मुझे लगता है कि आप प्रदर्शन अंतर देख सकते हैं। मेरे अचूक परीक्षण ने सुझाव दिया कि पृष्ठभूमि सत्र (अग्रभूमि से भी निकाल दिया गया) धीमा था, हालांकि मैंने हाल ही में इसका परीक्षण नहीं किया है। – Rob

+3

2।पृष्ठभूमि सत्र का उपयोग करते समय, आपको "पहली 20 प्रक्रिया को कतार" की आवश्यकता नहीं है। बस उन्हें सब कतारो। उन्हें इस तरह से मीटिंग करके, आप पृष्ठभूमि प्रक्रिया को धीमा करने जा रहे हैं क्योंकि यदि निलंबित/समाप्त हो गया है तो यह लगातार आपके ऐप को फिर से फायर कर रहा है। फोरग्राउंड सत्र में टाइमआउट से बचने के लिए समरूपता की डिग्री को नियंत्रित करने की आवश्यकता होती है, लेकिन पृष्ठभूमि सत्रों के लिए नहीं। (फिर फिर, अगर मैं अग्रभूमि सत्र में समेकन की डिग्री नियंत्रित कर रहा था, तो मुझे लगता है कि ऑपरेशन कतार उस मामले में आसान समाधान है। लेकिन यदि आप पृष्ठभूमि सत्र का उपयोग कर रहे हैं तो शायद यह अकादमिक है।) – Rob

उत्तर

22

जैसा कि फिलिप और रॉब ने टिप्पणियों में उल्लेख किया है, धीमापन इसलिए है क्योंकि NSURLSessionbackgroundSessionConfigurationWithIdentifier: के साथ शुरू किया गया है, डाउनलोड कार्यों को पृष्ठभूमि में निष्पादित किया जाएगा भले ही ऐप अग्रभूमि में हो। अग्रभूमि डाउनलोड के लिए, और पृष्ठभूमि डाउनलोड के लिए एक:

NSURLSessionConfiguration *foregroundSessionConfig = [NSURLSessionConfiguration defaultSessionConfiguration]; 
foregroundSessionConfig.HTTPMaximumConnectionsPerHost = 40; 

foregroundSession = [NSURLSession sessionWithConfiguration:foregroundSessionConfig 
                delegate:self 
              delegateQueue:nil]; 
[foregroundSession retain]; 

NSURLSessionConfiguration *backgroundSessionConfig = [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier:@"com.terato.darknessfallen.BackgroundDownload"]; 
backgroundSessionConfig.HTTPMaximumConnectionsPerHost = 40; 

backgroundSession = [NSURLSession sessionWithConfiguration:backgroundSessionConfig 
                delegate:self 
              delegateQueue:nil]; 
[backgroundSession retain]; 

एप्लिकेशन को पृष्ठभूमि में परिवर्तन किया जाता है, मैं बस cancelByProducingResumeData: डाउनलोड कार्य अभी भी है कि में से प्रत्येक पर फोन तो मैं NSURLSession के 2 उदाहरणों होने से इस समस्या को हल चल रहा है, और फिर इसे downloadTaskWithResumeData: को पारित:

- (void)switchToBackground 
{ 
    if (state == kDownloadManagerStateForeground) { 
     [foregroundSession getTasksWithCompletionHandler:^(NSArray *dataTasks, NSArray *uploadTasks, NSArray *downloadTasks) { 
      for (NSURLSessionDownloadTask *downloadTask in downloadTasks) { 
       [downloadTask cancelByProducingResumeData:^(NSData *resumeData) { 
        NSURLSessionDownloadTask *downloadTask = [backgroundSession downloadTaskWithResumeData:resumeData]; 
        [downloadTask resume]; 
       }]; 
      } 
     }]; 

     state = kDownloadManagerStateBackground; 
    } 
} 

इसी तरह, जब एप्लिकेशन को अग्रभूमि में स्विच किया गया है, मैं भी ऐसा ही लेकिन backgroundSession साथ foregroundSession बंद:

- (void)switchToForeground 
{ 
    if (state == kDownloadManagerStateBackground) { 
     [backgroundSession getTasksWithCompletionHandler:^(NSArray *dataTasks, NSArray *uploadTasks, NSArray *downloadTasks) { 
      for (NSURLSessionDownloadTask *downloadTask in downloadTasks) { 
       [downloadTask cancelByProducingResumeData:^(NSData *resumeData) { 
        NSURLSessionDownloadTask *downloadTask = [foregroundSession downloadTaskWithResumeData:resumeData]; 
        [downloadTask resume]; 
       }]; 
      } 
     }]; 

     state = kDownloadManagerStateForeground; 
    } 
} 

इसके अलावा, switchToBackground पर कॉल करने से पहले beginBackgroundTaskWithExpirationHandler: पर कॉल करना न भूलें जब ऐप पृष्ठभूमि पर स्विच हो। यह सुनिश्चित करना है कि पृष्ठभूमि में होने पर विधि को पूरा करने की अनुमति है। अन्यथा, ऐप को फिर से अग्रभूमि में प्रवेश करने के बाद ही इसे बुलाया जाएगा।

+0

अच्छा काम, उत्तर के रूप में प्रश्न को चिह्नित करने के लिए अपने उत्तर को स्वीकार करने के लिए मत भूलना। –

+0

आप इसे दो बार कॉल करते हैं, 'foregroundSessionConfig.HTTPMaximumConnectionsPerHost = 40;' मुझे लगता है कि दूसरी बार जब आप ऑब्जेक्ट 'BackgroundSessionConfig' ऑब्जेक्ट का उपयोग करना चाहते थे? –

+0

2015 और अभी भी मैन्युअल संदर्भ गिनती में ?! :) बीटीडब्ल्यू, बहुत अच्छा सवाल और जवाब, धन्यवाद। – Martin

संबंधित मुद्दे