word: store data entries as prepared subarrays
authorMischa POSLAWSKY <perl@shiar.org>
Sun, 26 Dec 2021 20:06:12 +0000 (21:06 +0100)
committerMischa POSLAWSKY <perl@shiar.org>
Fri, 31 Dec 2021 04:29:05 +0000 (05:29 +0100)
Time to split strings is comparable to directly loading structured values.
Considered hashes for scalability with more (optional) columns, but not
worth the cost at this time.

Benchmark loading 1264 rows in perl:
       rate memory size
strings 468/s  52kB 15kB
split  257/s 152kB  "
arrays 221/s 133kB 17kB
hashes 126/s 188kB 27kB

tools/mkwordlist
word.plp
word/quiz.js

index 3c5aac907ecc69b0fcaf46d97314d95176080599..78859b4a09cb2a0cb48dd39c5f7a1edddd90a5ca 100755 (executable)
@@ -10,10 +10,17 @@ my $db = Shiar_Sheet::DB->connect;
 say 'use utf8;';
 
 use Data::Dump 'pp';
+my %rows;
 if (my $lang = shift @ARGV) {
        my %filter = (lang => $lang);
-       say pp({ $db->select('_word_ref w' => "ref, exportform(row(w.*))", \%filter)->map })
+       my $cols = "ref, id, prio, array_to_string(form || alt, '/')";
+       %rows = $db->select(_word_ref => $cols, \%filter)->map_arrays;
+       say pp \%rows
                =~ s/\\x\{([0-9A-F]+)\}/chr hex $1/ger;
        exit;
 }
-say pp { $db->select(_cat_words => "coalesce(id::text, ''), forms")->map };
+else {
+       %rows = $db->select(_cat_words => "coalesce(id::text, ''), forms")->map;
+       $_ = [ map { [split /:/, $_, 3] } @{$_} ] for values %rows;
+       say pp \%rows;
+}
index 41d2bd330aa80a5d78b2a81c3a9e08284900ffdd..9ea54e89f7d002937e0c21dc12caf12ce5d2ff88 100644 (file)
--- a/word.plp
+++ b/word.plp
@@ -90,7 +90,7 @@ sub showimg {
 sub printimgs {
        say '<ul>';
        for my $row (@_) {
-               my ($id, $level, $title) = split /:/, $row, 3;
+               my ($id, $level, $title) = @{$row};
                $id or die "empty reference"; # assertion to prevent loops
                my @type;
                push @type, 'parent' if defined $table->{$id};
@@ -110,8 +110,8 @@ if (exists $get{q}) {
        if ($Request) {
                my @query = $Request;
                while (@query) {
-                       push @rows, grep { (split /:/)[1] <= $limit } @query;
-                       s/:.*// for @query;
+                       push @rows, grep { $_->[1] <= $limit } @query;
+                       $_ = $_->[0] for @query;
                        @query = map {$_ ? @{$_} : ()} @{$table}{@query};
                }
        }
index 0518fa14bdbc72c386f1b5abe4554c1f05d30965..b98842f18a074e0cc6643b4afe38f8ba6975e1a7 100644 (file)
@@ -26,7 +26,6 @@ class Quiz {
                        this.form = document.getElementById('quiz');
                        this.words = Object.values(json)
                                .sort(() => {return .5 - Math.random()}) // shuffle
-                               .map(row => row.split(/:/))
                        this.next();
                });
        }