Blazor Performance

Model Binding hat auch seine negativen Seiten. Wie schon auch mit WPF/UWP und MVVM Pattern können gerade lange Listen für erhebliche Probleme bei der Ausführung einer Anwendung sorgen. Mit ASP.NET core Blazor werden Änderungen im HTML DOM per Websocket Push vom Web Server zum Browser übertragen und dort per Blazor JavaScript Library im entsprechenden HMTL Node ausgetauscht. Es wird also im Gegensatz zu Angular nicht die Datenmenge, sondern der gerenderte HTML Code transferiert. Zeigt man eine sehr lange (und dumme) Liste mit 100000 Einträgen per HTML Table an, ergeben sich interessante Fragestellungen.

Zunächst eine kurze Anleitung wie man mit Chrome Websocket Traffic analysieren kann.

Starten Sie mit F12 die Chrome Developer Tools. Öffnen Sie den Reiter Network und selektieren den WS Tag. Laden sie die gewünschte Url im Browser. Wählen Sie den Http Request auf ihre Blazor Website aus. Dieser zeigt an Status 101 und Type Websocket.

image

Rechts sehen Sie nun die Nachrichten, die Browser und Server hin und her senden.

In der Regel sind das wenige Bytes. Außer für das Initiale Laden der kompletten Seite, samt langer Liste. Hier schlagen stolze 28MB zu Buche. Die gesamte Ladezeit von lokal beträgt 24 Sekunden,

image

Wenn man einen Eintrag der Binary Message Liste anklickt sieht man den Inhalt der NAchricht, mehr oder weniger. Ist eben einen BInary Message. Probiert man das mit der großen 27,4 MB Nachricht stürzen zumindest bei mir die Chrome Tools ab.

image

Diese lange Liste kann um einen Eintrag reduziert werden, 

image

Eine TR Zeile mit Inhalt umfasst 40 Bytes, eventuell noch mit Zeilenumbrüchen 48 Bytes. 100000 Zeilen rund 48 MB + Libarays, CSS und außen rum, knapp 50 MB. Das würde bei HTML ungefähr dank Kompression16-17 MB ergeben.

Wenn eine Reihe entfernt wird muss der normale HTTP Get die kompletten Daten immer und immer wieder laden. Was tut Blazor? Beinahe das selbe. Die Datenmenge liegt nun bei ca 22MB , wenn der Benutzer auf löschen klickt und damit eine Reihe entfernt. Es wird also die komplette Tabelle am Server gerendert und zum Browser gesendet. Wie soll die Blazor Engine am Browser auch erkennen, welcher HTML Node sich verändert hat. Dafür braucht es einen Schlüssel=Key.

Mit folgendem Code wird dann nur mehr wenige Bytes Netzwerk Traffic erzeugt

image

Die Anzeige im Browser erfolgt nach weniger als einer Sekunde.

   1:  <button @onclick="remove">remove </button>
   2:   
   3:  <table>
   4:      @foreach (var item in Liste)
   5:      {
   6:          <tr @key="@item.Key">
   7:              <td>@item.Key</td>
   8:              <td>@item.Value</td>
   9:          </tr>
  10:      }
  11:   
  12:  </table>
  13:  @code {
  14:      public Dictionary<int, string> Liste { get; set; }
  15:      public int counter = 1;
  16:      protected override async Task OnInitializedAsync()
  17:      {
  18:          Liste = new Dictionary<int, string>();
  19:          for (int i = 0; i < 100000; i++)
  20:          {
  21:              Liste.Add(i, $"{i:000000000000}");
  22:   
  23:          }
  24:      }
  25:      void remove()
  26:      {
  27:          Liste.Remove(counter);
  28:          counter++;
  29:      }
  30:  }

Disclaimer: Anders als bei Desktop Anwendungen gibt es keine virtualisierung der Anzeige ala VirtualizingStackPanel. Große Datenmengen müssen generell im Browser anders behandelt werden. Nicht nur technologisch sondern auch aus User Sichtweise, ist langes scrollen zu vermeiden.

Kommentare sind geschlossen