Noutati despre interfete web si interfete evoluate

Se afișează postările cu eticheta performanta. Afișați toate postările
Se afișează postările cu eticheta performanta. Afișați toate postările

duminică, 14 decembrie 2008

Speed of Browsers


Intr-un articol anterior vorbeam despre Web Workers. Pe scurt, "Web Workers"-ii reprezinta o modalitate prin care un script Javascript poate beneficia de facilitatile de multithreading oferite de sistemul de operare.

Motivul pentru care a aparut acest API (practic, utilizarea acestor facilitati se face prin intermediul unor functii disponibile in Javascript) il reprezinta dorinta utilizatorilor de a avea aplicatii web cat mai rapide, precum si dorinta programatorilor de a putea face aplicatii care sa ofere functii cat mai "dragute". Vezi Google Orice (Docs, Gmail etc.).

In ziua de azi, din ce in ce mai multe site-uri ofera continut care foloseste foarte mult facilitatile oferita de Javascript. Din aceasta cauza, baietii de la Google Chrome s-au gandit ca o dezvoltare logica a browser-elor inseamna marirea vitezei cu care se executa/interpreteaza codul Javascript. Astfel, in Chrome vine cu cateva lucruri diferite fata de alte browsere:
  1. fiecare tab ruleaza intr-un proces separat, in care codul Javascript poate rula in thread-uri separate. La pornirea Google Chrome se creaza un proces principal, de control, iar fiecare tab deschise duce la crearea unui nou proces. In felul acesta, un tab care face niste procesari intense nu afecteaza in niciun fel celelalte tab-uri;
  2. codul Javascript este compilat direct in cod binar specific masinii pe care ruleaza browserul. In Firefox 3, Javascript-ul este adus la forma unui limbaj intermediar (bytecode), dupa care este compilat la nevoie (oarecum asemanator cu ce se intampla in cazul Java). Firefox 3.1 are un mod diferit, despre care am sa vorbesc mai jos;
  3. Javascript-ul nu are suport direct pentru clase. Cei de la Chrome au introdus o notiune noua (hidden classes), prin care permit reutilizarea codului intr-un mod asemanator cu cel din limbajele de programare normala. Plus ca apare si un Garbage Collector...
(Detalii suplimentare despre V8, motorul Javascript al Chrome-ului gasiti la adresa: http://code.google.com/p/v8/)

Baietii de la Google au fost destul de destepti cand au luat decizia de a face un browser mai rapid. Nu neaparat pentru ca lor le-a iesit un produs bun, dar pentru ca au impins din spate ceilalti producatori.

Astfel se face ca cei de la Mozilla au facut o mica modificare in Firefox 3.1, care aduce un plus destul de important de viteza. Motorul Javascript din Firefox 3.1 nu mai este SpiderMonkey. El a fost inlocuit cu TraceMonkey, care foloseste o alta metoda de "interpretare" a codului. Practic, acesta nu mai genereaza un graf de control al fluxului (Control flow graph - CFG) in sensul clasic, si, in felul acesta, nu compileaza tot codul la inceput (ca Google Chrome) si nici nu aduce tot codul intr-un limbaj intermediar (ca Firefox 3.0.1). In felul acesta, se pot obtine pe alocuri viteze de circa 30 de ori mai mari decat in forma clasica. TraceMonkey foloseste trace-trees, despre gare gasiti mai multe detalii aici: http://www.ics.uci.edu/~franz/Site/pubs-pdf/ICS-TR-07-12.pdf


To be continued...


Ionut

Read more...

joi, 20 noiembrie 2008

Starcraf2 si XML-ul

Un post foarte scurt:

Nu stiu cati dintre cei trei care urmaresc acest blog sunt pasionati de Starcraft, dar e un lucru care merita sa fie spus despre site-ul Starcraft2: este facut doar cu XML-uri si XSL-uri (plus, evident, Flash).

Insa, din cauza asta, consumul de resurse este putin cam mare. Folosind Process Explorer, lucrurile raportate arata cam asa (am folosit ultimele versiuni disponibile pentru browsere, fiecare a fost deschis pe aceeasi masina si a fost incarcat doar site-ul http://www.starcraft2.com/, sistemul de operare fiind Windows XP SP3):

  1. Internet Explorer 7: private bytes: 72M, virtual size: 208M, 1 proces cu 12 thread-uri;
  2. Firefox: private bytes: 41M, virtual size: 115M, 1 proces cu 16 thread-uri;
  3. Chrome: private bytes: 18+17+48M (are trei procese diferite), virtual size: 125+76+127M, 3 procese cu cate 25, 2 si 7 thread-uri. Aici trebuie sa ma adaug si faptul ca are un consum imens de procesor (imi tine un core cam pe la 100%).

Asa ca vin si-mi pun o intrebare simpla: oare chiar merita sa folosesti XML-uri pentru a face interfete? Recunosc ca e simplu. De exemplu, site-ul Starcraft 2 e foarte curat. Codul sursa e pe intelesul oricui. Totul e frumos. Mai putin consumul de resurse...

Disclaimer: recunosc ca datele de performanta pentru browsere pot sa varieze, insa ele vor fi in jurul acelorasi valori.

Ionut

Read more...

Adunarea a doua siruri in Java

La cererea expresa a lui Florin si contrar vointei acestuia, subiectul primului meu post pentru proiectul de la cursul Interfete Evoluate va fi despre un lucru aparent banal: concatenarea a doua siruri in Java.

Operatia de adunare (concatenare) a doua siruri este una foarte raspandita in aplicatiile Java normale. Insa aceasta creaza probleme din cauza faptului ca obiectul String este imutabil. Practic, din adunarea a doua obiecte de tip String, va rezulta o noua instanta, complet diferita de primele doua. In codul compilat (adica in fisierul .class), acest lucru se face prin instantierea clasei StringBuilder si apelarea metodei append. Mai exact, daca vom scrie intr-o functie urmatoarea secventa de cod:


String s1 = "a";
String s2 = "b";
String s3 = s1 + s2;


Ea va fi compilata in:

String s1 = "a";
String s2 = "b";
String s3 = (new StringBuilder(String.valueOf(s1))).append(s2).toString();


Ca observatie, StringBuilder-ul este folosit doar de la Java 1.5. In versiunile mai vechi (care, din pacate inca se mai intalnesc...) se utilizeaza StringBuffer.

Este evident faptul ca apelul String.valueOf este inutil deoarece s1 este nenul (valueOf cu parametru de tip Object, intoarce sirul "null" daca parametrul este nul sau apeleaza functia toString() a obiectului daca acesta este nenul). De asemenea, in cazul in care o asemenea operatie se face des, cum ar fi intr-un ciclu, atunci este mai bine sa se reutilizeze instanta StringBuilder. Mai exact, daca avem urmatoarea secventa de cod:

for (int i=0; i<100; i++) {
String s1 = "a";
String s2 = "b";
String s3 = s1 + s2;
}

ea va fi compilata in:

for (int i=0; i<100; i++) {
String s1 = "a";
String s2 = "b";
String s3 = new StringBuilder(String.valueOf(s1)).append(s2).toString();
}

Evident, acest cod poate fi optimizat in felul urmator (facem abstractie de modul in care functioneaza instantierea obiectelor in Java):

StringBuilder buffer = new StringBuilder();
for (int i=0; i<100; i++) {
String s1 = "a";
String s2 = "b";
buffer.setLength(0);
String s3 = buffer.append(s1).append(s2).toString();
}


Ca incheiere, vreau sa mai adaug doar ca incepand cu Java 1.5, StringBuilder si StringBuffer au un parinte comun, AbstractStringBuilder (aici ma refer la JDK-ul de la Sun). Practic, in clasa abstracta sunt implementate toate operatiile, iar StringBuilder si StringBuffer actioneaza doar ca niste wrapper-e. Diferenta dintre cele doua clase este data de faptul ca StringBuffer este thread-safe deoarece apelurile sale sunt marcate ca synchronized.

Ionut

Read more...

Arhivă blog