Bug 39887 - NSUrlSessionDownloadDelegate is significantly slower than ModernHttpClient
Summary: NSUrlSessionDownloadDelegate is significantly slower than ModernHttpClient
Alias: None
Product: iOS
Classification: Xamarin
Component: Xamarin.iOS.dll ()
Version: XI 9.4 (iOS 9.2)
Hardware: PC Mac OS
: --- normal
Target Milestone: Untriaged
Assignee: Bugzilla
Depends on:
Reported: 2016-03-24 12:15 UTC by John Miller [MSFT]
Modified: 2016-03-24 12:40 UTC (History)
3 users (show)

Is this bug a regression?: ---
Last known good build:

Notice (2018-05-24): bugzilla.xamarin.com is now in read-only mode.

Please join us on Visual Studio Developer Community and in the Xamarin and Mono organizations on GitHub to continue tracking issues. Bugzilla will remain available for reference in read-only mode. We will continue to work on open Bugzilla bugs, copy them to the new locations as needed for follow-up, and add the new items under Related Links.

Our sincere thanks to everyone who has contributed on this bug tracker over the years. Thanks also for your understanding as we make these adjustments and improvements for the future.

Please create a new report on Developer Community or GitHub with your current version information, steps to reproduce, and relevant error messages or log files if you are hitting an issue that looks similar to this resolved bug and you do not yet see a matching new report.

Related Links:

Description John Miller [MSFT] 2016-03-24 12:15:55 UTC

   The attached sample reproduces a scenario where downloading an image with NSUrlSessionDownloadDelegate is much slower than when using ModernHttpClient with NativeMessageHandler. 

**Steps to Reproduce:**

   1. Run the attached project on an iOS simulator/device
   2. Press the button
   3. Observe the Application Output logs
   4. Repeat these steps a few times

**Actual Results:**

   NSUrlSessionDownloadDelegate takes ~1 second
   ModernHttpClient takes ~5 milliseconds

**Expected Results:**

   Similar times to download the image

**Build Date & Platform:**

   === Xamarin Studio ===

Version 6.0 (build 4801)
Installation UUID: e01c3049-a2d2-4e0a-aad8-afe6fb627c4d
	Mono 4.4.0 (mono-4.4.0-branch/f8474c4) (64-bit)
	GTK+ 2.24.23 (Raleigh theme)

	Package version: 404000040

=== Xamarin.Profiler ===

Not Installed

=== Apple Developer Tools ===

Xcode 7.2 (9548)
Build 7C68

=== Xamarin.iOS ===

Version: (Business Edition)
Hash: 962a050
Branch: master
Build date: 2016-01-29 16:59:11-0500

=== Xamarin.Android ===

Version: (Business Edition)
Android SDK: /Users/johnmiller/Library/Developer/Xamarin/android-sdk-macosx
	Supported Android versions:
		2.3   (API level 10)
		4.0.3 (API level 15)
		4.1   (API level 16)
		4.2   (API level 17)
		4.4   (API level 19)
		5.0   (API level 21)
		5.1   (API level 22)
		6.0   (API level 23)

SDK Tools Version: 24.4.1
SDK Platform Tools Version: 23.1
SDK Build Tools Version: 23.0.2

Java SDK: /usr
java version "1.8.0_60"
Java(TM) SE Runtime Environment (build 1.8.0_60-b27)
Java HotSpot(TM) 64-Bit Server VM (build 25.60-b23, mixed mode)

Android Designer EPL code available here:

=== Xamarin Android Player ===

Version: 0.6.5
Location: /Applications/Xamarin Android Player.app

=== Xamarin.Mac ===

Version: (Starter Edition)

=== Build Information ===

Release ID: 600004801
Git revision: f73f730c738baf8701a5892b7af64fd468d1dc0c
Build date: 2016-03-14 14:28:06-04
Xamarin addins: 3af7be6c701eb0137645a03e38b82f23b65738c3
Build lane: monodevelop-lion-cycle7

=== Operating System ===

Mac OS X 10.11.2
Comment 2 Sebastien Pouliot 2016-03-24 12:40:10 UTC
Reset (easier on simulator, create new app name on devices) then run (first time) to see:

2016-03-24 08:30:28.452 MapView[11068:6401131] DownloadWithWebClient : Elapsed : 675, number of bytes : 173985
2016-03-24 08:30:29.323 MapView[11068:6401131] DownloadWithDelegate : Elapsed : 869
2016-03-24 08:30:30.060 MapView[11068:6401131] DownloadWithModernHttpClient : Elapsed : 735, number of bytes : 173985

-> Numbers are nearly identical.

Run a second time

2016-03-24 08:31:11.291 MapView[11078:6405042] DownloadWithWebClient : Elapsed : 1669, number of bytes : 173985
2016-03-24 08:31:12.837 MapView[11078:6405042] DownloadWithDelegate : Elapsed : 1544
2016-03-24 08:31:12.914 MapView[11078:6405042] DownloadWithModernHttpClient : Elapsed : 76, number of bytes : 173985

-> large difference

Reset again and you'll have, again, similar numbers.

Why ? ModernHttpClient is smart enough to cache data. The 2nd+ time is just too fast to have gone thru the networking stack.

Neither iOS (by default) nor the attached code does caching, so your 2nd+ downloads need to be executed again (keeping similar times).

Grep in ModernHttpClient source code and you'll see:

src/ModernHttpClient/iOS/NSUrlSessionHandler.cs:                CachePolicy = (!this.DisableCaching ? NSUrlRequestCachePolicy.UseProtocolCachePolicy : NSUrlRequestCachePolicy.ReloadIgnoringCacheData),
src/ModernHttpClient/iOS/NSUrlSessionHandler.cs:            public override void WillCacheResponse (NSUrlSession session, NSUrlSessionDataTask dataTask,
src/ModernHttpClient/iOS/NSUrlSessionHandler.cs:                NSCachedUrlResponse proposedResponse, Action<NSCachedUrlResponse> completionHandler)