Ben Copsey

Add starting point for bandwidth average tracking

@@ -462,6 +462,8 @@ extern unsigned long const ASIWWANBandwidthThrottleAmount; @@ -462,6 +462,8 @@ extern unsigned long const ASIWWANBandwidthThrottleAmount;
462 + (unsigned long)maxBandwidthPerSecond; 462 + (unsigned long)maxBandwidthPerSecond;
463 + (void)setMaxBandwidthPerSecond:(unsigned long)bytes; 463 + (void)setMaxBandwidthPerSecond:(unsigned long)bytes;
464 464
  465 ++ (unsigned long)averageBandwidthUsedPerSecond;
  466 +
465 #if TARGET_OS_IPHONE 467 #if TARGET_OS_IPHONE
466 // Set to YES to automatically turn on throttling when WWAN is connected, and automatically turn it off when it isn't 468 // Set to YES to automatically turn on throttling when WWAN is connected, and automatically turn it off when it isn't
467 + (void)setShouldThrottleBandwidthForWWAN:(BOOL)throttle; 469 + (void)setShouldThrottleBandwidthForWWAN:(BOOL)throttle;
@@ -49,6 +49,8 @@ static NSError *ASIAuthenticationError; @@ -49,6 +49,8 @@ static NSError *ASIAuthenticationError;
49 static NSError *ASIUnableToCreateRequestError; 49 static NSError *ASIUnableToCreateRequestError;
50 static NSError *ASITooMuchRedirectionError; 50 static NSError *ASITooMuchRedirectionError;
51 51
  52 +static NSMutableArray *bandwidthUsageTracker = nil;
  53 +
52 // Used for throttling bandwidth 54 // Used for throttling bandwidth
53 // I am assuming you don't have a connection capable of more than 4GB/second? If so, why are you reading this? Aren't you supposed to be backing up the Internet?! 55 // I am assuming you don't have a connection capable of more than 4GB/second? If so, why are you reading this? Aren't you supposed to be backing up the Internet?!
54 static unsigned long bandwidthUsedInLastSecond = 0; 56 static unsigned long bandwidthUsedInLastSecond = 0;
@@ -78,6 +80,7 @@ BOOL shouldThrottleBandwidth = NO; @@ -78,6 +80,7 @@ BOOL shouldThrottleBandwidth = NO;
78 + (void)incrementBandwidthUsedInLastSecond:(unsigned long)bytes; 80 + (void)incrementBandwidthUsedInLastSecond:(unsigned long)bytes;
79 + (void)performBandwidthThrottling; 81 + (void)performBandwidthThrottling;
80 + (BOOL)shouldThrottleBandwidth; 82 + (BOOL)shouldThrottleBandwidth;
  83 ++ (void)recordBandwidthUsage;
81 84
82 @property (assign) BOOL complete; 85 @property (assign) BOOL complete;
83 @property (retain) NSDictionary *responseHeaders; 86 @property (retain) NSDictionary *responseHeaders;
@@ -122,6 +125,7 @@ BOOL shouldThrottleBandwidth = NO; @@ -122,6 +125,7 @@ BOOL shouldThrottleBandwidth = NO;
122 if (self == [ASIHTTPRequest class]) { 125 if (self == [ASIHTTPRequest class]) {
123 progressLock = [[NSRecursiveLock alloc] init]; 126 progressLock = [[NSRecursiveLock alloc] init];
124 bandwidthThrottlingLock = [[NSLock alloc] init]; 127 bandwidthThrottlingLock = [[NSLock alloc] init];
  128 + bandwidthUsageTracker = [[NSMutableArray alloc] initWithCapacity:10];
125 ASIRequestTimedOutError = [[NSError errorWithDomain:NetworkRequestErrorDomain code:ASIRequestTimedOutErrorType userInfo:[NSDictionary dictionaryWithObjectsAndKeys:@"The request timed out",NSLocalizedDescriptionKey,nil]] retain]; 129 ASIRequestTimedOutError = [[NSError errorWithDomain:NetworkRequestErrorDomain code:ASIRequestTimedOutErrorType userInfo:[NSDictionary dictionaryWithObjectsAndKeys:@"The request timed out",NSLocalizedDescriptionKey,nil]] retain];
126 ASIAuthenticationError = [[NSError errorWithDomain:NetworkRequestErrorDomain code:ASIAuthenticationErrorType userInfo:[NSDictionary dictionaryWithObjectsAndKeys:@"Authentication needed",NSLocalizedDescriptionKey,nil]] retain]; 130 ASIAuthenticationError = [[NSError errorWithDomain:NetworkRequestErrorDomain code:ASIAuthenticationErrorType userInfo:[NSDictionary dictionaryWithObjectsAndKeys:@"Authentication needed",NSLocalizedDescriptionKey,nil]] retain];
127 ASIRequestCancelledError = [[NSError errorWithDomain:NetworkRequestErrorDomain code:ASIRequestCancelledErrorType userInfo:[NSDictionary dictionaryWithObjectsAndKeys:@"The request was cancelled",NSLocalizedDescriptionKey,nil]] retain]; 131 ASIRequestCancelledError = [[NSError errorWithDomain:NetworkRequestErrorDomain code:ASIRequestCancelledErrorType userInfo:[NSDictionary dictionaryWithObjectsAndKeys:@"The request was cancelled",NSLocalizedDescriptionKey,nil]] retain];
@@ -1647,11 +1651,11 @@ BOOL shouldThrottleBandwidth = NO; @@ -1647,11 +1651,11 @@ BOOL shouldThrottleBandwidth = NO;
1647 } 1651 }
1648 1652
1649 // Reduce the buffer size if we're receiving data too quickly when bandwidth throttling is active 1653 // Reduce the buffer size if we're receiving data too quickly when bandwidth throttling is active
1650 - // This just augments the throttling done in performBandwidthThrottling 1654 + // This just augments the throttling done in performBandwidthThrottling to reduce the amount we go over the limit
1651 - if ([ASIHTTPRequest shouldThrottleBandwidth]) { 1655 + [bandwidthThrottlingLock lock];
1652 - long long maxSize = [ASIHTTPRequest maxBandwidthPerSecond]; 1656 + if (shouldThrottleBandwidth) {
1653 - if (maxSize > 0) { 1657 + if (maxBandwidthPerSecond > 0) {
1654 - maxSize = maxSize-[ASIHTTPRequest bandwidthUsedInLastSecond]; 1658 + long long maxSize = maxBandwidthPerSecond-bandwidthUsedInLastSecond;
1655 if (maxSize < 0) { 1659 if (maxSize < 0) {
1656 // We aren't supposed to read any more data right now, but we'll read a single byte anyway so the CFNetwork's buffer isn't full 1660 // We aren't supposed to read any more data right now, but we'll read a single byte anyway so the CFNetwork's buffer isn't full
1657 bufferSize = 1; 1661 bufferSize = 1;
@@ -1661,6 +1665,7 @@ BOOL shouldThrottleBandwidth = NO; @@ -1661,6 +1665,7 @@ BOOL shouldThrottleBandwidth = NO;
1661 } 1665 }
1662 } 1666 }
1663 } 1667 }
  1668 + [bandwidthThrottlingLock unlock];
1664 1669
1665 UInt8 buffer[bufferSize]; 1670 UInt8 buffer[bufferSize];
1666 CFIndex bytesRead = CFReadStreamRead(readStream, buffer, sizeof(buffer)); 1671 CFIndex bytesRead = CFReadStreamRead(readStream, buffer, sizeof(buffer));
@@ -2334,6 +2339,29 @@ BOOL shouldThrottleBandwidth = NO; @@ -2334,6 +2339,29 @@ BOOL shouldThrottleBandwidth = NO;
2334 [bandwidthThrottlingLock unlock]; 2339 [bandwidthThrottlingLock unlock];
2335 } 2340 }
2336 2341
  2342 ++ (void)recordBandwidthUsage
  2343 +{
  2344 + NSTimeInterval interval = [bandwidthThrottlingMeasurementDate timeIntervalSinceNow];
  2345 + while (interval-1 > 0) {
  2346 + [bandwidthUsageTracker removeObjectAtIndex:0];
  2347 + }
  2348 + [bandwidthUsageTracker addObject:[NSNumber numberWithUnsignedLong:bandwidthUsedInLastSecond]];
  2349 + bandwidthThrottlingMeasurementDate = [NSDate dateWithTimeIntervalSinceNow:1];
  2350 + bandwidthUsedInLastSecond = 0;
  2351 +}
  2352 +
  2353 ++ (unsigned long)averageBandwidthUsedPerSecond
  2354 +{
  2355 + [bandwidthThrottlingLock lock];
  2356 + int measurements = [bandwidthUsageTracker count];
  2357 + unsigned long long totalBytes = 0;
  2358 + for (NSNumber *bytes in bandwidthUsageTracker) {
  2359 + totalBytes += [bytes unsignedLongValue];
  2360 + }
  2361 + [bandwidthThrottlingLock unlock];
  2362 + return totalBytes/measurements;
  2363 +}
  2364 +
2337 + (void)performBandwidthThrottling 2365 + (void)performBandwidthThrottling
2338 { 2366 {
2339 // Other requests may have to wait for this lock if we're sleeping, but this is fine, since in that case we already know they shouldn't be sending or receiving data 2367 // Other requests may have to wait for this lock if we're sleeping, but this is fine, since in that case we already know they shouldn't be sending or receiving data
@@ -2342,7 +2370,7 @@ BOOL shouldThrottleBandwidth = NO; @@ -2342,7 +2370,7 @@ BOOL shouldThrottleBandwidth = NO;
2342 // Are we performing bandwidth throttling? 2370 // Are we performing bandwidth throttling?
2343 if (maxBandwidthPerSecond > 0) { 2371 if (maxBandwidthPerSecond > 0) {
2344 if (!bandwidthThrottlingMeasurementDate || [bandwidthThrottlingMeasurementDate timeIntervalSinceNow] < 0) { 2372 if (!bandwidthThrottlingMeasurementDate || [bandwidthThrottlingMeasurementDate timeIntervalSinceNow] < 0) {
2345 - bandwidthThrottlingMeasurementDate = [NSDate dateWithTimeIntervalSinceNow:1]; 2373 + [self recordBandwidthUsage];
2346 } 2374 }
2347 2375
2348 // How much data can we still send or receive this second? 2376 // How much data can we still send or receive this second?
@@ -2353,7 +2381,7 @@ BOOL shouldThrottleBandwidth = NO; @@ -2353,7 +2381,7 @@ BOOL shouldThrottleBandwidth = NO;
2353 2381
2354 // Yes, put this request to sleep until a second is up 2382 // Yes, put this request to sleep until a second is up
2355 [NSThread sleepUntilDate:bandwidthThrottlingMeasurementDate]; 2383 [NSThread sleepUntilDate:bandwidthThrottlingMeasurementDate];
2356 - bandwidthThrottlingMeasurementDate = [NSDate dateWithTimeIntervalSinceNow:1]; 2384 + [self recordBandwidthUsage];
2357 } 2385 }
2358 } 2386 }
2359 [bandwidthThrottlingLock unlock]; 2387 [bandwidthThrottlingLock unlock];
@@ -794,7 +794,6 @@ @@ -794,7 +794,6 @@
794 } 794 }
795 795
796 796
797 -  
798 @end 797 @end
799 798
800 799
This diff is collapsed. Click to expand it.