On parle Windows, C#, Apple, Android, Js, …

Image depuis HTTP avec C# XAML – Comparatifs et Performances – Partie 2

Introduction

 wp_ss_20141223_0001

Cet article traite des résultats des différentes méthodes pour lire une image provenant d’un site Http.

Les différentes implémentations ont été décrites dans l’article

Image depuis http avec C# Xaml – comparatifs et performances.

Mesures

L’image étalon fait 19ko et mesure 400×240 pixels. Elle est présente notamment sur les serveurs de Bing à l’adresse suivante :

http://www.bing.com/az/hprichbg/rb/ChristmasMarketNurnberg_FR-FR11351563819_1280x768.JPG

Le premier test va charger 10 fois la même image suivante :

ChristmasMarketNurnberg_FR-FR11351563819_400x240

Afin d’éviter les mises en cache http d’échanges, l’url demandée est accompagnée de paramètres fictifs dans la requête.

Exemple : http://192.168.0.47/ChristmasMarketNurnberg_FR-FR11351563819_400x240.jpg?test={0} où {0} sera remplacé lors des tests par des données uniques avec l’instruction

String.Format(url, DateTime.Now.Ticks)

Une méthode générique de benchmark a été réalisée. A titre indicatif, voici la méthode principale.

public static async Task BenchmarkTest(this IBenchmarkResult result, Func<string, Task<object>> test, string url, string title, string comment)
{
    await semaphore.WaitAsync();
    try
    {
        string resourceName = String.Empty;
        _buildLog.AppendLine("-----------------------");
        _buildLog.AppendLine(String.Format("Test {0} (x{1})", title, _nbBench));
        _buildLog.AppendLine(String.Format("-- {0} ", comment));
        result.BenchmarkLog= _buildLog.ToString();
        _startTime = DateTime.Now;
        _buildLog.AppendLine(String.Format("Start {0:HH:mm:ss}", _startTime));
        int nb = 0;
        int index = 0;
        while (nb > 0 || index <= _nbBench)
        {
            index++;
            if (index <= _nbBench)
            {
                nb++;
                {
                    System.Diagnostics.Debug.WriteLine("Add test {0}, index {1}", nb, index);
                    result.Image = await test(String.Format(url, DateTime.Now.Ticks));
                    nb--;
                    System.Diagnostics.Debug.WriteLine("remove test {0}", nb);
                }
            }
        }
        _buildLog.AppendLine(String.Format("Result {0} = {1:0.000} s", title, (DateTime.Now - _startTime).TotalSeconds));
        result.BenchmarkLog = _buildLog.ToString();
    }
    finally
    {
        semaphore.Release();
    }
}
  •  Le sémaphore sert à éviter les conflits
  • La méthode à tester est passée dans la Func Test
  • La boucle lance les tests à la suite (10x pour ces tests)

 

Pour rappel, les méthodes testées sont les suivantes :

  1. Http client et DataWriter : implementation classique avec le DataWriter
  2. Http Client et AsRandomAccessStream  : utilisation du AsRandomAccessStream (W8.1)
  3. HttpClient et AsRandomAccessStream avec ConfigureAwait : optimisation avec ConfigureAwait(false)
  4. HttpClient et MemoryStream dans une autre Task. Le memoryStream est traité à part dans une tâche asynchrone
  5. HttpRequest et MemoryStream dans une autre Task Le HttpRequest est utilisé à la place du HttpClient
  6. Actions à la place du Async / Await : Utilisation des Actions à la place du async/await
  7. HttpWebRequest et AsRandomAccessStream :  
  8. HttpWebRequest et AsRandomAccessStream avec Action : comme la 6 mais AsRandomAccessStream remplace la Task du MemoryStream
  9. HttpWebRequest, AsRandom Access Stream sans ConfigureAwait : Idem que la 2 mais avec HttpWebRequest

Test en local

Le test est réalisé sur un réseau local, via Wifi sur un Lumia 930. Les tests ont été mélangés (pour ne pas toujours commencé par le premier)

Le serveur est situé sur le réseau local.

Le tableau représente les valeurs en ms pour chaque série de tests.

Les moyennes sont sur la première ligne.

bench01

On peut déjà voir de gros écarts entre la première méthode traditionnelle et la 8, nous avons presque des temps qui sont divisés par 2.

On observe également que

  • Le HttpClient est bien plus lent que le HttpRequest (ce n’est pas une surprise)
  • Les méthodes utilisant des actions sont les plus rapides (pourquoi reste le grand mystère inexpliqué)

Test grandeur nature

Le test a ensuite été réalisé sur des connections 3G, 4G, Wifi avec un serveur distant.

Le serveur utilisé est le serveur de Bing. Les temps de connexions sont bien sûr plus variables et voici les résultats sur une connexion H+ réseau orange avec le 930.

Les moyennes sont toujours sur la première ligne.

Peu de différences avec les tests sur réseau local.

Les benchmarks 3, 6, 8 et 9 sont les meilleurs et seront conservés pour les autres tests

bench02

Le test suivant est réalisé sur un 920, toujours sur un réseau H+.

Bench3

Sur un Lumia 920, les méthodes 6 et 8 sortent du lot avec un gain d’une dizaine de pourcent.

J’ai pu faire des tests à plusieurs reprises sur des réseaux allant de la 4g au Edge et ce sont toujours ces 2 implémentations qui sortent du lot.

Conclusion

Dans mes Apps, je vais utiliser l’implémentation 8 qui reste simple (comparée à la solution 6), compréhensible et une des plus performantes.

Il serait intéressant de voir également si des téléphones avec un processeur un peu moins performant tel que le Lumia 520 enregistrent les mêmes écarts.

Le code source sera publié très prochainement.

 

Laissez un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.