Odeslat poptávku

Mapování data streamu na výkon mobilní aplikace

Současné architektury používané pro vývoj software mají přes všechny odlišnosti jednu věc společnou – snahu o loose coupling, tedy volné vazby mezi jednotlivými moduly. Jedním z prostředků, které umožňují dosažení tohoto cíle, je používání proprietárních objektů pro reprezentaci dat, což přináší neoddiskutovatelné výhody. 

Nové moduly aplikace je možné vyvíjet nezávisle na stavu ostatních modulů. Omezují se problémy s mergem při současném vývoji. Struktura objektů nebude navádět programátora na specifická řešení, která při pozdějších úpravách přestanou fungovat. Úprava pro znovupoužití v jiné aplikaci obvykle spočívá pouze v úpravě mapovacího interface.

Nicméně pro Android aplikace se může zdát, že se jedná o příliš náročné řešení. Na rozdíl od většiny business aplikací je většinou datový model relativně malý a téměř všechna data je potřeba dostat až do prezentační vrstvy. Znovupoužití celého modulu je reálné pravděpodobně jen u práce s uživatelem. Většinu logiky, která by se mohla měnit, obstarává server, tak by bylo zbytečné vytvářet mapovací funkce mezi prakticky stejnými objekty. Navíc když uživatel vyžaduje co možná nejrychlejší odezvu a výkon zařízení, na kterých mobilní aplikace může běžet. A je vlastně tento vliv měřitelný? Právě na poslední otázku cílí tento experiment. 

Experiment

Aktuálně Googlem doporučená architektura pro tvorbu Android aplikací je Model - View - View model (MVVM) s využitím Architecture Components, konkrétně komponenty ViewModel na místě view modelu, Activity a Fragment na místě view a vlastní implementace na místě modelu. Tímto jsou definovány dvě hranice logicky vyžadující mutaci dat, konkrétně na přechodu model/view model a view model/view. Samozřejmě je možné jich v rámci architektury konkrétní mobilní aplikace definovat více, ale princip je stále stejný. 

Pro účely experimentu byla vytvořena aplikace sestávající z jedné Activity a ViewModelu. Model pro zjednodušení nebyl implementován jako samostatná třída. Jako nosič dat byla zvolena komponenta LiveData a byl měřen rozdíl mezi časem přijetí informace o nové sadě generovaných dat v originálním streamu a sadě operací Transformations.Map (LiveData source, Function mapFunction). Dále byl měřen objem alokované paměti s a bez této sady mutací.

Testovací data byla generována jako seznam o tisíci objektech s náhodným textovým řetězcem a pěti náhodnými čísly s tím, že v každé mutaci byl vytvořen nový objekt a bylo odstraněno jedno z těchto čísel. Abychom minimalizovali vliv výkonu zařízení, tak testování probíhalo na emulátoru a sadě testovacích zařízení. 

Výsledky

Alokovaná paměť bez mapování streamu

Alokovaná paměť s mapovanými streamy

Výsledky napříč testovacími zařízeními byly konzistentní, zpoždění mezi obdržením nové sady dat v originálním streamu a mapovaném streamu byl v řádu milisekund (emulátor, nová zařízení) až nízkých desítek milisekund (low-end zařízení). Z hlediska alokované paměti nebyl pozorován rozdíl. Ani při použití textových dat o délce v řádu deseti tisíc znaků.

Z toho vyplývá, že samotné mapování streamů vliv má, nicméně ho lze považovat za zanedbatelný. Komplexnější mapovací funkce by samozřejmě vedly k větším zpožděním, ale v takovém případě by kromě mapování obsahovaly pravděpodobně i logiku aplikace. Toto zpoždění by tedy bylo nevyhnutelné.

Závěr je, že snažit se ušetřit výkon na rozhraní modulů nemá smysl. Pokud plánujete dloudobý vývoj mobilních aplikací, jsou proprietární třídy správnou cestou.