mirror of
https://github.com/johnkerl/miller.git
synced 2026-08-01 20:12:19 +00:00
884 lines
22 KiB
HTML
884 lines
22 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
|
|
<!-- PAGE GENERATED FROM template.html and content-for-whyc-details.html BY poki. -->
|
|
<!-- PLEASE MAKE CHANGES THERE AND THEN RE-RUN poki. -->
|
|
<head>
|
|
<meta http-equiv="Content-type" content="text/html;charset=UTF-8"/>
|
|
<meta name="description" content="Miller documentation"/>
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0"/> <!-- mobile-friendly -->
|
|
<meta name="keywords"
|
|
content="John Kerl, Kerl, Miller, miller, mlr, OLAP, data analysis software, regression, correlation, variance, data tools, " />
|
|
|
|
<title> Why C: details </title>
|
|
<link rel="stylesheet" type="text/css" href="css/miller.css"/>
|
|
<link rel="stylesheet" type="text/css" href="css/poki-callbacks.css"/>
|
|
</head>
|
|
|
|
<!-- ================================================================ -->
|
|
<script type="text/javascript">
|
|
var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
|
|
document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
|
|
</script>
|
|
<script type="text/javascript">
|
|
try {
|
|
var pageTracker = _gat._getTracker("UA-15651652-1");
|
|
pageTracker._trackPageview();
|
|
} catch(err) {}
|
|
</script>
|
|
<!-- ================================================================ -->
|
|
|
|
<body bgcolor="#ffffff">
|
|
|
|
<!-- ================================================================ -->
|
|
|
|
<!-- navbar -->
|
|
<div class="pokinav">
|
|
<center><titleinbody>Miller</titleinbody></center>
|
|
|
|
<!-- NAVBAR GENERATED FROM template.html BY poki -->
|
|
<br/>
|
|
<a class="poki-navbar-element" href="index.html">Overview</a>
|
|
|
|
<a class="poki-navbar-element" href="faq.html">Using</a>
|
|
|
|
<a class="poki-navbar-element" href="reference.html">Reference</a>
|
|
|
|
<a class="poki-navbar-element" href="why.html"><b>Background</b></a>
|
|
|
|
<a class="poki-navbar-element" href="contact.html">Repository</a>
|
|
|
|
<br/>
|
|
<br/><a href="why.html">Why?</a>
|
|
<br/><a href="whyc.html">Why C?</a>
|
|
<br/><a href="whyc-details.html"><b>Why C: details</b></a>
|
|
<br/><a href="etymology.html">Why call it Miller?</a>
|
|
<br/><a href="originality.html">How original is Miller?</a>
|
|
<br/><a href="performance.html">Performance</a>
|
|
</div>
|
|
|
|
<!-- page body -->
|
|
<p/>
|
|
|
|
<!-- BODY COPIED FROM content-for-whyc-details.html BY poki -->
|
|
<div class="pokitoc">
|
|
<center><titleinbody>Why C: details</titleinbody></center>
|
|
• <a href="#Overview">Overview</a><br/>
|
|
• <a href="#Timings">Timings</a><br/>
|
|
• <a href="#Discussion">Discussion</a><br/>
|
|
• <a href="#Source_code">Source code</a><br/>
|
|
• <a href="#C_cat_using_fgets">C cat using fgets</a><br/>
|
|
• <a href="#C_cat_using_getdelim">C cat using getdelim</a><br/>
|
|
• <a href="#C_cat_using_mmap">C cat using mmap</a><br/>
|
|
• <a href="#D_cat">D cat</a><br/>
|
|
• <a href="#Rust_cat">Rust cat</a><br/>
|
|
• <a href="#Go_cat">Go cat</a><br/>
|
|
• <a href="#Nim_cat">Nim cat</a><br/>
|
|
• <a href="#D_cut">D cut</a><br/>
|
|
• <a href="#Go_cut">Go cut</a><br/>
|
|
• <a href="#Nim_cut">Nim cut</a><br/>
|
|
• <a href="#Makefile">Makefile</a><br/>
|
|
• <a href="#Compiler_versions">Compiler versions</a><br/>
|
|
• <a href="#Hardware">Hardware</a><br/>
|
|
</div>
|
|
<p/>
|
|
|
|
<p/>
|
|
<button style="font-weight:bold;color:maroon;border:0" onclick="bodyToggler.expandAll();" href="javascript:;">Expand all sections</button>
|
|
<button style="font-weight:bold;color:maroon;border:0" onclick="bodyToggler.collapseAll();" href="javascript:;">Collapse all sections</button>
|
|
|
|
<a id="Overview"/><h1>Overview</h1>
|
|
<button style="font-weight:bold;color:maroon;border:0" padding=0 onclick="bodyToggler.toggle('body_section_toggle_overview');" href="javascript:;">Toggle section visibility</button>
|
|
<div id="body_section_toggle_overview" style="display: block">
|
|
|
|
<p/>This section contains details substantiating the discussion at <a href="whyc.html">Why C?</a>.
|
|
|
|
<p/a>I did simple experiments in several languages. In one experiment (<b>cat
|
|
tests</b>) I just read lines and printed them back out — a line-oriented
|
|
<code>cat</code>. In another (<b>cut tests</b>) I consumed input lines like
|
|
<code>x=1,y=2,z=3</code> one at a time, split them on commas and equals signs
|
|
to populate hash maps, transformed them (e.g. remove the <code>y</code> field),
|
|
and emitted them. Basically <code>mlr cut -x -f y</code> with DKVP format. I
|
|
didn’t do anything fancy — just using each language’s
|
|
<code>getline</code>, string-split, hashmap-put, etc. (For C, the hashmap logic
|
|
was my own and has turned into Miller per se.) And nothing was as fast
|
|
as C, so I used C. Here are the experiments I kept (I failed to keep the Lua
|
|
code, for example). Note that I re-ran the timings in 2019 using code written
|
|
in 2015, for purposes of creating this page.
|
|
|
|
</div>
|
|
<a id="Timings"/><h1>Timings</h1>
|
|
<button style="font-weight:bold;color:maroon;border:0" padding=0 onclick="bodyToggler.toggle('body_section_toggle_timings');" href="javascript:;">Toggle section visibility</button>
|
|
<div id="body_section_toggle_timings" style="display: block">
|
|
|
|
<p/>
|
|
<div class="pokipanel">
|
|
<pre>
|
|
----------------------------------------------------------------
|
|
$ wc -l ../data/bigger
|
|
1000000 ../data/bigger
|
|
|
|
$ ls -lh ../data/bigger
|
|
-rw----r-- 1 kerl kerl 59M Sep 18 21:47 ../data/bigger
|
|
|
|
$ head ../data/bigger
|
|
a=pan,b=pan,i=1,x=0.3467901443380824,y=0.7268028627434533
|
|
a=eks,b=pan,i=2,x=0.7586799647899636,y=0.5221511083334797
|
|
a=wye,b=wye,i=3,x=0.20460330576630303,y=0.33831852551664776
|
|
a=eks,b=wye,i=4,x=0.38139939387114097,y=0.13418874328430463
|
|
a=wye,b=pan,i=5,x=0.5732889198020006,y=0.8636244699032729
|
|
a=zee,b=pan,i=6,x=0.5271261600918548,y=0.49322128674835697
|
|
a=eks,b=zee,i=7,x=0.6117840605678454,y=0.1878849191181694
|
|
a=zee,b=wye,i=8,x=0.5985540091064224,y=0.976181385699006
|
|
a=hat,b=wye,i=9,x=0.03144187646093577,y=0.7495507603507059
|
|
a=pan,b=wye,i=10,x=0.5026260055412137,y=0.9526183602969864
|
|
|
|
----------------------------------------------------------------
|
|
$ cat timings.sh
|
|
|
|
time /bin/cat < ../data/bigger > /dev/null
|
|
time catc < ../data/bigger > /dev/null
|
|
time catc0 < ../data/bigger > /dev/null
|
|
time catm ../data/bigger > /dev/null
|
|
time catd < ../data/bigger > /dev/null
|
|
time catgo < ../data/bigger > /dev/null
|
|
time catrust < ../data/bigger > /dev/null
|
|
time catnim < ../data/bigger > /dev/null
|
|
|
|
time cutgo < ../data/bigger > /dev/null
|
|
time cutd < ../data/bigger > /dev/null
|
|
time cutnim < ../data/bigger > /dev/null
|
|
|
|
----------------------------------------------------------------
|
|
$ bash -x timings.sh
|
|
|
|
+ /bin/cat ../data/bigger
|
|
real 0m0.026s
|
|
user 0m0.000s
|
|
sys 0m0.026s
|
|
|
|
+ catc
|
|
real 0m0.097s
|
|
user 0m0.076s
|
|
sys 0m0.021s
|
|
|
|
+ catc0
|
|
real 0m0.057s
|
|
user 0m0.028s
|
|
sys 0m0.028s
|
|
|
|
+ catm ../data/bigger
|
|
real 0m0.197s
|
|
user 0m0.177s
|
|
sys 0m0.020s
|
|
|
|
+ catd
|
|
real 0m0.258s
|
|
user 0m0.213s
|
|
sys 0m0.054s
|
|
|
|
+ catgo
|
|
real 0m0.121s
|
|
user 0m0.111s
|
|
sys 0m0.024s
|
|
|
|
+ catrust
|
|
real 0m1.055s
|
|
user 0m1.035s
|
|
sys 0m0.020s
|
|
|
|
+ catnim
|
|
real 0m0.624s
|
|
user 0m0.432s
|
|
sys 0m0.192s
|
|
|
|
+ cutgo
|
|
real 0m1.073s
|
|
user 0m1.079s
|
|
sys 0m0.041s
|
|
|
|
+ cutd
|
|
real 0m4.233s
|
|
user 0m4.462s
|
|
sys 0m0.113s
|
|
|
|
+ cutnim
|
|
real 0m21.380s
|
|
user 0m21.350s
|
|
sys 0m0.024s
|
|
|
|
</pre>
|
|
</div>
|
|
<p/>
|
|
|
|
</div>
|
|
<a id="Discussion"/><h1>Discussion</h1>
|
|
<button style="font-weight:bold;color:maroon;border:0" padding=0 onclick="bodyToggler.toggle('body_section_toggle_discussion');" href="javascript:;">Toggle section visibility</button>
|
|
<div id="body_section_toggle_discussion" style="display: block">
|
|
|
|
<ul>
|
|
<li/> <code>/bin/cat</code> is quite a bit faster than my line-oriented C code.
|
|
This shows that my simple experiments here don’t exhaust the
|
|
possibilities of clever programming. Rather, they serve to compare and contrast
|
|
the performance of straightforward coding in various languages.
|
|
|
|
<li/> I didn’t get any of the other languages to do line-oriented
|
|
<code>cat</code> as fast as C. But Go was in the ballpark and was worth a
|
|
further look.
|
|
|
|
<li/> The <code>cut</code> experiments separated it out. I iteratively
|
|
commented out/in various steps of the <code>cut</code> steps and found (as
|
|
noted in the source code below) big chunks of <code>cutgo.go</code>’s
|
|
time in the simple map and write-to-stdout library-code operations. I failed
|
|
to retain <code>cutc.c</code> as I originally implemented it in 2015 (it
|
|
morphed gradually into Miller per se) but it was sufficiently faster than
|
|
<code>cutgo.go</code> that I stuck with C for implementing Miller.
|
|
|
|
<li/> The full Miller executable running <code>mlr cat</code> or <code>mlr
|
|
cut</code> is slower than these bare-bones C executables — I fully
|
|
implemented Miller only in one language so there’s no apples-to-apples
|
|
comparison with other languages.
|
|
|
|
<li/> While C was the clear winner in these very simple tests, it’s quite possible
|
|
that had I committed to another language for full-featured Miller, it would have been
|
|
faster in that language. That was a gamble I did not take.
|
|
|
|
</ul>
|
|
|
|
</div>
|
|
<a id="Source_code"/><h1>Source code</h1>
|
|
<button style="font-weight:bold;color:maroon;border:0" padding=0 onclick="bodyToggler.toggle('body_section_toggle_source_code');" href="javascript:;">Toggle section visibility</button>
|
|
<div id="body_section_toggle_source_code" style="display: block">
|
|
|
|
<a id="C_cat_using_fgets"/><h2>C cat using fgets</h2>
|
|
<p/>
|
|
<div class="pokipanel">
|
|
<pre>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
// ----------------------------------------------------------------
|
|
static int do_stream(char* file_name) {
|
|
FILE* input_stream = stdin;
|
|
FILE* output_stream = stdout;
|
|
|
|
if (strcmp(file_name, "-")) {
|
|
input_stream = fopen(file_name, "r");
|
|
if (input_stream == NULL) {
|
|
perror(file_name);
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
while (1) {
|
|
char* line = NULL;
|
|
size_t linecap = 0;
|
|
ssize_t linelen = getdelim(&line, &linecap, '\n', input_stream);
|
|
if (linelen <= 0) {
|
|
break;
|
|
}
|
|
fputs(line, output_stream);
|
|
free(line);
|
|
}
|
|
if (input_stream != stdin)
|
|
fclose(input_stream);
|
|
|
|
return 1;
|
|
}
|
|
|
|
// ================================================================
|
|
int main(int argc, char** argv) {
|
|
int ok = 1;
|
|
if (argc == 1) {
|
|
ok = ok && do_stream("-");
|
|
} else {
|
|
for (int argi = 1; argi < argc; argi++) {
|
|
ok = do_stream(argv[argi]);
|
|
}
|
|
}
|
|
return ok ? 0 : 1;
|
|
}
|
|
</pre>
|
|
</div>
|
|
<p/>
|
|
|
|
<a id="C_cat_using_getdelim"/><h2>C cat using getdelim</h2>
|
|
<p/>
|
|
<div class="pokipanel">
|
|
<pre>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#define MYBUFSIZ 8192
|
|
static char iobuf[MYBUFSIZ];
|
|
|
|
// ----------------------------------------------------------------
|
|
static int do_stream(char* file_name) {
|
|
FILE* input_stream = stdin;
|
|
FILE* output_stream = stdout;
|
|
|
|
if (strcmp(file_name, "-")) {
|
|
input_stream = fopen(file_name, "r");
|
|
if (input_stream == NULL) {
|
|
perror(file_name);
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
while (1) {
|
|
char* line = fgets(iobuf, BUFSIZ, input_stream);
|
|
if (line == NULL)
|
|
break;
|
|
fputs(line, output_stream);
|
|
}
|
|
if (input_stream != stdin)
|
|
fclose(input_stream);
|
|
|
|
return 1;
|
|
}
|
|
|
|
// ================================================================
|
|
int main(int argc, char** argv) {
|
|
int ok = 1;
|
|
if (argc == 1) {
|
|
ok = ok && do_stream("-");
|
|
} else {
|
|
for (int argi = 1; argi < argc; argi++) {
|
|
ok = do_stream(argv[argi]);
|
|
}
|
|
}
|
|
return ok ? 0 : 1;
|
|
}
|
|
</pre>
|
|
</div>
|
|
<p/>
|
|
|
|
<a id="C_cat_using_mmap"/><h2>C cat using mmap</h2>
|
|
<p/>
|
|
<div class="pokipanel">
|
|
<pre>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <fcntl.h>
|
|
#include <unistd.h>
|
|
#include <sys/stat.h>
|
|
#include <sys/mman.h>
|
|
|
|
// ----------------------------------------------------------------
|
|
static void emit(char* sol, char* eol, FILE* output_stream) {
|
|
size_t ntowrite = eol - sol;
|
|
size_t nwritten = fwrite(sol, 1, ntowrite, output_stream);
|
|
if (nwritten != ntowrite) {
|
|
perror("fwrite");
|
|
exit(1);
|
|
}
|
|
}
|
|
|
|
// ----------------------------------------------------------------
|
|
static int do_stream(char* file_name) {
|
|
FILE* output_stream = stdout;
|
|
int fd = open(file_name, O_RDONLY);
|
|
if (fd < 0) {
|
|
perror("open");
|
|
exit(1);
|
|
}
|
|
struct stat stat;
|
|
if (fstat(fd, &stat) < 0) {
|
|
perror("fstat");
|
|
exit(1);
|
|
}
|
|
char* sof = mmap(NULL, (size_t)stat.st_size, PROT_READ|PROT_WRITE, MAP_FILE|MAP_PRIVATE, fd, (off_t)0);
|
|
if (sof == MAP_FAILED) {
|
|
perror("mmap");
|
|
exit(1);
|
|
}
|
|
char* eof = sof + stat.st_size;
|
|
char* sol = sof;
|
|
char* eol;
|
|
char* p = sof;
|
|
|
|
while (p < eof) {
|
|
if (*p == '\n') {
|
|
*p = 0;
|
|
eol = p;
|
|
emit(sol, eol, output_stream);
|
|
p++;
|
|
sol = p;
|
|
} else {
|
|
p++;
|
|
}
|
|
}
|
|
|
|
if (close(fd) < 0) {
|
|
perror("close");
|
|
exit(1);
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
// ================================================================
|
|
int main(int argc, char** argv) {
|
|
int ok = 1;
|
|
for (int argi = 1; argi < argc; argi++) {
|
|
ok = do_stream(argv[argi]);
|
|
}
|
|
return ok ? 0 : 1;
|
|
}
|
|
</pre>
|
|
</div>
|
|
<p/>
|
|
|
|
<a id="D_cat"/><h2>D cat</h2>
|
|
<p/>
|
|
<div class="pokipanel">
|
|
<pre>
|
|
// Reads $(D stdin) and writes it to $(D stdout).
|
|
import std.stdio;
|
|
|
|
void main()
|
|
{
|
|
string line;
|
|
while ((line = stdin.readln()) !is null)
|
|
write(line);
|
|
}
|
|
</pre>
|
|
</div>
|
|
<p/>
|
|
|
|
<a id="Rust_cat"/><h2>Rust cat</h2>
|
|
<p/>
|
|
<div class="pokipanel">
|
|
<pre>
|
|
use std::io;
|
|
use std::io::BufRead;
|
|
|
|
fn main() {
|
|
for line in io::stdin().lock().lines() {
|
|
print!("{}", line.unwrap());
|
|
}
|
|
}
|
|
</pre>
|
|
</div>
|
|
<p/>
|
|
|
|
<a id="Go_cat"/><h2>Go cat</h2>
|
|
<p/>
|
|
<div class="pokipanel">
|
|
<pre>
|
|
package main
|
|
|
|
import (
|
|
"bufio"
|
|
"io"
|
|
"log"
|
|
"os"
|
|
)
|
|
|
|
// ----------------------------------------------------------------
|
|
func main() {
|
|
args := os.Args[1:]
|
|
includeFields := []string {"a", "x"};
|
|
|
|
ok := true
|
|
if len(args) == 0 {
|
|
ok = handle("-", includeFields) && ok
|
|
} else {
|
|
for _, arg := range args {
|
|
ok = handle(arg, includeFields) && ok
|
|
}
|
|
}
|
|
if ok {
|
|
os.Exit(0)
|
|
} else {
|
|
os.Exit(1)
|
|
}
|
|
}
|
|
|
|
// ----------------------------------------------------------------
|
|
func handle(fileName string, includeFields []string) (ok bool) {
|
|
inputStream := os.Stdin
|
|
if fileName != "-" {
|
|
var err error
|
|
if inputStream, err = os.Open(fileName); err != nil {
|
|
log.Println(err)
|
|
return false
|
|
}
|
|
}
|
|
|
|
reader := bufio.NewReader(inputStream)
|
|
writer := bufio.NewWriter(os.Stdout)
|
|
eof := false
|
|
|
|
for !eof {
|
|
line, err := reader.ReadString('\n')
|
|
if err == io.EOF {
|
|
err = nil
|
|
eof = true
|
|
} else if err != nil {
|
|
log.Println(err)
|
|
if fileName != "-" {
|
|
inputStream.Close()
|
|
}
|
|
return false
|
|
} else {
|
|
writer.WriteString(line)
|
|
}
|
|
}
|
|
if fileName != "-" {
|
|
inputStream.Close()
|
|
}
|
|
writer.Flush()
|
|
|
|
return true
|
|
}
|
|
</pre>
|
|
</div>
|
|
<p/>
|
|
|
|
<a id="Nim_cat"/><h2>Nim cat</h2>
|
|
<p/>
|
|
<div class="pokipanel">
|
|
<pre>
|
|
for line in stdin.lines:
|
|
echo(line)
|
|
</pre>
|
|
</div>
|
|
<p/>
|
|
|
|
<a id="D_cut"/><h2>D cut</h2>
|
|
<p/>
|
|
<div class="pokipanel">
|
|
<pre>
|
|
// Reads $(D stdin) and writes it to $(D stdout).
|
|
// http://dlang.org/hash-map.html
|
|
import std.stdio;
|
|
import std.string;
|
|
import std.array;
|
|
|
|
void main() {
|
|
string[] includeFields = ["a", "x"];
|
|
string line;
|
|
while ((line = stdin.readln()) !is null) {
|
|
// Input string to hashmap.
|
|
string[string] oldmap;
|
|
string[] fields = split(line, ',');
|
|
foreach (field; fields) {
|
|
string[] kvps = split(field, '='); // really want splitN with max #parts = 2
|
|
oldmap[kvps[0]] = kvps[1];
|
|
}
|
|
|
|
// Hashmap-to-hashmap transform.
|
|
// Note: unordered hashmap here.
|
|
string[string] newmap;
|
|
foreach (includeField; includeFields) {
|
|
if (includeField in oldmap) {
|
|
newmap[includeField] = oldmap[includeField];
|
|
}
|
|
}
|
|
|
|
// Hashmap to output strings.
|
|
int i = 0;
|
|
foreach (key; newmap.keys) {
|
|
if (i > 0)
|
|
write(',');
|
|
write(key);
|
|
write('=');
|
|
write(newmap[key]);
|
|
i++;
|
|
}
|
|
write('\n');
|
|
}
|
|
}
|
|
</pre>
|
|
</div>
|
|
<p/>
|
|
|
|
<a id="Go_cut"/><h2>Go cut</h2>
|
|
<p/>
|
|
<div class="pokipanel">
|
|
<pre>
|
|
package main
|
|
|
|
import (
|
|
"bufio"
|
|
"io"
|
|
"log"
|
|
"os"
|
|
"strings"
|
|
)
|
|
|
|
// ----------------------------------------------------------------
|
|
func main() {
|
|
args := os.Args[1:]
|
|
includeFields := []string {"a", "x"};
|
|
|
|
ok := true
|
|
if len(args) == 0 {
|
|
ok = handle("-", includeFields) && ok
|
|
} else {
|
|
for _, arg := range args {
|
|
ok = handle(arg, includeFields) && ok
|
|
}
|
|
}
|
|
if ok {
|
|
os.Exit(0)
|
|
} else {
|
|
os.Exit(1)
|
|
}
|
|
}
|
|
|
|
// ----------------------------------------------------------------
|
|
func handle(fileName string, includeFields []string) (ok bool) {
|
|
inputStream := os.Stdin
|
|
if fileName != "-" {
|
|
var err error
|
|
if inputStream, err = os.Open(fileName); err != nil {
|
|
log.Println(err)
|
|
return false
|
|
}
|
|
}
|
|
|
|
reader := bufio.NewReader(inputStream)
|
|
writer := bufio.NewWriter(os.Stdout)
|
|
eof := false
|
|
|
|
for !eof {
|
|
line, err := reader.ReadString('\n')
|
|
if err == io.EOF {
|
|
err = nil
|
|
eof = true
|
|
} else if err != nil {
|
|
log.Println(err)
|
|
if fileName != "-" {
|
|
inputStream.Close()
|
|
}
|
|
return false
|
|
} else {
|
|
|
|
// 0.030s
|
|
|
|
// Line to map
|
|
mymap := make(map[string]string)
|
|
fields := strings.Split(line, ",");
|
|
for _, field := range(fields) {
|
|
kvps := strings.SplitN(field, "=", 2)
|
|
mymap[kvps[0]] = kvps[1]
|
|
}
|
|
// 0.220s
|
|
// delta 0.190s
|
|
// 27%
|
|
|
|
// Map-to-map transform
|
|
newmap := make(map[string]string)
|
|
for _, includeField := range(includeFields) {
|
|
value, present := mymap[includeField]
|
|
if present {
|
|
newmap[includeField] = value
|
|
}
|
|
}
|
|
// 0.280s
|
|
// delta 0.060s
|
|
// 9%
|
|
|
|
// Map to string
|
|
outs := make([]string, len(newmap))
|
|
i := 0
|
|
for k, v := range(newmap) {
|
|
outs[i] = k + "=" + v
|
|
i++
|
|
}
|
|
// 0.320s
|
|
// delta 0.040s
|
|
// 6%
|
|
|
|
out := strings.Join(outs, ",")
|
|
// 0.330s
|
|
// delta 0.010s
|
|
// 2%
|
|
|
|
// Write to output stream
|
|
//fmt.Println("")
|
|
writer.WriteString(out)
|
|
// delta 0.390s
|
|
// 56%
|
|
|
|
}
|
|
}
|
|
if fileName != "-" {
|
|
inputStream.Close()
|
|
}
|
|
writer.Flush()
|
|
|
|
return true
|
|
}
|
|
</pre>
|
|
</div>
|
|
<p/>
|
|
|
|
<a id="Nim_cut"/><h2>Nim cut</h2>
|
|
<p/>
|
|
<div class="pokipanel">
|
|
<pre>
|
|
import strutils, tables
|
|
|
|
for line in stdin.lines:
|
|
#var map: OrderedTable[string,string]
|
|
var map = {"":""}.newOrderedTable
|
|
#var map = initTable[string, string]
|
|
#var map: OrderedTable[string, string]
|
|
#var map: newOrderedTable[string, string](16)
|
|
for word in line.split(","):
|
|
var pair = word.split("=")
|
|
#echo(pair[0])
|
|
#echo(pair[1])
|
|
#echo()
|
|
#map[pair[0]] = pair[1]
|
|
map.add(pair[0], pair[1])
|
|
</pre>
|
|
</div>
|
|
<p/>
|
|
|
|
</div>
|
|
<a id="Makefile"/><h1>Makefile</h1>
|
|
<button style="font-weight:bold;color:maroon;border:0" padding=0 onclick="bodyToggler.toggle('body_section_toggle_makefile');" href="javascript:;">Toggle section visibility</button>
|
|
<div id="body_section_toggle_makefile" style="display: block">
|
|
|
|
<p/>
|
|
<div class="pokipanel">
|
|
<pre>
|
|
all: catc catc0 catm catd catrust catgo catnim cutd cutgo cutnim
|
|
allc: catc catc0 catm
|
|
|
|
catc: catc.c
|
|
gcc -Wall catc.c -o catc
|
|
catc0: catc0.c
|
|
gcc -Wall catc0.c -o catc0
|
|
catm: catm.c
|
|
gcc -Wall catm.c -o catm
|
|
catd: catd.d
|
|
dmd -O catd.d
|
|
catrust: catrust.rs
|
|
rustc catrust.rs
|
|
catgo: catgo.go
|
|
go build catgo.go
|
|
catnim: catnim.nim
|
|
nim compile catnim.nim
|
|
cutd: cutd.d
|
|
dmd -O cutd.d
|
|
cutgo: cutgo.go
|
|
go build cutgo.go
|
|
cutnim: cutnim.nim
|
|
nim compile cutnim.nim
|
|
</pre>
|
|
</div>
|
|
<p/>
|
|
|
|
</div>
|
|
<a id="Compiler_versions"/><h1>Compiler versions</h1>
|
|
<button style="font-weight:bold;color:maroon;border:0" padding=0 onclick="bodyToggler.toggle('body_section_toggle_versions');" href="javascript:;">Toggle section visibility</button>
|
|
<div id="body_section_toggle_versions" style="display: block">
|
|
|
|
<p/>
|
|
<div class="pokipanel">
|
|
<pre>
|
|
$ gcc --version
|
|
gcc (Ubuntu 7.3.0-27ubuntu1~18.04) 7.3.0
|
|
Copyright (C) 2017 Free Software Foundation, Inc.
|
|
This is free software; see the source for copying conditions. There is NO
|
|
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
|
|
$ dmd --version
|
|
DMD64 D Compiler v2.088.0
|
|
Copyright (C) 1999-2019 by The D Language Foundation, All Rights Reserved written by Walter Bright
|
|
|
|
$ rustc --version
|
|
rustc 1.36.0
|
|
|
|
$ go version
|
|
go version go1.10.4 linux/amd64
|
|
|
|
$ nim --version
|
|
Nim Compiler Version 0.17.2 (2018-02-05) [Linux: amd64]
|
|
Copyright (c) 2006-2018 by Andreas Rumpf
|
|
|
|
active boot switches: -d:release
|
|
|
|
</pre>
|
|
</div>
|
|
<p/>
|
|
|
|
|
|
</div>
|
|
<a id="Hardware"/><h1>Hardware</h1>
|
|
<button style="font-weight:bold;color:maroon;border:0" padding=0 onclick="bodyToggler.toggle('body_section_toggle_hardware');" href="javascript:;">Toggle section visibility</button>
|
|
<div id="body_section_toggle_hardware" style="display: block">
|
|
|
|
<p/>
|
|
<div class="pokipanel">
|
|
<pre>
|
|
$ uname -a
|
|
Linux sprax 4.15.0-20-generic #21-Ubuntu SMP Tue Apr 24 06:16:15 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux
|
|
|
|
$ cat /proc/cpuinfo
|
|
processor : 0
|
|
vendor_id : GenuineIntel
|
|
cpu family : 6
|
|
model : 142
|
|
model name : Intel(R) Core(TM) i7-8550U CPU @ 1.80GHz
|
|
stepping : 10
|
|
microcode : 0x96
|
|
cpu MHz : 796.615
|
|
cache size : 8192 KB
|
|
physical id : 0
|
|
siblings : 8
|
|
core id : 0
|
|
cpu cores : 4
|
|
apicid : 0
|
|
initial apicid : 0
|
|
fpu : yes
|
|
fpu_exception : yes
|
|
cpuid level : 22
|
|
wp : yes
|
|
flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat
|
|
pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp
|
|
lm constant_tsc art arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc
|
|
cpuid aperfmperf tsc_known_freq pni pclmulqdq dtes64 monitor ds_cpl vmx est tm2
|
|
ssse3 sdbg fma cx16 xtpr pdcm pcid sse4_1 sse4_2 x2apic movbe popcnt
|
|
tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch
|
|
cpuid_fault epb invpcid_single pti tpr_shadow vnmi flexpriority ept vpid
|
|
fsgsbase tsc_adjust bmi1 avx2 smep bmi2 erms invpcid mpx rdseed adx smap
|
|
clflushopt intel_pt xsaveopt xsavec xgetbv1 xsaves ibpb ibrs stibp dtherm ida
|
|
arat pln pts hwp hwp_notify hwp_act_window hwp_epp
|
|
bugs : cpu_meltdown spectre_v1 spectre_v2
|
|
bogomips : 3984.00
|
|
clflush size : 64
|
|
cache_alignment : 64
|
|
address sizes : 39 bits physical, 48 bits virtual
|
|
power management:
|
|
|
|
... (8 CPUs total)
|
|
</pre>
|
|
</div>
|
|
<p/>
|
|
|
|
</div>
|
|
|
|
<!-- ================================================================ -->
|
|
<script type="text/javascript" src="js/miller-doc-toggler.js"></script>
|
|
<!-- wtf -->
|
|
<script type="text/javascript">
|
|
// Put this at the bottom of the page since its constructor scans the
|
|
// document's div tags to find the toggleables.
|
|
const bodyToggler = new MillerDocToggler(
|
|
"body_section_toggle_",
|
|
'maroon',
|
|
'maroon',
|
|
);
|
|
</script>
|
|
|
|
</body>
|
|
</html>
|