Created
August 8, 2014 06:23
-
-
Save bogen/e41e2ca5e197279659bc to your computer and use it in GitHub Desktop.
echo that will handle embedded nuls
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
See https://github.com/Araq/Nimrod/issues/1137 (nimecho0 and nimecho1 echo strings with embedded nuls) | |
$ nimrod c -x:off --opt:speed --deadCodeElim:on --stackTrace:off --lineTrace:off nimecho.nim | |
$ ./nimecho 0 > /dev/null | |
using nimecho0 | |
1.8825269999999998e+00 seconds elapsed | |
1.8825269999999999e-06 seconds per iteration | |
string used: some very long string some very long string some very long string some very long string some very long string some very long string | |
$ ./nimecho 1 > /dev/null | |
using nimecho1 (smallest code) | |
2.2058490000000002e+00 seconds elapsed | |
2.2058490000000000e-06 seconds per iteration | |
string used: some very long string some very long string some very long string some very long string some very long string some very long string | |
$ ./nimecho e > /dev/null | |
using original echo | |
9.7179199999999999e-01 seconds elapsed | |
9.7179199999999994e-07 seconds per iteration | |
string used: some very long string some very long string some very long string some very long string some very long string some very long string | |
$ ./nimecho 3 | |
some very long string some very long string some very long string some very long string some very long string some very long string 1235.5999999999999996e+00 | |
some very long string some very long string some very long string some very long string some very long string some very long string 1235.5999999999999996e+00 | |
some very long string some very long string some very long string some very long string some very long string some very long string 1235.5999999999999996e+00 | |
nulltest | |
nulltest | |
----------------------------------------- | |
My vote is for nimecho1 even though it is the slowest, because it is simplest code |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import os, strutils, times | |
let argv = commandLineParams() | |
proc nimecho0 (a: varargs[string, `$`]) {.compilerProc.} = | |
# declare external c functions. Use ints for pointers to avoid casting | |
proc c_fwrite (buf: int, size, n: int, f: TFile) {.importc: "fwrite", noDecl.} | |
proc c_memcpy (a: int, b: cstring, size: int) {.importc: "memcpy", noDecl.} | |
proc c_alloca (n: int): int {.importc: "alloca", noDecl.} | |
var size : int = 1 # reserve space for trailing newline | |
for i in 0..a.len-1: size += a [i].len # add sum of string lengths | |
let dst0 = c_alloca (size) # allocate output buffer on the stack | |
var dst = dst0 # point to the start of the buffer | |
for i in 0..a.len-1: # for all strings to be displayed | |
c_memcpy (dst, a [i], a [i].len) # append string to the output buffer | |
dst += a [i].len # advance to the end of the buffer | |
c_memcpy (dst, "\n", 1) # append the trailing newline | |
c_fwrite (dst0, size, 1, stdout) # write the buffer to standard out | |
proc nimecho1 (a: varargs[string, `$`]) = | |
# join strings and append new line | |
let buffer = join (a) & "\n"; | |
# write the buffer to standard out | |
discard writeBuffer (stdout, cstring (buffer), buffer.len); | |
proc test () = | |
const testString = "some very long string some very long string some very long string some very long string some very long string some very long string " | |
proc usenimecho1 () = nimecho1 testString, 1, 2, 3, 5.6 | |
proc useorigecho () = echo testString, 1, 2, 3, 5.6 | |
proc usenimecho0 () = nimecho0 testString, 1, 2, 3, 5.6 | |
var testecho = usenimecho1 | |
if argv.len > 0: | |
if argv [0][0] == 'e': | |
writeln stderr, "using original echo" | |
testecho = useorigecho | |
if argv [0][0] == '0': | |
writeln stderr, "using nimecho0" | |
testecho = usenimecho0 | |
if argv [0][0] == '1': | |
writeln stderr, "using nimecho1 (smallest code)" | |
testecho = usenimecho1 | |
if argv [0][0] == '3': | |
useorigecho () | |
usenimecho1 () | |
usenimecho0 () | |
nimecho0 () | |
nimecho1 () | |
nimecho0 ("null\0test") | |
nimecho1 ("null\0test") | |
return | |
const loops = 1_000_000 | |
let start = cpuTime () | |
for i in 1..loops: testecho () | |
let finish = cpuTime () | |
let elapsed = finish-start | |
writeln stderr, elapsed, " seconds elapsed" | |
writeln stderr, elapsed/float (loops), " seconds per iteration" | |
writeln stderr, "string used: ", testString | |
test () |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment