Toggle navigation
Toggle navigation
This project
Loading...
Sign in
iOS
/
asi-http-request
Go to a project
Toggle navigation
Toggle navigation pinning
Projects
Groups
Snippets
Help
Project
Activity
Repository
Pipelines
Graphs
Issues
0
Merge Requests
0
Wiki
Network
Create a new issue
Builds
Commits
Authored by
Ben Copsey
2009-12-19 16:56:52 +0000
Browse Files
Options
Browse Files
Download
Email Patches
Plain Diff
Commit
9c90f90c4bcd56df6c9775224da53e536b3cea0b
9c90f90c
1 parent
a38a87fc
Added support for persistent http connections
More performance tests
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
192 additions
and
13 deletions
Classes/ASIHTTPRequest.h
Classes/ASIHTTPRequest.m
Classes/Tests/PerformanceTests.h
Classes/Tests/PerformanceTests.m
Classes/ASIHTTPRequest.h
View file @
9c90f90
...
...
@@ -331,6 +331,14 @@ extern unsigned long const ASIWWANBandwidthThrottleAmount;
// The number of times this request has retried (when numberOfTimesToRetryOnTimeout > 0)
int
retryCount
;
// When YES, requests will keep the connection to the server alive for a while to allow subsequent requests to re-use it for a substatial speed-boost
// Persistent connections only work when the server sends a 'Keep-Alive' header
// Default is YES
BOOL
shouldAttemptPersistentConnection
;
// Set to yes when an appropriate keep-alive header is found
BOOL
canUsePersistentConnection
;
}
#pragma mark init / dealloc
...
...
@@ -666,4 +674,5 @@ extern unsigned long const ASIWWANBandwidthThrottleAmount;
@property
(
assign
)
BOOL
shouldRunInBackgroundThread
;
@property
(
assign
)
int
numberOfTimesToRetryOnTimeout
;
@property
(
assign
,
readonly
)
int
retryCount
;
@property
(
assign
)
BOOL
shouldAttemptPersistentConnection
;
@end
...
...
Classes/ASIHTTPRequest.m
View file @
9c90f90
...
...
@@ -21,7 +21,7 @@
#import "ASIInputStream.h"
// Automatically set on build
NSString
*
ASIHTTPRequestVersion
=
@"v1.2-5
2
2009-12-19"
;
NSString
*
ASIHTTPRequestVersion
=
@"v1.2-5
3
2009-12-19"
;
NSString
*
const
NetworkRequestErrorDomain
=
@"ASIHTTPRequestErrorDomain"
;
...
...
@@ -154,6 +154,7 @@ static BOOL isiPhoneOS2;
@property
(
assign
)
BOOL
isSynchronous
;
@property
(
assign
)
BOOL
inProgress
;
@property
(
assign
)
int
retryCount
;
@property
(
assign
)
BOOL
canUsePersistentConnection
;
@end
...
...
@@ -191,6 +192,7 @@ static BOOL isiPhoneOS2;
self
=
[
super
init
];
[
self
setRequestMethod
:
@"GET"
];
[
self
setShouldAttemptPersistentConnection
:
YES
];
[
self
setShouldPresentCredentialsBeforeChallenge
:
YES
];
[
self
setShouldRedirect
:
YES
];
[
self
setShowAccurateProgress
:
YES
];
...
...
@@ -808,6 +810,9 @@ static BOOL isiPhoneOS2;
CFReadStreamSetProperty
(
readStream
,
kCFStreamPropertySSLSettings
,
[
NSMutableDictionary
dictionaryWithObject
:(
NSString
*
)
kCFBooleanFalse
forKey
:(
NSString
*
)
kCFStreamSSLValidatesCertificateChain
]);
}
// Use a persistent connection if possible
CFReadStreamSetProperty
(
readStream
,
kCFStreamPropertyHTTPAttemptPersistentConnection
,
kCFBooleanTrue
);
// Handle proxy settings
...
...
@@ -930,10 +935,20 @@ static BOOL isiPhoneOS2;
[
self
scheduleReadStream
];
}
while
(
!
complete
)
{
[
self
checkRequestStatus
];
CFRunLoopRunInMode
(
kCFRunLoopDefaultMode
,
0
.
25
,
NO
);
}
// if ([NSThread isMainThread]) {
// [NSTimer scheduledTimerWithTimeInterval:0.25 target:self selector:@selector(updateStatus:) userInfo:nil repeats:YES];
// CFRunLoopRunInMode(kCFRunLoopDefaultMode, timeOutSeconds, NO);
//
// } else if (!uploadProgressDelegate && !downloadProgressDelegate) {
// CFRunLoopRunInMode(kCFRunLoopDefaultMode, timeOutSeconds, NO);
// [self checkRequestStatus];
// } else {
while
(
!
complete
)
{
[
self
checkRequestStatus
];
CFRunLoopRunInMode
(
kCFRunLoopDefaultMode
,
0
.
25
,
NO
);
}
//}
}
// This gets fired every 1/4 of a second in asynchronous requests to update the progress and work out if we need to timeout
...
...
@@ -1594,11 +1609,32 @@ static BOOL isiPhoneOS2;
}
// Handle connection persistence
if
([
self
shouldAttemptPersistentConnection
]
&&
[[[
self
responseHeaders
]
objectForKey
:
@"Connection"
]
isEqualToString
:
@"Keep-Alive"
])
{
NSString
*
keepAliveHeader
=
[[
self
responseHeaders
]
objectForKey
:
@"Keep-Alive"
];
if
(
keepAliveHeader
)
{
int
timeout
=
0
;
int
max
=
0
;
NSScanner
*
scanner
=
[
NSScanner
scannerWithString
:
keepAliveHeader
];
[
scanner
scanString
:
@"timeout="
intoString
:
NULL
];
[
scanner
scanInt
:
&
timeout
];
[
scanner
scanUpToString
:
@"max="
intoString
:
NULL
];
[
scanner
scanString
:
@"max="
intoString
:
NULL
];
[
scanner
scanInt
:
&
max
];
if
(
max
>
5
)
{
[
self
setCanUsePersistentConnection
:
YES
];
CFRetain
(
readStream
);
[
NSTimer
scheduledTimerWithTimeInterval
:
max
target
:[
self
class
]
selector
:
@selector
(
closePersistentConnection
:
)
userInfo
:
(
id
)
readStream
repeats
:
NO
];
}
}
}
}
CFRelease
(
headers
);
return
isAuthenticationChallenge
;
}
#pragma mark http authentication
...
...
@@ -2222,12 +2258,14 @@ static BOOL isiPhoneOS2;
if
([
self
needsRedirect
])
{
return
;
}
long
long
bufferSize
=
2048
;
if
(
contentLength
>
262144
)
{
bufferSize
=
65536
;
}
else
if
(
contentLength
>
65536
)
{
bufferSize
=
16384
;
}
// long long bufferSize = 2048;
// if (contentLength > 262144) {
// bufferSize = 65536;
// } else if (contentLength > 65536) {
// bufferSize = 16384;
// }
long
long
bufferSize
=
262144
;
// Reduce the buffer size if we're receiving data too quickly when bandwidth throttling is active
// This just augments the throttling done in measureBandwidthUsage to reduce the amount we go over the limit
...
...
@@ -2397,7 +2435,9 @@ static BOOL isiPhoneOS2;
if
(
readStreamIsScheduled
)
{
CFReadStreamUnscheduleFromRunLoop
(
readStream
,
CFRunLoopGetCurrent
(),
kCFRunLoopDefaultMode
);
}
CFReadStreamClose
(
readStream
);
if
(
!
canUsePersistentConnection
)
{
CFReadStreamClose
(
readStream
);
}
CFRelease
(
readStream
);
readStream
=
NULL
;
}
...
...
@@ -2421,6 +2461,13 @@ static BOOL isiPhoneOS2;
}
}
+
(
void
)
closePersistentConnection
:
(
NSTimer
*
)
timer
{
CFReadStreamRef
stream
=
(
CFReadStreamRef
)[
timer
userInfo
];
CFReadStreamClose
(
stream
);
CFRelease
(
stream
);
}
#pragma mark NSCopying
-
(
id
)
copyWithZone
:
(
NSZone
*
)
zone
...
...
@@ -3427,6 +3474,8 @@ static BOOL isiPhoneOS2;
@synthesize
shouldRunInBackgroundThread
;
@synthesize
numberOfTimesToRetryOnTimeout
;
@synthesize
retryCount
;
@synthesize
shouldAttemptPersistentConnection
;
@synthesize
canUsePersistentConnection
;
@end
...
...
Classes/Tests/PerformanceTests.h
View file @
9c90f90
...
...
@@ -10,6 +10,8 @@
#import "ASITestCase.h"
@interface
PerformanceTests
:
ASITestCase
{
NSURL
*
testURL
;
NSDate
*
testStartDate
;
int
requestsComplete
;
NSMutableArray
*
responseData
;
...
...
@@ -19,6 +21,7 @@
-
(
void
)
testASIHTTPRequestAsyncPerformance
;
-
(
void
)
testNSURLConnectionAsyncPerformance
;
@property
(
retain
,
nonatomic
)
NSURL
*
testURL
;
@property
(
retain
,
nonatomic
)
NSDate
*
testStartDate
;
@property
(
assign
,
nonatomic
)
int
requestsComplete
;
@property
(
retain
,
nonatomic
)
NSMutableArray
*
responseData
;
...
...
Classes/Tests/PerformanceTests.m
View file @
9c90f90
...
...
@@ -9,6 +9,7 @@
#import "PerformanceTests.h"
#import "ASIHTTPRequest.h"
@interface
NSURLConnectionSubclass
:
NSURLConnection
{
int
tag
;
}
...
...
@@ -21,11 +22,105 @@
@implementation
PerformanceTests
-
(
void
)
setUp
{
[
self
setTestURL
:[
NSURL
URLWithString
:
@"http://allseeing-i.com"
]];
}
-
(
void
)
testASIHTTPRequestSynchronousPerformance
{
[
self
performSelectorOnMainThread
:
@selector
(
runSynchronousASIHTTPRequests
)
withObject
:
nil
waitUntilDone
:
YES
];
}
-
(
void
)
runSynchronousASIHTTPRequests
{
int
runTimes
=
10
;
NSTimeInterval
times
[
runTimes
];
int
i
;
for
(
i
=
0
;
i
<
runTimes
;
i
++
)
{
NSDate
*
startTime
=
[
NSDate
date
];
ASIHTTPRequest
*
request
=
[
ASIHTTPRequest
requestWithURL
:
testURL
];
//Send the same headers as NSURLRequest
[
request
addRequestHeader
:
@"Pragma"
value
:
@"no-cache"
];
[
request
addRequestHeader
:
@"Accept"
value
:
@"*/*"
];
[
request
addRequestHeader
:
@"Accept-Language"
value
:
@"en/us"
];
[
request
setUseCookiePersistance
:
NO
];
[
request
setUseSessionPersistance
:
NO
];
//[request setShouldRunInBackgroundThread:YES];
[
request
startSynchronous
];
if
([
request
error
])
{
NSLog
(
@"Request failed - cannot proceed with test"
);
return
;
}
times
[
i
]
=
[[
NSDate
date
]
timeIntervalSinceDate
:
startTime
];
}
NSTimeInterval
bestTime
=
1000
;
NSTimeInterval
worstTime
=
0
;
NSTimeInterval
totalTime
=
0
;
for
(
i
=
0
;
i
<
runTimes
;
i
++
)
{
if
(
times
[
i
]
<
bestTime
)
{
bestTime
=
times
[
i
];
}
if
(
times
[
i
]
>
worstTime
)
{
worstTime
=
times
[
i
];
}
totalTime
+=
times
[
i
];
}
NSLog
(
@"Ran runTimes requests in %f seconds (average time: %f secs / best time: %f secs / worst time: %f secs)"
,
totalTime
,
totalTime
/
runTimes
,
bestTime
,
worstTime
);
}
-
(
void
)
testNSURLConnectionSynchronousPerformance
{
[
self
performSelectorOnMainThread
:
@selector
(
runSynchronousNSURLConnections
)
withObject
:
nil
waitUntilDone
:
YES
];
}
-
(
void
)
runSynchronousNSURLConnections
{
int
runTimes
=
10
;
NSTimeInterval
times
[
runTimes
];
int
i
;
for
(
i
=
0
;
i
<
runTimes
;
i
++
)
{
NSDate
*
startTime
=
[
NSDate
date
];
NSURLResponse
*
response
=
nil
;
NSError
*
error
=
nil
;
NSMutableURLRequest
*
request
=
[
NSMutableURLRequest
requestWithURL
:
testURL
cachePolicy
:
NSURLRequestReloadIgnoringLocalCacheData
timeoutInterval
:
10
];
[
NSURLConnection
sendSynchronousRequest
:
request
returningResponse
:
&
response
error
:&
error
];
if
(
error
)
{
NSLog
(
@"Request failed - cannot proceed with test"
);
return
;
}
times
[
i
]
=
[[
NSDate
date
]
timeIntervalSinceDate
:
startTime
];
}
NSTimeInterval
bestTime
=
1000
;
NSTimeInterval
worstTime
=
0
;
NSTimeInterval
totalTime
=
0
;
for
(
i
=
0
;
i
<
runTimes
;
i
++
)
{
if
(
times
[
i
]
<
bestTime
)
{
bestTime
=
times
[
i
];
}
if
(
times
[
i
]
>
worstTime
)
{
worstTime
=
times
[
i
];
}
totalTime
+=
times
[
i
];
}
NSLog
(
@"Ran runTimes requests in %f seconds (average time: %f secs / best time: %f secs / worst time: %f secs)"
,
totalTime
,
totalTime
/
runTimes
,
bestTime
,
worstTime
);
}
-
(
void
)
testASIHTTPRequestAsyncPerformance
{
[
self
performSelectorOnMainThread
:
@selector
(
startASIHTTPRequests
)
withObject
:
nil
waitUntilDone
:
NO
];
}
-
(
void
)
testASIHTTPRequestAsyncPerformanceWithQueue
{
[
self
performSelectorOnMainThread
:
@selector
(
startASIHTTPRequestsWithQueue
)
withObject
:
nil
waitUntilDone
:
NO
];
}
-
(
void
)
startASIHTTPRequests
{
...
...
@@ -35,11 +130,33 @@
int
i
;
for
(
i
=
0
;
i
<
10
;
i
++
)
{
ASIHTTPRequest
*
request
=
[
ASIHTTPRequest
requestWithURL
:[
NSURL
URLWithString
:
@"http://allseeing-i.com/ASIHTTPRequest/tests/the_great_american_novel_(abridged).txt"
]];
//Send the same headers as NSURLRequest
[
request
addRequestHeader
:
@"Pragma"
value
:
@"no-cache"
];
[
request
addRequestHeader
:
@"Accept"
value
:
@"*/*"
];
[
request
addRequestHeader
:
@"Accept-Language"
value
:
@"en/us"
];
[
request
setDelegate
:
self
];
[
request
start
];
}
}
-
(
void
)
startASIHTTPRequestsWithQueue
{
bytesDownloaded
=
0
;
[
self
setRequestsComplete
:
0
];
[
self
setTestStartDate
:[
NSDate
date
]];
int
i
;
NSOperationQueue
*
queue
=
[[[
NSOperationQueue
alloc
]
init
]
autorelease
];
for
(
i
=
0
;
i
<
10
;
i
++
)
{
ASIHTTPRequest
*
request
=
[
ASIHTTPRequest
requestWithURL
:[
NSURL
URLWithString
:
@"http://allseeing-i.com/ASIHTTPRequest/tests/the_great_american_novel_(abridged).txt"
]];
//Send the same headers as NSURLRequest
[
request
addRequestHeader
:
@"Pragma"
value
:
@"no-cache"
];
[
request
addRequestHeader
:
@"Accept"
value
:
@"*/*"
];
[
request
addRequestHeader
:
@"Accept-Language"
value
:
@"en/us"
];
[
request
setDelegate
:
self
];
[
queue
addOperation
:
request
];
}
}
-
(
void
)
requestFailed
:
(
ASIHTTPRequest
*
)
request
{
GHFail
(
@"Cannot proceed with ASIHTTPRequest test - a request failed"
);
...
...
@@ -99,6 +216,7 @@
}
}
@synthesize
testURL
;
@synthesize
requestsComplete
;
@synthesize
testStartDate
;
@synthesize
responseData
;
...
...
Please
register
or
login
to post a comment