Portál AbcLinuxu, 19. říjen 2017 16:55

Ze 4 s na 0,9 s – programovací jazyk Vala v praxi

6. 8. 2013 | Vratislav Podzimek
Články - Ze 4 s na 0,9 s – programovací jazyk Vala v praxi  

Před rokem jsem se ve dvou článcích zaměřených na programovací jazyk Vala věnoval jeho základům a snažil jsem se nastínit, jaké výhody přináší. Původním záměrem bylo postupně ukazovat vlastnosti Valy na jednoduché "ukázkové" aplikaci bez reálného využití.

Bohužel jsem však nenašel dostatek času, který bych takovým snahám mohl věnovat, a tak se k šíření povědomí o Vale vracím až nyní, kdy mě pracovní povinnosti přiměly Valu znovu oprášit a použít. Věřím, že reálné využití s reálnými výsledky lépe vystihne, proč se vyplatí o Vale uvažovat jako o programovacím jazyku některého z příštího projektů, kterými se budete věnovat.

Obsah

Zasazení do kontextu

link

V práci působím jako jeden z vývojářů značně populárního instalátoru GNU/Linuxové distribuce Fedora (a všeho od ní odvozeného) – Anacondy. Jedním z úkolů instalátoru je nastavení lokalizace systému (a samotné instalace), tedy jeho jazyka, rozložení klávesnice, časového pásma, fontu pro systémovou konzoli, formátu papíru apod. S tím však přichází několik algoritmicky neřešitelných problémů, které lze rozdělit do dvou kategorií: 1. Odkud vzít seznam jazyků, rozložení klávesnic, časových pásem apod., ze kterých může uživatel vybírat? 2. Jak vzájemně odvozovat informace z jedné volby pro pro volby ostatní?

Instalátor Anaconda proto ve svých zdrojových kódech obsahoval soubor s názvem lang-table, jenž obsahoval seznam jazyků spolu s mapováním na jejich zkratku, preferovaný konzolový font, tzv. locale, rozložení klávesnice a časové pásmo. Jeden řádek souboru tedy vypadal např. takto:

Czech cs latarcyrheb-sun16 cs_CZ.UTF-8 cz-lat2 Europe/Prague

Na začátku běhu instalátoru byl soubor lang-table zpracován a uživateli byl nabídnut seznam "podporovaných" jazyků, ze kterých mohl vybírat, a další hodnoty byly odvozeny na základě tohoto výběru s tím, že např. časové pásmo bylo možné později upravit. Toto řešení však znamenalo, že přidání dalšího jazyka do výběru instalátoru znamenalo přidání řádku do lang-table a tím změnu zdrojových kódů. Navíc byl tento soubor udržován vývojáři instalátoru, kteří ve většině případů neměli ponětí, jaké je správné výchozí rozložení klávesnice nebo časové pásmo pro který jazyk.

Bylo tedy zřejmé, že je potřeba přijít s lepším, samostatným, rozšiřitelným a snadněji udržovatelným řešením. Prvním krokem byl přechod instalátoru k zobrazování výběru jazyků na základě dostupných překladů. Jenže jak algoritmicky přejít od řetězce "cs" k locale "cs_CZ.UTF-8", kde vzít řetězce "Czech" a "čeština" apod.? Některé z těchto problémů řešily různé kusy "magického kódu", který však v mnoha případech selhával, locales byly vyřešeny pomocí tabulky mapující na ně zkratky jazyků (označujících překlady). Tedy opět dost problémů, spousta nefungujících případů a složitá údržba. Proto vznikla iniciativa, jejíž výsledkem byly diskuze na Developer Conference 2013 v Brně a následný vznik projektu Mika Fabiana, langtable (tedy o mínus méně), který obsahuje právě taková mapování a seznamy (v podobě XML dokumentů) spolu s pythonním modulem pro dotazování. Jedná se tedy o samostatný, lépe udržovatelný, znovu využitelný a odborníky vyvíjený a udržovaný projekt, který vyřešil spoustu palčivých problémů Anacondy (částečně již u verze použité ve Fedoře 19, plně pak od Fedory 20) a do budoucna snad i jiných instalátorů, aplikací atd.

Případ pro Valu

link

Projekt langtable pro Anacondu přinesl mnoho výhod – méně řádků zdrojových kódů, jejich lepší čitelnost, větší přesnost údajů a nahrazením modulu python-babel a objektů z něj získávaných také úsporu 20 MB v paměťové náročnosti instalátoru. Jak se říká: "So far, so good." Nicméně, jak asi již mnohé napadá, Python není zrovna ideální na zpracování velkého množství XML dat. Původní verze langtable používala modul z lxml, s jehož pomocí byl vytvořen tzv. Element Tree (v podstatě DOM strom), jenž byl procházen a z dat v něm obsažených byly tvořeny objekty ukládané v datových strukturách užívaných při dotazování. Protože však takto vytvořený strom spolu s objekty zabíral poměrně velké množství paměti (více než 30 MB pro asi 2,5 MB XML dat), bylo zpracování dat přepsáno na využití tzv. SAX parseru, který vytváří pythonní objekty přímo při průchodu XML daty. Tím bylo dosaženo úspory téměř poloviny obsazené paměti, avšak za cenu dvojnásobného navýšení času zpracování dat a tím i importu modulu langtable (např. na mém netbooku z asi 2 sekund na 4 sekundy, což už je poměrně nepřijatelná hodnota). Důvodem pro zpomalení je fakt, že zatímco lxml je napsán v Céčku, SAX parser volá funkce napsané v Pythonu. Dalším problémem je prakticky nemožnost paralelizace, neboť zpracování tří samostatných XML ve třech samostatných vláknech vede v Pythonu díky GIL (Global Interpreter Lock) ke zpomalení, namísto očekávaného zrychlení. V neposlední řadě je zde problém s tím, že pythonní modul lze jen stěží použít z jiného prostředí nebo programovacího jazyka, než je Python.

A teď tedy, abych navnadil všechny, co už po dlouhém, Valu opomíjejícím úvodu usínají a chystají se článek zavřít, to nejdůležitější – přepsání modulu langtable do Valy, jemuž se budu věnovat ve zbytku článku, snižuje paměťovou náročnost o další 1 MB a především zrychluje import z Pythonu (zahrnující zpracování XML dat) na přibližně 0,9 sekundy! Navíc lze takto napsaný a zkompilovaný modul se dvěma malými doplňujícími soubory pro introspekci používat z velkého množství programovacích jazyků od Pythonu, přes Perl, Javu a D až po Haskell a řadu dalších.

Zpracování XML dat

link

libxml2 a Vala

link

Jak jsem již zmínil v předchozích odstavcích, není nutné pro zpracování XML dat vytvářet strom elementů, a proto i "valová" verze knihovny langtable využívá tzv. Simple API for XML, neboli SAX, konkrétně implementaci knihovny libxml2. Tato knihovna podporuje introspekci (i když nepoužívá přímo knihovnu GObject) a byl k ní vytvořen (vygenerován a doladěn) tzv. .vapi soubor, který definuje třídy, struktury, typy apod. pro Valu a obsahuje jejich mapování na funkce, struktury apod. knihovny libxml2. Zároveň tento soubor definuje jmenný prostor (namespace) Xml a nepoužijeme-li na začátku našeho zdrojového kódu using Xml;, musíme pro volání, deklarování atd. používat tento prefix. .vapi soubor je tedy v podstatě i takovou "lehce hardcorovou" dokumentací pro používání knihovny libxml2 z Valy. Nás nejvíce zajímá struktura Xml.SAXHandler, její atributy sloužící pro uložení odkazů na funkce reagující na události (viz dále) a její metoda (ano struktury ve Vale mohou mít metody) user_parse_file, jenž provádí zpracování dokumentu specifikovaného jedním z argumentů.

Základy SAX

link

Protože dále budu vysvětlovat, jak funguje kód pro zpracování XML dat a proč vypadá zrovna tak, jak vypadá, začnu něčím, co by se dalo nazvat "SAX v kostce" (odborníci na XML snad prominou). SAX je totiž velmi jednoduché, univerzální, ale poněkud "spartánské" API. Parser prochází XML dokument a při tom vyvolává události, na které reaguje handler. Jinými slovy, parser volá patřičné funkce handleru pro každou událost, která nastane. Pro začátek dokumentu je to funkce startDocument, pro konec dokumentu endDocument, obdobně pro začátek/konec elementu, characters pro textová data (obsah elementů) a tak dále. Celkově je funkcí přes 20, ale implementace SAX většinou (libxml2 není výjimkou) umožňují definování pouze těch funkcí, které chceme provádět, a ponechání ostatních na výchozí hodnotě, což je ekvivalentní ignorování odpovídajících událostí.

Funkce definované SAX však dostávají jako argumenty velmi málo informací z XML dokumentu, např funkci startElement je předán pouze název elementu a seznam atributů, funkci characters jsou pak předána pouze textová data, na která parser narazil. Proto je vždy navíc předáván odkaz (void *) na libovolnou datovou strukturu, jež je předána parseru ve funkci user_parse_file. Programátor využívající SAX musí zajistit, aby tato datová struktura obsahovala veškeré informace nutné pro běh funkcí reagujících na události. "Jednoduchým" příkladem může být předávání odkazu na strom elementů doposud zpracované části dokumentu a jeho postupné rozšiřování. Pokud však chceme s daty z XML dokumentu pracovat jiným způsobem (např. kvůli rychlosti či paměťové náročnosti), musíme ve funkcích vytvářet úplně jiné struktury. A to je právě i případ langtable.

Chtěl bych zde předem upozornit, že jsem se držel struktury i algoritmů původní pythonní verze knihovny a neměl jsem v úmyslu je nijak optimalizovat a upravovat, neboť chci, aby se "valová" verze stala upstreamem a nadále byla vyvíjena a udržována Mikem Fabianem, autorem langtable. Zároveň si tak ukážeme, jak podobná Vala Pythonu může být. Za slušné a zdvořilé připomínky ke kódu, optimalizacím, refaktoringu apod. však budu samozřejmě vděčný.

Zpracování XML dat

link

A teď už k samotmému kódu. Knihovna langtable ukládá veškerá data ve třech interních, globálních datových strukturách odpovídajících třem XML souborům. Tyto datové struktury mapují ID elementů na objekty obsahující informace o nich. Např. struktura languages_db obsahuje jako klíč cs, jehož hodnotou je objekt držící kódy jazyka, názvy jazyka v různých překladech, teritoria (de facto státy) spojená s jazykem, locale hodnoty, preferované klávesnice atd. Proto handler pro zpracování souboru languages.xml bude vytvářet právě takové objekty a přidávat je do "databáze" languages_db.

Protože pro vytváření struktur mapujících řetězce na objekty budeme používat knihovnu Gee, která poskytuje práci s generikami velmi podobnou např. generikám z Javy nebo C#, začíná zdrojový kód langtable.vala (který doporučuji mít otevřený ve vedlejší záložce prohlížeče nebo oblíbeném editoru) řádkem using Gee;, abychom se vyhnuli zbytečnému psaní prefixu Gee. na mnoha místech. Tento jmenný prostor s ničím, co je základní součástí Valy, nekoliduje a troufnu si říci, že v podstatě tvoří jeden ze základních elementů pro programování ve Vale. Samotná knihovna langtable pak používá jmenný prostor langtable, což je, jak si později vysvětlíme, nutné pro správné fungování introspekce např. z Pythonu a bez jmenného prostoru by nám Vala neumožnila deklarovat globální proměnné apod. V několika dalších řádcích zdrojového kódu jsou pak definovány třídy pojmenovávající instance generických typů, jež usnadňují a zpřehledňují další kód. Strukturu RankedItem a výčtový typ LocFields prozatím přeskočme a podívejme se na deklarace oněch tří hlavních datových struktur ("databází"). Protože mimo funkce a metody nelze vytvářet instance (Kdy by se kód provedl?), jedná se pouze o deklarace proměnných, jež budou odkazovat na instance, které později vytvoříme ve funkci (lépe řečeno procedůře) init. Ve stejném duchu je pak deklarována proměnná pro regulární výraz, kterému se budu věnovat v části o dotazování. Číselnou konstantu (důležitou rovněž až pro dotazování) však samozřejmě můžeme plně definovat i s hodnotou.

Tím se dostáváme k části zdrojového kódu zajišťující zpracování souboru languages.xml. Nejprve definujeme výčtový typ LanguageFields, s jehož pomocí budeme ve funkcích handleru určovat, kam mají být ukládána data.

/***************** languages.xml parsing *****************/
	private enum LanguageFields {
	// attributes of the LanguagesDBitem
	languageId,
	iso639_1,
	iso639_2_t,
	iso639_2_b,

	// fields for storing item IDs, ranks and translated names
	item_id,
	item_rank,
	item_name,

	// indicate we shouldn't store data anywhere
	NONE,
}

Následuje definice třídy LanguagesDBitem, což je právě ona třída udržující informace o jednom jazyce, jejíž instance se budou objevovat jako hodnoty v mapování languages_db. Má několik atributů různých typů a jednoduchý konstruktor, který tyto atributy inicializuje.

private class LanguagesDBitem : GLib.Object {
	public string languageId;
	public string iso639_1;
	public string iso639_2_t;
	public string iso639_2_b;

	public NamesMap names;
	public StringRankMap locales;
	public StringRankMap territories;
	public StringRankMap keyboards;
	public StringRankMap consolefonts;
	public StringRankMap timezones;

	public LanguagesDBitem () {
		languageId = "";
		iso639_1 = "";
		iso639_2_t = "";
		iso639_2_b = "";
		names = new NamesMap ();
		locales = new StringRankMap ();
		territories = new StringRankMap ();
		keyboards = new StringRankMap ();
		consolefonts = new StringRankMap ();
		timezones = new StringRankMap ();
	}
}

Dále je definována třída LanguagesParsingDriver, jejíž instance je využívána jako datová struktura udržující informace o parsování a předávaná funkcím handleru. Její atribut store_to typu LanguageFields určuje, kam mají být ukládána data předaná funkci characters. Atribut current_item odkazuje na právě vytvářenou instanci LanguagesDBitem, několik dalších atributů pak slouží pro ukládání dočasných dat. Poslední z nich, in_names typu bool, slouží handleru pro indikaci, zdali je parser zrovna v podstromě elementu names či nikoliv, což je důležité, protože element languageId může v závislosti na poloze obsahovat ID zpracovávaného jazyka nebo jazyka překladu názvu právě zpracovávaného jazyka (doporčuji nahlédnout např. na začátek souboru languages.xml).

private class LanguageParsingDriver : GLib.Object {
	public LanguageFields store_to;
	public LanguagesDBitem curr_item;
	public string item_id;
	public string item_rank;
	public string item_name;
	public bool in_names;

	public LanguageParsingDriver () {
		store_to = LanguageFields.NONE;
		curr_item = null;
		item_id = "";
		item_rank = "";
		item_name = "";
		in_names = false;
	}
}

To je vše ke třídám, které budeme používat v handleru pro zpracování XML dat o jazycích a nyní se můžeme podívat na funkce, jež budou volány pro jednotlivé události. Jako první je definována funkce languageStartElement pro reakci na začátek elementu. Ta nejprve získá instanci třídy LanguagesParsingDriver pomocí dynamického přetypování argumentu void* data a na základě jména začínajícího elementu upraví atributy této instance, aby bylo možné v následující volání funkce languageCharacters (viz dále) ukládat data na správné místo.

private void languageStartElement (void* data, string name, string[] attrs) {
	LanguageParsingDriver driver = data as LanguageParsingDriver;

	switch (name) {
	case "language":
		driver.curr_item = new LanguagesDBitem ();
		break;
	case "languageId":
		if (!driver.in_names)
			driver.store_to = LanguageFields.languageId;
		else
			driver.store_to = LanguageFields.item_id;
		break;
	case "iso639-1":
		driver.store_to = LanguageFields.iso639_1;
		break;
	case "iso639-2-t":
		driver.store_to = LanguageFields.iso639_2_t;
		break;
	case "iso639-2-b":
		driver.store_to = LanguageFields.iso639_2_b;
		break;
	case "names":
		driver.in_names = true;
		break;
	case "localeId":
	case "keyboardId":
	case "territoryId":
	case "consolefontId":
	case "timezoneId":
		driver.store_to = LanguageFields.item_id;
		break;
	case "trName":
		driver.store_to = LanguageFields.item_name;
		break;
	case "rank":
		driver.store_to = LanguageFields.item_rank;
		break;
	}
}

Velmi podobně jako funkce languagesStartElement vypadá i funkce languagesEndElement pro reakci na konec elementu.

private void languageEndElement (void* data, string name) {
	LanguageParsingDriver driver = data as LanguageParsingDriver;

	switch (name) {
		case "language":
		languages_db[driver.curr_item.languageId] = driver.curr_item;
		driver.curr_item = null;
		break;
	case "names":
		driver.in_names = false;
		break;
	case "name":
		driver.curr_item.names[driver.item_id] = driver.item_name;
		driver.item_id = "";
		driver.item_name = "";
		break;
	case "locale":
		driver.curr_item.locales[driver.item_id] = int.parse(driver.item_rank);
		driver.item_id = "";
		driver.item_rank = "";
		break;
	case "keyboard":
		driver.curr_item.keyboards[driver.item_id] = int.parse(driver.item_rank);
		driver.item_id = "";
		driver.item_rank = "";
		break;
	case "territory":
		driver.curr_item.territories[driver.item_id] = int.parse(driver.item_rank);
		driver.item_id = "";
		driver.item_rank = "";
		break;
	case "consolefont":
		driver.curr_item.consolefonts[driver.item_id] = int.parse(driver.item_rank);
		driver.item_id = "";
		driver.item_rank = "";
		break;
	case "timezone":
		driver.curr_item.timezones[driver.item_id] = int.parse(driver.item_rank);
		driver.item_id = "";
		driver.item_rank = "";
		break;
	}

	driver.store_to = LanguageFields.NONE;
}

Ta získané hodnoty ukládá na správná místa – informace o jazyce do aktuální instance třídy LanguagesDBitem a tuto instanci samotnou pak do "databáze" languages_db. Zároveň tato funkce nastavuje pole pro ukládání dočasných dat na výchozí hodnoty (prázdné řetězce, null, false), aby nebyla míchána data jednotlivých elementů, a indikaci, kam se mají ukládat příští data (driver.store_to) nastavuje na LanguageFields.NONE, tedy hodnotu značící, že nejsou očekávána žádná data. Poslední v řadě funkcí handleru pro zpracování souboru langauges.xml je languagesCharacters, která se stará o zpracování obsahů jednotlivých elementů. SAX specifikuje, že tato funkce je volána s textovými daty obsaženými v elementu, avšak tato data mohou být předána postupně v několika voláních.

private void languageCharacters (void* data, string char_buf, int len)	{
	LanguageParsingDriver driver = data as LanguageParsingDriver;
	string chars = char_buf[0:len].strip ();

	if (chars == "")
		// nothing to save
		return;

	if (driver.curr_item == null || driver.store_to == LanguageFields.NONE)
		// no idea where to save characters
		return;

	switch (driver.store_to) {
	case LanguageFields.languageId:
		driver.curr_item.languageId += chars;
		break;
	case LanguageFields.iso639_1:
		driver.curr_item.iso639_1 += chars;
		break;
	case LanguageFields.iso639_2_t:
		driver.curr_item.iso639_2_t += chars;
		break;
	case LanguageFields.iso639_2_b:
		driver.curr_item.iso639_2_b += chars;
		break;
	case LanguageFields.item_id:
		driver.item_id += chars;
		break;
	case LanguageFields.item_rank:
		driver.item_rank += chars;
		break;
	case LanguageFields.item_name:
		driver.item_name += chars;
		break;
	}
}

V argumentech je předáván odkaz na (interní) buffer obsahující data a délka aktuálně platných dat. Proto funkce languagesCharacters nejprve z bufferu vykopíruje data, která chce ukládat, a odstřihne prázdné znaky na začátku i konci takto získaných dat (pro případ, že by data v elementech končila novými řádky apod.). Vytváření výřezů se ve Vale chová podle toho, jestli výsledek ukládáme do unowned nebo owned proměnné. V prvním případě je výsledkem podřetězec vyřezávaného řetězce, ve druhém případě kopie tohoto podřetězce. Protože jsou interní atributy a proměnné bez upřesnění owned, vytvoří výřez ve funkci languagesCharacters kopii dat. Ta je poté ořezána, což vytvoří další kopii dat, ale díky automatické správě paměti je první (dočasná) kopie automaticky odstraněna. Dále funce pouze vezme takto upravená data a zřetězí je s daty obsaženými v poli, kdo něhož má zrovna ukládat. Proto bylo důležité tato pole ve funkci languagesEndElement vyčistit.

To je vše, co potřebujeme pro handler reagující na události při zpracování souboru languages.xml. Velmi podobně pak vypadají funkce pro zpracování dalších dvou souborů, liší se jen počty a názvy atributů, do nichž jsou ukládána data. Funkce pro handlery nedělají žádnou validaci XML souborů, neboť by to bylo zbytečně složité, když lze kontrolu provádět jednoduše "externě" pomocí schémat RelaxNG, která jsou k dispozici společně s XML daty. Pro zpracování souborů už zbývá jen vytvořit instance struktury SAXHandler, nastavit její atributy startElement, endElement a characters na naše funkce a zavolat metody user_parse_file handlerů s cestami k XML souborům a instancemi "driverů".

Protože se jedná o stejný kód pro všechny soubory a protože budeme chtít data zpracovávat paralelně ve více vláknech, definujeme ještě třídu FileParser, která v konstruktoru dostane všechny parametry potřebné pro volání user_parse_file ve své metodě parse. Konstruktor navíc testuje, jestli existuje verze souboru v čisté textové podobě, případně jako zkomprimovaná verze, neboť i základní rychlá komprimace XML data zmenšuje až o řád. Skvělou vlastností knihovny libxml2 je to, že zkomprimovaná data v souboru se správnou (obvyklou) příponou automaticky zpracovává pomocí dekomprimace. Proto stačí pouze zjistit, která verze je k dispozici a případně patřičně upravit cestu.

private class FileParser : GLib.Object {
	private Xml.SAXHandler handler;
	private string real_path;
	private void* driver;

	public FileParser (Xml.startElementSAXFunc start,
				Xml.endElementSAXFunc end,
				Xml.charactersSAXFunc chars,
				void* driver,
				string fpath) {

		handler = Xml.SAXHandler ();
		handler.startElement = start;
		handler.endElement = end;
		handler.characters = chars;

		this.driver = driver;

		real_path = fpath;

		if (!FileUtils.test (real_path, FileTest.EXISTS)) {
			if (FileUtils.test (real_path + ".gz", FileTest.EXISTS))
				real_path += ".gz";
			else
				real_path = "";
		}
	}

	public bool parse () {
		if (real_path == "")
			return false;
		else
			handler.user_parse_file (driver, real_path);

		// successfully parsed
		return true;
	}
}

Poslední důležitou funkcí pro tuto část je init, jenž se stará o inicializaci knihovny, tedy především zpracování XML dat a vytvoření interních "databází", ze kterých jsou pak získávána data v dotazovacích funkcích, kterým se budeme věnovat příště. Jako první krok funkce init vytvoří instance pro tyto databáze spolu s instancemi "driverů", jež ponesou data řídící zpracování. Dalším krokem je vytvoření instancí třídy FileParser pro jednotlivé XML soubory a poté jsou vytvořena vlákna, která volají metody parse takto vytvořených parserů.

public void init () {
	keyboards_db = new KeyboardsDB ();
	territories_db = new TerritoriesDB ();
	languages_db = new LanguagesDB ();

	var kb_driver = new KeyboardParsingDriver ();
	var ter_driver = new TerritoryParsingDriver ();
	var lang_driver = new LanguageParsingDriver ();

	var keyb_parser = new FileParser (keyboardStartElement, keyboardEndElement,
					keyboardCharacters, kb_driver,
					"/usr/share/langtable/keyboards.xml");
	var ter_parser = new FileParser (territoryStartElement, territoryEndElement,
					territoryCharacters, ter_driver,
					"/usr/share/langtable/territories.xml");
	var lang_parser = new FileParser (languageStartElement, languageEndElement,
					languageCharacters, lang_driver,
					"/usr/share/langtable/languages.xml");

	Thread<bool> keyb_thread = new Thread<bool> ("KeybThread", keyb_parser.parse);
	Thread<bool> terr_thread = new Thread<bool> ("TerThread", ter_parser.parse);
	Thread<bool> lang_thread = new Thread<bool> ("LangThread", lang_parser.parse);

	locale_regex = new Regex (
		// language must be 2 or 3 lower case letters:
		"^(?P<language>[a-z]{2,3}" +
		// language is only valid if
		"(?=$|@" + // locale string ends here or only options follow
		"|_[A-Z][a-z]{3}(?=$|@|_[A-Z]{2}(?=$|@))" + // valid script follows
		"|_[A-Z]{2}(?=$|@)" + // valid territory follows
		"))" +
		// script must be 1 upper case letter followed by
		// 3 lower case letters:
		"(?:_(?P<script>[A-Z][a-z]{3})" +
		// script is only valid if
		"(?=$|@" + // locale string ends here or only options follow
		"|_[A-Z]{2}(?=$|@)" + // valid territory follows
		")){0,1}" +
		// territory must be 2 upper case letters:
		"(?:_(?P<territory>[A-Z]{2})" +
		// territory is only valid if
		"(?=$|@" + // locale string ends here or only options follow
		")){0,1}");

	if (!keyb_thread.join ())
		warning ("Failed to load keyboard data!");
	if (!terr_thread.join ())
		warning ("Failed to load territory data!");
	if (!lang_thread.join ())
		warning ("Failed to load language data!");
}

Zde si dovolím dvě poznámky k práci s vlákny ve Vale:

  1. 1. Při tvorbě (a tím i spuštění vlákna) nelze volané funkci předávat argumenty. Proto, chceme-li pracovat s nějakými externími parametry (což je obvyklé), musíme vytvořit třídu, její instanci, nastavit této instanci atributy a posléze volat metodu této instance, která má samozřejmě přístup ke všem atributům. To je tedy jeden z důvodů, proč jsme tvořili třídu FileParser.
  2. 2. Vlákna jsou ve Vale generiky. Typ, jenž u vlákna specifikujeme, je typ návratové hodnoty metody/funkce, kterou vlákno provádí.

Poněkud děsivý regulární výraz, který se objevuje ve funkci init, si necháme na příště, kdy se budeme věnovat dotazovacím funkcím. Zvědavé však již teď upozorním, že tento regulární výraz byl bez změny převzat z původního zdrojového kódu pythonního modulu langtable. V závěru inicializace pak již jen počkáme na vlákna zpracovávající XML soubory a zkontrolujeme, že zpracování proběhlo v pořádku pomocí návratových hodnot.

A to už je tedy úplně vše, co potřebujeme, abychom mohli zdrojový kód zkompilovat a pomocí volání funkce init vyvolat zpracování dat, které ve srovnání s pythonní verzí trvá v závislosti na hardware čtvrtinu nebo i setinu času. Příště se podíváme na dotazovací funkce, s jejíchž pomocí bude možné knihovnu opravdu používat, kompilaci knihovny do podoby, ve které může být používána např. z Pythonu a několik dalších souvisejících tipů a triků.

Odkazy

link

Seriál Programování v jazyce Vala (dílů: 3)

První díl: Programování v jazyce Vala – úvod, poslední díl: Ze 4 s na 0,9 s – programovací jazyk Vala v praxi.
Předchozí díl: Programování v jazyce Vala - základní prvky jazyka

Další články z této rubriky

LLVM a Clang – více než dobrá náhrada za GCC
Ze 4 s na 0,9 s – programovací jazyk Vala v praxi
Reverzujeme ovladače pro USB HID zařízení
Linux: systémové volání splice()
Programování v jazyce Vala - základní prvky jazyka

Diskuse k tomuto článku

Limoto avatar 6.8.2013 01:26 Limoto | skóre: 32 | blog: Limotův blog | Prostějov
Rozbalit Rozbalit vše Re: Ze 4 s na 0,9 s – programovací jazyk Vala v praxi
Odpovědět | Sbalit | Link | Blokovat | Admin
značně populárního intalátoru GNU/Linuxové distribuce Fedora

Pobavilo :-D :-D (a je tam překlep)

vain avatar 6.8.2013 08:38 vain | skóre: 16
Rozbalit Rozbalit vše Re: Ze 4 s na 0,9 s – programovací jazyk Vala v praxi
Co máte všichni proti instalátoru Fedory? :-) Vidím ho jednou za uherský rok a vždycky se na něj těším, co všechno se změnilo a jak vypadá. Jste všichni burani, co to neumí ocenit ;-)
If the only choice you've got is to do the wrong thing, then it's not really the wrong thing, it's more like fate.
6.8.2013 10:31 Pavel Ruzicka
Rozbalit Rozbalit vše Re: Ze 4 s na 0,9 s – programovací jazyk Vala v praxi
Minuly tyden jsem instaloval Fedoru19 na novy pocitac s UEFI (byl vypnuty secureboot) a byl to tedy porod. Ten nastroj na vybrani partitionu je opravdu strasny. Chtel jsem system nainstalovat na jiz rozdeleny disk (swap, /, /home) a /home zachovat. Po asi deseti pokusech se mi ho podarilo prinutit k takovemu rozdeleni. Po instalaci a rebootu ovsem skoncil GRUB s ERROR15. Po nekolika pokusech o rescue a rucnimu nahrani bootloaderu jsem to vzdal a bez problemu nainstaloval Mageiu3. Za par dni jsem tomu dal dalsi sanci. Anaconda selhala z divnou chybou jeste pred vyberem jazyka. Byla to divna chyba s DHCPv6. Po odpojeni sitoveho kabelu Anaconda nabehla a dokonce po instalaci system nabootoval. Beh Fedory je v pohode, ale ten instalator je teda opravdu katastrofa.
7.8.2013 17:26 M4rtinK
Rozbalit Rozbalit vše Re: Ze 4 s na 0,9 s – programovací jazyk Vala v praxi
Ten nastroj na vybrani partitionu je opravdu strasny.
Je doplním že je vypsaná diplomka/bakalářka na téma lepší vizualizace rozdelění disků v Anacondě. Nechce se toho někdo chopit ? :)
7.8.2013 22:22 erino72 | skóre: 2
Rozbalit Rozbalit vše Re: Ze 4 s na 0,9 s – programovací jazyk Vala v praxi
Neskoro, bakalarky sa vyberali v aprili...
7.8.2013 23:53 asdf
Rozbalit Rozbalit vše Re: Ze 4 s na 0,9 s – programovací jazyk Vala v praxi
Co takhle místo toho použít Windows? Ten má dobrej instalátor...
Václav 8.8.2013 09:23 Václav "Darm" Novák | skóre: 26 | blog: Darmovy_kecy | Bechyně / Praha
Rozbalit Rozbalit vše Re: Ze 4 s na 0,9 s – programovací jazyk Vala v praxi
Díky, pobavilo :)
Cross my heart and hope to fly, stick a cupcake in my eye!
6.8.2013 02:10 Jardík
Rozbalit Rozbalit vše Re: Ze 4 s na 0,9 s – programovací jazyk Vala v praxi
Odpovědět | Sbalit | Link | Blokovat | Admin
if (!FileUtils.test (real_path, FileTest.EXISTS)) {
	if (FileUtils.test (real_path + ".gz", FileTest.EXISTS))
		real_path += ".gz";
	else
		real_path = "";
}
Opravdu?? Takovéhle konstrukce by v programu neměli co dělat. To je race-condition jak sviňa.
6.8.2013 07:02 karelI
Rozbalit Rozbalit vše Re: Ze 4 s na 0,9 s – programovací jazyk Vala v praxi
By byla race-condition pokud by se ty soubory pri behu programu vytvarely (v jinym threadu). Pokud tam jsou jen vykopirovany z nejakyho baliku a pak se pousti tento skript, pak je to uplne jedno.
6.8.2013 10:46 Jardík
Rozbalit Rozbalit vše Re: Ze 4 s na 0,9 s – programovací jazyk Vala v praxi
A jak máte v programu ošetřeno, že jiné programy nebudou měnit soubory, nebo se někdo nerozhodne tam připojit filesystém? Bylo by dobré rizika alespoň minimalizovat, třeba použitím správné kombinace flagů při volání open(). Na co zbytečně testovat existenci před voláním open a zvyšovat riziko? open() vám chybu při neexistenci souboru (popř. při existenci, pokud potřebujete opak) vrátí.
6.8.2013 11:12 karelI
Rozbalit Rozbalit vše Re: Ze 4 s na 0,9 s – programovací jazyk Vala v praxi
Slovy klasika - jak mate osetreno ze vam nekdo nevynda procesor. Kdyz pracujete s okolnim svetem, tak k chybam proste dochazi a vetsinou nema moc smysl se toho vyvarovat. V tomto pripade urcite staci smysluplne zarvat a skocit, coz zde chybi.

Me pripada vhodne oddelit zjistovani jak se vlastne soubor jmenuje od vlastniho otevreni a zpracovani souboru.
6.8.2013 12:36 logik
Rozbalit Rozbalit vše Re: Ze 4 s na 0,9 s – programovací jazyk Vala v praxi
To samozřejmě neošetříte. Ale případ "mizejícího" souboru ošetříte snadno a tak je chyba ho neošetřit...

A to, že se před samotnou operací ošetří "X milionů" možnejch chyb je právě překonané paradigma. Právě proto vznikli výjimky, aby člověk psal kód co nejvíce přímočaře a ošetření chyb bylo "vedle".
6.8.2013 15:13 nikdo
Rozbalit Rozbalit vše Re: Ze 4 s na 0,9 s – programovací jazyk Vala v praxi
Já za překonané paradigma zase považuji to, že některé paradigma je "vyšší, lepčí a hezčí", než paradigma jiné-překonané.

Nicméně - v tomto konkrétním případě bych asi taky zavolal open a "počkal, co to udělá" :-)
Bedňa avatar 7.8.2013 22:10 Bedňa | skóre: 33 | blog: Žumpa | Horňany
Rozbalit Rozbalit vše Re: Ze 4 s na 0,9 s – programovací jazyk Vala v praxi
+1 a výsmech pseudo vývojárom.
Pokecajte si s umelou stupiditou na http://www.kernelultras.org/
Bedňa avatar 7.8.2013 22:12 Bedňa | skóre: 33 | blog: Žumpa | Horňany
Rozbalit Rozbalit vše Re: Ze 4 s na 0,9 s – programovací jazyk Vala v praxi
tak k chybam proste dochazi a vetsinou nema moc smysl se toho vyvarovat. V tomto pripade urcite staci smysluplne zarvat a skocit, coz zde chybi.
Radostný svet užívateľov.
Pokecajte si s umelou stupiditou na http://www.kernelultras.org/
24.8.2013 17:29 karelI
Rozbalit Rozbalit vše Re: Ze 4 s na 0,9 s – programovací jazyk Vala v praxi
Jen jsem tim chtel rict, ze nema smysl osetrovat 10 neocekavanych stavu kdyz vas dalsich 50 ani nenapadne ze by mohly nastat a ve vysledku stejne vsechny vedou k tomu ze vylitne vyjimka a nelze precist soubor a tedy program nemuze pokracovat. Lepsi jednoduchy a prehledny program ktery rekne co je blbe nez hromada balastu ktera se snazi o nemozne. Mate snad jiny navrh?
6.8.2013 17:15 petr_p | skóre: 59 | blog: pb
Rozbalit Rozbalit vše Re: Ze 4 s na 0,9 s – programovací jazyk Vala v praxi
Neviděl jste Anacondu. Jeden z jejích vývojářů říká, že ji ani není možné restartovat, protože se všude předpokládá výchozí stav. Tedy představa, že by někdo paralelně něco dělal se soubory, je zcela podružná.
6.8.2013 07:05 karelI
Rozbalit Rozbalit vše Re: Ze 4 s na 0,9 s – programovací jazyk Vala v praxi
Odpovědět | Sbalit | Link | Blokovat | Admin
Dotaz na autora z praxe - jak se tvari vasi kolegove na to, ze az v te firme jednoho dne prestanete pracovat, tak jim tam zbyde par set radku kodu v jazyce o kterym nikdo v te dobe ani nemusi vedet natoz aby ho dokazal opravit/vylepsit/prelozit/pustit?
6.8.2013 08:57 racik
Rozbalit Rozbalit vše Re: Ze 4 s na 0,9 s – programovací jazyk Vala v praxi
Verim, ze dobre, ved to moze prelozit do C a nechat im zdrojak. Dufam ze jazyk C uz budu poznat.
6.8.2013 09:12 Já
Rozbalit Rozbalit vše Re: Ze 4 s na 0,9 s – programovací jazyk Vala v praxi
A viděli jste někdy ten výstup? :D Dobře, jo? :D
6.8.2013 10:49 Jardík
Rozbalit Rozbalit vše Re: Ze 4 s na 0,9 s – programovací jazyk Vala v praxi
C zdroják z Valy je opravdu příšerný a je velmi obtížné poznat, co to dělá se všemi těmi náhodnými přiřazovaními do dočasných proměnných stupidních jmen, tam a zpět, ... vždycky se modlím, aby to kompilátor zvládl zoptimalizovat. Z dvou řádku kódu je Vala schopná udělat 20 řádkový bastl.
6.8.2013 15:07 Já
Rozbalit Rozbalit vše Re: Ze 4 s na 0,9 s – programovací jazyk Vala v praxi
No mně nejvíc dostalo, když jsem viděl nějakou knihovnu ve Vala s výraznou poznámkou, že kvůli Vala nelze garantovat céčkové API, tak ať ho nikdo nepoužívá. Takže asi tak.
11.8.2013 12:14 v.podzimek | skóre: 17
Rozbalit Rozbalit vše Re: Ze 4 s na 0,9 s – programovací jazyk Vala v praxi
V prvé řadě, langtable a ani žádná z jejích verzí nezůstane nikde ve firmě. Je to normální upstream projekt, který může dál rozvíjet, upravovat, forkovat apod. kdokoliv a věřím, že někdo kdo rozumí něčemu, co vypadá jako Java/C# a má slušné komentáře (ty do kódu teprve přijdou), se určitě najde.
6.8.2013 09:02 Petr Ježek | skóre: 10
Rozbalit Rozbalit vše Re: Ze 4 s na 0,9 s – programovací jazyk Vala v praxi
Odpovědět | Sbalit | Link | Blokovat | Admin
Ehm, ona je vala něčím programátorský neznámým bez dokumentace a vývojářských nástrojů?
Archlinux for your comps, faster running guaranted!
6.8.2013 09:23 karelI
Rozbalit Rozbalit vše Re: Ze 4 s na 0,9 s – programovací jazyk Vala v praxi
Predpokladam ze to je reakce na me...

Ja nerikam ze to nejde, ja se ptal jak se na to tvari ostatni. Zkuste beznemu programatorovi predhodit nejaky kod v mene znamem jazyce a muzete treba zmerit za jak dlouho vypatra jak presne se chova operator == na stringach. I kdyz jak to tak znam, tak to nejak zbastli a bude doufat ze to slape. Kazdopadne produktivita nebo spolehlivost rapidne klesa.

Je proste velky rozdil mezi situaci, kdy se ve firme pouziva nejake rozumne male mnozstvi nastroju se kteryma se vsichni smirili a naucili se je pouzivat a naopak kdy si kazdej svuj kod bastli v cem se mu zamane (hmm, xml, tak co treba vala).
Luboš Doležel (Doli) avatar 6.8.2013 09:27 Luboš Doležel (Doli) | skóre: 98 | blog: Doliho blog | Kladensko
Rozbalit Rozbalit vše Re: Ze 4 s na 0,9 s – programovací jazyk Vala v praxi
Že je Vala jazyk evidentně oficiálně podporovaný v GNOME a že Red Hat hraje nemalou roli v GNOME, tak bych to neviděl až tak zle.
6.8.2013 21:39 M4rtinK
Rozbalit Rozbalit vše Re: Ze 4 s na 0,9 s – programovací jazyk Vala v praxi
Navíc když je knihovna napsaná ve Vale a postavená na GObjectu, je možné ji snadno použít ze všech jazyků podporovaných GObjectem: z C, C++, Pythonu, Javascriptu, Ruby, Lispu, ...

To pro knihovnu napsanou v Python tak jednoduše nejde.
6.8.2013 09:09 mikro
Rozbalit Rozbalit vše Re: Ze 4 s na 0,9 s – programovací jazyk Vala v praxi
Odpovědět | Sbalit | Link | Blokovat | Admin
Chlapci, a ze by ste problem vyriesili nahradou XML za nieco menej narocne na spracovanie, to vam nenapadlo? Niezeby vyriesenie problemu novym programovacim jazykom nemalo nieco do seba ;-), ale pripajam sa ku komentaru vyssie, byt zamestnancom, ktory po tebe tento projekt ma prevziat, tak to by padalo naozaj vela sprostych slov. "Ved to ma strojovy export do C" mi prave ako dobry protiargument nepride.
6.8.2013 20:15 Kvakor
Rozbalit Rozbalit vše Re: Ze 4 s na 0,9 s – programovací jazyk Vala v praxi
Já bych podobný problém řešil rozdělením na dva nástroje - jedním programem, který by onen obří XML "přežvýkal" do něčeho, co by bylo možné snadněji zpracovat, a druhého programu, který by s ním manipuloval. Protože první program by se pouštěl jen v případě změny zdrojového XML nebo převodu na jinou platformu (pokud by "přežvýkaná" data byla platformově závislá), může být klidně psaný v "pomalém" skritpvacím jazyce. A u druhého programu je pak možné držet v paměti jen data, přes která se vyhledává (něco na způsob indexů v databázi) a zbytek načítat ze souboru dle potřeby.
xkucf03 avatar 6.8.2013 22:15 xkucf03 | skóre: 46 | blog: xkucf03
Rozbalit Rozbalit vše Re: Ze 4 s na 0,9 s – programovací jazyk Vala v praxi
rozdělením na dva nástroje - jedním programem, který by onen obří XML "přežvýkal" do něčeho, co by bylo možné snadněji zpracovat

Nebo rovnou může vygenerovat kód v daném jazyce, který vytvoří patřičné objekty – a hezky propojené mezi sebou (místo aby sis někde přečetl textový řetězec a pak ho jinde hledal v nějaké mapě, tak to může být rovnou ukazatel/reference na ten objekt).

Nebo, pokud nechceme všechna data držet v paměti, může být výsledkem indexovaný binární soubor, ve kterém se bude snadno vyhledávat.

Mám rád, když se lidé přou, znamená to, že vědí, co dělají, a že mají směr. Frantovo.cz, SQL-Výuka.cz, Nekuřák.net
7.8.2013 20:04 kořen
Rozbalit Rozbalit vše Re: Ze 4 s na 0,9 s – programovací jazyk Vala v praxi
Proto bych to napsal v lispu a byla by to zároveň konfigurace i program.
7.8.2013 20:14 deda.jabko | skóre: 23 | blog: blog co se jmenuje "každý den jinak" | za new york city dvakrát doleva a pak už se doptáte
Rozbalit Rozbalit vše Re: Ze 4 s na 0,9 s – programovací jazyk Vala v praxi
Tohle neni prilis originalni napad... #37. :-]]
Asi před rokem se dostali hackeři na servry Debianu a ukradli jim zdrojové kódy.
xkucf03 avatar 7.8.2013 20:32 xkucf03 | skóre: 46 | blog: xkucf03
Rozbalit Rozbalit vše Re: Ze 4 s na 0,9 s – programovací jazyk Vala v praxi

A jak tam zapíšeš ty reference? (abys toho při tvorbě dat musel napsat minimum, ale zároveň to bylo propojené, aby při běhu nebylo potřeba prohledávat nějaké mapy podle textových klíčů, ale měl jsi hned odkaz na další objekt)

Mám rád, když se lidé přou, znamená to, že vědí, co dělají, a že mají směr. Frantovo.cz, SQL-Výuka.cz, Nekuřák.net
6.8.2013 09:45 Lulu
Rozbalit Rozbalit vše Re: Ze 4 s na 0,9 s – programovací jazyk Vala v praxi
Odpovědět | Sbalit | Link | Blokovat | Admin
Taky bych chtel neco rici.

Sila Pythonu je predevsim v rychlosti vyvoje, ale podle toho jak koukam na zdrojak langtable.py, tak to psal clovek, kteremu DRY princip moc nerika..:

elif name == u"name": self._names[str(self._item_id)] = self._item_name self._clear_item() elif name == u"locale": self._locales[str(self._item_id)] = int(self._item_rank) self._clear_item() elif name == u"territory": self._territories[str(self._item_id)] = int(self._item_rank) self._clear_item() elif name == u"keyboard": self._keyboards[str(self._item_id)] = int(self._item_rank) self._clear_item() elif name == u"consolefont": self._consolefonts[str(self._item_id)] = int(self._item_rank) self._clear_item() elif name == u"timezone": self._timezones[str(self._item_id)] = int(self._item_rank) self._clear_item()

Toto je jasne opakovani se porad dokola, a to neni jediny pripad ...

Z toho co jsem videl, si myslim ze toto psal nekdo kdo je primarne C++/Vala programator, kde se programuje timto stylem, proto si dovolim rici, ze pokud chcete urychlit svuj program, tak by to chtelo vic abstrakci, a rozhodne mene radku kodu, Python script s 1300+ radky je spatne. Toto ma byt rozdelene do nekolika (mozna desitek) mensich scriptu v ramci jednoho modulu, nebo pouzivat vice standartnich knihoven ...

Prectete si ZEN Pythonu ....

Stejne tak se mi nelibi neco jako

if neco == None: return

Znovu, ZEN Pythonu, explicit is better than implicit, zde ma byt return None, nebo False ... zkratka neco .. Snazite si setrit si pismena na spatnych mistech ...

Nerikam ze jste spatni programatori, tak na me prosim nekricte, ale jelikoz ja delam v Pythonu kazdy den a vidivam casto Python kod od Cckaru, poznam jak to vypada ...

Z nejakeho duvodu maji Cckari tendenci psat strasne kodu .. :D

Mozna kdyby to napsal nekdo kdo dela Python uz par let, bylo by to rychlejsi, stejne tak jak kluci psali, zmenit XML na neco jineho je taky dobrej napad ..

A jeste poznamka k tvemu GIL v Pythonu, proc bys na cteni vicero souboru nemohl pouzit multiprocessing?? (vice ram, ja vim, ale jde to optimalizovat)

Cau
6.8.2013 10:43 zde
Rozbalit Rozbalit vše Re: Ze 4 s na 0,9 s – programovací jazyk Vala v praxi
Až bude Python opět použitelný (tj startup nebude trvat 50ms ale 5ms), tak mě vzbuďte.
6.8.2013 11:54 Lulu
Rozbalit Rozbalit vše Re: Ze 4 s na 0,9 s – programovací jazyk Vala v praxi
No, zalezi co delas .. fajn

udelej si prazdny soubor none.py

spust time python none.py

dle meho mereni se cas pohybuje mezi 10-17ms

coz je cas inicializace python interpreteru ...

Takze nevim o cem pises ...
Conscript89 avatar 6.8.2013 13:10 Conscript89 | Brno
Rozbalit Rozbalit vše Re: Ze 4 s na 0,9 s – programovací jazyk Vala v praxi
Todle je krasny srovnani :D
Na Sandy Bridge i5 stroji (Fedora 19):
$ time python /dev/null

real    0m0.014s
user    0m0.010s
sys     0m0.003s
Na Atom D510 (CentOS 6.4):
$ time python /dev/null

real    0m0.062s
user    0m0.034s
sys     0m0.020s
Takze tu muzeme vsichni hazet cislama, jak chceme :)
I can only show you the door. You're the one that has to walk through it.
6.8.2013 13:25 Lulu
Rozbalit Rozbalit vše Re: Ze 4 s na 0,9 s – programovací jazyk Vala v praxi
Tak tak,

uzivatel `zde` to urcite poustel na i486 s 66MHz a 16MB RAM .. to se pak muzem divit ze mu to trva 50ms ze ... :D
7.8.2013 00:20 Václav HFechs Švirga | skóre: 26 | blog: HF | Kopřivnice
Rozbalit Rozbalit vše Re: Ze 4 s na 0,9 s – programovací jazyk Vala v praxi
$ time python /dev/null
real    0m0.027s
user    0m0.008s
sys     0m0.012s

$ time python3 /dev/null
real    0m0.047s
user    0m0.040s
sys     0m0.004s
core duo 2 (6 GB ram)

python3 mi 50 mS trvá taky, samozřejmě po opětovném spouštění, ať se python dostane z disku do cache.
Baník pyčo!
6.8.2013 13:44 bubla
Rozbalit Rozbalit vše Re: Ze 4 s na 0,9 s – programovací jazyk Vala v praxi
Teď jsem to zkusil u sebe a zjistil jsem, že pythonu 3 to zabere cca 2x tolik (64-bit Archlinux) Nevíte, čím to?
Jardík avatar 6.8.2013 14:35 Jardík | skóre: 40 | blog: jarda_bloguje
Rozbalit Rozbalit vše Re: Ze 4 s na 0,9 s – programovací jazyk Vala v praxi
$time python3 /dev/null

real    0m0.121s
user    0m0.107s
sys     0m0.013s

$time python2 /dev/null

real    0m0.183s
user    0m0.163s
sys     0m0.013s
Na Athlon X2 5200+ 2.6GHz, podtaktovaný na 1GHz
Věřím v jednoho Boha.
bubla avatar 6.8.2013 21:38 bubla | skóre: 10 | Rosice
Rozbalit Rozbalit vše Re: Ze 4 s na 0,9 s – programovací jazyk Vala v praxi
$time python3 /dev/null

real	0m0.072s
user	0m0.030s
sys	0m0.003s

$time python2 /dev/null

real	0m0.028s
user	0m0.017s
sys	0m0.007s
7.8.2013 14:30 zde
Rozbalit Rozbalit vše Re: Ze 4 s na 0,9 s – programovací jazyk Vala v praxi
Nojo, každopádně je to příšerně pomalý.. aplikace se v tom nějak lepit dají, ale na skriptování (to volat to z něčeho jiného) to použitelné není. Přitom i ten blbej perl je výrazně rychlejší (o lua nemluvě).
[~]$ time python -c ''

real	0m0.027s
user	0m0.024s
sys	0m0.003s

[~]$ time perl -e ''

real	0m0.004s
user	0m0.001s
sys	0m0.003s

[~]$ time lua -e ''

real	0m0.002s
user	0m0.000s
sys	0m0.001s
Bystroushaak avatar 7.8.2013 16:32 Bystroushaak | skóre: 32 | blog: Bystroushaakův blog | Praha
Rozbalit Rozbalit vše Re: Ze 4 s na 0,9 s – programovací jazyk Vala v praxi
na skriptování (to volat to z něčeho jiného) to použitelné není
27 milisekund není tak špatné, pokud to člověk nebude volat někde ve smyčce, tak mi to přijde docela použitelné.
mirec avatar 10.8.2013 15:07 mirec | skóre: 31 | blog: mirecove_dristy | Poprad
Rozbalit Rozbalit vše Re: Ze 4 s na 0,9 s – programovací jazyk Vala v praxi
Čo tak python -S -c ''? Prípadne by sa dal ešte zneužiť fork.
LinuxOS.sk | USE="-fotak -zbytocnosti -farebne_lcd +vydrz +odolnost +java" emerge telefon
Rezza avatar 6.8.2013 13:58 Rezza | skóre: 25 | blog: rezza | Brno
Rozbalit Rozbalit vše Re: Ze 4 s na 0,9 s – programovací jazyk Vala v praxi
Odpovědět | Sbalit | Link | Blokovat | Admin
"Proto vznikla iniciativa, jejíž výsledkem byly diskuze na Developer Conference 2013 v Brně a následný vznik projektu Mika Fabiana" - takze se to podarilo? Perfektni!
wamba avatar 6.8.2013 16:03 wamba | skóre: 37 | blog: wamba
Rozbalit Rozbalit vše Re: Ze 4 s na 0,9 s – programovací jazyk Vala v praxi
Odpovědět | Sbalit | Link | Blokovat | Admin
tak to opakování kódu mě taky udivilo především ve switch.

Python není zrovna ideální na zpracování velkého množství XML dat

no můj názor je opačný, že na tohle je vhodný skriptovací jazyk s příslušnou knihovnou (např. napsanou v C) "téměř" ideální

ten regex by šel napsat (no zabralo mi nějaký čas, než jsem přišel na to, čemu vlastně má odpovídat)
my $local_regex = qr{
    ^                         #zacatek stringu raději bych použil \A
    (?P<language>
        [a-z]{2,3}            #locale
        (?:
            _
            (?P<script>
                [A-Z][a-z]{3} #script (optional)
            )
        )?
        (?:
            _
            (?P<territory>
                [A-Z]{2}     #territory (optional)
            )
        )?
        (?:                 #místo nasl 4 řádků bych mohl použít i to vaše (?: @ | $ )
            @.*             #options (optional)
        )?
        $                   #konec stringu raději \z
    )
}xms;
nebo ještě lépe
my $under_line = q{_};
my $at_sign    = q{@};
my $locale_rs  = '[a-z]{2,3}';
my $script_rs  = '(?P<script>
    [A-Z][a-z]{3}
)';
my $territory_rs = '(?P<territory>
    [A-Z]{2}
)';
my $options_rs = q{.*};

my $local_re = qr{
    \A
    (?P<language>
        $locale_rs
        (?: $under_line $script_rs    )?
        (?: $under_line $territory_rs )?
        (?: $at_sign    $options_rs   )?
    )
    \z
}xms;
PS. psáno pro Perl pro Valu si to prosím upravte
This would have been so hard to fix when you don't know that there is in fact an easy fix.
xkucf03 avatar 6.8.2013 18:12 xkucf03 | skóre: 46 | blog: xkucf03
Rozbalit Rozbalit vše Java, deklarativní mapování, relační databáze
Odpovědět | Sbalit | Link | Blokovat | Admin

V první řadě díky za pokračování seriálu. Valu jsem zatím k ničemu nepoužil, ale už po ní zálibně koukám celkem dlouho :-)

řádkem using Gee;, abychom se vyhnuli zbytečnému psaní prefixu Gee. na mnoha místech. Tento jmenný prostor s ničím, co je základní součástí Valy, nekoliduje

Lepší je importovat jen ty třídy, které používám, ne celý jmenný prostor. Alespoň tak to dělám v Javě.

Ta získané hodnoty ukládá na správná místa – informace o jazyce do aktuální instance třídy LanguagesDBitem a tuto instanci samotnou pak do "databáze" languages_db. Zároveň tato funkce nastavuje pole pro ukládání dočasných dat na výchozí hodnoty (prázdné řetězce, null, false), aby nebyla míchána data jednotlivých elementů, a indikaci, kam se mají ukládat příští data (driver.store_to) nastavuje na LanguageFields.NONE, tedy hodnotu značící, že nejsou očekávána žádná data.

SAX je určitě zlepšení, ale přijde mi to pořád hodně nízkoúrovňové. Mnohem elegantnější by bylo použít nějaké mapování z XML na objekty. Jak by to vypadalo v Javě: LangTable. Ale zase to (mapování) nemusí být optimální z hlediska výkonu – pak je otázka, jestli mít hezký stručný kód (pár řádků, holé struktury s pár anotacemi, žádné cykly ani switche) nebo výkonově optimalizovaný kód se spoustou ručně psaného balastu. Parsování keyboards.xml na mém počítači zabralo 114 ms.

BTW: nechcete někdo tenhle kousek programu napsat v jiném jazyce, který by umožnil jednoduché mapování (deklarativní, bez zbytečného ručně psaného kódu) a zároveň by byl rychlejší než ta Java? :-)

Jak tak koukám do těch datových souborů, jsou to struktury, kde všechno souvisí se vším. To se v XML sice namodelovat dá a pokud napíšeš slušně schéma, dá se v tom i udržet referenční integrita, ale není to úplně ono.1 Relační databáze by asi byla přirozenější a vhodnější než XML2. Navíc bys ani nemusel řešit to mapování na objekty – pomocí jednoduchého SQL dotazu by sis vytáhl přesně to, co potřebuješ. Jedinou nevýhodu vidím v horším verzování – chce to verzovat SQL skript místo binárních databázových souborů, takže je to krok navíc při kompilaci (ale to zas taková tragédie není).

[1] navíc současný stav (tři soubory) není dokonalý, přijde mi, že tam bude spousta duplicit a příležitostí pro vznik nekonzistence
[2] nebo jakýkoli podobný souborový formát – ne, INI, JSON, YAML atd. skutečně není řešením

Mám rád, když se lidé přou, znamená to, že vědí, co dělají, a že mají směr. Frantovo.cz, SQL-Výuka.cz, Nekuřák.net
6.8.2013 20:35 deda.jabko | skóre: 23 | blog: blog co se jmenuje "každý den jinak" | za new york city dvakrát doleva a pak už se doptáte
Rozbalit Rozbalit vše Re: Java, deklarativní mapování, relační databáze
Relační databáze by asi byla přirozenější a vhodnější než XML2. Navíc bys ani nemusel řešit to mapování na objekty – pomocí jednoduchého SQL dotazu by sis vytáhl přesně to, co potřebuješ. Jedinou nevýhodu vidím v horším verzování – chce to verzovat SQL skript místo binárních databázových souborů, takže je to krok navíc při kompilaci (ale to zas taková tragédie není)
To je tak neunixove reseni az to boli.
Relační databáze by asi byla přirozenější a vhodnější než XML nebo jakýkoli podobný souborový formát – ne, INI, JSON, YAML atd. skutečně není řešením.
A co tak pouzit vlastni jednoduchy DSL a parser si nechat vygenerovat treba Antlr?

Asi před rokem se dostali hackeři na servry Debianu a ukradli jim zdrojové kódy.
xkucf03 avatar 6.8.2013 22:51 xkucf03 | skóre: 46 | blog: xkucf03
Rozbalit Rozbalit vše Re: Java, deklarativní mapování, relační databáze
To je tak neunixove reseni az to boli.

SQL skript je přece krásný textový konfigurák s jasnou syntaxí :-)

Pak se akorát parsuje pomocí již hotového nástroje, uloží se efektivním způsobem a dá se k němu přistupovat pomocí určitého existujícího API.

A co tak pouzit vlastni jednoduchy DSL a parser si nechat vygenerovat treba Antlr?

To je taky možnost, ale nebude to pak další z mnoha různých syntaxí, které se uživatel musí učit? DSL mi přijde vhodné pro úlohy, které jsou sice specifické (obecný jazyk pro ně není ideální), ale přesto opakovatelné (používají se na víc místech, ve víc programech).

Šel bych na to asi buď cestou relační databáze (pokud se hodí silný dotazovací jazyk) nebo cestou předžvýkání – buď do binárního souboru (pokud to chceme mít na disku) nebo do kódu daného jazyka (pokud můžeme mít všechno v paměti).

Mám rád, když se lidé přou, znamená to, že vědí, co dělají, a že mají směr. Frantovo.cz, SQL-Výuka.cz, Nekuřák.net
7.8.2013 02:21 deda.jabko | skóre: 23 | blog: blog co se jmenuje "každý den jinak" | za new york city dvakrát doleva a pak už se doptáte
Rozbalit Rozbalit vše Re: Java, deklarativní mapování, relační databáze
SQL skript je přece krásný textový konfigurák s jasnou syntaxí :-)
Nejsem si prilis jisty, jestli to myslis vazne nebo jako sverazny humor. Uz jsem videl ledacos...
To je taky možnost, ale nebude to pak další z mnoha různých syntaxí, které se uživatel musí učit?
Naucit se novy format je intelektualne minimalne stejne tak narocne jako naucit se schema XML souboru.
Šel bych na to asi buď cestou relační databáze (pokud se hodí silný dotazovací jazyk) nebo cestou předžvýkání – buď do binárního souboru (pokud to chceme mít na disku) nebo do kódu daného jazyka (pokud můžeme mít všechno v paměti).
V takovem pripade budes muset spravovat krome programu samotneho jeste dalsi nastroje na spravu jeho konfigurace.

Koncepcne by to bylo nejlepsi udelat v LISPu nebo Schemu, diskuze, jestli je to lepsi realizovat jako data, program, DSL by uplne odpadla.

Asi před rokem se dostali hackeři na servry Debianu a ukradli jim zdrojové kódy.
xkucf03 avatar 7.8.2013 09:16 xkucf03 | skóre: 46 | blog: xkucf03
Rozbalit Rozbalit vše Re: Java, deklarativní mapování, relační databáze
Naucit se novy format je intelektualne minimalne stejne tak narocne jako naucit se schema XML souboru.

Souhlasím, jenže při existenci XML schématu ti hodně pomůže editor – např. takový Emacs ti bude napovídat a kontrolovat syntaxi, aniž bys musel něco řešit – stačí když vedle editovaného souboru bude Relax NG schéma se stejným názvem. V případě nového formátu ti ani neobarví syntaxi, natož aby ti kontroloval správnost a hlásil chyby.

Koncepcne by to bylo nejlepsi udelat v LISPu nebo Schemu

Něříkám, že to nezní zajímavě :-) Můžeš napsat příklad, jak by ta data (ty tři XML soubory) vypadala? Jak by se tam např. zapisovala vazba mezi jazykem a teritoriem a klávesnicí a teritoriem, kde teritorium je definované na jednom místě a má zase vazby na jazyky, klávesnice a další věci?

diskuze, jestli je to lepsi realizovat jako data, program, DSL by uplne odpadla.

A není pak riziko, že taková konfigurace bude příliš mocná a případná chyba nebo záměrná změna v ní může rozhodit celý program a změnit jeho chování? Trochu mi to připomíná situaci, kdy vezmeš data, o kterých někdo tvrdí, že jsou JSON, a zavoláš na nich eval(). Něco podobného je ten SQL skript, ve kterém by mohly být kromě očekávaných INSERTů i příkazy DELETE, DROP TABLE atd. (i když tohle jde aspoň řešit přes vhodně nastavená práva v DB).

Mám rád, když se lidé přou, znamená to, že vědí, co dělají, a že mají směr. Frantovo.cz, SQL-Výuka.cz, Nekuřák.net
7.8.2013 13:16 deda.jabko | skóre: 23 | blog: blog co se jmenuje "každý den jinak" | za new york city dvakrát doleva a pak už se doptáte
Rozbalit Rozbalit vše Re: Java, deklarativní mapování, relační databáze
Souhlasím, jenže při existenci XML schématu ti hodně pomůže editor
Zase DSL muze byt tak jednoduchy, ze si vystacis i s notepadem. Kdyz si budes konfiguraci zapisovat v SQL, editor ti moc nepomuze.
Můžeš napsat příklad, jak by ta data (ty tři XML soubory) vypadala?
Nechce se mi nad tim moc premyslet. Ale proc ne treba jako XML prepsane do S-vyrazu?
(languages
   (language
      :id aa
      :iso639-1 aa
      :iso639-2-t aar
      :iso639-2-b aar
      :names ((aa Qafar) (az afarca) ...))
   (language ...))
A není pak riziko, že taková konfigurace bude příliš mocná a případná chyba nebo záměrná změna v ní může rozhodit celý program a změnit jeho chování?
Tohle je hodne hloupy argument. Zakladem unixove filozofie je, ze uzivatel vi, co dela.
Trochu mi to připomíná situaci, kdy vezmeš data, o kterých někdo tvrdí, že jsou JSON, a zavoláš na nich eval().
To je presne to proc tu pisu o LISPu. Protoze tak se na tu konfiguraci muzes divat jako na data, ale soucasne i na DSL, ktery ti muze overovat validitu dat, vytvaret objekty, atd. a soucasne by to odpovidalo predzvykani do konkretniho jazyka, jak navrhujes.
Něco podobného je ten SQL skript, ve kterém by mohly být kromě očekávaných INSERTů i příkazy DELETE, DROP TABLE atd.
Ne, neni, viz ma predchozi poznamka.
Asi před rokem se dostali hackeři na servry Debianu a ukradli jim zdrojové kódy.
Bystroushaak avatar 7.8.2013 23:46 Bystroushaak | skóre: 32 | blog: Bystroushaakův blog | Praha
Rozbalit Rozbalit vše Re: Java, deklarativní mapování, relační databáze
Relax NG schéma
Wow, díky, to jsem neznal a přitom hledal :)
7.8.2013 09:03 ed | skóre: 18
Rozbalit Rozbalit vše Re: Ze 4 s na 0,9 s – programovací jazyk Vala v praxi
Odpovědět | Sbalit | Link | Blokovat | Admin
ako som zacal citat tento clanok, tak som nadobudol dva dojmy, ktore su pre mna poslednu dobu pre linuxovy svet celkom charakteristicke:

1. "the problem is... linux sometimes acts like a 3rd world country, no quality control, no standards" (grep z irc ##slackware na freenode, zial uz nepamatam nick) na mnoho veci existuje kod, ale tento kod je bud pochybnej kvality a este pochybnejsej funkcie, alebo by teoreticky aj bol pouzitelny ale a) bud nema dostacujucu, alebo absolutne ziadnu dokumentaciu b) je to tak nechutny bloatware, ze si ho clovek radsej reimplementuje sam. ziarivym prikladom druheho pripadu budiz kniznica glib2, ktora sice obsahuje haldu uzitocnych algoritmov, ale je to taky bloatware, ze pre drvivu vacsinu programov, ktore by ju aj pouzili je nepouzitelne velka.

2. nulova podpora zero investigation ci uz na strane pouzivatela, alebo na strane programatorov. okolo open source vznikol kopec dobre mienenych a feature-rich technologii, ale opat. bud je treba studovat neumerne vela howto / tutorialov / manualov (ak existuju) na to, aby sa rozchodili trivialne featury, alebo je naopak cela vec tak brutalne zautomatizovana, ze do toho rucne nie je mozne vobec zasiahnut. prikladom prvej budiz jabber. teoreticky ten protokol vie kopec veci, ale preco, PRECO sakra do toho protokolu nebol vstavany zeroconf? to si fakt musim pre kazdy jeden ucet RUCNE nastavovat take prkotiny ako je server na prenos suborov, pripadne server na videohovory? nech mi nikto nehovori, ze sa to neda dorpavit do klienta automaticky. ze si to potom pouzivatel zmeni, je jeho vec. ale nemusi sa hladat po standardnych hodnotach, ani riesit, preco mu skapala funkcia, ak sa nahodou adresy zmenia...

a potom tretia vec. Vala. fakt; naozaj? da sa to exportovat do mnoho inych zhruba rovnako pouzitelnych jazykov, ako je vala samotna? a ako argument pouzit, ze povodny kod ide pouzit +- len z pythonu? osobne mi pride rozumnejsie napisat vec v C/C++ a potom na to robit bindingy na ine jazyky, co obvykle prinasa moznost pokryt PODSTATNE sirsie spektrum jazykov, ako robit to "ritou dopredu".
Conscript89 avatar 7.8.2013 09:30 Conscript89 | Brno
Rozbalit Rozbalit vše Re: Ze 4 s na 0,9 s – programovací jazyk Vala v praxi
to si fakt musim pre kazdy jeden ucet RUCNE nastavovat take prkotiny ako je server na prenos suborov
Ne, u verejne IP to neni potreba.
I can only show you the door. You're the one that has to walk through it.
9.8.2013 11:18 ed | skóre: 18
Rozbalit Rozbalit vše Re: Ze 4 s na 0,9 s – programovací jazyk Vala v praxi
uspesne sa vam podarilo neodhalit pointu
xkucf03 avatar 7.8.2013 09:32 xkucf03 | skóre: 46 | blog: xkucf03
Rozbalit Rozbalit vše Re: Ze 4 s na 0,9 s – programovací jazyk Vala v praxi
bud je treba studovat neumerne vela howto / tutorialov / manualov (ak existuju) na to, aby sa rozchodili trivialne featury, alebo je naopak cela vec tak brutalne zautomatizovana, ze do toho rucne nie je mozne vobec zasiahnut.

S čím to srovnáváš? Ono vždycky najdeš něco, co tě bude štvát, ale otázka je, jestli jinde je to lepší. U proprietárního softwaru jsem se nezřídka setkal s tím, že musíš strávit několik dní, jen aby sis rozchodil verzovací systém a vývojové prostředí. Naopak u svobodného softwaru se většinou klade důraz na snižování té vstupní bariéry (autoři chtějí, aby jim ostatní mohli přispět), zdrojáky si stáhneš nějakým obvyklým systémem (mercurial, git, svn, bzr, cvs) a dáš ./configure && make && make install nebo něco podobného, případně přečteš README a doinstaluješ pár knihoven ze své distribuce.

Mám rád, když se lidé přou, znamená to, že vědí, co dělají, a že mají směr. Frantovo.cz, SQL-Výuka.cz, Nekuřák.net
9.8.2013 11:17 ed | skóre: 18
Rozbalit Rozbalit vše Re: Ze 4 s na 0,9 s – programovací jazyk Vala v praxi
porovnavat to staci kludne s nejakymi starsimi (tak 6+ rokov starsimi) open source vecami. kym boli veci na tom tak, ze bol problem nieco rozchodit, existovali k vsetkemu tony manualovych stranok, ak si dnes zoberem nejaky projekt, ktory je hostovany na webe freedesktopu, tak je celkom slusna sanca, ze k nemu neexistuje vobec ziadna, alebo len totalne nepouzitelna (t.j. manazerska) dokumentacia. a je jedno, v akom stadiu ten ktory projekt je. posledna taka vec, na ktorej som si nadrel hubu je dokumentacia EXA. schvalne si skus najst nejake ucelenejsie info. najlepsie co mas, su doxygenove komentare k funkciam v zdrojakoch. co je sice fajn mat dokumentaciu API, ale stale to moc nehovori o koncepte ako celku.
xkucf03 avatar 9.8.2013 11:46 xkucf03 | skóre: 46 | blog: xkucf03
Rozbalit Rozbalit vše Re: Ze 4 s na 0,9 s – programovací jazyk Vala v praxi

Svobodný/otevřený software je čím dál úspěšnější a věnuje se mu čím dál víc lidí – s tím přirozeně souvisí i to, že se rozšiřuje rozpětí kvality: od perfektních kousků až po úplný brak.

A trochu tomu nahrávají i weby jako GitHub – pamatuji si jak dřív bylo potřeba žádat o schválení projektu na SourceForge nebo si vytvořit vlastní web a rozjet vlastní verzovací systém. Dneska stačí prsknout zdrojáky na hosting a je to – hodně lidí se pak ani neobtěžuje s tím, aby napsali aspoň abstrakt, k čemu že ten jejich program vlastně slouží.

Mám rád, když se lidé přou, znamená to, že vědí, co dělají, a že mají směr. Frantovo.cz, SQL-Výuka.cz, Nekuřák.net
11.8.2013 23:35 mankind_boost
Rozbalit Rozbalit vše Re: Ze 4 s na 0,9 s – programovací jazyk Vala v praxi
Taková koncentrace buzzwordů se jen tak nevidí :-D

feature-rich technologii, zero investigation, ...

ISSN 1214-1267, (c) 1999-2007 Stickfish s.r.o.