# A micro-benchmark

**URL:** <https://racket.discourse.group/t/a-micro-benchmark/2347>\
**Category:** General\
**Created:** [September 28, 2023, 5:08pm UTC](https://racket.discourse.group/t/a-micro-benchmark/2347 "2023-09-28T17:08:30Z")\
**Posts on this page:** 9\
**Page:** 4

<div class="post-metadata">

**Author:** ![soegaard](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/soegaard/32/19_2.png) [@soegaard](https://racket.discourse.group/u/soegaard)\
**Post date:** [October 9, 2023, 9:30pm UTC](https://racket.discourse.group/t/a-micro-benchmark/2347/61 "2023-10-09T21:30:45Z")

</div>

> I haven't studied macros yet.  
> What makes these things macros?

In "vector-wraps.rkt. you will see:

```scheme
(define-syntax-rule (define-vector-wraps <pattern> ...) <template>)

```

This defines `define-vector-wraps` as a macro.

In this case the macro is defined using a "rule".  
When `define-vector-wraps` is used, the expander matches the macro call to the patterns.  
It then constructs the code in the template by substituting syntax from the patterns.

In this case the pattern is rather long, since it consists of definitions of quite a few functions and macros. In the case of `f64vector` we get definitions of `in-fXvector, unsafe-f64vector-copy!, for/f64vector, for*/f64vector, f64vector-copy`.

---

<div class="post-metadata">

**Author:** ![shawnw](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/shawnw/32/1031_2.png) [@shawnw](https://racket.discourse.group/u/shawnw)\
**Post date:** [October 9, 2023, 9:51pm UTC](https://racket.discourse.group/t/a-micro-benchmark/2347/62 "2023-10-09T21:51:43Z")

</div>

As already mentioned, in my `extra-srfi-libs` package.

```plaintext
raco pkg install extra-srfi-libs

```

or the equivalent in the DrRacket package manager window to install.

---

<div class="post-metadata">

**Author:** ![lewisl](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/lewisl/32/1321_2.png) [@lewisl](https://racket.discourse.group/u/lewisl)\
**Post date:** [October 9, 2023, 10:00pm UTC](https://racket.discourse.group/t/a-micro-benchmark/2347/63 "2023-10-09T22:00:55Z")

</div>

should that have been `(define-vector-wraps "f64vector")`?

---

<div class="post-metadata">

**Author:** ![soegaard](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/soegaard/32/19_2.png) [@soegaard](https://racket.discourse.group/u/soegaard)\
**Post date:** [October 9, 2023, 10:07pm UTC](https://racket.discourse.group/t/a-micro-benchmark/2347/64 "2023-10-09T22:07:41Z")

</div>

> [@soegaard](#):
>
> `"f64lvector"`

Yes! The "f64lvector" ought to be "f64vector". I think the string is used in error messages.

---

<div class="post-metadata">

**Author:** ![countvajhula](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/countvajhula/32/65_2.png) [@countvajhula](https://racket.discourse.group/u/countvajhula)\
**Post date:** [October 11, 2023, 8:04pm UTC](https://racket.discourse.group/t/a-micro-benchmark/2347/65 "2023-10-11T20:04:03Z")

</div>

(I haven't followed this thread in detail so apologies if this has been covered)

If you can implement [`gen:sequence`](https://docs.racket-lang.org/collections/collections-api.html#%28part._.Sequences%29) for the data structure, you can use the Generic Collections library's [`in`](https://docs.racket-lang.org/collections/collections-api.html#%28def._%28%28lib._data%2Fcollection..rkt%29._in%29%29) and other generic sequence utilities provided there. For built-in Racket data structures that aren't already supported, it may be necessary to submit a pull request to the library to add a [default implementation](https://github.com/lexi-lambda/racket-collections/blob/c4822fc200b0488922cd6e86b4f2ea7cf8c565da/collections-lib/data/collection/collection.rkt#L213).

---

<div class="post-metadata">

**Author:** ![countvajhula](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/countvajhula/32/65_2.png) [@countvajhula](https://racket.discourse.group/u/countvajhula)\
**Post date:** [October 11, 2023, 8:09pm UTC](https://racket.discourse.group/t/a-micro-benchmark/2347/66 "2023-10-11T20:09:14Z")

</div>

This looks great. I submitted a request to [support in-VM benchmarking](https://github.com/sharkdp/hyperfine/issues/571) to hyperfine some time back, but they decided it was out of scope for the project. It'll be nice to have a visualization tool like this in Racket as @soegaard said.

---

<div class="post-metadata">

**Author:** ![rogert](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/rogert/32/2474_2.png) [@rogert](https://racket.discourse.group/u/rogert)\
**Post date:** [October 12, 2023, 4:26pm UTC](https://racket.discourse.group/t/a-micro-benchmark/2347/67 "2023-10-12T16:26:44Z")

</div>

Prompted by @sschwarzer's questions:

> [@sschwarzer](#):
>
> - How fast is _idiomatic_ code, without any optimizations? ...
> - How fast can I make the code if I have to and what effort is needed for that?

...I produced some variants in ChezScheme (Racket's backend). My idiomatic baseline is `flvector-sum`:

> <https://github.com/rogerturner/A-micro-benchmark/blob/main/flvector-bench.ss#L20-35>

The [fl.vector library](https://github.com/rogerturner/A-micro-benchmark/blob/main/fl.vector.ss) implements simple lazy allocation and manual loop unrolling, with `fl.vector-sum` and `fl*vector-sum` variants. Sample timings:

```
*Version* *Timings in seconds for 1000 executions*
baseline .19
unroll make .14
unroll sum .12
unroll both .07
fl. +unroll .07
fl. "lazy" .000007

```

(all produce the correct result 😉 )

---

<div class="post-metadata">

**Author:** ![Zeb](https://avatars.discourse-cdn.com/v4/letter/z/57b2e6/32.png) [@Zeb](https://racket.discourse.group/u/Zeb)\
**Post date:** [October 13, 2023, 3:28am UTC](https://racket.discourse.group/t/a-micro-benchmark/2347/68 "2023-10-13T03:28:55Z")

</div>

Why is the lazy result so much faster than anything else we've seen so far?

---

<div class="post-metadata">

**Author:** ![rogert](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/rogert/32/2474_2.png) [@rogert](https://racket.discourse.group/u/rogert)\
**Post date:** [October 13, 2023, 9:59am UTC](https://racket.discourse.group/t/a-micro-benchmark/2347/69 "2023-10-13T09:59:53Z")

</div>

The conventional Scheme to allocate a vector is `(make-vector length fill)`;  
the [fl.vector library](https://github.com/rogerturner/A-micro-benchmark/blob/main/fl.vector.ss) just saves `length` and `fill`, so `fl.vector-sum` can produce the sum by multiplication:

> <https://github.com/rogerturner/A-micro-benchmark/blob/main/fl.vector.ss#L24>

Allocation of the 800Kb vector is in `fl.vector-set!`; some sample stats in flvector-bench:

> <https://github.com/rogerturner/A-micro-benchmark/blob/main/flvector-bench.ss#L104>

...show 800Mb total memory allocation (as expected), but 32Kb for the "lazy" run.

fl.vector contains versions of the basic vector procedures (-ref, -length, etc), which  
should produce correct results for either flvector or fl.vector arguments.

It may be worth noting that the ChezScheme compiler (and hence Racket) can inline  
procedures from a user library, so uses are comparable in execution to standard library procedures.

[Previous page](https://racket.discourse.group/t/a-micro-benchmark/2347.md?page=3)
