Udostępnij za pośrednictwem


Wydajność międzyplatformowa

Niska wydajność aplikacji przedstawia się na wiele sposobów. Może to sprawić, że aplikacja wydaje się nie odpowiadać, może powodować powolne przewijanie i może zmniejszyć żywotność baterii. Jednak optymalizacja wydajności wymaga więcej niż tylko zaimplementowania wydajnego kodu. Należy również rozważyć środowisko użytkownika dotyczące wydajności aplikacji. Na przykład zapewnienie, że operacje są wykonywane bez blokowania użytkownikowi wykonywania innych działań, mogą pomóc w ulepszaniu środowiska użytkownika.

Korzystanie z profilera

Podczas tworzenia aplikacji ważne jest, aby podjąć próbę optymalizacji kodu tylko po jego profilowaniu. Profilowanie to technika określania, gdzie optymalizacje kodu będą miały największy wpływ na zmniejszenie problemów z wydajnością. Profiler śledzi użycie pamięci aplikacji i rejestruje czas działania metod w aplikacji. Te dane ułatwiają nawigowanie po ścieżkach wykonywania aplikacji oraz koszt wykonywania kodu, dzięki czemu można odnaleźć najlepsze możliwości optymalizacji.

Narzędzie Xamarin Profiler będzie mierzyć, oceniać i pomagać w znajdowaniu problemów związanych z wydajnością w aplikacji. Może służyć do profilowania aplikacji platform Xamarin.iOS i Xamarin.Android z poziomu Visual Studio dla komputerów Mac lub programu Visual Studio. Aby uzyskać więcej informacji na temat programu Xamarin Profiler, zobacz Wprowadzenie do programu Xamarin Profiler.

Podczas profilowania aplikacji zalecane są następujące najlepsze rozwiązania:

  • Unikaj profilowania aplikacji w symulatorze, ponieważ symulator może zakłócać wydajność aplikacji.
  • W idealnym przypadku profilowanie powinno być wykonywane na różnych urządzeniach, ponieważ pomiary wydajności na jednym urządzeniu nie zawsze będą pokazywać charakterystykę wydajności innych urządzeń. Jednak co najmniej profilowanie powinno być wykonywane na urządzeniu, które ma najniższą oczekiwaną specyfikację.
  • Zamknij wszystkie inne aplikacje, aby upewnić się, że cały wpływ profilowanej aplikacji jest mierzony, a nie innych aplikacji.

Zwalnianie zasobów IDisposable

Interfejs IDisposable udostępnia mechanizm wydawania zasobów. Udostępnia metodę Dispose , która powinna zostać zaimplementowana w celu jawnego wydania zasobów. IDisposable nie jest destruktorem i powinien być implementowany tylko w następujących okolicznościach:

  • Gdy klasa jest właścicielem niezarządzanych zasobów. Typowe niezarządzane zasoby, które wymagają zwolnienia plików, strumieni i połączeń sieciowych.
  • Gdy klasa jest właścicielem zarządzanych IDisposable zasobów.

Użytkownicy typu mogą następnie wywoływać implementację IDisposable.Dispose , aby zwolnić zasoby, gdy wystąpienie nie jest już wymagane. Istnieją dwa podejścia do osiągnięcia tego celu:

  • Zawijając IDisposable obiekt w instrukcji using .
  • Zawijając wywołanie elementu IDisposable.Dispose w try/finally bloku.

Zawijanie obiektu IDisposable w instrukcji using

W poniższym przykładzie kodu pokazano, jak opakowować IDisposable obiekt w instrukcji using :

public void ReadText (string filename)
{
  ...
  string text;
  using (StreamReader reader = new StreamReader (filename)) {
    text = reader.ReadToEnd ();
  }
  ...
}

Klasa StreamReader implementuje IDisposablemetodę , a using instrukcja udostępnia wygodną składnię, która wywołuje StreamReader.Dispose metodę w StreamReader obiekcie przed wyjściem z zakresu. using W bloku StreamReader obiekt jest tylko do odczytu i nie można go ponownie przypisać. Instrukcja using zapewnia również, że Dispose metoda jest wywoływana nawet w przypadku wystąpienia wyjątku, ponieważ kompilator implementuje język pośredni (IL) dla try/finally bloku.

Zawijanie wywołania do funkcji IDisposable.Dispose w bloku Try/Finally

W poniższym przykładzie kodu pokazano, jak opakowować wywołanie IDisposable.Dispose w try/finally bloku:

public void ReadText (string filename)
{
  ...
  string text;
  StreamReader reader = null;
  try {
    reader = new StreamReader (filename);
    text = reader.ReadToEnd ();
  } finally {
    if (reader != null) {
      reader.Dispose ();
    }
  }
  ...
}

Klasa StreamReader implementuje IDisposablemetodę , a finally blok wywołuje metodę StreamReader.Dispose , aby zwolnić zasób.

Aby uzyskać więcej informacji, zobacz IDisposable Interface (Interfejs IDisposable).

Anulowanie subskrypcji zdarzeń

Aby zapobiec wyciekom pamięci, zdarzenia powinny zostać anulowane przed likwidacją obiektu subskrybenta. Dopóki zdarzenie nie zostanie anulowane, pełnomocnik zdarzenia w obiekcie publikowania ma odwołanie do delegata, który hermetyzuje procedurę obsługi zdarzeń subskrybenta. Tak długo, jak obiekt publikowania przechowuje to odwołanie, odzyskiwanie pamięci nie spowoduje odzyskania pamięci obiektu subskrybenta.

Poniższy przykład kodu pokazuje, jak anulować subskrypcję zdarzenia:

public class Publisher
{
  public event EventHandler MyEvent;

  public void OnMyEventFires ()
  {
    if (MyEvent != null) {
      MyEvent (this, EventArgs.Empty);
    }
  }
}

public class Subscriber : IDisposable
{
  readonly Publisher publisher;

  public Subscriber (Publisher publish)
  {
    publisher = publish;
    publisher.MyEvent += OnMyEventFires;
  }

  void OnMyEventFires (object sender, EventArgs e)
  {
    Debug.WriteLine ("The publisher notified the subscriber of an event");
  }

  public void Dispose ()
  {
    publisher.MyEvent -= OnMyEventFires;
  }
}

Klasa Subscriber anuluje subskrypcję zdarzenia w swojej Dispose metodzie.

Cykle odwołań mogą również wystąpić w przypadku używania procedur obsługi zdarzeń i składni lambda, ponieważ wyrażenia lambda mogą odwoływać się do obiektów i utrzymywać ich przy życiu. W związku z tym odwołanie do metody anonimowej może być przechowywane w polu i używane do anulowania subskrypcji zdarzenia, jak pokazano w poniższym przykładzie kodu:

public class Subscriber : IDisposable
{
  readonly Publisher publisher;
  EventHandler handler;

  public Subscriber (Publisher publish)
  {
    publisher = publish;
    handler = (sender, e) => {
      Debug.WriteLine ("The publisher notified the subscriber of an event");
    };
    publisher.MyEvent += handler;
  }

  public void Dispose ()
  {
    publisher.MyEvent -= handler;
  }
}

Pole handler utrzymuje odwołanie do metody anonimowej i jest używane do subskrypcji zdarzeń i anulowania subskrypcji.

Używanie słabych odwołań do zapobiegania nieśmiertelnym obiektom

Uwaga

Deweloperzy systemu iOS powinni zapoznać się z dokumentacją dotyczącą unikania odwołań cyklicznych w systemie iOS w celu zapewnienia wydajnego używania pamięci przez aplikacje.

Opóźnienie kosztu tworzenia obiektów

Inicjowanie z opóźnieniem może służyć do odroczenia tworzenia obiektu do momentu jego pierwszego użycia. Ta technika jest używana głównie w celu zwiększenia wydajności, uniknięcia obliczeń i zmniejszenia wymagań dotyczących pamięci.

Rozważ użycie leniwej inicjalizacji dla obiektów, które są kosztowne do utworzenia w tych dwóch scenariuszach:

  • Aplikacja może nie używać obiektu .
  • Przed utworzeniem obiektu należy wykonać inne kosztowne operacje.

Klasa Lazy<T> służy do definiowania typu zainicjowanego z opóźnieniem, jak pokazano w poniższym przykładzie kodu:

void ProcessData(bool dataRequired = false)
{
  Lazy<double> data = new Lazy<double>(() =>
  {
    return ParallelEnumerable.Range(0, 1000)
                 .Select(d => Compute(d))
                 .Aggregate((x, y) => x + y);
  });

  if (dataRequired)
  {
    if (data.Value > 90)
    {
      ...
    }
  }
}

double Compute(double x)
{
  ...
}

Inicjowanie z opóźnieniem następuje przy pierwszym uzyskiwaniu Lazy<T>.Value dostępu do właściwości. Opakowany typ jest tworzony i zwracany przy pierwszym dostępie oraz przechowywany dla dowolnego przyszłego dostępu.

Aby uzyskać więcej informacji na temat leniwego inicjowania, zobacz Lazy Initialization (Inicjowanie z opóźnieniem).

Implementowanie operacji asynchronicznych

Platforma .NET udostępnia asynchroniczne wersje wielu interfejsów API. W przeciwieństwie do synchronicznych interfejsów API asynchroniczne interfejsy API zapewniają, że aktywny wątek wykonywania nigdy nie blokuje wywoływanego wątku przez znaczną ilość czasu. W związku z tym podczas wywoływania interfejsu API z wątku interfejsu użytkownika użyj asynchronicznego interfejsu API, jeśli jest dostępny. Spowoduje to odblokowanie wątku interfejsu użytkownika, co pomoże ulepszyć środowisko użytkownika w aplikacji.

Ponadto długotrwałe operacje powinny być wykonywane w wątku w tle, aby uniknąć blokowania wątku interfejsu użytkownika. Platforma .NET udostępnia async słowa kluczowe i await , które umożliwiają pisanie kodu asynchronicznego, który wykonuje długotrwałe operacje w wątku w tle i uzyskuje dostęp do wyników po zakończeniu. Jednak podczas wykonywania długotrwałych operacji asynchronicznie za await pomocą słowa kluczowego nie gwarantuje to, że operacja zostanie uruchomiona w wątku w tle. Zamiast tego można to osiągnąć, przekazując długotrwałą operację do Task.Runmetody , jak pokazano w poniższym przykładzie kodu:

public class FaceDetection
{
  ...
  async void RecognizeFaceButtonClick(object sender, EventArgs e)
  {
    await Task.Run(() => RecognizeFace ());
    ...
  }

  async Task RecognizeFace()
  {
    ...
  }
}

Metoda RecognizeFace jest wykonywana w wątku w tle, a RecognizeFaceButtonClick metoda czeka na RecognizeFace zakończenie metody przed kontynuowaniem.

Długotrwałe operacje powinny również obsługiwać anulowanie. Na przykład kontynuowanie długotrwałej operacji może stać się niepotrzebne, jeśli użytkownik przejdzie do aplikacji. Wzorzec implementowania anulowania jest następujący:

  • Utwórz CancellationTokenSource wystąpienie. To wystąpienie będzie zarządzać powiadomieniami o anulowaniu i wysyłać je.
  • CancellationTokenSource.Token Przekaż wartość właściwości do każdego zadania, które powinno być anulowane.
  • Podaj mechanizm dla każdego zadania, aby reagować na anulowanie.
  • Wywołaj metodę w CancellationTokenSource.Cancel celu dostarczenia powiadomienia o anulowaniu.

Ważne

Klasa CancellationTokenSource implementuje IDisposable interfejs, więc CancellationTokenSource.Dispose metoda powinna być wywoływana po zakończeniu CancellationTokenSource wystąpienia.

Aby uzyskać więcej informacji, zobacz Async Support Overview (Omówienie pomocy technicznej asynchronicznych).

Korzystanie z modułu odśmiecającego pamięci SGen

Języki zarządzane, takie jak C#, używają odzyskiwania pamięci, aby odzyskać pamięć przydzieloną do obiektów, które nie są już używane. Dwa moduły odśmieceń pamięci używane przez platformę Xamarin to:

  • SGen — jest to generowanie modułu odśmiecającego pamięci i jest domyślnym modułem odśmiecającym pamięci na platformie Xamarin.
  • Boehm — jest to konserwatywny, niegeneracyjny moduł bezużyteczny. Jest to domyślny moduł odśmiecywania pamięci używany dla aplikacji platformy Xamarin.iOS korzystających z klasycznego interfejsu API.

Program SGen wykorzystuje jedną z trzech stertów do przydzielania miejsca dla obiektów:

  • Przedszkole — w tym miejscu przydzielane są nowe małe obiekty. Gdy przedszkole zabraknie miejsca, nastąpi drobne odzyskiwanie pamięci. Wszystkie obiekty aktywne zostaną przeniesione do sterty głównej.
  • Sterta główna — w tym miejscu przechowywane są długotrwałe obiekty. Jeśli nie ma wystarczającej ilości pamięci na głównym stercie, nastąpi poważne odzyskiwanie pamięci. Jeśli główne odzyskiwanie pamięci nie zwolni wystarczającej ilości pamięci, SGen poprosi system o więcej pamięci.
  • Duża przestrzeń obiektu — w tym miejscu przechowywane są obiekty wymagające więcej niż 8000 bajtów. Duże obiekty nie zaczną się w przedszkolu, ale zamiast tego zostaną przydzielone w tej stercie.

Jedną z zalet SGen jest to, że czas potrzebny na wykonanie drobnego odzyskiwania pamięci jest proporcjonalny do liczby nowych obiektów na żywo, które zostały utworzone od czasu ostatniego drobnego odzyskiwania pamięci. Zmniejszy to wpływ odzyskiwania pamięci na wydajność aplikacji, ponieważ te drobne odzyskiwanie pamięci zajmie mniej czasu niż główne odzyskiwanie pamięci. Główne odzyskiwanie pamięci będzie nadal występować, ale rzadziej.

Moduł odśmiecaczy SGen jest domyślnym modułem zbierającym elementy W środowisku Xamarin.iOS 9.2.1 i nowszym, dlatego będzie używany automatycznie. Należy pamiętać, że możliwość zmiany modułu odśmiecenia pamięci została usunięta z nowszych wersji programu Visual Studio. Aby uzyskać więcej informacji, zobacz Nowy system zliczania odwołań.

Zmniejszenie ciśnienia na modułu odśmiecającego pamięci

Gdy program SGen uruchamia odzyskiwanie pamięci, zatrzyma wątki aplikacji podczas odzyskiwania pamięci. Gdy pamięć jest odzyskiwana, aplikacja może napotkać krótką pauzę lub zacinanie w interfejsie użytkownika. Jak można perceptowalne to wstrzymanie zależy od dwóch czynników:

  1. Częstotliwość — częstotliwość odzyskiwania pamięci. Częstotliwość odzyskiwania pamięci zwiększa się w miarę przydzielania większej ilości pamięci między kolekcjami.
  2. Czas trwania — czas trwania każdego pojedynczego odzyskiwania pamięci. Jest to w przybliżeniu proporcjonalne do liczby zbieranych obiektów aktywnych.

Łącznie oznacza to, że jeśli wiele obiektów zostanie przydzielonych, ale nie pozostanie przy życiu, będzie wiele krótkich odzyskiwania pamięci. Z drugiej strony, jeśli nowe obiekty są przydzielane powoli, a obiekty pozostają aktywne, będzie mniej, ale dłuższe odzyskiwanie pamięci.

Aby zmniejszyć obciążenie modułu odśmiecającego śmieci, postępuj zgodnie z następującymi wytycznymi:

  • Unikaj odzyskiwania pamięci w ciasnych pętlach przy użyciu pul obiektów. Jest to szczególnie istotne w przypadku gier, które muszą z wyprzedzeniem tworzyć większość swoich obiektów.
  • Jawne wydawanie zasobów, takich jak strumienie, połączenia sieciowe, duże bloki pamięci i pliki, gdy nie są już wymagane. Aby uzyskać więcej informacji, zobacz Release IDisposable Resources (Zwalnianie zasobów IDisposable).
  • Cofnięć rejestrację procedur obsługi zdarzeń, gdy nie są już wymagane, aby obiekty były zbierane. Aby uzyskać więcej informacji, zobacz Anulowanie subskrypcji zdarzeń.

Zmniejszanie rozmiaru aplikacji

Ważne jest, aby zrozumieć proces kompilacji na każdej platformie, aby zrozumieć, skąd pochodzi rozmiar pliku wykonywalnego aplikacji:

  • Aplikacje systemu iOS są kompilowane przed czasem (AOT) w języku zestawu arm. Platforma .NET Framework jest dołączona, a nieużywane klasy są usuwane tylko wtedy, gdy włączono odpowiednią opcję konsolidatora.
  • Aplikacje systemu Android są kompilowane do języka pośredniego (IL) i pakowane przy użyciu maszyny MonoVM i kompilacji just in time (JIT). Nieużywane klasy platformy są usuwane tylko wtedy, gdy włączono odpowiednią opcję konsolidatora.
  • Aplikacje systemu Windows Telefon są kompilowane do języka IL i wykonywane przez wbudowane środowisko uruchomieniowe.

Ponadto, jeśli aplikacja intensywnie korzysta z typów ogólnych, ostateczny rozmiar pliku wykonywalnego będzie się zwiększać, ponieważ będzie zawierać natywnie skompilowane wersje ogólnych możliwości.

Aby zmniejszyć rozmiar aplikacji, platforma Xamarin zawiera konsolidator w ramach narzędzi kompilacji. Domyślnie konsolidator jest wyłączony i musi być włączony w opcjach projektu dla aplikacji. W czasie kompilacji przeprowadzi ona analizę statyczną aplikacji w celu określenia typów i elementów członkowskich, które są rzeczywiście używane przez aplikację. Następnie usunie wszystkie nieużywane typy i metody z aplikacji.

Poniższy zrzut ekranu przedstawia opcje konsolidatora w Visual Studio dla komputerów Mac dla projektu platformy Xamarin.iOS:

Linker options for Xamarin.iOS

Poniższy zrzut ekranu przedstawia opcje konsolidatora w Visual Studio dla komputerów Mac dla projektu platformy Xamarin.Android:

Linker options for Xamarin.Android

Konsolidator udostępnia trzy różne ustawienia do kontrolowania jego zachowania:

  • Nie łącz — nieużywane typy i metody zostaną usunięte przez konsolidator. Ze względu na wydajność jest to domyślne ustawienie kompilacji debugowania.
  • Zestawy SDK platformy linków/zestawy SDK — to ustawienie zmniejszy tylko rozmiar tych zestawów dostarczanych przez platformę Xamarin. Nie będzie to miało wpływu na kod użytkownika.
  • Połącz wszystkie zestawy — jest to bardziej agresywna optymalizacja, która będzie dotyczyć zestawów SDK i kodu użytkownika. W przypadku powiązań spowoduje to usunięcie nieużywanych pól kopii zapasowych i uczyni każde wystąpienie (lub powiązane obiekty) lżejszym, zużywając mniej pamięci.

Połącz wszystkie zestawy powinny być używane z ostrożnością, ponieważ może to spowodować awarię aplikacji w nieoczekiwany sposób. Analiza statyczna wykonywana przez konsolidator może nie identyfikować poprawnie całego wymaganego kodu, co powoduje usunięcie zbyt dużej ilości kodu ze skompilowanej aplikacji. Ta sytuacja będzie manifestować się tylko w czasie wykonywania, gdy aplikacja ulegnie awarii. Z tego powodu należy dokładnie przetestować aplikację po zmianie zachowania konsolidatora.

Jeśli testowanie nie ujawni, że konsolidator niepoprawnie usunął klasę lub metodę, można oznaczyć typy lub metody, które nie są statycznie przywołyane, ale są wymagane przez aplikację przy użyciu jednego z następujących atrybutów:

  • Xamarin.iOS.Foundation.PreserveAttribute — Ten atrybut jest przeznaczony dla projektów Xamarin.iOS.
  • Android.Runtime.PreserveAttribute — Ten atrybut jest przeznaczony dla projektów platformy Xamarin.Android.

Na przykład może być konieczne zachowanie domyślnych konstruktorów typów, które są dynamicznie tworzone. Ponadto użycie serializacji XML może wymagać zachowania właściwości typów.

Aby uzyskać więcej informacji, zobacz Konsolidator dla systemów iOS i Konsolidator dla systemu Android.

Dodatkowe techniki redukcji rozmiaru

Istnieje wiele różnych architektur procesora CPU, które obsługują urządzenia przenośne. W związku z tym Xamarin.iOS i Xamarin.Android tworzą pliki binarne tłuszczu zawierające skompilowane wersje aplikacji dla każdej architektury procesora CPU. Dzięki temu aplikacja mobilna może działać na urządzeniu niezależnie od architektury procesora CPU.

Poniższe kroki mogą służyć do dalszego zmniejszenia rozmiaru pliku wykonywalnego aplikacji:

  • Upewnij się, że utworzono kompilację wydania.
  • Zmniejsz liczbę architektur tworzonych przez aplikację, aby uniknąć tworzenia danych binarnych FAT.
  • Upewnij się, że kompilator LLVM jest używany do generowania bardziej zoptymalizowanego pliku wykonywalnego.
  • Zmniejsz rozmiar kodu zarządzanego aplikacji. Można to osiągnąć, włączając konsolidator w każdym zestawie (Połącz wszystko dla projektów systemu iOS i Połącz wszystkie zestawy dla projektów systemu Android).

Aplikacje dla systemu Android można również podzielić na oddzielny zestaw APK dla każdego ABI ("architektura"). Dowiedz się więcej w tym wpisie w blogu: Jak zachować rozmiar aplikacji systemu Android w dół.

Optymalizowanie zasobów obrazu

Obrazy to niektóre z najdroższych zasobów używanych przez aplikacje i są często przechwytywane w wysokiej rozdzielczości. Chociaż tworzy to żywe obrazy pełne szczegółów, aplikacje, które wyświetlają takie obrazy, zwykle wymagają większego użycia procesora CPU w celu dekodowania obrazu i większej ilości pamięci do przechowywania zdekodowanego obrazu. Dekodowanie obrazu o wysokiej rozdzielczości w pamięci jest marnotrawne, gdy zostanie on przeskalowany w dół do mniejszego rozmiaru na potrzeby wyświetlania. Zamiast tego zmniejsz zużycie procesora CPU i pamięci, tworząc wiele wersji rozdzielczości przechowywanych obrazów, które są zbliżone do przewidywanych rozmiarów wyświetlania. Na przykład obraz wyświetlany w widoku listy powinien być najprawdopodobniej niższą rozdzielczością niż obraz wyświetlany na pełnym ekranie. Ponadto skalowane w dół wersje obrazów o wysokiej rozdzielczości można załadować, aby efektywnie wyświetlać je przy minimalnym wpływie pamięci. Aby uzyskać więcej informacji, zobacz Wydajne ładowanie dużych map bitowych.

Niezależnie od rozdzielczości obrazu wyświetlanie zasobów obrazu może znacznie zwiększyć ilość pamięci aplikacji. W związku z tym należy je utworzyć tylko wtedy, gdy jest to wymagane i należy je zwolnić natychmiast, gdy aplikacja nie będzie już ich wymagała.

Skrócenie okresu aktywacji aplikacji

Wszystkie aplikacje mają okres aktywacji, czyli czas między uruchomieniem aplikacji a czasem, w którym aplikacja jest gotowa do użycia. Ten okres aktywacji zapewnia użytkownikom pierwsze wrażenie aplikacji, dlatego ważne jest, aby skrócić okres aktywacji i postrzeganie jej przez użytkownika, aby uzyskać korzystne pierwsze wrażenie aplikacji.

Przed wyświetleniem początkowego interfejsu użytkownika przez aplikację powinien zostać wyświetlony ekran powitalny wskazujący użytkownikowi, że aplikacja jest uruchamiana. Jeśli aplikacja nie może szybko wyświetlić swojego początkowego interfejsu użytkownika, ekran powitalny powinien służyć do informowania użytkownika o postępie w okresie aktywacji, aby zapewnić pewność, że aplikacja nie zawiesiła się. To zapewnienie może być paskiem postępu lub podobną kontrolą.

W okresie aktywacji aplikacje wykonują logikę aktywacji, która często obejmuje ładowanie i przetwarzanie zasobów. Okres aktywacji można zmniejszyć, upewniając się, że wymagane zasoby są pakowane w aplikacji, zamiast pobierać zdalnie. Na przykład w niektórych okolicznościach może być to odpowiednie w okresie aktywacji, aby załadować lokalnie przechowywane dane zastępcze. Następnie po wyświetleniu początkowego interfejsu użytkownika i możliwości interakcji użytkownika z aplikacją dane zastępcze mogą być stopniowo zastępowane ze źródła zdalnego. Ponadto logika aktywacji aplikacji powinna wykonywać tylko pracę wymaganą do rozpoczęcia korzystania z aplikacji przez użytkownika. Może to pomóc, jeśli opóźni ładowanie dodatkowych zestawów, ponieważ zestawy są ładowane po raz pierwszy.

Zmniejsz komunikację z usługami sieci Web

Połączenie do usługi internetowej z poziomu aplikacji może mieć wpływ na wydajność aplikacji. Na przykład zwiększone wykorzystanie przepustowości sieci spowoduje zwiększone użycie baterii urządzenia. Ponadto użytkownicy mogą używać aplikacji w ograniczonym środowisku przepustowości. W związku z tym rozsądne jest ograniczenie wykorzystania przepustowości między aplikacją a usługą internetową.

Jednym z podejść do zmniejszenia wykorzystania przepustowości aplikacji jest kompresowanie danych przed przesłaniem ich za pośrednictwem sieci. Jednak dodatkowe użycie procesora CPU z procesu kompresji może również spowodować zwiększone użycie baterii. W związku z tym ten kompromis należy dokładnie ocenić przed podjęciem decyzji, czy przenieść skompresowane dane za pośrednictwem sieci.

Innym problemem, który należy wziąć pod uwagę, jest format danych, które są przesyłane między aplikacją a usługą internetową. Dwa podstawowe formaty to Extensible Markup Language (XML) i JavaScript Object Notation (JSON). XML to format wymiany danych oparty na tekście, który generuje stosunkowo duże ładunki danych, ponieważ zawiera dużą liczbę znaków formatowania. JSON to format wymiany danych oparty na tekście, który generuje kompaktowe ładunki danych, co powoduje zmniejszenie wymagań dotyczących przepustowości podczas wysyłania danych i odbierania danych. W związku z tym format JSON jest często preferowanym formatem dla aplikacji mobilnych.

Zaleca się używanie obiektów transferu danych (DTO) podczas przesyłania danych między aplikacją a usługą internetową. Obiekt DTO zawiera zestaw danych do przesyłania przez sieć. Korzystając z jednostek DTO, można przesyłać więcej danych w jednym wywołaniu zdalnym, co może pomóc zmniejszyć liczbę zdalnych wywołań wykonanych przez aplikację. Ogólnie rzecz biorąc, zdalne wywołanie przenoszące większy ładunek danych zajmuje podobną ilość czasu jako wywołanie, które przenosi tylko mały ładunek danych.

Dane pobierane z usługi internetowej powinny być buforowane lokalnie, a buforowane dane są używane, a nie wielokrotnie pobierane z usługi internetowej. Jednak podczas wdrażania tej metody należy zaimplementować odpowiednią strategię buforowania w celu zaktualizowania danych w lokalnej pamięci podręcznej, jeśli zmieni się w usłudze internetowej.

Podsumowanie

W tym artykule opisano i omówiono techniki zwiększania wydajności aplikacji utworzonych przy użyciu platformy Xamarin. Łącznie te techniki mogą znacznie zmniejszyć ilość pracy wykonywanej przez procesor CPU i ilość pamięci zużywanej przez aplikację.