question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Benchmark setup and caching of repeated operations

See original GitHub issue

I’m developing a library where an operation might be performed once or multiple times. I’d like to benchmark how long setup takes as well as how much caching might speed up subsequent operations.

For example, say I wanted to investigate the performance of compiled vs static regular expressions.

What I’d like is to be able to do the following:

        [Benchmark]
        public IEnumerable<Action> Regex_Match_Compiled()
        {
            string value;
            var regex = new Regex("[ ](.*)!", RegexOptions.Compiled);
            for (int i = 0; i < 3; i++)
            {
                yield return () => value = regex.Match("Hello, World!").Groups[1].Value;
            }
        }

        [Benchmark]
        public IEnumerable<Action> Regex_Match_Static()
        {
            string value;
            for (int i = 0; i < 3; i++)
            {
                yield return () => value = Regex.Match("Hello, World!", "[ ](.*)!").Groups[1].Value;
            }
        }
Method Median StdDev
Regex_Match_Compiled(1) 1,035,622.7664 ns 21,349.3871 ns
Regex_Match_Compiled(2) 10234.7148 ns 60,138.4160 ns
Regex_Match_Compiled(3) 10640.9544 ns 21,160.7904 ns
Regex_Match_Static(1) 943.3168 ns 29.4935 ns
Regex_Match_Static(2) 948.445 ns 67.2509 ns
Regex_Match_Static(3) 798.6434 ns 19.6410 ns

At the moment, I could do something like this:

        [Benchmark]
        public void Regex_Match_Compiled_1()
        {
            Execute(Regex_Match_Compiled(1));
        }

        [Benchmark]
        public void Regex_Match_Compiled_2()
        {
            Execute(Regex_Match_Compiled(2));
        }

        [Benchmark]
        public void Regex_Match_Compiled_3()
        {
            Execute(Regex_Match_Compiled(3));
        }

        [Benchmark]
        public void Regex_Match_Static_1()
        {
            Execute(Regex_Match_Static(1));
        }

        [Benchmark]
        public void Regex_Match_Static_2()
        {
            Execute(Regex_Match_Static(2));
        }

        [Benchmark]
        public void Regex_Match_Static_3()
        {
            Execute(Regex_Match_Static(3));
        }

        static void Execute(IEnumerable<Action> actions)
        {
            foreach(var action in actions)
            {
                action();
            }
        }

        public IEnumerable<Action> Regex_Match_Compiled(int n)
        {
            string value;
            var regex = new Regex("[ ](.*)!", RegexOptions.Compiled);
            for (int i = 0; i < n; i++)
            {
                yield return () => value = regex.Match("Hello, World!").Groups[1].Value;
            }
        }

        public IEnumerable<Action> Regex_Match_Static(int n)
        {
            string value;
            for (int i = 0; i < n; i++)
            {
                yield return () => value = Regex.Match("Hello, World!", "[ ](.*)!").Groups[1].Value;
            }
        }
Method Median StdDev
Regex_Match_Compiled_1 1,035,622.7664 ns 21,349.3871 ns
Regex_Match_Compiled_2 1,045,857.4812 ns 60,138.4160 ns
Regex_Match_Compiled_3 1,056,498.4356 ns 21,160.7904 ns
Regex_Match_Static_1 943.3168 ns 29.4935 ns
Regex_Match_Static_2 1,891.7618 ns 67.2509 ns
Regex_Match_Static_3 2,690.4052 ns 19.6410 ns

It’s not pretty and I have to subtract the results to see how long a single operation takes.

Does that make sense or is there already some way to do this?

Issue Analytics

  • State:closed
  • Created 7 years ago
  • Comments:7 (4 by maintainers)

github_iconTop GitHub Comments

2reactions
adamsitnikcommented, Sep 20, 2016

I think my confusion has been because [Setup] doesn’t behave as someone who is used to NUnit would expect. It isn’t called before each [Benchmark] method, but is a one-time-setup that is called even before the warm-up iterations. This means that any caching done by the [Benchmark] methods is lost during warm-up.

@jcansdale I have just added extra explanation to Setup and Cleanup attribute summary to avoid confusion in the future. Thanks for the input!

0reactions
jcansdalecommented, Sep 20, 2016

It looks like the regex is parsed and the source gets prepared when the Regex is constructed. When Match gets called it looks in a cache for a compiled assembly (keyed off the source + parameters). Compilation only happens if it can’t find anything in the cache. That’s what I think is going on - the Regex source is pretty hairy. 😉

Read more comments on GitHub >

github_iconTop Results From Across the Web

Java Caching Benchmarks 2016 - Part 1 - cruftex.net
The first benchmark is about inserting entries in the cache. The run variants are: The number of entries inserted and the number of...
Read more >
How to benchmark software performance under same ...
Record PC state ( RAM, CPU temp, Disk type, cache etc. ) Reboot PC; Run program A; Record time take to run, file...
Read more >
How to Write Accurate Benchmarks in Go | by Teiva Harsanyi
The benchmark time is set by default to 1 second and can be ... a repeatedly called CPU-bound function, CPU caching may come...
Read more >
Java Caching – Benchmarks
The benchmarks are designed to highlight differences between caching implementations. We keep interpretations of the results sparse and only comment on effects ...
Read more >
benchmark/docs/user_guide.md at main · google/benchmark
In multithreaded benchmarks, each counter is set on the calling thread only. When the benchmark finishes, the counters from each thread will be...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found