Benchmarking
The benchmarking codebase in this project is designed to understand and compare the performance of Value Objects, a specific approach to representing data in code. The primary motivation is to assess whether Value Objects, which emphasize immutability and strong type checking, offer performance advantages compared to traditional approaches that use primitive types.
Benchmarking Approach
Benchmarking Scenarios
The code focuses on two fundamental scenarios:
- Domain Logic: Benchmarking the performance of Value Objects when used within the business logic (domain) of an application.
- Infrastructure Logic: Benchmarking the performance of Value Objects when used within the infrastructure layer, such as data persistence or networking.
Testing Value Objects
The benchmarks test the performance of Value Objects in scenarios involving different types of data:
- Integers: Benchmarks are executed with Value Objects containing integers, like
Vo_int_1
,Vo_int_2
, etc. These Value Objects vary in complexity, ranging from simple structures to more elaborate compositions. - Doubles: Similar to integers, the benchmarks test the performance of Value Objects that hold double-precision floating-point numbers (
Vo_double_1
,Vo_double_2
, etc.). - Strings: Benchmarks are performed with Value Objects that store string values (
Vo_string_1
,Vo_string_2
, etc.).
Benchmarking Configuration
The benchmarks are configured to assess performance across various aspects:
- Memory Usage: The
MemoryDiagnoser
attribute is used to analyze the memory consumption of each benchmark scenario. - Native Memory Profiling: The
NativeMemoryProfiler
attribute helps to track and analyze native memory allocation and usage, providing insights into the memory footprint of the code.
Example Benchmarks:
UsingPrimitivesInDomain
: Benchmarks the performance of an example domain using primitive types (e.g.,int
,double
,string
).UsingValueObjectsInDomain
: Benchmarks the performance of an example domain using Value Objects.UsingPrimitivesInInfrastructure
: Benchmarks the performance of example infrastructure code using primitive types.UsingValueObjectsInInfrastructure
: Benchmarks the performance of example infrastructure code using Value Objects.
Benchmarking Implementation
The BenchmarkRunner
class from the BenchmarkDotNet library is used to execute and analyze the benchmarks.
Running the Benchmarks:
- The
Program.cs
file executes the benchmarks usingBenchmarkRunner.Run()
. - The benchmarks are run multiple times to ensure accurate and statistically significant results.
Example Domain & Infrastructure Logic:
- ExampleDomainUsingValueObjects: Demonstrates the use of Value Objects within a domain model (e.g., a
Customer
class using aCustomerId
Value Object). - ExampleInfrastructureUsingValueObjects: Demonstrates the use of Value Objects within infrastructure code (e.g., a database repository working with Value Objects).
Performance Metrics:
The benchmarks are designed to collect metrics like:
- Time Taken: Measures the duration of the benchmark operations.
- Memory Allocation: Records the memory usage during the benchmark execution.
- Native Memory Allocation: Identifies native memory allocation events and usage.
- Other Relevant Metrics: Other metrics specific to the benchmark scenarios may be collected.
Analysis:
The benchmark results are analyzed to compare the performance of Value Objects with the use of primitive types in both domain and infrastructure scenarios. The metrics collected help to understand the tradeoffs and potential benefits of using Value Objects in terms of performance and memory consumption.
Example Code Snippets:
// Program.cs
BenchmarkRunner.Run();
// Benchmarks.cs
[Benchmark]
public void UsingValueObjectsInDomain()
{
new ExampleDomainUsingValueObjects().Run();
}
// ExampleDomainUsingValueObjects.cs
internal class ExampleDomainUsingValueObjects
{
List _list = new List(1_000_000);
internal void Run()
{
for (int i = 0; i < 1000; i++)
{
_list.Add(new Customer { CustomerId = CustomerId.From(i) });
}
}
}
Top-Level Directory Explanations
tests/ - This directory contains unit tests for the StringlyTyped library. It includes benchmark tests and small tests.