Loupe

#Windows : obtenir la consommation mémoire réelle de votre application

Surveiller la consommation mémoire de votre application est une bonne pratique. La plus basse elle est, la plus performante est votre application. Aussi au bout d’une certaine limite, une exception est levée et votre application crashe lamentablement.

 

La méthode classique de lecture de cette information est d’utiliser la méthode GC.GetTotalMemory :

var usedMemory = GC.GetTotalMemory(true) / (1024L * 1024L) + "Mo";

Une fois le gestionnaire de tâche ou un utilitaire tel que Process Explorer lancé, vous remarquerez que les valeurs ne sont pas bonnes.

error

En effet, la couche XAML est maintenant en natif dans le SDK Windows et vous n’aurez donc pas la consommation de vos composants natifs et donc pas celle des vues. Celles-ci représentent souvent une grosse partie de votre consommation mémoire.

 

Obtenir les bonnes informations

Pour obtenir les informations complètes, on va donc utiliser la méthode GetProcessMemoryInfo de la DLL psapi à grand coup de DllImport  :

  1. On définit dans le code les différents objets et méthodes manipulées,
  2. On récupère l’identifiant de processus de notre application avec la méthode GetCurrentProcess.
  3. On récupère les informations d’utilisation mémoire en utilisant GetProcessMemoryInfo

 

Voici la définition des objets manipulés :

[DllImport("kernel32.dll")]
private static extern IntPtr GetCurrentProcess();

[StructLayout(LayoutKind.Sequential, Size = 40)]
private struct PROCESS_MEMORY_COUNTERS
{
    public uint cb;
    public uint PageFaultCount;
    public uint PeakWorkingSetSize;
    public uint WorkingSetSize;
    public uint QuotaPeakPagedPoolUsage;
    public uint QuotaPagedPoolUsage;
    public uint QuotaPeakNonPagedPoolUsage;
    public uint QuotaNonPagedPoolUsage;
    public uint PagefileUsage;
    public uint PeakPagefileUsage;
}

[DllImport("psapi.dll", SetLastError = true)]
static extern bool GetProcessMemoryInfo(IntPtr hProcess,
    out PROCESS_MEMORY_COUNTERS counters, uint size);

 

Et le code de lecture des informations et alors très simple car il suffit d’appeler les deux méthodes.

Ici j’affiche le working set et les bytes privés (pour connaitre la différence entre ces deux valeurs suivez ce lien) :

var currentProcessHandle = GetCurrentProcess();
PROCESS_MEMORY_COUNTERS memoryCounters;
memoryCounters.cb = (uint)Marshal.SizeOf<PROCESS_MEMORY_COUNTERS>();
if (GetProcessMemoryInfo(currentProcessHandle, out memoryCounters, memoryCounters.cb))
{
    _targetTextBlock.Text = "MAN " + GC.GetTotalMemory(true) / (1024L * 1024L) + "Mo"
        + Environment.NewLine
        + "PFU " + memoryCounters.PagefileUsage / (1024L * 1024L) + "Mo"
        + Environment.NewLine
        + "WS  " + memoryCounters.WorkingSetSize / (1024L * 1024L) + "Mo";
}

 

Pas de publication sur le Store

Bien sûr, on est sur un cas d’usage interdit par le Store lors de la publication et il faudra bien faire attention d’enlever ces méthodes lors de la publication finale du package. Cela peut être fait facilement en utilisant des directives de pré-compilation.

errorValid

Bonus : afficher cette valeur au dessus de votre UI

Un petit bonus qui peut être pratique : voici le code créant une Popup qui sera affichée au dessus de votre application pour afficher les différentes consommations. J’utilise un DispatcherTimer pour rafraichir ces valeurs toutes les secondes.

//création d'un timer
var dt = new DispatcherTimer();
dt.Interval = TimeSpan.FromSeconds(1);
IntPtr currentProcessHandle = GetCurrentProcess();
dt.Tick += (_, __) => CalculateMemory(currentProcessHandle);
dt.Start();

// création d'une popup
var p = new Popup();
_targetTextBlock = new TextBlock()
{
    FontSize = 16,
    Foreground = new SolidColorBrush(Colors.Black)
};

p.Child = new Border
{
    Background = new SolidColorBrush(Colors.White),
    Child = _targetTextBlock,
};

// afficahge de la popup
p.IsOpen = true;

//calcul initial
CalculateMemory(currentProcessHandle);

Et le rendu final :

exemple

 

Bon code !

Photo de profil

Ces billets pourraient aussi vous intéresser

Vous nous direz ?!

Commentaires

comments powered by Disqus