NSURLRequest Very Slow at First?

Discussion in 'iOS Programming' started by gwelmarten, Mar 22, 2013.

  1. gwelmarten macrumors 6502

    Joined:
    Jan 17, 2011
    Location:
    England!
    #1
    Hi there
    So, I am using NSURLRequest in my app twice to get two .txt files from my server using the following code:

    Code:
        NSString *responseStringIfYes;
        NSURLResponse *responseIfYes;
        NSError *errorIfYes = nil;
        NSURLRequest *requestIfYes = [[NSMutableURLRequest alloc]
                                      initWithURL:[NSURL URLWithString:@"http://my-site.com/open-if-no--maintenance-mode-if-yes.txt"]
                                      cachePolicy:NSURLRequestReloadIgnoringLocalCacheData
                                      timeoutInterval:5]; // 5 second timeout?
    
    
        NSData* dataIfYes = [NSURLConnection sendSynchronousRequest:requestIfYes returningResponse:&responseIfYes error:&errorIfYes];
    
        responseStringIfYes = [[NSString alloc] initWithData:dataIfYes encoding:NSUTF8StringEncoding];
        NSLog(@"Recieved String Result: %@", responseStringIfYes);
    
    
        // Get text for the message contents.
        NSString *responseStringMessage;
        NSURLResponse *responseMessage;
        NSError *errorMessage = nil;
        NSURLRequest *requestMessage = [[NSMutableURLRequest alloc]
                                        initWithURL:[NSURL URLWithString:@"http://my-site.com/maintenance-message-contents.txt"]
                                        cachePolicy:NSURLRequestReloadIgnoringLocalCacheData
                                        timeoutInterval:5]; // 5 second timeout?
    
    
        NSData* dataMessage = [NSURLConnection sendSynchronousRequest:requestMessage returningResponse:&responseMessage error:&errorMessage];
    
    
        responseStringMessage = [[NSString alloc] initWithData:dataMessage encoding:NSUTF8StringEncoding];
    
        NSLog(@"Recieved String Result: %@", responseStringMessage);

    and am having some problems with the timings. I use the following in terminal to setup a pipe to my server, increasing the ping to simulate a poor internet connection (to test the app in such an environment).

    Code:
    ipfw pipe 1 config delay 1500ms bw 1Mbit/s plr 0
    I have this setup for a pipe to and from my server, so when I ping the server in terminal I get a ping time of a little over 3000ms. Because my timeout is 5s, I would not have thought this was a problem. However, I am having a problem with the first request, as follows:

    In my log, I get:


    Code:
    2013-03-22 17:27:40.385 Million Taps[5898:c07] Checking Maintenance Mode
    
    2013-03-22 17:27:46.623 Million Taps[5898:c07] Recieved String Result: no
    
    2013-03-22 17:27:49.746 Million Taps[5898:c07] Recieved String Result: Maintenance Mode Active

    which shows that it takes 6.3 seconds from checking maintenance mode to getting the first file, and then the second files comes just over 3000ms after it is first requested.

    My question is: why does the first file not come just over 3000ms after it is first requested also? Seems very odd?

    Thanks,

    Sam
     
  2. Duncan C macrumors 6502a

    Duncan C

    Joined:
    Jan 21, 2008
    Location:
    Northern Virginia
    #2

    I don't know the answer to your question about longer-than-expected delays.

    However, I want to point out that you should not use synchronous NSURLConnection calls in production code. it locks up the user interface until the download is complete.

    Use sendAsynchronousRequest:queue:completionHandler: instead.

    That method will invoke the provided completion handler block once the download is complete, and pass you the resulting data. That makes it very easy to create an async download and return control to the user until the download is complete.

    Alternatively you can use the older initWithRequest:delegate:startImmediately: form, and set up an NSURLConnectionDelegate and NSURLConnectionDataDelegate to handle the incoming data. (If you're downloading very large files it might be better to use
    Code:
    initWithRequest:delegate:startImmediately:
    and append your data to a file as it comes in rather than holding entire byte-stream in memory until it's complete)
     
  3. chown33 macrumors 604

    Joined:
    Aug 9, 2009
    #3
    Maybe the longer initial delay is due to the TCP three-way handshake (you can look this up) that establishes a connection.

    Since 'ipfw pipe' appears to be applied at the packet level, establishing a connection would probably take longer than reusing an existing connection.

    The HTTP protocol supports keep-alive connections (again, you can look this up).

    Putting it all together, suppose the first connection creates a keep-alive connection, and the second one reuses the existing connection. Then I would fully expect the first connection to take longer than all subsequent ones to the same host, within the limits of the keep-alive time.

    If you want a better picture of what happens on the wire, you need a tool that lets you look at the traffic on the wire. Look up wireshark and tcpdump.
     

Share This Page