I am using Alamofire to do a basic requests to an API endpoint. I noticed that the more often I do these tests, the longer the Alamofire request seems to take.
I can reproduce this behaviour with the code sample below. This does a bunch of requests and prints the duration of the request to the console. The last request is about .5 seconds slower than the first one. The amount of slow down seems to be related to the amount of JSON the API returns (our API returns much more data and the slow down is much more significant)
Am I hitting some kind of caching mechanism here?
let testURL = "https://httpbin.org/get"
for var i = 0; i < 100; i++ {
let startDate = NSDate()
Alamofire.request(.GET, testURL)
.responseJSON { response in
print("Duration of request: \(NSDate().timeIntervalSinceDate(startDate))")
}
}
The problem here is not Alamofire, but how you are measuring the latency. You are queueing 100 requests, so the time it takes for each is very small. But since they are queued up, when the last request runs, will depend on the majority of previous requests finishing.
You should use the request timeline object to obtain the latency, with
request.timeline.totalDuration, for example.
Related
I have a timeOutInterval set to 30 seconds on all my requests via this code:
class DefaultAlamofireSession: Alamofire.Session {
static let shared: DefaultAlamofireSession = {
let configuration = URLSessionConfiguration.default
configuration.timeoutIntervalForRequest = 30
configuration.timeoutIntervalForResource = 30
return DefaultAlamofireSession(configuration: configuration)
}()
}
While testing, I noticed that only my GET requests get timed out at 30 seconds. My POST requests are still using the default interval which is 60 seconds.
Can anyone explain why and possibly tell me how I can make the POST requests also time out at 60 seconds?
Thanks a lot,
Paprika
URLSessionConfiguration.timeoutIntervalForRequest does not do what you think it does. From Apple's docs:
This property determines the request timeout interval for all tasks within sessions based on this configuration. The request timeout interval controls how long (in seconds) a task should wait for additional data to arrive before giving up. The timer associated with this value is reset whenever new data arrives. When the request timer reaches the specified interval without receiving any new data, it triggers a timeout.
So that property only controls the timeout between chunks of response Data. That's not typically what you want. Instead, you want to set the URLRequest.timeoutInterval directly, which does more of what you want.
If during a connection attempt the request remains idle for longer than the timeout interval, the request is considered to have timed out. The default timeout interval is 60 seconds.
As you can see, this timeout applies to the connection attempt, which is what most people think of as a request's timeout.
You can customize this value in Alamofire by applying a RequestAdapter to your custom Session. Or, you can use the requestModifier closure that available on the various request* methods.
If I set an 5 mins timeout interval for Alamofire request like below, it means an individual/overall API sync would take 5 mins?
sessionConfiguration.timeoutIntervalForRequest = 300
self.defaultManager = Alamofire.SessionManager(configuration: sessionConfiguration, serverTrustPolicyManager: policyManager)
No, it means that max time for timeout response is 300 seconds. If API finishes earlier you won't have to wait that much.
Regarding second question - it depends on your backend. For most cases 60 seconds is more then enough, however if you have any call that exceed it then you need to increase it. Note that it doesn't take parsing time into the consideration, just getting response from server. If you have large object that needs x minutes to parse but get it in 50 seconds it will be fine.
The main reason for timeout is because your server might never response and instead of letting your app hang, you can handle timeout error somehow.
I'm trying to fetch some weather data (Location forecast). This request return a couple of kb. OK, so I would only like to request the first part or terminate the request when i get the line
<temperature id="TTT" unit="celsius" value="xxxx"/>
Is it possible to do a URLRequest in iOS Swift that request a certain number of bytes/chars. Or is put into chunks and then terminated when temperature is received. I could setup a server acting as proxy and cut down the data exchanged to my app, but it would be nice if I could avoid this.
I'm creating an IOS app using swift.
Recently, I've encountered a weird bug.
Im trying to check if a url is valid, therefore, I'm creating a request with the url and check for the response. I do this task with dataTaskWithRequest of NSUrlSession.
The weird bug is that if the URL is alibaba ,the response returns after a long time(more than 20 seconds sometimes).
Why does that happen?
As far as i concerned it happens only with this specific url.
Here is some code although its not necessary .
let request = NSMutableURLRequest(URL: validatedUrl)
request.HTTPMethod = "HEAD"
let session = NSURLSession.sharedSession()
let task = session.dataTaskWithRequest(request){ data, response, error in
// The response here returns after a very long time
let url = request.URL!.absoluteString
I would appreciate some help guys!
You're retrieving the contents of a URL over the Internet. The speed at which this happens is arbitrary. It depends on the speed of the DNS server that looks up the hostname, the speed of the web server that responds to the request, the speed of the user's Internet connection, and the speed of every network in between.
You can safely assume that it will either succeed or time out within three minutes. Twenty seconds isn't even slightly unusual over a cellular network.
You should probably rethink what you're doing with this URL and why you're doing it, or at least try to figure out a way to avoid keeping the user waiting while you fetch the URL.
i have an HttpWebRequest that do 'POST' to a web server and get an HTML page In response.
I've been asked how is the best practice to know that the response i got has been changed or not?
I can't relay on the web server headers, they don't have to be.
this will increase performance in a way that i wont be need to parse the response over again and will go to the next request in a half of a sec or so.
thank you in advanced
You can tell your webserver about last modification date. see here. If you can't rely on that you have to parse your response anyway. You could do that quickly using md5. So you "md5" your current response and compare it with the previous.
You shouldn't be attempting to rely on the headers for a POST request, as it shouldn't emit any caching headers anyway.
What you need to do instead is perform a hash/checksum (this can either be CRC(32) for absolute performance or a "real" hash such as md5) on the returned content (this means, everything underneath the \r\n\r\n in the headers) and do a comparison that way.
It should be good enough to store the last request's checksum/hash and compare against that.
For example (psuedo):
int lastChecksum = 0;
bool hasChanged() {
performWebRequest();
string content = stripHeaders();
int checksum = crc32string(content);
if(checksum != lastChecksum) {
lastChecksum = checksum;
return true;
}
return false;
}