multiple fixes:

- don’t do function copying in benchmarking
- fix the array_update benchmark
- add Filepath.file-from-path
- add tests for the `Filepath` module
- reformat a lot of documentation
This commit is contained in:
hellerve 2019-02-15 14:48:49 +01:00
parent e24fd38258
commit 9848e8fb34
11 changed files with 81 additions and 26 deletions

View File

@ -10,7 +10,7 @@
(defn some-updating []
(let-do [a (replicate n &12345)
b (aupdate a 0 inc-ref)]
b (aupdate a 0 &inc-ref)]
(assert (= (nth &b 0) &12346))
(assert (= (nth &b 1) &12345))))

View File

@ -8,7 +8,9 @@
(private min-runs)
(hidden min-runs)
(doc set-min-runs! "Set the minimum number of runs. If your functions takes a large amount of time, experimenting with this might make sense.")
(doc set-min-runs! "sets the minimum number of runs to `n`.
If your functions takes a large amount of time, experimenting with this might make sense. The default value is `50`, which means that your function runs at least `50` times before even hitting a timeout.")
(defn set-min-runs! [n]
; / 2 because we run it twice per benchmarking run,
; but this is an implementation detail
@ -36,7 +38,7 @@
(defn ns-iter-inner [f n]
(let [start (get-time-elapsed)]
(do
(for [i 0 n] (ignore (f)))
(for [i 0 n] (ignore (~f)))
(Double.- (get-time-elapsed) start))))
(private print-bench-results)
@ -55,7 +57,7 @@
samples (Array.replicate min-runs &zero)]
(do
(for [i 0 min-runs]
(Array.aset! &samples i (Double./ (ns-iter-inner @&f (Double.to-int n)) n))) ;; TODO: Get rid of '@&' here.
(Array.aset! &samples i (Double./ (ns-iter-inner f (Double.to-int n)) n)))
(Statistics.summary &(Statistics.winsorize &samples 5.0)))))
(private min-one)
@ -65,9 +67,9 @@
; it is actually possible to make this run forever by supplying a _really_
; long-running function, where long-running is everything over 30ms.
(doc bench "Benchmark function f and print the results.")
(doc bench "benchmarks the function `f` and prints the results to `stdout`.")
(defn bench [f]
(let [ns (ns-iter-inner @&f 1) ;; @& HACK, TODO: Should be able to pass the ref instead
(let [ns (ns-iter-inner &f 1)
ns-target-total 1000000.0
_n (Double./ ns-target-total (min-one ns))
n (min-one _n)
@ -77,8 +79,8 @@
(do
(while (and (Double.< total 3000000000.0) (not done))
(let [loop-start (get-time-elapsed)
summ (get-samples @&f n) ;; @& HACK, TODO: Should be able to pass the ref instead
summ5 (get-samples @&f n) ;; @& HACK, TODO: Should be able to pass the ref instead
summ (get-samples &f n)
summ5 (get-samples &f n)
loop-run (- (get-time-elapsed) loop-start)]
(if (and
(Double.> loop-run 100000.0)

View File

@ -8,7 +8,7 @@
(register from-int (Fn [Int] Char))
(register copy (Fn [&Char] Char))
(doc meaning "Convert a numerical char into the appropriate number.")
(doc meaning "converts a numerical char into the appropriate number (e.g. from `\1` to `1`).")
(defn meaning [char-ref]
(cond
(= @char-ref \0) 0
@ -26,11 +26,11 @@
(defn /= [a b]
(not (= (the Char a) b)))
(doc lower-case? "Tests whether a character is lower case.")
(doc lower-case? "tests whether a character is lower case.")
(defn lower-case? [c]
(and (<= \a c) (<= c \z)))
(doc upper-case? "Tests whether a character is upper case.")
(doc upper-case? "tests whether a character is upper case.")
(defn upper-case? [c]
(and (<= \A c) (<= c \Z)))
)

View File

@ -25,22 +25,24 @@
@"bg-cyan" @"46"
@"bg-white" @"47"})
(doc color "Generates ANSI coloration.")
(doc color "generates ANSI coloration based on a color name `cname`.")
(defn color [cname]
(let [n (Map.get &table cname)]
(String.append "\x1b[" &(String.append &n "m"))))
(doc colorize "Wraps a string in ANSI coloration and prints it.")
(doc colorize "wraps a string `s` in ANSI coloration based on a color name `cname` and prints it.
It will reset the color afterwards.")
(defn colorize [cname s]
(String.append &(color cname) &(String.append s &(color "reset"))))
)
(defmodule IO
(doc color "Sets the output color using ANSI.")
(doc color "sets the output color using ANSI coloration based on a color name `cname`.")
(defn color [cname]
(print &(Color.color cname)))
(doc colorize "Wraps a string in ANSI coloration and prints it.")
(doc colorize "wraps a string in ANSI coloration based on a color name `cname` and prints it.")
(defn colorize [cname s]
(print &(Color.colorize cname s)))
)

View File

@ -2,7 +2,9 @@
(defmodule Debug
(doc sanitize-addresses "Instruct the compiler to sanitize addresses.")
(doc sanitize-addresses "instructs the compiler to sanitize addresses.
This might not work on all compilers, but reasonably new versions of GCC and Clang are supported.")
(defdynamic sanitize-addresses []
(add-cflag "-fsanitize=address"))
@ -10,14 +12,14 @@
(register reset-memory-balance! (Fn [] ()))
(register log-memory-balance! (Fn [Bool] ()))
(doc memory-logged "Log all calls to memory allocation within te form. Requires compiling with --log-memory.")
(doc memory-logged "logs all calls to memory allocation within the form. Requires the flag `--log-memory` to be passed during compilation.")
(defmacro memory-logged [form]
(list 'do
'(Debug.log-memory-balance! true)
form
'(Debug.log-memory-balance! false)))
(doc assert-balanced "Raises an error if the memory balance (numberr of alloc:s - number of free:s) isn't 0. Requires compiling with --log-memory.")
(doc assert-balanced "raises an error if the memory balance (number of `alloc`s - number of `free`s) isn't `0`. Requires the flag `--log-memory` to be passed durng compilation.")
(defmacro assert-balanced [form]
(list 'let '[balance (Debug.memory-balance)]
(list 'do
@ -29,14 +31,14 @@
(System.exit 1)))
())))
(doc trace "Print the value of an expression to stdout, then return its value.")
(doc trace "prints the value of an expression to `stdout`, then returns its value.")
(defmacro trace [x]
(list 'let-do (array 'tmp x)
(list 'IO.println (list 'ref (list 'fmt "%s:%d:%d: %s" (file x) (line x) (column x) '&(str tmp))))
'tmp)
)
(doc leak-array "Leak some memory. Useful for testing tools that detect leaks.")
(doc leak-array "leaks some memory. This function is useful for testing tools that detect leaks.")
(register leak-array (Fn [a] ()) "Debug_leak_MINUS_array")
)

View File

@ -49,7 +49,9 @@
min
val)))
(doc approx "checks whether x and y are approximately (i.e. margin of error of 0.00001) equal")
(doc approx "checks whether `x` and `y` are approximately equal.
The margin of error is `0.00001`.")
(defn approx [x y]
(if (> x y)
(< (- x y) 0.00001)
@ -58,6 +60,7 @@
(defn /= [x y]
(not (Double.= x y)))
(doc zero "returns the value `0.0`.")
(defn zero []
0.0)

View File

@ -2,11 +2,17 @@
(use Array)
(doc dir-from-path "Removes the file-name part of a path to a file.")
(doc dir-from-path "removes the file name part of a path to a file, similar to the `basename` utility in Shell scripting.")
(defn dir-from-path [path]
(let [segments (split-by path &[\/])
n (dec (length &segments))
without-last (prefix-array &segments n)]
(concat &(copy-map &(fn [s] (str* s "/")) &without-last))))
(doc file-from-path "removes the base name part of a path to a file, similar to the `filename` utility in Shell scripting.")
(defn file-from-path [path]
(let [segments (split-by path &[\/])]
; this is actually safe here, because split by will return an array of
; length > 0
(unsafe-last &segments)))
)

View File

@ -25,7 +25,9 @@
min
val)))
(doc approx "checks whether x and y are approximately (i.e. margin of error of 0.00001) equal")
(doc approx "checks whether `x` and `y` are approximately equal.
The margin of error is 0.00001.")
(defn approx [x y]
(if (> x y)
(< (- x y) 0.00001f)
@ -55,6 +57,7 @@
(register copy (Fn [(Ref Float)] Float))
(register abs (Fn [Float] Float))
(doc zero "returns `0.0f`.")
(defn zero []
0.0f)

View File

@ -23,6 +23,6 @@
(fmt-internal (String.substring s (+ (inc idx) next) len)
(cdr args)))))))))))
(doc fmt "fmt formats a string. It supports all of the string interpolations defined in format of the type that should be interpolated (e.g. %d and %x on integers).")
(doc fmt "formats a string. It supports all of the string interpolations defined in format of the type that should be interpolated (e.g. %d and %x on integers).")
(defmacro fmt [s :rest args]
(fmt-internal s args))

View File

@ -1,9 +1,9 @@
(defmodule Geometry
(doc degree-to-radians "Converts degrees expressed as a double into radians.")
(doc degree-to-radians "converts degrees expressed as a double `n` into radians.")
(defn degree-to-radians [n]
(Double.* n (Double./ Double.pi 180.0)))
(doc radians-to-degree "Converts radians expressed as a double into degree.")
(doc radians-to-degree "converts radians expressed as a double `n` into degrees.")
(defn radians-to-degree [n]
(Double.* n (Double./ 180.0 Double.pi)))
)

37
test/filepath.carp Normal file
View File

@ -0,0 +1,37 @@
(load "Filepath.carp")
(load "Test.carp")
(use-all Test Filepath)
(deftest test
(assert-equal test
"test.h"
&(file-from-path "/an/absolute/path/for/test.h")
"file-from-path works with non-empty paths"
)
(assert-equal test
"."
&(file-from-path ".")
"file-from-path works with relative paths"
)
(assert-equal test
""
&(file-from-path "")
"file-from-path works with empty paths"
)
(assert-equal test
"/an/absolute/path/for/"
&(dir-from-path "/an/absolute/path/for/test.h")
"dir-from-path works with non-empty paths"
)
(assert-equal test
""
&(dir-from-path ".")
"dir-from-path works with relative paths"
)
(assert-equal test
""
&(dir-from-path "")
"dir-from-path works with empty paths"
)
)