diff --git a/benches/README.md b/benches/README.md index 3716c9c0..d2d8f63d 100644 --- a/benches/README.md +++ b/benches/README.md @@ -18,6 +18,9 @@ Run them using the following commands: ``` cargo bench --bench run_criterion +# run a particular criterion benchmark +cargo bench --bench run_criterion -- + # to run iai, you need valgrind installed and to install iai-callgrind-runner # at the same version as is in Cargo.toml: cargo install iai-callgrind-runner --version 0.7.3 @@ -30,14 +33,12 @@ the same setup code from `benches.rs`. ## Setup -`setup.rs` contains the setup code for the actual benchmarks, which are run -using the `Benches` struct. `fn benches()` at the top of the file is where the -benchmarks are defined. +`setup.rs` contains the setup code to run benchmarks. `fn prolog_benches()` at +the top of the file is where the benchmarks are defined. -Benchmarks are organized around running queries against one prolog module file. -Before any runs start, `Benches::new()` reads the module files and initializes a -new `scryer_prolog::machine::Machine` for each file; multiple queries can be -declared to be benchmarked in the context of that module/machine instance. +Benchmarks are organized around running queries against a prolog module file. +Before a benchmark starts, `benchmark.setup()` is called which reads the module +file and initializes a new `scryer_prolog::machine::Machine`. Each benchmark measurement is done by running a query against the machine. In the case of criterion each query is run many times, in the case of iai it's run @@ -58,17 +59,17 @@ Some tips: * The goal of benchmarking is to know if a library or engine change improved performance or not. -* Once a benchmark is defined and named, don't change it's definition. If a - benchmark needs to change to be more useful, give the new definition a new - name. This will prevent charts from showing wild changes in performance just - because the definition changed (see previous). -* Aim for queries to execute in about 0.1-0.5s realtime. Longer runtimes make it +* Once a benchmark is defined and named, avoid changing it's definition. In + general, if a benchmark needs to change to be more useful, give the new + definition a new name. This will prevent charts from showing wild changes in + performance just because the definition changed (see previous). +* Aim for queries to execute in less than 0.5s realtime. Longer runtimes make it easier for humans to see big differences, but benchmarks either run 10x slower (iai) or execute repeatedly to attain statistical significance (criterion) and - in both cases queries that take 5+ seconds quickly become unweildly. + in both cases queries that take longer become cumbersome to run. * Consider that the library runtime actually parses the text output of the top - level. So keep the output small and don't use custom outputs or it will fail - to parse. + level. So don't use custom outputs or it will fail to parse. Also keep the + output small so it doesn't just benchmark the ouput parsing code. * DO test the output of the benchmark run, we don't want to count broken benchmarks. * Because a query may run against the same machine multiple times, don't @@ -89,7 +90,5 @@ results. - [ ] Currently, the execution time to load a module is not benchmarked. It would be nice to have at least one benchmark for loading a module (probably a big one). -- [ ] Adjust the benchmark execution strategy to allow queries to modify the - engine state (`assertz` etc). - [ ] Write a new action that consumes the test and benchmark results and plots them over time and publishes a report (github pages?). diff --git a/benches/csv.pl b/benches/csv.pl new file mode 100644 index 00000000..9f2156b5 --- /dev/null +++ b/benches/csv.pl @@ -0,0 +1,41 @@ +:- use_module(library(dcgs)). +:- use_module(library(lists)). +:- use_module(library(dif)). + +% util +peek(T), [T] --> [T]. + +% eof is only true at the end of the string, but does not consume anything. +% A sprinkle of state may be needed to avoid matching multiple times. +eof_([], []). +eof --> call(eof_). + +% csv rules +rows([]) --> rows_end. +rows([R | Rs]) --> row(R),rows(Rs). + +rows_end --> [eof], eof. % --> [eof-the-atom], eof-the-dcgrule + +row([F]) --> field(F),row_end. +row([F | Fs]) --> field(F),row(Fs). + +row_end --> [eol], peek(_). +row_end, [eof] --> [eol], eof. + +field([]) --> field_end. +field([C | Cs]) --> [C], {maplist(dif(C), [eof,eol | "\n;"])}, field(Cs). + +field_end --> ";". +field_end, [eol] --> "\n". +field_end, [eol] --> eof. + +data("0000;;Cc;0;BN;;;;;N;NULL;;;;\n0001;;Cc;0;BN;;;;;N;START OF HEADING;;;;\n0002;;Cc;0;BN;;;;;N;START OF TEXT;;;;\n0003;;Cc;0;BN;;;;;N;END OF TEXT;;;;\n0004;;Cc;0;BN;;;;;N;END OF TRANSMISSION;;;;\n0005;;Cc;0;BN;;;;;N;ENQUIRY;;;;\n0006;;Cc;0;BN;;;;;N;ACKNOWLEDGE;;;;\n0007;;Cc;0;BN;;;;;N;BELL;;;;\n0008;;Cc;0;BN;;;;;N;BACKSPACE;;;;\n0009;;Cc;0;S;;;;;N;CHARACTER TABULATION;;;;\n000A;;Cc;0;B;;;;;N;LINE FEED (LF);;;;\n000B;;Cc;0;S;;;;;N;LINE TABULATION;;;;\n000C;;Cc;0;WS;;;;;N;FORM FEED (FF);;;;\n000D;;Cc;0;B;;;;;N;CARRIAGE RETURN (CR);;;;\n000E;;Cc;0;BN;;;;;N;SHIFT OUT;;;;\n000F;;Cc;0;BN;;;;;N;SHIFT IN;;;;\n0010;;Cc;0;BN;;;;;N;DATA LINK ESCAPE;;;;\n0011;;Cc;0;BN;;;;;N;DEVICE CONTROL ONE;;;;\n0012;;Cc;0;BN;;;;;N;DEVICE CONTROL TWO;;;;\n0013;;Cc;0;BN;;;;;N;DEVICE CONTROL THREE;;;;\n0014;;Cc;0;BN;;;;;N;DEVICE CONTROL FOUR;;;;\n0015;;Cc;0;BN;;;;;N;NEGATIVE ACKNOWLEDGE;;;;\n0016;;Cc;0;BN;;;;;N;SYNCHRONOUS IDLE;;;;\n0017;;Cc;0;BN;;;;;N;END OF TRANSMISSION BLOCK;;;;\n0018;;Cc;0;BN;;;;;N;CANCEL;;;;\n0019;;Cc;0;BN;;;;;N;END OF MEDIUM;;;;\n001A;;Cc;0;BN;;;;;N;SUBSTITUTE;;;;\n001B;;Cc;0;BN;;;;;N;ESCAPE;;;;\n001C;;Cc;0;B;;;;;N;INFORMATION SEPARATOR FOUR;;;;\n001D;;Cc;0;B;;;;;N;INFORMATION SEPARATOR THREE;;;;\n001E;;Cc;0;B;;;;;N;INFORMATION SEPARATOR TWO;;;;\n001F;;Cc;0;S;;;;;N;INFORMATION SEPARATOR ONE;;;;\n0020;SPACE;Zs;0;WS;;;;;N;;;;;\n0021;EXCLAMATION MARK;Po;0;ON;;;;;N;;;;;\n0022;QUOTATION MARK;Po;0;ON;;;;;N;;;;;\n0023;NUMBER SIGN;Po;0;ET;;;;;N;;;;;\n0024;DOLLAR SIGN;Sc;0;ET;;;;;N;;;;;\n0025;PERCENT SIGN;Po;0;ET;;;;;N;;;;;\n0026;AMPERSAND;Po;0;ON;;;;;N;;;;;\n0027;APOSTROPHE;Po;0;ON;;;;;N;APOSTROPHE-QUOTE;;;;\n0028;LEFT PARENTHESIS;Ps;0;ON;;;;;Y;OPENING PARENTHESIS;;;;\n0029;RIGHT PARENTHESIS;Pe;0;ON;;;;;Y;CLOSING PARENTHESIS;;;;\n002A;ASTERISK;Po;0;ON;;;;;N;;;;;\n002B;PLUS SIGN;Sm;0;ES;;;;;N;;;;;\n002C;COMMA;Po;0;CS;;;;;N;;;;;\n002D;HYPHEN-MINUS;Pd;0;ES;;;;;N;;;;;\n002E;FULL STOP;Po;0;CS;;;;;N;PERIOD;;;;\n002F;SOLIDUS;Po;0;CS;;;;;N;SLASH;;;;\n0030;DIGIT ZERO;Nd;0;EN;;0;0;0;N;;;;;\n0031;DIGIT ONE;Nd;0;EN;;1;1;1;N;;;;;\n0032;DIGIT TWO;Nd;0;EN;;2;2;2;N;;;;;\n0033;DIGIT THREE;Nd;0;EN;;3;3;3;N;;;;;\n0034;DIGIT FOUR;Nd;0;EN;;4;4;4;N;;;;;\n0035;DIGIT FIVE;Nd;0;EN;;5;5;5;N;;;;;\n0036;DIGIT SIX;Nd;0;EN;;6;6;6;N;;;;;\n0037;DIGIT SEVEN;Nd;0;EN;;7;7;7;N;;;;;\n0038;DIGIT EIGHT;Nd;0;EN;;8;8;8;N;;;;;\n0039;DIGIT NINE;Nd;0;EN;;9;9;9;N;;;;;\n003A;COLON;Po;0;CS;;;;;N;;;;;\n003B;SEMICOLON;Po;0;ON;;;;;N;;;;;\n003C;LESS-THAN SIGN;Sm;0;ON;;;;;Y;;;;;\n003D;EQUALS SIGN;Sm;0;ON;;;;;N;;;;;\n003E;GREATER-THAN SIGN;Sm;0;ON;;;;;Y;;;;;\n003F;QUESTION MARK;Po;0;ON;;;;;N;;;;;\n0040;COMMERCIAL AT;Po;0;ON;;;;;N;;;;;\n0041;LATIN CAPITAL LETTER A;Lu;0;L;;;;;N;;;;0061;\n0042;LATIN CAPITAL LETTER B;Lu;0;L;;;;;N;;;;0062;\n0043;LATIN CAPITAL LETTER C;Lu;0;L;;;;;N;;;;0063;\n0044;LATIN CAPITAL LETTER D;Lu;0;L;;;;;N;;;;0064;\n0045;LATIN CAPITAL LETTER E;Lu;0;L;;;;;N;;;;0065;\n0046;LATIN CAPITAL LETTER F;Lu;0;L;;;;;N;;;;0066;\n0047;LATIN CAPITAL LETTER G;Lu;0;L;;;;;N;;;;0067;\n0048;LATIN CAPITAL LETTER H;Lu;0;L;;;;;N;;;;0068;\n0049;LATIN CAPITAL LETTER I;Lu;0;L;;;;;N;;;;0069;\n004A;LATIN CAPITAL LETTER J;Lu;0;L;;;;;N;;;;006A;\n004B;LATIN CAPITAL LETTER K;Lu;0;L;;;;;N;;;;006B;\n004C;LATIN CAPITAL LETTER L;Lu;0;L;;;;;N;;;;006C;\n004D;LATIN CAPITAL LETTER M;Lu;0;L;;;;;N;;;;006D;\n004E;LATIN CAPITAL LETTER N;Lu;0;L;;;;;N;;;;006E;\n004F;LATIN CAPITAL LETTER O;Lu;0;L;;;;;N;;;;006F;\n0050;LATIN CAPITAL LETTER P;Lu;0;L;;;;;N;;;;0070;\n0051;LATIN CAPITAL LETTER Q;Lu;0;L;;;;;N;;;;0071;\n0052;LATIN CAPITAL LETTER R;Lu;0;L;;;;;N;;;;0072;\n0053;LATIN CAPITAL LETTER S;Lu;0;L;;;;;N;;;;0073;\n0054;LATIN CAPITAL LETTER T;Lu;0;L;;;;;N;;;;0074;\n0055;LATIN CAPITAL LETTER U;Lu;0;L;;;;;N;;;;0075;\n0056;LATIN CAPITAL LETTER V;Lu;0;L;;;;;N;;;;0076;\n0057;LATIN CAPITAL LETTER W;Lu;0;L;;;;;N;;;;0077;\n0058;LATIN CAPITAL LETTER X;Lu;0;L;;;;;N;;;;0078;\n0059;LATIN CAPITAL LETTER Y;Lu;0;L;;;;;N;;;;0079;\n005A;LATIN CAPITAL LETTER Z;Lu;0;L;;;;;N;;;;007A;\n005B;LEFT SQUARE BRACKET;Ps;0;ON;;;;;Y;OPENING SQUARE BRACKET;;;;\n005C;REVERSE SOLIDUS;Po;0;ON;;;;;N;BACKSLASH;;;;\n005D;RIGHT SQUARE BRACKET;Pe;0;ON;;;;;Y;CLOSING SQUARE BRACKET;;;;\n005E;CIRCUMFLEX ACCENT;Sk;0;ON;;;;;N;SPACING CIRCUMFLEX;;;;\n005F;LOW LINE;Pc;0;ON;;;;;N;SPACING UNDERSCORE;;;;\n0060;GRAVE ACCENT;Sk;0;ON;;;;;N;SPACING GRAVE;;;;\n0061;LATIN SMALL LETTER A;Ll;0;L;;;;;N;;;0041;;0041\n0062;LATIN SMALL LETTER B;Ll;0;L;;;;;N;;;0042;;0042\n0063;LATIN SMALL LETTER C;Ll;0;L;;;;;N;;;0043;;0043\n0064;LATIN SMALL LETTER D;Ll;0;L;;;;;N;;;0044;;0044\n0065;LATIN SMALL LETTER E;Ll;0;L;;;;;N;;;0045;;0045\n0066;LATIN SMALL LETTER F;Ll;0;L;;;;;N;;;0046;;0046\n0067;LATIN SMALL LETTER G;Ll;0;L;;;;;N;;;0047;;0047\n0068;LATIN SMALL LETTER H;Ll;0;L;;;;;N;;;0048;;0048\n0069;LATIN SMALL LETTER I;Ll;0;L;;;;;N;;;0049;;0049\n006A;LATIN SMALL LETTER J;Ll;0;L;;;;;N;;;004A;;004A\n006B;LATIN SMALL LETTER K;Ll;0;L;;;;;N;;;004B;;004B\n006C;LATIN SMALL LETTER L;Ll;0;L;;;;;N;;;004C;;004C\n006D;LATIN SMALL LETTER M;Ll;0;L;;;;;N;;;004D;;004D\n006E;LATIN SMALL LETTER N;Ll;0;L;;;;;N;;;004E;;004E\n006F;LATIN SMALL LETTER O;Ll;0;L;;;;;N;;;004F;;004F\n0070;LATIN SMALL LETTER P;Ll;0;L;;;;;N;;;0050;;0050\n0071;LATIN SMALL LETTER Q;Ll;0;L;;;;;N;;;0051;;0051\n0072;LATIN SMALL LETTER R;Ll;0;L;;;;;N;;;0052;;0052\n0073;LATIN SMALL LETTER S;Ll;0;L;;;;;N;;;0053;;0053\n0074;LATIN SMALL LETTER T;Ll;0;L;;;;;N;;;0054;;0054\n0075;LATIN SMALL LETTER U;Ll;0;L;;;;;N;;;0055;;0055\n0076;LATIN SMALL LETTER V;Ll;0;L;;;;;N;;;0056;;0056\n0077;LATIN SMALL LETTER W;Ll;0;L;;;;;N;;;0057;;0057\n0078;LATIN SMALL LETTER X;Ll;0;L;;;;;N;;;0058;;0058\n0079;LATIN SMALL LETTER Y;Ll;0;L;;;;;N;;;0059;;0059\n007A;LATIN SMALL LETTER Z;Ll;0;L;;;;;N;;;005A;;005A\n007B;LEFT CURLY BRACKET;Ps;0;ON;;;;;Y;OPENING CURLY BRACKET;;;;\n007C;VERTICAL LINE;Sm;0;ON;;;;;N;VERTICAL BAR;;;;\n007D;RIGHT CURLY BRACKET;Pe;0;ON;;;;;Y;CLOSING CURLY BRACKET;;;;\n007E;TILDE;Sm;0;ON;;;;;N;;;;;\n007F;;Cc;0;BN;;;;;N;DELETE;;;;\n0080;;Cc;0;BN;;;;;N;;;;;\n0081;;Cc;0;BN;;;;;N;;;;;\n0082;;Cc;0;BN;;;;;N;BREAK PERMITTED HERE;;;;\n0083;;Cc;0;BN;;;;;N;NO BREAK HERE;;;;\n0084;;Cc;0;BN;;;;;N;;;;;\n0085;;Cc;0;B;;;;;N;NEXT LINE (NEL);;;;\n0086;;Cc;0;BN;;;;;N;START OF SELECTED AREA;;;;\n0087;;Cc;0;BN;;;;;N;END OF SELECTED AREA;;;;\n0088;;Cc;0;BN;;;;;N;CHARACTER TABULATION SET;;;;\n0089;;Cc;0;BN;;;;;N;CHARACTER TABULATION WITH JUSTIFICATION;;;;\n008A;;Cc;0;BN;;;;;N;LINE TABULATION SET;;;;\n008B;;Cc;0;BN;;;;;N;PARTIAL LINE FORWARD;;;;\n008C;;Cc;0;BN;;;;;N;PARTIAL LINE BACKWARD;;;;\n008D;;Cc;0;BN;;;;;N;REVERSE LINE FEED;;;;\n008E;;Cc;0;BN;;;;;N;SINGLE SHIFT TWO;;;;\n008F;;Cc;0;BN;;;;;N;SINGLE SHIFT THREE;;;;\n0090;;Cc;0;BN;;;;;N;DEVICE CONTROL STRING;;;;\n0091;;Cc;0;BN;;;;;N;PRIVATE USE ONE;;;;\n0092;;Cc;0;BN;;;;;N;PRIVATE USE TWO;;;;\n0093;;Cc;0;BN;;;;;N;SET TRANSMIT STATE;;;;\n0094;;Cc;0;BN;;;;;N;CANCEL CHARACTER;;;;\n0095;;Cc;0;BN;;;;;N;MESSAGE WAITING;;;;\n0096;;Cc;0;BN;;;;;N;START OF GUARDED AREA;;;;\n0097;;Cc;0;BN;;;;;N;END OF GUARDED AREA;;;;\n0098;;Cc;0;BN;;;;;N;START OF STRING;;;;\n0099;;Cc;0;BN;;;;;N;;;;;\n009A;;Cc;0;BN;;;;;N;SINGLE CHARACTER INTRODUCER;;;;\n009B;;Cc;0;BN;;;;;N;CONTROL SEQUENCE INTRODUCER;;;;\n009C;;Cc;0;BN;;;;;N;STRING TERMINATOR;;;;\n009D;;Cc;0;BN;;;;;N;OPERATING SYSTEM COMMAND;;;;\n009E;;Cc;0;BN;;;;;N;PRIVACY MESSAGE;;;;\n009F;;Cc;0;BN;;;;;N;APPLICATION PROGRAM COMMAND;;;;\n00A0;NO-BREAK SPACE;Zs;0;CS; 0020;;;;N;NON-BREAKING SPACE;;;;\n00A1;INVERTED EXCLAMATION MARK;Po;0;ON;;;;;N;;;;;\n00A2;CENT SIGN;Sc;0;ET;;;;;N;;;;;\n00A3;POUND SIGN;Sc;0;ET;;;;;N;;;;;\n00A4;CURRENCY SIGN;Sc;0;ET;;;;;N;;;;;\n00A5;YEN SIGN;Sc;0;ET;;;;;N;;;;;\n00A6;BROKEN BAR;So;0;ON;;;;;N;BROKEN VERTICAL BAR;;;;\n00A7;SECTION SIGN;Po;0;ON;;;;;N;;;;;\n00A8;DIAERESIS;Sk;0;ON; 0020 0308;;;;N;SPACING DIAERESIS;;;;\n00A9;COPYRIGHT SIGN;So;0;ON;;;;;N;;;;;\n00AA;FEMININE ORDINAL INDICATOR;Lo;0;L; 0061;;;;N;;;;;\n00AB;LEFT-POINTING DOUBLE ANGLE QUOTATION MARK;Pi;0;ON;;;;;Y;LEFT POINTING GUILLEMET;;;;\n00AC;NOT SIGN;Sm;0;ON;;;;;N;;;;;\n00AD;SOFT HYPHEN;Cf;0;BN;;;;;N;;;;;\n00AE;REGISTERED SIGN;So;0;ON;;;;;N;REGISTERED TRADE MARK SIGN;;;;\n00AF;MACRON;Sk;0;ON; 0020 0304;;;;N;SPACING MACRON;;;;\n00B0;DEGREE SIGN;So;0;ET;;;;;N;;;;;\n00B1;PLUS-MINUS SIGN;Sm;0;ET;;;;;N;PLUS-OR-MINUS SIGN;;;;\n00B2;SUPERSCRIPT TWO;No;0;EN; 0032;;2;2;N;SUPERSCRIPT DIGIT TWO;;;;\n00B3;SUPERSCRIPT THREE;No;0;EN; 0033;;3;3;N;SUPERSCRIPT DIGIT THREE;;;;\n00B4;ACUTE ACCENT;Sk;0;ON; 0020 0301;;;;N;SPACING ACUTE;;;;\n00B5;MICRO SIGN;Ll;0;L; 03BC;;;;N;;;039C;;039C\n00B6;PILCROW SIGN;Po;0;ON;;;;;N;PARAGRAPH SIGN;;;;\n00B7;MIDDLE DOT;Po;0;ON;;;;;N;;;;;\n00B8;CEDILLA;Sk;0;ON; 0020 0327;;;;N;SPACING CEDILLA;;;;\n00B9;SUPERSCRIPT ONE;No;0;EN; 0031;;1;1;N;SUPERSCRIPT DIGIT ONE;;;;\n00BA;MASCULINE ORDINAL INDICATOR;Lo;0;L; 006F;;;;N;;;;;\n00BB;RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK;Pf;0;ON;;;;;Y;RIGHT POINTING GUILLEMET;;;;\n00BC;VULGAR FRACTION ONE QUARTER;No;0;ON; 0031 2044 0034;;;1/4;N;FRACTION ONE QUARTER;;;;\n00BD;VULGAR FRACTION ONE HALF;No;0;ON; 0031 2044 0032;;;1/2;N;FRACTION ONE HALF;;;;\n00BE;VULGAR FRACTION THREE QUARTERS;No;0;ON; 0033 2044 0034;;;3/4;N;FRACTION THREE QUARTERS;;;;\n00BF;INVERTED QUESTION MARK;Po;0;ON;;;;;N;;;;;\n00C0;LATIN CAPITAL LETTER A WITH GRAVE;Lu;0;L;0041 0300;;;;N;LATIN CAPITAL LETTER A GRAVE;;;00E0;\n00C1;LATIN CAPITAL LETTER A WITH ACUTE;Lu;0;L;0041 0301;;;;N;LATIN CAPITAL LETTER A ACUTE;;;00E1;\n00C2;LATIN CAPITAL LETTER A WITH CIRCUMFLEX;Lu;0;L;0041 0302;;;;N;LATIN CAPITAL LETTER A CIRCUMFLEX;;;00E2;\n00C3;LATIN CAPITAL LETTER A WITH TILDE;Lu;0;L;0041 0303;;;;N;LATIN CAPITAL LETTER A TILDE;;;00E3;\n00C4;LATIN CAPITAL LETTER A WITH DIAERESIS;Lu;0;L;0041 0308;;;;N;LATIN CAPITAL LETTER A DIAERESIS;;;00E4;\n00C5;LATIN CAPITAL LETTER A WITH RING ABOVE;Lu;0;L;0041 030A;;;;N;LATIN CAPITAL LETTER A RING;;;00E5;\n00C6;LATIN CAPITAL LETTER AE;Lu;0;L;;;;;N;LATIN CAPITAL LETTER A E;;;00E6;\n00C7;LATIN CAPITAL LETTER C WITH CEDILLA;Lu;0;L;0043 0327;;;;N;LATIN CAPITAL LETTER C CEDILLA;;;00E7;\n00C8;LATIN CAPITAL LETTER E WITH GRAVE;Lu;0;L;0045 0300;;;;N;LATIN CAPITAL LETTER E GRAVE;;;00E8;\n00C9;LATIN CAPITAL LETTER E WITH ACUTE;Lu;0;L;0045 0301;;;;N;LATIN CAPITAL LETTER E ACUTE;;;00E9;\n00CA;LATIN CAPITAL LETTER E WITH CIRCUMFLEX;Lu;0;L;0045 0302;;;;N;LATIN CAPITAL LETTER E CIRCUMFLEX;;;00EA;\n00CB;LATIN CAPITAL LETTER E WITH DIAERESIS;Lu;0;L;0045 0308;;;;N;LATIN CAPITAL LETTER E DIAERESIS;;;00EB;\n00CC;LATIN CAPITAL LETTER I WITH GRAVE;Lu;0;L;0049 0300;;;;N;LATIN CAPITAL LETTER I GRAVE;;;00EC;\n00CD;LATIN CAPITAL LETTER I WITH ACUTE;Lu;0;L;0049 0301;;;;N;LATIN CAPITAL LETTER I ACUTE;;;00ED;\n00CE;LATIN CAPITAL LETTER I WITH CIRCUMFLEX;Lu;0;L;0049 0302;;;;N;LATIN CAPITAL LETTER I CIRCUMFLEX;;;00EE;\n00CF;LATIN CAPITAL LETTER I WITH DIAERESIS;Lu;0;L;0049 0308;;;;N;LATIN CAPITAL LETTER I DIAERESIS;;;00EF;\n00D0;LATIN CAPITAL LETTER ETH;Lu;0;L;;;;;N;;;;00F0;\n00D1;LATIN CAPITAL LETTER N WITH TILDE;Lu;0;L;004E 0303;;;;N;LATIN CAPITAL LETTER N TILDE;;;00F1;\n00D2;LATIN CAPITAL LETTER O WITH GRAVE;Lu;0;L;004F 0300;;;;N;LATIN CAPITAL LETTER O GRAVE;;;00F2;\n00D3;LATIN CAPITAL LETTER O WITH ACUTE;Lu;0;L;004F 0301;;;;N;LATIN CAPITAL LETTER O ACUTE;;;00F3;\n00D4;LATIN CAPITAL LETTER O WITH CIRCUMFLEX;Lu;0;L;004F 0302;;;;N;LATIN CAPITAL LETTER O CIRCUMFLEX;;;00F4;\n00D5;LATIN CAPITAL LETTER O WITH TILDE;Lu;0;L;004F 0303;;;;N;LATIN CAPITAL LETTER O TILDE;;;00F5;\n00D6;LATIN CAPITAL LETTER O WITH DIAERESIS;Lu;0;L;004F 0308;;;;N;LATIN CAPITAL LETTER O DIAERESIS;;;00F6;\n00D7;MULTIPLICATION SIGN;Sm;0;ON;;;;;N;;;;;\n00D8;LATIN CAPITAL LETTER O WITH STROKE;Lu;0;L;;;;;N;LATIN CAPITAL LETTER O SLASH;;;00F8;\n00D9;LATIN CAPITAL LETTER U WITH GRAVE;Lu;0;L;0055 0300;;;;N;LATIN CAPITAL LETTER U GRAVE;;;00F9;\n00DA;LATIN CAPITAL LETTER U WITH ACUTE;Lu;0;L;0055 0301;;;;N;LATIN CAPITAL LETTER U ACUTE;;;00FA;\n00DB;LATIN CAPITAL LETTER U WITH CIRCUMFLEX;Lu;0;L;0055 0302;;;;N;LATIN CAPITAL LETTER U CIRCUMFLEX;;;00FB;\n00DC;LATIN CAPITAL LETTER U WITH DIAERESIS;Lu;0;L;0055 0308;;;;N;LATIN CAPITAL LETTER U DIAERESIS;;;00FC;\n00DD;LATIN CAPITAL LETTER Y WITH ACUTE;Lu;0;L;0059 0301;;;;N;LATIN CAPITAL LETTER Y ACUTE;;;00FD;\n00DE;LATIN CAPITAL LETTER THORN;Lu;0;L;;;;;N;;;;00FE;\n00DF;LATIN SMALL LETTER SHARP S;Ll;0;L;;;;;N;;;;;\n00E0;LATIN SMALL LETTER A WITH GRAVE;Ll;0;L;0061 0300;;;;N;LATIN SMALL LETTER A GRAVE;;00C0;;00C0\n00E1;LATIN SMALL LETTER A WITH ACUTE;Ll;0;L;0061 0301;;;;N;LATIN SMALL LETTER A ACUTE;;00C1;;00C1\n00E2;LATIN SMALL LETTER A WITH CIRCUMFLEX;Ll;0;L;0061 0302;;;;N;LATIN SMALL LETTER A CIRCUMFLEX;;00C2;;00C2\n00E3;LATIN SMALL LETTER A WITH TILDE;Ll;0;L;0061 0303;;;;N;LATIN SMALL LETTER A TILDE;;00C3;;00C3\n00E4;LATIN SMALL LETTER A WITH DIAERESIS;Ll;0;L;0061 0308;;;;N;LATIN SMALL LETTER A DIAERESIS;;00C4;;00C4\n00E5;LATIN SMALL LETTER A WITH RING ABOVE;Ll;0;L;0061 030A;;;;N;LATIN SMALL LETTER A RING;;00C5;;00C5\n00E6;LATIN SMALL LETTER AE;Ll;0;L;;;;;N;LATIN SMALL LETTER A E;;00C6;;00C6\n00E7;LATIN SMALL LETTER C WITH CEDILLA;Ll;0;L;0063 0327;;;;N;LATIN SMALL LETTER C CEDILLA;;00C7;;00C7\n00E8;LATIN SMALL LETTER E WITH GRAVE;Ll;0;L;0065 0300;;;;N;LATIN SMALL LETTER E GRAVE;;00C8;;00C8\n00E9;LATIN SMALL LETTER E WITH ACUTE;Ll;0;L;0065 0301;;;;N;LATIN SMALL LETTER E ACUTE;;00C9;;00C9\n00EA;LATIN SMALL LETTER E WITH CIRCUMFLEX;Ll;0;L;0065 0302;;;;N;LATIN SMALL LETTER E CIRCUMFLEX;;00CA;;00CA\n00EB;LATIN SMALL LETTER E WITH DIAERESIS;Ll;0;L;0065 0308;;;;N;LATIN SMALL LETTER E DIAERESIS;;00CB;;00CB\n00EC;LATIN SMALL LETTER I WITH GRAVE;Ll;0;L;0069 0300;;;;N;LATIN SMALL LETTER I GRAVE;;00CC;;00CC\n00ED;LATIN SMALL LETTER I WITH ACUTE;Ll;0;L;0069 0301;;;;N;LATIN SMALL LETTER I ACUTE;;00CD;;00CD\n00EE;LATIN SMALL LETTER I WITH CIRCUMFLEX;Ll;0;L;0069 0302;;;;N;LATIN SMALL LETTER I CIRCUMFLEX;;00CE;;00CE\n00EF;LATIN SMALL LETTER I WITH DIAERESIS;Ll;0;L;0069 0308;;;;N;LATIN SMALL LETTER I DIAERESIS;;00CF;;00CF\n00F0;LATIN SMALL LETTER ETH;Ll;0;L;;;;;N;;;00D0;;00D0\n00F1;LATIN SMALL LETTER N WITH TILDE;Ll;0;L;006E 0303;;;;N;LATIN SMALL LETTER N TILDE;;00D1;;00D1\n00F2;LATIN SMALL LETTER O WITH GRAVE;Ll;0;L;006F 0300;;;;N;LATIN SMALL LETTER O GRAVE;;00D2;;00D2\n00F3;LATIN SMALL LETTER O WITH ACUTE;Ll;0;L;006F 0301;;;;N;LATIN SMALL LETTER O ACUTE;;00D3;;00D3\n00F4;LATIN SMALL LETTER O WITH CIRCUMFLEX;Ll;0;L;006F 0302;;;;N;LATIN SMALL LETTER O CIRCUMFLEX;;00D4;;00D4\n00F5;LATIN SMALL LETTER O WITH TILDE;Ll;0;L;006F 0303;;;;N;LATIN SMALL LETTER O TILDE;;00D5;;00D5\n00F6;LATIN SMALL LETTER O WITH DIAERESIS;Ll;0;L;006F 0308;;;;N;LATIN SMALL LETTER O DIAERESIS;;00D6;;00D6"). + +codename(Codepoint, Codename) :- + data(Data), + phrase(rows(Rows), Data), + member(Row, Rows), + Row = [Codepoint, Codename | _]. + +% work around weird parsing behavior with extraneous choicepoints +get_codename(Codepoint, Codename) :- findall(Name, codename(Codepoint,Name), Names), Names = [Codename | _]. diff --git a/benches/run_criterion.rs b/benches/run_criterion.rs index c0cdea32..61895c39 100644 --- a/benches/run_criterion.rs +++ b/benches/run_criterion.rs @@ -1,9 +1,16 @@ -use criterion::{criterion_group, criterion_main, Criterion}; +use criterion::{criterion_group, criterion_main, BatchSize, Criterion}; mod setup; fn bench_criterion(c: &mut Criterion) { - setup::benches().run_all_criterion(c); + for (&name, bench) in setup::prolog_benches().iter() { + match bench.strategy { + setup::Strategy::Fresh => c.bench_function(name, |b| { + b.iter_batched(|| bench.setup(), |mut r| r(), BatchSize::LargeInput) + }), + setup::Strategy::Reuse => c.bench_function(name, |b| b.iter(bench.setup())), + }; + } } criterion_group!( diff --git a/benches/run_iai.rs b/benches/run_iai.rs index bcb990d4..99bec8f2 100644 --- a/benches/run_iai.rs +++ b/benches/run_iai.rs @@ -3,15 +3,15 @@ use iai_callgrind::{library_benchmark, library_benchmark_group, main}; mod setup; #[library_benchmark] -#[bench::normal(setup::benches())] -fn bench_edges(mut b: setup::Benches) { - b.run_once("count_edges_short"); +#[bench::normal(setup::prolog_benches()["count_edges_short"].setup())] +fn bench_edges(mut run: impl FnMut()) { + run(); } #[library_benchmark] -#[bench::normal(setup::benches())] -fn bench_numlist(mut b: setup::Benches) { - b.run_once("numlist_short"); +#[bench::normal(setup::prolog_benches()["numlist_short"].setup())] +fn bench_numlist(mut run: impl FnMut()) { + run(); } library_benchmark_group!( diff --git a/benches/setup.rs b/benches/setup.rs index 2ca880ce..3096950d 100644 --- a/benches/setup.rs +++ b/benches/setup.rs @@ -1,116 +1,93 @@ use std::{collections::BTreeMap, fs, path::Path}; -use criterion::{black_box, Criterion}; - use maplit::btreemap; use scryer_prolog::machine::{ parsed_results::{QueryMatch, QueryResolution, Value}, Machine, }; -pub fn benches() -> Benches { - Benches::new(&[ +pub fn prolog_benches() -> BTreeMap<&'static str, PrologBenchmark> { + [ ( - "benches/edges.pl", // name of the prolog module file to load - &[ - ( - "count_edges_short", // name of the benchmark - "independent_set_count(ky, Count).", // query to benchmark in the context of the loaded module - btreemap! { "Count".to_string() => Value::try_from("2869176".to_string()).unwrap() }, // List of expected bindings - ), - ( - "count_edges", // multiple benchmark queries can be defined per module - "independent_set_count(aa, Count).", // consider making the query adjustable to tune the runtime - btreemap! { "Count".to_string() => Value::try_from("211954906".to_string()).unwrap(), }, - ), - ], + "count_edges", // name of the benchmark + "benches/edges.pl", // name of the prolog module file to load + "independent_set_count(aa, Count).", // query to benchmark in the context of the loaded module + Strategy::Reuse, + btreemap! { "Count" => Value::try_from("211954906".to_string()).unwrap(), }, // list of expected bindings ), ( + "count_edges_short", + "benches/edges.pl", // use the same file in multiple benchmarks + "independent_set_count(ky, Count).", // consider making the query adjustable to tune the run time to ~0.1s + Strategy::Reuse, + btreemap! { "Count" => Value::try_from("2869176".to_string()).unwrap() }, + ), + ( + "numlist_short", "benches/numlist.pl", - &[( - "numlist_short", - "run_numlist(1000000, Head).", - btreemap! { "Head".to_string() => Value::try_from("1".to_string()).unwrap()}, - )], + "run_numlist(1000000, Head).", + Strategy::Reuse, + btreemap! { "Head" => Value::try_from("1".to_string()).unwrap()}, ), - ]) + ( + "csv_codename", + "benches/csv.pl", + "get_codename(\"0020\",Name).", + Strategy::Reuse, + btreemap! { "Name" => Value::try_from("SPACE".to_string()).unwrap()}, + ), + ] + .map(|b| { + ( + b.0, + PrologBenchmark { + name: b.0, + filename: b.1, + query: b.2, + strategy: b.3, + bindings: b.4, + }, + ) + }) + .into() } -pub struct Benches { - machines: Vec, - runs: BTreeMap, -} - -pub struct Run { - machine_idx: usize, - name: &'static str, - query: &'static str, - bindings: BTreeMap, -} - -// Required for using a mutex. It doesn't actually send anything across threads, -// and this is just a benchmark, so it Should Be Fine(tm). ¯\_(ツ)_/¯ -unsafe impl Send for Benches {} - -impl Benches { - #[allow(clippy::type_complexity)] - pub fn new( - benches: &[( - &'static str, - &[(&'static str, &'static str, BTreeMap)], - )], - ) -> Self { - let mut machines = vec![]; - let mut runs = BTreeMap::new(); - - for b in benches { - let content = fs::read_to_string(b.0).unwrap(); - let name = Path::new(b.0).file_stem().unwrap().to_str().unwrap(); - let mut machine = Machine::new_lib(); - machine.load_module_string(name, content); - machines.push(machine); - let idx = machines.len() - 1; - runs.extend(b.1.iter().cloned().map(|r| { - ( - r.0.to_string(), - Run { - machine_idx: idx, - name: r.0, - query: r.1, - bindings: r.2, - }, - ) - })); - } - - Benches { machines, runs } - } - +pub enum Strategy { #[allow(dead_code)] - pub fn run_all_criterion(&mut self, c: &mut Criterion) { - for (_, runner) in self.runs.iter() { - let machine = &mut self.machines[runner.machine_idx]; - c.bench_function(runner.name, |b| { - b.iter(|| { - Self::run(machine, runner); - }) - }); + Fresh, + Reuse, +} + +pub struct PrologBenchmark { + pub name: &'static str, + pub filename: &'static str, + pub query: &'static str, + pub strategy: Strategy, + pub bindings: BTreeMap<&'static str, Value>, +} + +impl PrologBenchmark { + pub fn setup(&self) -> impl FnMut() { + let program = fs::read_to_string(self.filename).unwrap(); + let module_name = Path::new(self.filename) + .file_stem() + .and_then(|s| s.to_str()) + .unwrap(); + + let mut machine = Machine::new_lib(); + machine.load_module_string(module_name, program); + + let benchmark_name = self.name; + let query = self.query; + let expected = QueryResolution::Matches(vec![QueryMatch::from(self.bindings.clone())]); + + move || { + use criterion::black_box; + let result = black_box(machine.run_query(black_box(query.to_string()))); + match result { + Ok(r) => assert_eq!(&r, &expected), + Err(e) => panic!("benchmark {} failed with: {}", benchmark_name, e), + } } } - - #[allow(dead_code)] - pub fn run_once(&mut self, name: &str) { - let runner = &self.runs[name]; - let machine = &mut self.machines[runner.machine_idx]; - Self::run(machine, runner); - } - - fn run(machine: &mut Machine, runner: &Run) { - assert_eq!( - black_box(machine.run_query(black_box(runner.query.to_string()))), - Ok(QueryResolution::Matches(vec![QueryMatch::from( - runner.bindings.clone() - )])) - ); - } } diff --git a/src/codegen.rs b/src/codegen.rs index 7297b72c..bc675640 100644 --- a/src/codegen.rs +++ b/src/codegen.rs @@ -296,11 +296,10 @@ impl DebrayAllocator { self.mark_var_in_non_callable(var_num, term_loc, vr, code); temp_v!(arg) } else { - match &self.var_data.records[var_num].allocation { - VarAlloc::Perm(_, PermVarAllocation::Pending) => { - self.mark_var_in_non_callable(var_num, term_loc, vr, code); - } - _ => {} + if let VarAlloc::Perm(_, PermVarAllocation::Pending) = + &self.var_data.records[var_num].allocation + { + self.mark_var_in_non_callable(var_num, term_loc, vr, code); } self.increment_running_count(var_num);