Both sides previous revision
Previous revision
|
|
treex:api-implementation [2016/01/08 19:27] popel |
treex:api-implementation [2016/01/08 23:17] (current) popel |
| 0.5 | 0.5 | ''while (<$fh>) {chomp;}'' | načtení řádka po řádce | | | 0.5 | 0.5 | ''while (<$fh>) {chomp;}'' | načtení řádka po řádce | |
| 0.3 | 0.8 | ''$line eq "" or $line =~ /^#/'' | test prázdné řádky a komentáře | | | 0.3 | 0.8 | ''$line eq "" or $line =~ /^#/'' | test prázdné řádky a komentáře | |
| 0.7 | 1.5 | ''split /\t/, $line'' | split 9 atributů dle tabů | | | 0.6 | 1.4 | ''split /\t/, $line'' | split 9 atributů dle tabů (výsledek se zahodí) | |
| 4.3 | 5.8 | ''my ($id, $form, $lemma,...) ='' | uložení těch hodnot do proměnných | | | 4.1 | 5.5 | ''($id, $form, $lemma,...) =...'' | uložení těch hodnot do proměnných | |
| |x5.6 | 7.0 | ''my ($id, $form, $lemma,...) =...'' | uložení těch hodnot do nově alokovaných proměnných (které se asi odalokují, až vypadnou ze scope) | |
| |x4.7 | 6.1 | ''@pole =...'' | uložení těch hodnot do pole | |
|x3.9 | | ''UD::Node->new(form=>$form,...)'' | vytvoření 0.8M uzlů se stejnými atributy, tedy 200K uzlů za sekundu, viz [[#Benchmark konstruktorů v Perlu|následující benchmark]]| | |x3.9 | | ''UD::Node->new(form=>$form,...)'' | vytvoření 0.8M uzlů se stejnými atributy, tedy 200K uzlů za sekundu, viz [[#Benchmark konstruktorů v Perlu|následující benchmark]]| |
| 4.5 |10.3 | ''UD::Node->new(form=>$form,...)'' | vytvoření 0.8M uzlů ze skutečných dat| | | 4.8 |10.3 | ''UD::Node->new(form=>$form,...)'' | vytvoření 0.8M uzlů ze skutečných dat| |
|x0.4 |10.7 | ''push @all_nodes, $node'' | uzly se ukládají do pole| | |x0.4 |10.7 | ''push @all_nodes, $node'' | uzly se ukládají do pole| |
| 1.9 |12.2 | ''weaken($node->{_parent}=$root)...'' | uzly se ukládají do dokumentu, věší se na kořen, přidávají do jeho seznamu dětí| | | 1.9 |12.2 | ''weaken($node->{_parent}=$root)...'' | uzly se ukládají do dokumentu, věší se na kořen, přidávají do jeho seznamu dětí| |
| 1.2 |13.4 | ''weaken($node->{_parent}=$parent)...''| uzly se věší na skutečného rodiče (v druhém průchodu, pomocné pole ''@parents'')| | | 1.2 |13.4 | ''weaken($node->{_parent}=$parent)...''| uzly se věší na skutečného rodiče (v druhém průchodu, pomocné pole ''@parents'')| |
| 2.5 |15.9 | ''set_parent($parent,{cycles=>'no-check'})'' | set_parent místo optimalizovaného kódu (který neřešil předchozího rodiče atd.)| | | 1.4 |14.8 | ''set_parent_nocheck($parent)'' | set_parent_nocheck místo optimalizovaného kódu (který neřešil předchozího rodiče atd.)| |
| 0.7 |**16.6**| ''set_parent($parent)'' | testování cyklů | | | 1.8 |**16.6**| ''set_parent($parent)'' | testování cyklů | |
|10.0 |26.6 | ''$root->create_child...'' | původní implementace, kde se uzly převěšují z kořene na skutečného rodiče a děti jsou pole| | |10.0 |26.6 | ''$root->create_child...'' | původní implementace, kde se uzly převěšují z kořene na skutečného rodiče a děti jsou pole| |
| |
| |
* Původní implementace byla velmi neefektivní, protože se při převěšování z kořene musely uzly odebrat z pole dětí kořene, čili se muselo to pole překopírovat a zmenšit o jeden prvek a složitost byla kvadratická. Samotné převěšení trvalo 7s (a ještě 3s asi kvůli ''$root->create_child(...)'' místo ''UD::Node->new(...)''). Kdyby byly děti implementované spojákem místo pole (to mám stále v plánu), tak to bude míň než 7s, ale stejně je zbytečné při načítání CoNLL-U uzly dávat do spojáků dětí kořene, ze kterého vím, že je budu za chvíli odebírat. | * Původní implementace byla velmi neefektivní, protože se při převěšování z kořene musely uzly odebrat z pole dětí kořene, čili se muselo to pole překopírovat a zmenšit o jeden prvek a složitost byla kvadratická. Samotné převěšení trvalo 7s (a ještě 3s asi kvůli ''$root->create_child(...)'' místo ''UD::Node->new(...)''). Kdyby byly děti implementované spojákem místo pole (to mám stále v plánu), tak to bude míň než 7s, ale stejně je zbytečné při načítání CoNLL-U uzly dávat do spojáků dětí kořene, ze kterého vím, že je budu za chvíli odebírat. |
* Vypuštěním testování cyklů v CoNLL-U závislostech se ušetří necelá sekunda, což za to asi nestojí. | * Vypuštěním testování cyklů v CoNLL-U závislostech se ušetří 1.8s, což za to asi nestojí. |
* Optimalizací kódu set_parent bez volání této metody se jakoby ušetří 2.5s. | * Původně jsem používal ''set_parent($parent, {cycles=>'no-check'})'', jenže vytváření toho hashe s parametrem spolklo asi polovinu času ušetřeného vypuštěním kontroly cyklů. |
* Poměrně dost času (4.3s) zabere vytváření 9 proměnných ''$form, $lemma,...''. Nešikovné je, že při ''UD::Node->new(form=>$form,...)'' se tyto proměnné zkopírují do hashe a ty původní vypadnou ze scope a musejí se odalokovat. Čili vytváření uzlu zabere skoro stejný čas (4.5s). | * Optimalizací kódu set_parent bez volání této metody se ušetří 1.4s. To za to asi taky nestojí. |
* Když jsem všechny uzly ukládal do pole, tak odalokování pole (s 0.8M uzlů) trvalo cca 1s. To jsem do profilingu nezahrnul, ale benchmark jsem musel ručně spouštět víckrát. | * Poměrně dost času (4.1s) zabere naplnění 9 proměnných ''$form, $lemma,...''. Při ''UD::Node->new(form=>$form,...)'' se tyto proměnné kopírují do hashe, který bude instancí objektu. Celkem to trvá 4.8s, tedy zřejmě 4.1s kopírování a 0.7s vytvoření hashe a jeho blessování, ale celé je to v XS (asi o 20% rychlejší než v Perlu), takže kdo ví. |
| * Zdá se, že deklarováním 9 'my' proměnných až ve vnitřním cyklu přes uzly/řádky si přidám 1.5s. Možná proto, že se musejí odalokovávat (nebo přepisovat na undef), když vypadnou ze scope. |
| * Myslel jsem si, že by místo 9 proměnných mohlo být rychlejší jedno pole, ale to je pomalejší (už jen naplnění toho pole, zatím bez vytváření uzlu), a to o 0.6s. Vlastně se není co divit, protože perlí pole má krom nějakou režii navíc. |
| * Když jsem všechny uzly z celého souboru ukládal do jednoho pole, tak odalokování pole (s 0.8M uzlů) trvalo cca 1s. To jsem do profilingu nezahrnul, ale benchmark jsem musel ručně spouštět víckrát. |
| |
===== Benchmark konstruktorů v Perlu ===== | ===== Benchmark konstruktorů v Perlu ===== |