LINUXSOFT.cz Přeskoč levou lištu
Uživatel: Heslo:  
   CZUKPL

> Benchmark práce s objekty v jazycích C++, Vala a Python

Již delší dobu se chystám programovat v jazyku Vala. Jde o objektově orientovaný jazyk postavený nad GObject. Mima jiného mě zajímala i rychlost výsledného programu. Připravil sem tedy test, který porovnává rychlost práce s třídami a instancemi s ostatními jazyky, ve kterých programuji.

20.9.2011 10:00 | Ondřej Tůma | Články autora | přečteno 3452×

Kompilátor jazyka Vala sám nevytváří binární kód, ale vygeneruje kód v čistém C, který je kompilován běžným kompilátorem, typicky gcc. A protože je inspirován vysokoúrovňovými jazyky a orientován právě na GObject, je interní práce s objekty od ostatních jazyků odlišná. Objekty jsou udržovány v paměti obdobně jako v jazyku Python pomocí referencí. Počítají se tedy reference na objekt, a pokud jsou vynulovány, objekt je z paměti uvolněn.

Test spočívá v definici jednoduché třídy Foo, která má jeden parametr typu integer. Tato třída je následně milionkrát vytvořena, je vyčten její parametr (zavolána metoda instance) a následně zničena. Ještě než přijde řada na zdrojové kódy testů, rád bych uvedl, že jsem si vědom, že kód není nijak optimalizován na konkrétní jazyky a v řadě případů by šel jistě napsat daleko efektivněji. Účelem testu však bylo zjistit, jaké jsou nároky na CPU při běžném použití.

Následují jednotlivé zdrojové kódy, případně jejich variace a výsledný čas měřený nástrojem time. Čas byl měřen třikrát a v grafech jsou použity průměry naměřených hodnot.

C++

V případě C++ jsem do testu začlenil použití třídy (class) bez předka. Rozdíl v použití struktury (struct) je velmi malý a pro srovnání s jazykem Vala vlastně ne zcela vypovídající.
int count = 1000*1000;

class Foo {
private:
int i;

public:
Foo(int i){
this->i = i;
}
int geti(){
return this->i;
}
};

int main(int argv, char ** argc){
for (int i = 0; i < (count); i++){
Foo foo(i);
foo.geti();
}

return 0;
}
C++ class:                                  avg
real 0m0.038s 0m0.039s 0m0.027s 0m0.035s
user 0m0.040s 0m0.032s 0m0.028s 0m0.033s
sys 0m0.000s 0m0.000s 0m0.000s 0m0.000

A také dědění třídy Glib.Object z glibmm, což je c++ wrapper nad glib knihovnou. Rozdíl mezi glibmm a Valou je zejména v tom, že výsledný program nevyžaduje žádnou další knihovnu ke svému provozu.
#include <glibmm/object.h>
#include <glibmm/init.h>

int count = 1000*1000;

class Foo : public Glib::Object {
private:
int i;

public:
Foo(int i):Glib::Object(){
this->i = i;
}
int geti(){
return this->i;
}
};

int main(int argv, char ** argc){
Glib::init();

for (int i = 0; i < (count); i++){
Foo foo(i);
foo.geti();
}

return 0;
}
C++ GObject:                                avg
real 0m5.222s 0m5.308s 0m5.225s 0m5.252s
user 0m5.140s 0m5.176s 0m5.124s 0m5.174s
sys 0m0.004s 0m0.016s 0m0.012s 0m0.011s

Vala

Jazyk Vala může přistupovat k třídám různými způsoby. Nejpodobnější třídě tak jak ji známe z C++ je Struct, který je značně omezen v případě použití jako třídy, nicméně režie okolo vytváření a práce se strukturou se blíží režii v C++, což je dáno zejména tím, že se nepracuje s referencemi.
int count = 1000*1000;

struct Foo {
public int i;
public Foo.new(int i){
this.i = i;
}

public int geti(){
return this.i;
}
}

public int main(string[] args){
for (int i = 0; i < (count); i++){
Foo foo = Foo(){
i = i
};
foo.geti();
}

return 0;
}
Vala struct:                                avg
real 0m0.102s 0m0.102s 0m0.105s 0m0.103s
user 0m0.088s 0m0.096s 0m0.096s 0m0.093s
sys 0m0.008s 0m0.000s 0m0.004s 0m0.004s

Další možnost jak vytvořit odlehčenou třídu je použití direktivy [Compact].
int count = 1000*1000;

[Compact]
class Foo {
public int i;

public Foo(int i){
this.i = i;
}

public int geti(){
return this.i;
}
}

public int main(string[] args){
for (int i = 0; i < (count); i++){
Foo foo = new Foo(i);
foo.geti();
}

return 0;
}
Vala compat class:                          avg
real 0m0.393s 0m0.395s 0m0.399s 0m0.396s
user 0m0.388s 0m0.396s 0m0.392s 0m0.392s
sys 0m0.000s 0m0.004s 0m0.004s 0m0.003s

V jazyce Vala lze dále dělit třídy na ty které nejsou děděny z GLib.Object a ty které jsou. Tyto dvě skupiny budou nejčastěji používané a dva předchozí testy jsou malým porušením testu, neboť se snaží optimalizovat výsledný kód. Ty třídy které nejsou potomky GLib.Object mají o něco menší režii.
int count = 1000*1000;

class Foo {
private int i;

public Foo(int i){
this.i = i;
}

public int geti(){
return this.i;
}
}

public int main(string[] args){
for (int i = 0; i < (count); i++){
Foo foo = new Foo(i);
foo.geti();
}

return 0;
}
Vala class:                                 avg
real 0m2.712s 0m2.758s 0m2.404s 0m2.634s
user 0m2.620s 0m2.716s 0m2.372s 0m2.569s
sys 0m0.004s 0m0.012s 0m0.012s 0m0.009s

Na závěr tedy kód a čas v případě použití třídy, která je potomkem GLib.Object. Je asi vhodné dodat, že právě tyto třídy jsou v jazyce Vala preferované, což je vzhledem k nejčastějšímu použití jazyka pochopitelné.
int count = 1000*1000;

class Foo: GLib.Object {
private string name;
private int i;

public Foo(string name, int i){
this.name = name;
this.i = i;
}

public int geti(){
return this.i;
}
}

public int main(string[] args){
for (int i = 0; i < (count); i++){
Foo foo = new Foo("This is funcking foo", i);
foo.geti();
}

return 0;
}
Vala GObject:                               avg
real 0m6.042s 0m6.052s 0m6.142s 0m6.079s
user 0m5.956s 0m5.932s 0m6.040s 0m5.976s
sys 0m0.004s 0m0.012s 0m0.008s 0m0.008s

Python

Jak už bylo zmíněno, i Python používá ke správě objektů reference. A jelikož je Python jeden z mých hlavních programovacích jazyků, začlenil i jeho tři testy.

První test používá třídu bez předka. Jde o vlastně starý koncept tříd v Pythonu, který je udržován zejména kvůli zpětné kompatibilitě.
count = 1000*1000

class Foo:
def __init__(self, name, i):
self.name = name
self.i = i

def geti(self):
return self.i

for i in xrange(count):
foo = Foo("This is funcking foo", i)
foo.geti()
Python class:                               avg
real 0m6.052s 0m5.771s 0m6.066s 0m5.963s
user 0m5.888s 0m5.636s 0m5.912s 0m5.812s
sys 0m0.004s 0m0.020s 0m0.012s 0m0.012s

V druhém testu je použita třída object. Jde tedy o standardní způsob vytváření objektů. Takto vytvořené třídy a jejich instance mají některé další možnosti, a je to poznat i na režii CPU.
count = 1000*1000

class Foo(object):
def __init__(self, name, i):
self.name = name
self.i = i

def geti(self):
return self.i

for i in xrange(count):
foo = Foo("This is funcking foo", i)
foo.geti()
Python Object:                              avg
real 0m7.129s 0m7.611s 0m6.910s 0m6.883s
user 0m6.972s 0m6.484s 0m6.768s 0m6.741s
sys 0m0.020s 0m0.020s 0m0.028s 0m0.023s

Poslední test stejně jako v C++ nebo Vale používá třídu poděděnou z gobject.GObject. Zde už režie cpu dosahovala poněkud extrémních hodnot.
import gobject

count = 1000*1000

class Foo(gobject.GObject):
def __init__(self, name, i):
gobject.GObject.__init__(self)
self.name = name
self.i = i

def geti(self):
return self.i

for i in xrange(count):
#glib.init()

foo = Foo("This is funcking foo", i)
foo.geti()
Pthon GObject:                              avg
real 0m39.760s 0m39.194s 0m39.332s 0m39.760s
user 0m38.990s 0m38.518s 0m38.658s 0m38.772s
sys 0m0.032s 0m0.020s 0m0.040s 0m0.031s

Grafy


Obr1: Použití základních tříd jazyka.


Obr2: Použití tříd odvozených od GObject implementace v daném jazyku.

Pár slov na závěr

Z uvedených výsledků je zřejmé, že si jazyk Vala nestojí zase až tak špatně. Nicméně vzhledem k tomu, že jde o jazyk určený zejména k tvorbě grafických programů, je škoda, že chybí srovnání s jazyky C# (Mono) a Java. Stejně tak zde chybí test GObjectu v čistém C, který je značněji komplikovanější na použití, bylo by však vidět jak moc si člověk pohorší s výkonem výsledné aplikace.

Výsledný program nebyl nijak optimalizován, to znamená že kompilace probíhala bez dalších parametrů. Stejně tak sem si vědom, že jednotlivé jazyky používají různé vlastní optimalizace a ty, i když nejsou předmětem testu ovlivňují výsledky. A v konečné fázi si rozhodně nemyslím, že typická aplikace vytváří a následně ničí milion objektů. Na druhou stranu rozsáhlá aplikace může takových objektů mít opravdu mnoho, což je ale zcela jiná kapitola.

Jednoznačnou výhodu Valy proti C++ s glibmm vidím zejména v novém přístupu k programování. Jde o jiný jazyk, podobný spíše vysokoúrovňovým jazykům, který je ale šitý na míru GObjectu, tedy GTK+ knihovně. Výsledný kód je ale kompilovaný do binární podoby externím programátorem, a tak nejsou zapotřebí žádné další knihovny, což je vidět i na velikostech výsledných binárek.

Verze pro tisk

pridej.cz

 

DISKUZE

Drobné chybky 21.9.2011 09:55 mmmmario
  L Re: Drobné chybky 23.9.2011 18:52 Aleš Hakl
    L Re: Drobné chybky 23.9.2011 18:55 Aleš Hakl
      L Re: Drobné chybky 25.9.2011 16:42 mmmmario




Příspívat do diskuze mohou pouze registrovaní uživatelé.
> Vyhledávání software
> Vyhledávání článků

4.9.2016 20:13 /Pavel `Goldenfish' Kysilka
PR: Dne 22.9.2016 proběhne v Praze konference Cloud computing v praxi. Tématy bude např. nejnovější trendy v oblasti cloudu a cloudových řešení, provozování ERP v cloudu, o hostování různých typů softwaru, ale třeba i o zálohování dat nabízeném podnikům formou služby.
Přidat komentář

1.9.2016 11:27 /Honza Javorek
Česká konference o Pythonu, PyCon CZ, stále hledá přednášející skrz dobrovolné přihlášky. Máte-li zajímavé téma, neváhejte a zkuste jej přihlásit, uzávěrka je již 12. září. Konference letos přijímá i přednášky v češtině a nabízí pomoc s přípravou začínajícím speakerům. Řečníci mají navíc vstup zadarmo! Více na webu.
Přidat komentář

27.8.2016 8:55 /Delujek
Dnes po 4 letech komunitního vývoje vyšla diaspora 0.6.0.0
diaspora* je open-source, distribuovaná sociální síť s důrazem na soukromý
Více v oficiálním blog-postu
Přidat komentář

24.8.2016 6:44 /Ondřej Čečák
Poslední týden CFP LinuxDays 2016; pokud byste rádi přednášeli na LinuxDays 2016 8. a 9. října v Praze, můžete svůj příspěvek přihlásit, následovat bude veřejné hlasování.
Přidat komentář

9.8.2016 22:56 /Petr Ježek
Zařazení souborového systému reiser4 do jádra 4.7 znamená konečně konec patchování jádra jen kvůli možnosti použít reiser4.
Přidat komentář

12.7.2016 13:14 /František Kučera
Spolek OpenAlt zve na 130. distribuovaný sraz příznivců svobodného softwaru a otevřených technologií (hardware, 3D tisk, SDR, DIY, makers…), který se bude konat ve čtvrtek 21. července od 18:00 v Radegastovně Perón (Stroupežnického 20, Praha 5).
Přidat komentář

11.7.2016 16:53 /Redakce Linuxsoft.cz
Konference LinuxDays hledá přednášející. Přihlášky poběží do konce prázdnin, v září bude hlasování a program. Více na https://www.linuxdays.cz/2016/cfp/.
Přidat komentář

8.5.2016 17:19 /Redakce Linuxsoft.cz
PR: Dne 26.5.2016 proběhne v Praze konference Cloud computing v praxi. Tématy bude např. nejnovější trendy v oblasti cloudu a cloudových řešení, cloudové služby, infrastruktura cloudu, efektivní využití cloudu, možné nástrahy cloudů a jak se jim vyhnout
Přidat komentář

   Více ...   Přidat zprávičku

> Poslední diskuze

19.9.2016 21:04 / Marek Schoř
Poděkování

1.9.2016 13:07 / Walker
hardwood floor refinishing

12.8.2016 11:51 / Josef Zapletal
Jak udělat HTML/Javascript swiping gallery do mobilu?

8.8.2016 14:58 / Adams
fairies for hire

28.7.2016 15:51 / pepan
Re: NetBeans vs Eclipse

Více ...

ISSN 1801-3805 | Provozovatel: Pavel Kysilka, IČ: 72868490 (2003-2016) | mail at linuxsoft dot cz | Design: www.megadesign.cz | Textová verze