Wpływ dekompresji kodu źródłowego (unminify process) na wydajność aplikacji mapowej*

Wydajność jest kluczowym atrybutem użyteczności. Na wydajność aplikacji internetowej mają wpływ m.in. skrypty, pliki graficzne i biblioteki programistyczne. Jaki wpływ na wydajność aplikacji mapowej ma dekompresja kodu źródłowego (unminifikacja)? Czy aplikację o zdekompresowanym kodzie źródłowym charakteryzuje pierwotna wydajność?

*Król, K. (2020). Impact of source code decompression (unminify process) on the map application performance. Geomatics, Landmanagement and Landscape (GLL), 3 (ahead of print).

Aby odpowiedzieć na te pytania przygotowano prototypową aplikację mapową. Aplikację utworzono w trzech wariantach: 1) podstawowym, 2) zminimalizowanym (minified) oraz 3) zdekompresowanym (unminified source code). Dla każdego z wariantów wykonano testy wydajności. Wyniki porównano. Wprowadzono nowe pojęcia: wydajność pierwotna, wydajność wtórna i recykling kodu. Wykazano, że wydajność wtórna stanowiła wynik kompromisu pomiędzy wydajnością pierwotną a „czystością” (czytelnością) kodu.

Transformacja kodu ma znaczenie

Istnieje wiele rodzajów transformacji kodu. Przekształcenia mające na celu zmniejszenie rozmiaru kodu nazywane są minifikacją (minimalizowanie, minification). Bardziej złożone transformacje, które mają na celu uniemożliwić lub utrudnić odczytanie kodu określane są jako „zaciemnianie kodu” (code obfuscation). W uzasadnionych przypadkach stosowana jest zarówno minifikacja, jak i zaciemnianie kodu [Skolka i in. 2019].

Minifikacja = optymalizacja kodu?

Minifikacja polega na usunięciu wszystkich zbędnych znaków z kodu źródłowego, np. HTML, CSS lub JavaScript, bez zmiany funkcjonalności tego kodu. Z kodu usuwane są znaki, które ułatwiają jego czytelność, ale nie są wymagane do jego wykonania, m.in. znaki nowej linii, tabulatory i spacje. Komentarze, które ułatwiają interpretację kodu także są usuwane [Souders 2007]. Głównym celem minifikacji jest zmniejszenie rozmiaru kodu źródłowego, przez co poprawa wydajności programu/aplikacji. Minifikacja bywa także wykorzystywana do zaciemniania kodu, tak aby zmniejszyć jego czytelność [Hague et al. 2019].

Zoptymalizowany kod źródłowy bywa trudny w interpretacji dla programisty zatem optymalizację przeprowadza się przeważnie w końcowym etapie tworzenia programu (wersja produkcyjna). Zalecane jest zachowanie pliku źródłowego, ponieważ proces odwrotny może być trudny do przeprowadzenia lub nie da satysfakcjonujących rezultatów.
Programiści często minifikują kod źródłowy, aby uzyskać lepszą wydajność aplikacji. Minifikacja jest procesem odwracalnym, jeśli zostanie przeprowadzona w odpowiedni sposób. Unminifikację kodu można przeprowadzić ręcznie lub przy pomocy wybranych narzędzi komputerowych.

Narzędzia pomocne w audycie SEO

Ferdinandi [2018] poddał minifikacji nieduże pliki JavaScript (o rozmiarze 25KB). Minifikacja pozwoliła zredukować ich rozmiar tylko nieznacznie. Zwrócił on uwagę, że taki rezultat nie będzie miał żadnego znaczenia dla użytkowników korzystających z szybkich łączy internetowych. Jednak w krajach rozwijających się, gdzie występują znaczące problemy z dostępem do internetu ma to większe znaczenie [Schuppan 2009]. Może to mieć także szczególne znaczenie w przypadku aplikacji mobilnych. Jednocześnie Ferdinandi [2018] zauważył, że jeśli w kodzie jest dużo białych znaków i długich komentarzy, minifikacja może znacząco zredukować rozmiar pliku.

Zaciemnianie kodu

Zaciemnianie kodu, zwane także obfuskacją (obfuscation) lub „maskowaniem kodu” to technika przekształcania kodu źródłowego, która zachowuje jego semantykę, tzn. sposób w jaki działa aplikacja pozostaje niezmieniony, lecz znacząco utrudnia zrozumienie kodu. Obfuskacja polega na takim przekształceniu kodu źródłowego, np. poprzez zmianę jego struktury, aby utrudnić jego zrozumienie, przy jednoczesnym zachowaniu oryginalnej funkcjonalności [Ceccato i in. 2014]. Nie należy utożsamiać obfuskacji z minifikacją, ani też szyfrowaniem, ponieważ nie istnieje hasło umożliwiające odszyfrowanie zaciemnionego kodu.

Jak zaciemnić kod źródłowy?

Wyróżnia się trzy zasadnicze typy obfuskacji [Collberg et al. 1997]: (1) layout transformation (layout obfuscations) – polega na zmianie nazw identyfikatorów, zmianie formatowania kodu lub usuwaniu komentarzy, (2) data transformation (data obfuscations) – polega np. na rozdzielaniu zmiennych, konwersji statycznych danych do procedury, zmianie kodowania, zmianie długości życia zmiennej lub łączeniu zmiennych skalarnych, (3) control transformation (control-flow obfuscations) – polega m.in. na zmianie przebiegu lub rozszerzeniu warunków pętli, zmianie kolejności komend, pętli lub wyrażeń. Istnieją także inne typy transformacji obfuskacyjnych np. Dead-Code Insertion, Subroutine Reordering lub Register Reassignment, które są stosowane w złośliwym oprogramowaniu polimorficznym i metamorficznym [You and Yim 2010].

Unminify, reformat and reindent ugly code

Unminifikacja jest procesem odwrotnym do minifikacji. Unminifikacja bywa pomocna gdy deweloper oprogramowania posiada jedynie wersję produkcyjną pliku z kodem, który został poddany minifikacji lub obfuskacji. Modyfikacja takiego kodu może być utrudniona – mozolna i czasochłonna, lub niemożliwa. Zasadniczo efekty minifikacji można cofnąć jeśli z kodu usunięte zostały tylko białe znaki i komentarze. Jest to jednak niemożliwe, gdy kod zostanie zaciemniony, np. w przypadku kodu JavaScript. Wtedy pomocna może okazać się inżynieria wsteczna (reverse engineering). Nawet jeśli proces unminifikacji nie przywróci oryginalnej struktury kodu to przynajmniej zwiększy jego czytelność, co ułatwi „naprawę kodu”.

Proces cofania efektów minifikacji lub obfuskacji jest często nazywany „upiększaniem” ponieważ sprawia, że kod (np. HTML, CSS lub JavaScript) „wygląda pięknie”. Innymi słowy unminifikacja sprawia, że kod jest ponownie możliwy do odczytania.

Materiały i metody

W celach badawczych utworzono prototypową aplikację internetową. Aplikację utworzono w taki sposób, że grafiki rastrowe były nałożone na siebie jedna na drugą i wywoływane w oknie przeglądarki internetowej w wyniku aktywności użytkownika (ryc. 1). Następnie przeprowadzono testy wydajności przy pomocy wybranych aplikacji internetowych.

ryc1-unminify Rycina 1. Schemat nakładania rastrów w aplikacji internetowej

Testy wydajności podzielono na trzy zasadnicze etapy [Budiman et al. 2019]:
etap pierwszy E1 (preliminary testing, Pre-Test),
etap drugi E2 (testy po optymalizacji kodu, Post-Test) oraz
etap trzeci E3 (testy po unminifikacji kodu, Final-Test).

W pierwszy etapie dokonano pomiaru wydajności pierwotnej, tzn. wydajności bazowej wersji aplikacji – przed minifikacją kodu. Następnie dokonano pomiaru wydajności wtórnej. W dalszej kolejności dokonano minifikacji kodu i powtórzono test wydajności (etap E2). Kompresji poddano pliki HTML, CSS oraz JavaScript. Operację wykonano przy pomocy wybranych narzędzi internetowych (HTMLCompressor; CSS Compressor; JSCompress). W ostatnim etapie dokonano pomiaru wydajności wtórnej (E3), tzn. wydajności aplikacji po zastosowaniu narzędzi do unminifikacji kodu. Unminifikację wykonano przy pomocy wybranych narzędzi internetowych (Unminify; CSSunminify). Tak przetworzony kod został określony jako „kod poddany recyklingowi”, czyli kod możliwy do ponownej edycji.

W ten sposób zmierzono wydajność aplikacji internetowej w trzech wersjach:
1) bazowej (pierwotnej),
2) zoptymalizowanej (skompresowanej),
3) bazowej zmodyfikowanej (wersja „recyklingowa”).

Uzyskane wyniki porównano.

Efekty minifikacji

W procesie minifikacji zmniejszeniu uległy rozmiary plików składowych aplikacji (tab. 1).

Table 1. Rozmiary plików składowych aplikacji

Rodzaj plików (jednostka miary) Rozmiary plików w teście E1 Rozmiary plików w teście E2 Rozmiary plików w teście E3
HTML (KB) 18.5 16.3 22.0
CSS (KB) 1.03 0.577 0.813
JavaScript (KB) 2.31 0.938 1.20
Suma 21.84 17.815 24.013

Źródło: badania własne

Minikacja kodu zmniejszyła pliki składowe aplikacji o niecałe 20%, co miało nieznaczny wpływ na poprawę wydajności aplikacji (w przyjętym modelu badań). Unminifikacja kodu sprawiła, że wydajność aplikacji powróciła do stanu sprzed kompresji (tab. 2). Jednocześnie jednak poprawiona została struktura kodu. Wydajność aplikacji po zdekompresowaniu była w przypadku większości wskaźników zbliżona do wersji pierwotnej lub identyczna.

Table 2. Wartości wskaźników wydajności

Performance tool Key performance indicators (KPIs) Wynik pomiaru E1 Wynik pomiaru E2 Wynik pomiaru E3
GTmetrix Total Page Size (MB) 1.05 1.05 1.05
PageSpeed Score C (70%) C (70%) C (70%)
YSlow C (78%) C (79%) C (78%)
Fully Loaded Time 2.2(s) 2.2(s) 2.2(s)
BlazeMeter Avg. Throughput (Hits/s) 59.56 60.11 60.02
Avg. Response Time (ms) 327.93 324.63 325.07
Response Time (ms) 329 329 329
Avg. Bandwidth (MiB/s) 1.09 996.68 1.3
Max Users 20 20 20

Źródło: badania własne

Badania pokazały, że wydajność pierwotna była wydajnością najmniej korzystną, chociaż różnice pomiędzy poszczególnymi wariantami aplikacji były nieduże. W tym miejscu należy nadmienić, że wskaźnik Avg. Response Time to destymulanta i oczekiwana jest jego jak najmniejsza wartość. Zabiegi minifikacji oraz unminifikacji nie miały wpływu na wartość wskaźnika Response Time.

Kiedy minifikacja ma sens?

Im mniejsze są pliki składowe aplikacji oraz zmiany wynikające z kompresji kodu, tym czulsze powinno być narzędzie do pomiaru wydajności. Niewielkie zmiany objętości plików, które mają wpływ na wydajność aplikacji mogą nie zostać odnotowane przez mało czułe narzędzia testujące lub „zaginąć” w wyniku zaokrąglenia wartości wskaźników. Tymczasem nawet najmniejsze zmiany objętości plików mogą mieć wpływ na wydajność aplikacji, w szczególności gdy jest ona przeznaczona dla urządzeń mobilnych.

Unminifikacja miała korzystny wpływ na strukturę kodu i wielkość plików składowych testowanej aplikacji. Testy potwierdziły główną zaletę unminifikacji, którą jest porządkowanie kodu. Efektem unminifikacji był schludny i uporządkowany kod, wyrównany i hierarchiczny, co znacząco ułatwiało jego interpretację. Jednocześnie porządkowanie kodu miało wpływ na wydajność aplikacji, chociaż badania pokazały, że stosunkowo niewielki.

Źródła

  • Budiman, E., Puspitasari, N., Wati, M., Widians, J. A. (2019). Web Performance Optimization Techniques for Biodiversity Resource Portal. IOP Journal of Physics: Conference Series, 1230(1), 012011. https://doi.org/10.1088/1742-6596/1230/1/012011
  • Ceccato, M., Di Penta, M., Falcarin, P., Ricca, F., Torchiano, M., Tonella, P. (2014). A family of experiments to assess the effectiveness and efficiency of source code obfuscation techniques. Empirical Software Engineering, 19(4), 1040-1074. https://doi.org/10.1007/s10664-013-9248-x
  • Collberg, C., Thomborson, C., Low, D. (1997). A taxonomy of obfuscating transformations. Department of Computer Science, The University of Auckland, New Zealand.
  • Ferdinandi, K. (2018). Does minification actually matter? Go Make Things Blog, https://gomakethings.com/does-minification-actually-matter/
  • Hague, M., Lin, A. W., Hong, C. D. (2019). CSS Minification via Constraint Solving. ACM Transactions on Programming Languages and Systems (TOPLAS), 41(2), 12.
  • Schuppan, T. (2009). E-Government in developing countries: Experiences from sub-Saharan Africa. Government Information Quarterly, 26(1), 118-127. https://doi.org/10.1016/j.giq.2008.01.006
  • Skolka, P., Staicu, C. A., Pradel, M. (2019). Anything to Hide? Studying Minified and Obfuscated Code in the Web. In The World Wide Web Conference (pp. 1735-1746). ACM.
  • Souders, S. (2007). High Performance Web Sites: Essential Knowledge for Front-End Engineers. O’Reilly Media.
  • You, I., Yim, K. (2010). Malware obfuscation techniques: A brief survey. International conference on broadband, wireless computing, communication and applications (pp. 297-300). IEEE.

One Comment

  1. Pingback: Wydajność aplikacji mapowej na urządzeniach mobilnych – Karol Król

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *