Jattac.Libs.Profiling
1.0.4
dotnet add package Jattac.Libs.Profiling --version 1.0.4
NuGet\Install-Package Jattac.Libs.Profiling -Version 1.0.4
<PackageReference Include="Jattac.Libs.Profiling" Version="1.0.4" />
<PackageVersion Include="Jattac.Libs.Profiling" Version="1.0.4" />
<PackageReference Include="Jattac.Libs.Profiling" />
paket add Jattac.Libs.Profiling --version 1.0.4
#r "nuget: Jattac.Libs.Profiling, 1.0.4"
#:package Jattac.Libs.Profiling@1.0.4
#addin nuget:?package=Jattac.Libs.Profiling&version=1.0.4
#tool nuget:?package=Jattac.Libs.Profiling&version=1.0.4
Jattac.Libs.Profiling
A lightweight, dependency-injection-friendly library for profiling method execution times in .NET applications using a dynamic proxy and attributes.
This tool allows you to non-invasively measure the performance of specific methods or entire classes with minimal configuration.
Features
- Automatic Service Discovery: Scans your assemblies to find and register services for profiling with a single command.
- Flexible Attribute-Based Control: Add an attribute to interfaces, classes, or methods to control profiling.
- DI Integration: Easily registers profiled services with your
IServiceCollection
. - Async Support: Seamlessly profiles both synchronous and asynchronous (Task-based) methods.
- Configuration-Based: Enable or disable profiling globally via your
appsettings.json
file. - Detailed Summaries: Provides clear console logs, including execution time summaries and a list of the slowest calls for each service instance.
Getting Started
Follow these steps to integrate the execution time profiler into your .NET application.
1. Install the NuGet Package
Install the package from NuGet using the .NET CLI or the NuGet Package Manager.
.NET CLI:
dotnet add package Jattac.Libs.Profiling
Package Manager Console:
Install-Package Jattac.Libs.Profiling
2. Apply the Attribute
To mark services for profiling, add the [MeasureExecutionTime]
attribute. You can place it on an interface, a class, or an individual method.
Example:
using Jattac.Libs.Profiling;
// You can place the attribute on the interface...
[MeasureExecutionTime(logSummary: true)]
public interface IMyService
{
void DoWork();
[MeasureExecutionTime(logSummary: false)] // Or on a specific method
Task DoSpecificWorkAsync();
}
// ...or you can place it on the class.
[MeasureExecutionTime(trackSlowest: true)]
public class MyOtherService : IMyOtherService
{
//...
}
logSummary: true
: Generates a summary table of all calls for the service instance when it's disposed.trackSlowest: true
: Keeps track of the slowest method calls for the service instance.
3. Configure Your Application
Add a section to your appsettings.json
file to control the profiler's behavior.
{
"ExecutionTime": {
"EnableTiming": true,
"UseCultureFormatting": true
}
}
EnableTiming: true
: Profiling is enabled. Set tofalse
to disable all profiling, which removes any performance overhead.UseCultureFormatting: true
: Numbers in the summary tables are formatted with thousand separators for readability (e.g.,1,000
). Set tofalse
to output raw, unformatted numbers (e.g.,1000
), which can be easier for some log parsers to ingest.
4. Configure Your Services
In your application's startup file (e.g., Program.cs
), use the AddProfiledServices
extension method to automatically find and register all the services you marked with the attribute.
Example in Program.cs
(.NET 6+):
using Jattac.Libs.Profiling;
var builder = WebApplication.CreateBuilder(args);
// Automatically find and register all services marked for profiling
// in the current assembly.
builder.Services.AddProfiledServices(builder.Configuration);
// ... other services
var app = builder.Build();
The AddProfiledServices
method will discover any service where the interface or the implementation class has the [MeasureExecutionTime]
attribute.
Manual Registration
If you prefer to register services manually, you can still use the ProfileScoped
method.
builder.Services.ProfileScoped<IMyManualService, MyManualService>(builder.Configuration);
Example Output
When your application runs and the profiled methods are called, you will see output in the console.
Individual Method Log
14:25:10.152: Method MyService.DoWork took 52 ms
14:25:10.355: Method MyService.DoSpecificWorkAsync took 201 ms
Slowest Calls Summary
Top Execution Times (Slowest):
-----------------------------
| MyService.DoSpecificWorkAsync | 201 ms |
| MyService.DoWork | 52 ms |
-----------------------------
Execution Summary
Execution Summary:
-------------------------------------------
| Method Name | Count | Avg ms | Min ms | Max ms |
-------------------------------------------
| MyService.DoSpecificWorkAsync | 1 | 201 ms | 201 ms | 201 ms |
| MyService.DoWork | 1 | 52 ms | 52 ms | 52 ms |
-------------------------------------------
Limitations
Please be aware of the following limitations when using this library:
No Private Method Profiling: The proxy-based approach can only intercept calls to public methods on a service's interface. It cannot profile private, protected, or internal methods. For this, a more advanced, runtime-level profiler (like those in Visual Studio) is required.
Scoped Lifetime Only: All services registered by this library (both automatically and manually) are forced into a Scoped lifetime. Singleton and Transient lifetimes are not supported.
One-to-One Mapping for Auto-Discovery: The
AddProfiledServices()
auto-discovery feature is designed for scenarios where there is a one-to-one mapping between an interface and its implementation. If you have an interface with multiple implementations, you must use manual registration for each one.Performance Overhead: While lightweight, the proxying mechanism does introduce a small amount of performance overhead for each profiled method call. We strongly recommend using the
EnableTiming: false
configuration in performance-sensitive production environments.
Advanced Notes & Important Behaviors
Please be aware of the following behaviors to ensure the library works as expected in your application.
Dependency Injection: Attribute Wins
If the auto-discovery feature finds a service marked for profiling, it will overwrite any existing manual registration for that service. This is an intentional design choice, as the [MeasureExecutionTime]
attribute is treated as the definitive source of truth.
Attribute Placement and Precedence
The library is flexible about where you place the [MeasureExecutionTime]
attribute. Here is the order of precedence:
- For enabling profiling on all methods of a service: An attribute on the class takes precedence over an attribute on the interface.
- For profiling a specific method: An attribute on either the class method or the interface method will cause it to be profiled (if profiling isn't already enabled for the whole class).
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net8.0
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.