Skip to content

feat: add BenchmarkDotNet performance benchmarks#17

Merged
teesofttech merged 1 commit into
masterfrom
feat/issue-12-benchmarks
Jun 23, 2026
Merged

feat: add BenchmarkDotNet performance benchmarks#17
teesofttech merged 1 commit into
masterfrom
feat/issue-12-benchmarks

Conversation

@teesofttech

@teesofttech teesofttech commented Jun 15, 2026

Copy link
Copy Markdown
Owner

Closes #12

Summary

  • Adds CronCraft.Benchmarks/ as a new console project using BenchmarkDotNet 0.14.0
  • Project registered in CronCraft.sln
  • README updated with run instructions and a sample results table

Benchmark scenarios (9 total)

Benchmark Expression
Simple */5 * * * *
With day list 0 */2 * * 1,2,3,4,5
With day-of-month 0 4 27 */6 ?
Quartz 6-part 0 15 10 * * ?
Quartz 7-part 0 0 12 1/1 * ? *
With timezone 30 14 * * * + WCAST
Spanish 0 9 * * 1 (es)
French 0 9 * * 1 (fr)
Day-of-month + weekday 0 23 15 * 1

[MemoryDiagnoser] is enabled so allocation counts appear alongside timing.
[ShortRunJob] keeps local runs fast — remove it for full statistical precision.

How to run

cd CronCraft.Benchmarks
dotnet run -c Release -- --filter *

# Run a single benchmark by name
dotnet run -c Release -- --filter *Simple*

Test plan

  • dotnet build CronCraft.sln --configuration Release — succeeds, 0 warnings
  • All 18 existing tests continue to pass

Summary by CodeRabbit

  • New Features

    • Added a performance benchmarking suite to measure cron expression conversion speed across multiple scenarios, including various cron formats, localization options, and timezone handling.
  • Documentation

    • Added instructions on running performance benchmarks with sample results included in the README.

Closes #12

- Add CronCraft.Benchmarks/ console project targeting net8.0 with BenchmarkDotNet 0.14.0
- 9 benchmark scenarios: simple, day-list, day-of-month, Quartz 6-part, Quartz 7-part,
  timezone, Spanish, French, and combined day-of-month+weekday
- [MemoryDiagnoser] tracks allocations alongside timing
- [ShortRunJob] keeps local runs fast; remove for full CI-grade precision
- Project added to CronCraft.sln
- README updated with run instructions and sample results table

Run with: cd CronCraft.Benchmarks && dotnet run -c Release -- --filter *

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings June 15, 2026 14:44
@coderabbitai

coderabbitai Bot commented Jun 15, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

A new CronCraft.Benchmarks console project is added, using BenchmarkDotNet 0.14.0 to benchmark ToHumanReadable across nine cron expression scenarios including simple, Quartz, timezone-aware, and localized (Spanish/French) variants. The solution file is updated to register the project and add x64/x86 platform configurations. The README receives a new "Performance Benchmarks" section.

Changes

BenchmarkDotNet Benchmarks Project

Layer / File(s) Summary
Benchmark project setup and implementation
CronCraft.Benchmarks/CronCraft.Benchmarks.csproj, CronCraft.Benchmarks/CronHelperBenchmarks.cs
CronCraft.Benchmarks.csproj targets net8.0 as an executable with BenchmarkDotNet 0.14.0 and a CronCraft project reference. CronHelperBenchmarks configures memory diagnostics and a short-run job, initializes CronSettings instances for Spanish and French locales plus a cached TimeZoneInfo in Setup(), and defines nine [Benchmark] methods covering simple, day-list, day-of-month, Quartz 6-part, Quartz 7-part, timezone-aware, Spanish, French, and combined day-of-month/weekday cron expressions.
Solution wiring and README documentation
CronCraft.sln, README.md
The solution registers CronCraft.Benchmarks with its GUID and extends SolutionConfigurationPlatforms and ProjectConfigurationPlatforms to include x64/x86 mappings for all projects. The README adds a "Performance Benchmarks" section with dotnet run commands and a sample results table.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Poem

🐇 Hop, hop, benchmark time has come,
Nine cron expressions, let the timers hum!
Spanish and French, and Quartz parts galore,
A README now tells you how to explore.
The rabbit watches nanoseconds fly,
Performance measured — my, oh my! 🕐

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title 'feat: add BenchmarkDotNet performance benchmarks' clearly and concisely describes the main change: adding a new benchmarking project using BenchmarkDotNet.
Linked Issues check ✅ Passed The PR meets all coding requirements from issue #12: implements 9 benchmark scenarios covering all required types, uses BenchmarkDotNet correctly with memory diagnostics, adds the new project to the solution, and updates README with instructions.
Out of Scope Changes check ✅ Passed All changes are directly related to issue #12 objectives: new benchmarks project, benchmark implementations, solution file integration, and README documentation updates.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/issue-12-benchmarks

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a new BenchmarkDotNet-based benchmarks console project to the CronCraft solution to measure ToHumanReadable performance across multiple cron expression variants and locales, and documents how to run those benchmarks.

Changes:

  • Introduces CronCraft.Benchmarks project with 9 benchmark scenarios and BenchmarkDotNet configuration attributes.
  • Registers the new benchmarks project in CronCraft.sln.
  • Updates README.md with benchmark run instructions and sample output.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 4 comments.

File Description
README.md Adds benchmark documentation (run instructions + sample results).
CronCraft.sln Adds the benchmarks project to the solution (and new solution platform configs).
CronCraft.Benchmarks/CronHelperBenchmarks.cs Adds the BenchmarkDotNet entrypoint and benchmark scenarios.
CronCraft.Benchmarks/CronCraft.Benchmarks.csproj Adds the new benchmarks console project and BenchmarkDotNet package reference.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

using CronCraft.Extensions;
using CronCraft.Models;

BenchmarkRunner.Run<CronHelperBenchmarks>();
{
_settings = new CronSettings { Language = "en", DayNameFormat = "short" };

_timeZone = TimeZoneInfo.FindSystemTimeZoneById("W. Central Africa Standard Time");
Comment on lines +3 to +9
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
Comment thread CronCraft.sln
Comment on lines 15 to +21
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|Any CPU = Release|Any CPU
Release|x64 = Release|x64
Release|x86 = Release|x86

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@CronCraft.Benchmarks/CronHelperBenchmarks.cs`:
- Line 23: The benchmark setup uses TimeZoneInfo.FindSystemTimeZoneById with a
Windows-specific timezone ID that may fail on non-Windows systems without ICU
support, causing TimeZoneNotFoundException and breaking the benchmark on
contributor machines. Create a helper method (e.g., TryResolveTimeZone) that
attempts to resolve the timezone ID but includes try-catch error handling for
TimeZoneNotFoundException and InvalidTimeZoneException, with a fallback to
TimeZoneInfo.Utc if resolution fails. Then replace the direct
FindSystemTimeZoneById call with a call to this new helper method to ensure the
benchmark setup succeeds across all environments.

In `@README.md`:
- Around line 114-115: The unquoted wildcard `*` in the dotnet filter commands
on lines 114 and 127 will be expanded by the shell before dotnet receives them,
causing unexpected filtering behavior. Quote the wildcard filter argument in
both locations to prevent shell glob expansion: change `--filter *` to `--filter
"*"` on line 114 and similarly on line 127 so the literal asterisk is passed to
dotnet as intended.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 9a3f7486-f5ee-42ce-a6ec-8fad689e1cbd

📥 Commits

Reviewing files that changed from the base of the PR and between 4610fbe and 0a07342.

📒 Files selected for processing (4)
  • CronCraft.Benchmarks/CronCraft.Benchmarks.csproj
  • CronCraft.Benchmarks/CronHelperBenchmarks.cs
  • CronCraft.sln
  • README.md

{
_settings = new CronSettings { Language = "en", DayNameFormat = "short" };

_timeZone = TimeZoneInfo.FindSystemTimeZoneById("W. Central Africa Standard Time");

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

fd -t f "CronHelperBenchmarks.cs" --exec cat -n {}

Repository: teesofttech/CronCraft

Length of output: 2834


🌐 Web query:

.NET TimeZoneInfo FindSystemTimeZoneById Windows timezone ID non-Windows platforms cross-platform IANA

💡 Result:

In.NET 6 and later, the TimeZoneInfo.FindSystemTimeZoneById method provides cross-platform support for both Windows time zone IDs (e.g., "Pacific Standard Time") and IANA time zone IDs (e.g., "America/Los_Angeles") regardless of the underlying operating system [1][2][3]. Key details regarding this functionality include: Integration and Requirements The runtime achieves this by leveraging the ICU (International Components for Unicode) library [1][4]. For this cross-platform resolution to function, the environment must have ICU support enabled [4]. On Windows, this requires that the application not be running in globalization invariant mode and that NLS (National Language Support) is not enabled [1][4]. On Linux-based environments (such as Docker containers), ensure the necessary time zone data (often provided by the tzdata package) is installed, as some minimal images may not include it by default [5]. Behavior When you call FindSystemTimeZoneById with an ID, the method attempts to resolve the identifier using the available system provider [1][3]. If the runtime detects an ID that does not match the native format of the host OS, it can automatically perform the necessary conversion to resolve the time zone correctly [5][3]. This eliminates the need for manual mapping or third-party conversion libraries in many modern applications [6][7]. Compatibility Note While.NET 6+ simplified this process, older versions of.NET (such as.NET Framework or early.NET Core versions) did not support cross-platform ID resolution [8][9]. In those environments, developers were required to either manually handle the differences using conditional logic or use community libraries like TimeZoneConverter to map between Windows and IANA identifiers [5][6][10]. For applications targeting.NET 6+, you can generally use either ID format with confidence, provided your environment is correctly configured with ICU support [1][4]. If you encounter issues in specific deployments, verifying that the host system has the required ICU and timezone data installed is the recommended first step [4][5].

Citations:


🏁 Script executed:

find . -name "*.csproj" -o -name "*.fsproj" | grep -i benchmark | head -5 | xargs cat

Repository: teesofttech/CronCraft

Length of output: 545


Add error handling for timezone resolution to ensure benchmark portability.

Line 23 uses a Windows timezone ID that requires proper environment configuration (ICU support and timezone data) to work cross-platform with .NET 8. While .NET 8 can resolve Windows IDs on non-Windows systems, environments without ICU or timezone data will fail with TimeZoneNotFoundException. Add a try-catch fallback or attempt alternative IDs to ensure the benchmark setup succeeds across all contributor environments.

Suggested patch
-        _timeZone = TimeZoneInfo.FindSystemTimeZoneById("W. Central Africa Standard Time");
+        _timeZone = TryResolveTimeZone("W. Central Africa Standard Time", "Africa/Lagos");
private static TimeZoneInfo TryResolveTimeZone(params string[] ids)
{
    foreach (var id in ids)
    {
        try { return TimeZoneInfo.FindSystemTimeZoneById(id); }
        catch (TimeZoneNotFoundException) { }
        catch (InvalidTimeZoneException) { }
    }
    return TimeZoneInfo.Utc;
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@CronCraft.Benchmarks/CronHelperBenchmarks.cs` at line 23, The benchmark setup
uses TimeZoneInfo.FindSystemTimeZoneById with a Windows-specific timezone ID
that may fail on non-Windows systems without ICU support, causing
TimeZoneNotFoundException and breaking the benchmark on contributor machines.
Create a helper method (e.g., TryResolveTimeZone) that attempts to resolve the
timezone ID but includes try-catch error handling for TimeZoneNotFoundException
and InvalidTimeZoneException, with a fallback to TimeZoneInfo.Utc if resolution
fails. Then replace the direct FindSystemTimeZoneById call with a call to this
new helper method to ensure the benchmark setup succeeds across all
environments.

Comment thread README.md
Comment on lines +114 to +115
dotnet run -c Release -- --filter *
```

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Quote benchmark filter wildcards to avoid shell glob expansion.

The commands on Line 114 and Line 127 use unquoted *; shells may expand these before dotnet receives them, causing unexpected filtering behavior.

Suggested patch
-dotnet run -c Release -- --filter *
+dotnet run -c Release -- --filter "*"
...
-> Tip: add `--filter *Simple*` to run a single benchmark by name.
+> Tip: add `--filter "*Simple*"` to run a single benchmark by name.

Also applies to: 127-127

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@README.md` around lines 114 - 115, The unquoted wildcard `*` in the dotnet
filter commands on lines 114 and 127 will be expanded by the shell before dotnet
receives them, causing unexpected filtering behavior. Quote the wildcard filter
argument in both locations to prevent shell glob expansion: change `--filter *`
to `--filter "*"` on line 114 and similarly on line 127 so the literal asterisk
is passed to dotnet as intended.

@teesofttech
teesofttech merged commit 525173b into master Jun 23, 2026
4 checks passed
@github-actions

Copy link
Copy Markdown

🎉 Thank you for your contribution!

This PR was included in CronCraft v1.0.6 and is now live on NuGet for everyone to use. We really appreciate the time and effort you put in — it makes the library better for the whole community! 🚀

dotnet add package CronCraft --version 1.0.6

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add performance benchmarks using BenchmarkDotNet

2 participants