Search Unity

Asset Bundle download speed

Discussion in 'Asset Bundles' started by mobilizAR, Nov 29, 2018.

  1. mobilizAR

    mobilizAR

    Joined:
    Jul 28, 2016
    Posts:
    13
    Hey guys,

    Just wanted to understand something better. So I have few asset bundles that I download from a CDN network. The speed that I get while downloading on iOS/Android Unity app is pretty slow. But if I try and download using Chrome browser on the same device, it takes about 6-7 seconds, whereas in Unity it takes about 60-70 seconds.

    Any idea why this is happening and/or how to increase the download speed for asset bundles in unity3d?

    I am using WebRequest.GetAssetBundle(url, version, crc) method to download it.

    Unity3d Version 2017.2.0f3

    Thank you.

    PS : I am using 2 servers for CDN download. Azure, and AWS. On both the same problem is happening.
     
  2. Aurimas-Cernius

    Aurimas-Cernius

    Unity Technologies

    Joined:
    Jul 31, 2013
    Posts:
    3,732
    GetAssetBundle() attaches DownloadHandlerAssetBundle to UWR, which loads asset bundles on the fly. Received bytes are fed to AssetBundle system, so it is slower than just a download. If you'd use Get() instead, the download should be faster, however it will give you much higher memory usage (entire bundle will be kept in memory), so it's trading one thing for another.
     
  3. mobilizAR

    mobilizAR

    Joined:
    Jul 28, 2016
    Posts:
    13
    Hey, thanks for replying.

    I tried doing that also, still the download speed is very slow. Is there any other way or settings that I might have missed?
     
  4. mobilizAR

    mobilizAR

    Joined:
    Jul 28, 2016
    Posts:
    13
    PS : I have a small check that keeps checking if the download.progress is stagnant for 10 seconds, and then aborts the web request so that the user isn't stuck there forever (used to happen before I implemented this)

    So usually, I get the abort request error because it is stagnant for 10 seconds.
     
  5. Aurimas-Cernius

    Aurimas-Cernius

    Unity Technologies

    Joined:
    Jul 31, 2013
    Posts:
    3,732
    Perhaps caching is involved? In UnityWebRequest implementation we disable caching, so bundle is always downloaded from server, you can enable caching by commenting one line of code in either WWWConnection.mm or UnityWebRequest.mm (depending on your Unity version).
     
  6. mobilizAR

    mobilizAR

    Joined:
    Jul 28, 2016
    Posts:
    13
    The caching is definitely on, because once the Bundle is downloaded, the next time it takes 1 second to load from cache.

    Here is the code I use to download a normal bundle, below :

    Code (CSharp):
    1. string url = string.Format ("{0}{1}", a_strHostName, a_strAssetBundleName);
    2.         Hash128 version = a_version;
    3.         UnityWebRequest request = UnityWebRequest.GetAssetBundle (url, version, 0);
    4.         request.SendWebRequest ();
    5.         float counter = 0;
    6.         float m_fLastDownloadProgress = 0;
    7.         while (!request.isDone && request.error == null) {
    8.             if (OnCategoryDownloading != null)
    9.                 OnCategoryDownloading (cat, request.downloadProgress);
    10.             if (request.downloadProgress == m_fLastDownloadProgress) {
    11.                 counter += Time.deltaTime;
    12.                 if (counter > MAX_TIME_TO_WAIT_ON_SAME_PROGRESS) {
    13.                     Debug.Log ("Time!!!");
    14.                     request.Abort ();
    15.                 }
    16.             } else {
    17.                 m_fLastDownloadProgress = request.downloadProgress;
    18.                 counter = 0;
    19.             }
    20.             yield return null;
    21.         }
    22.         if (request.error != null) {
    23.             if (OnCategoryDownloadError != null)
    24.                 OnCategoryDownloadError (cat, request.error);
    25.         } else {
    26.             if (OnCategoryDownloadedSuccesssfully != null)
    27.                 OnCategoryDownloadedSuccesssfully (cat, request, url, version);
    28.         }
    29.         request.Dispose ();
    This is in a loop depending on how many "categories" a user selects.
     
  7. Aurimas-Cernius

    Aurimas-Cernius

    Unity Technologies

    Joined:
    Jul 31, 2013
    Posts:
    3,732
    How long does it take to download the bundle using UnityWebRequest.Get()?
    Is there a particular progress pattern?
     
  8. mobilizAR

    mobilizAR

    Joined:
    Jul 28, 2016
    Posts:
    13
    So I wrote a small code (same as mentioned above) yesterday to download a bundle from Azure CDN and S3 CDN using GetAssetBundle and Get()

    Both took the same time on WiFi. 6 seconds total using GetAssetBundle(), and 4 seconds to download using Get() and 2 seconds to convert it to AssetBundle.

    No such progress pattern. I have my logs and analytics in place, and its all over the place. Most of the error outs are because of me aborting it manually since it was stagnant for 10 seconds. Sometimes I got an error saying "Unable to complete SSL connection", and "Cannot resolve destination host".
     
  9. AteoMarcel

    AteoMarcel

    Joined:
    Jan 5, 2017
    Posts:
    17
    We had the same problem with downloading an asset bundle as a file. (We used Webrequest.Get() from the start) it could be downloaded in 2 seconds in the browser and took 20-30 seconds on mobile (android and IOS).
    What we intend to use now is the .Net WebClient.

    Our code looks something like this:

    Code (CSharp):
    1.  
    2. using System.Net;
    3. using System.Security.Cryptography.X509Certificates;
    4. using System.Net.Security;
    5.  
    6. void safeFileUsingWebClient(string url, string path) {
    7.  
    8.             WebClient client = new WebClient();
    9.            // We need to authentificate on the server.
    10.             string auth = GetAuthString();
    11.             WebHeaderCollection header = new WebHeaderCollection {
    12.                 { "Authorization", auth }
    13.             };
    14.  
    15.             Uri uri = new Uri(url);
    16.          
    17.             // Might be needed had errors without this?!
    18.             Debug.Log(uri.AbsolutePath);
    19.             ServicePointManager.ServerCertificateValidationCallback = RemoteCertificateValidationCallback;
    20.  
    21.             byte[]  data =client.DownloadData(uri);
    22.  
    23.             File.WriteAllBytes(path, data);
    24.             Log("File saved under " + path);
    25.         }
    26.  
    27.        private static bool RemoteCertificateValidationCallback(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors){
    28.             return true;
    29.         }
    The part with the RemoteCertificateValidationCallback was needed, since we run into an "TlsException: Invalid certificate received from server. Error code: 0xffffffff800b010a" error when we tried it without it.

    It is still not 100% working (we had some errors with "404 file not found" with this implementation (which we never had with the unity webrequest).
    However, it takes 5 seconds instead of 20-30 to download the file with the new webclient.
     
  10. KB73

    KB73

    Joined:
    Feb 7, 2013
    Posts:
    234
    We used Webclient, proxy is null etc and still getting performance issues.
    If we download any file of equivalent size outside of the app i.e. through google play store or through web browser, we get the file in 5-10seconds off the device.
    If in the app, same network, same device, just call WebClient .net or UnityWebRequest our 100MB file takes 30-40seconds..so we're about 3-4x slower.
    We're at a loss as what to do - clearly something in Unity is causing an issue as the links outside work fine and >WAY< faster
    This is on both ios and android, 2018.2-2018.4 at least, IL2CPP .NET 4
    Tried http and https etc..

    We're going to look at the traffic next to see if we can figure out what is going on

    Any other things we could try?

    thanks
     
  11. UweR7

    UweR7

    Joined:
    Jul 27, 2017
    Posts:
    20
    Same issue(!) here.

    Changed from
    Code (CSharp):
    1. using(var www = new WWW(url)) { ... }
    to
    Code (CSharp):
    1.  using (var www = UnityWebRequest.Get(url)) {...}
    and from Unity 2017 to 2018.4.4f1 (IL2CPP, ARMv7, ARM64)

    Result:
    Without any further code, config., etc. change doubles the asset bundle download time!
    Tried also this well working code

    Code (CSharp):
    1. // Needed for https calls. Accepts all certs.
    2. ServicePointManager.ServerCertificateValidationCallback += (p1, p2, p3, p4) => true;

    Code (CSharp):
    1. byte[] dataAsByteArray = null;
    2. using (var client = new HttpClient())
    3. {
    4.       var result = client.GetAsync(url).Result;
    5.       result.EnsureSuccessStatusCode();
    6.       dataAsByteArray = result.Content.ReadAsByteArrayAsync().Result;
    7. }
    No change. Still very very slow. Measured average: 1.667 MBytes/sec!
    Using the in my code generated URI in a web browser shows a download speed of 3.4 MBytes/sec.
     
    Last edited: Aug 2, 2019
  12. UweR7

    UweR7

    Joined:
    Jul 27, 2017
    Posts:
    20
    BTW and off topic
    The apk file size doubles also from around 54 MB to 94 MB!
     
  13. bmarinariSparky

    bmarinariSparky

    Joined:
    Jan 5, 2018
    Posts:
    10
    These results sound like compression issues to me. If you have compression enabled on caching, the bundle will be compressed as LZ4 on download I believe, if it is not already using LZ4. That means if the bundle uses LZMA or no compression, it will be decompressed first and recompressed after the download.

    If the cache does not have compression enabled, you will still pay a heavy decompression cost when you load an asset from it. If your bundles are relatively large, this can be huge if it is compressed with LZMA.

    TL;DR -- Use chunk based compression for your bundles and see if it improves. Maybe also test uncompressed just to see the results.
     
  14. KB73

    KB73

    Joined:
    Feb 7, 2013
    Posts:
    234
    Hi bmarinari, we're using LZ4 and don't use the Unity Cache System
     
  15. UweR7

    UweR7

    Joined:
    Jul 27, 2017
    Posts:
    20
  16. Paul-Naylor

    Paul-Naylor

    Joined:
    Apr 15, 2013
    Posts:
    2
    We're having the same issue. Is there an open issue for this? If not I'll create one.
     
  17. ThanosMoptil

    ThanosMoptil

    Joined:
    Apr 26, 2022
    Posts:
    4
    This is still an issue. We are testing some Addressables over 5G and 1,5gb/s download speed, and it appears to be very slow. For 180mb it needs around 30seconds. They are hosted on Azure Storage and the speed there is supposed to be 60gbs. I am using the Addressables.DownloadDependenciesAsync method.
     
    DeathPro likes this.