Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

EventHub EventSource remove allocations and boxing #26989

Merged
merged 12 commits into from
Feb 23, 2022
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
<ApiCompatVersion>5.6.2</ApiCompatVersion>
<PackageTags>Azure;Event Hubs;EventHubs;.NET;Event Processor;EventProcessor;$(PackageCommonTags)</PackageTags>
<TargetFrameworks>$(RequiredTargetFrameworks)</TargetFrameworks>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>

<ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

using System;
using System.Diagnostics.Tracing;
using System.Runtime.CompilerServices;
using Azure.Core.Diagnostics;

namespace Azure.Messaging.EventHubs.Processor.Diagnostics
Expand Down Expand Up @@ -396,9 +398,9 @@ public virtual void InvalidCheckpointFound(string partitionId,
///
[Event(36, Level = EventLevel.Verbose, Message = "Starting to retrieve checkpoint for FullyQualifiedNamespace: '{0}'; EventHubName: '{1}'; ConsumerGroup: '{2}'; PartitionId: '{3}'.")]
public virtual void GetCheckpointStart(string fullyQualifiedNamespace,
string eventHubName,
string consumerGroup,
string partitionId)
string eventHubName,
danielmarbach marked this conversation as resolved.
Show resolved Hide resolved
string consumerGroup,
string partitionId)
{
if (IsEnabled())
{
Expand All @@ -417,9 +419,9 @@ public virtual void GetCheckpointStart(string fullyQualifiedNamespace,
///
[Event(37, Level = EventLevel.Verbose, Message = "Completed retrieving checkpoint for FullyQualifiedNamespace: '{0}'; EventHubName: '{1}'; ConsumerGroup: '{2}'. PartitionId: '{3}'.")]
public virtual void GetCheckpointComplete(string fullyQualifiedNamespace,
string eventHubName,
string consumerGroup,
string partitionId)
string eventHubName,
string consumerGroup,
string partitionId)
{
if (IsEnabled())
{
Expand All @@ -439,15 +441,173 @@ public virtual void GetCheckpointComplete(string fullyQualifiedNamespace,
///
[Event(38, Level = EventLevel.Error, Message = "An exception occurred when retrieving checkpoint for FullyQualifiedNamespace: '{0}'; EventHubName: '{1}'; ConsumerGroup: '{2}'; PartitionId: '{3}'; ErrorMessage: '{4}'.")]
public virtual void GetCheckpointError(string fullyQualifiedNamespace,
string eventHubName,
string consumerGroup,
string partitionId,
string errorMessage)
string eventHubName,
string consumerGroup,
string partitionId,
string errorMessage)
{
if (IsEnabled())
{
WriteEvent(38, fullyQualifiedNamespace ?? string.Empty, eventHubName ?? string.Empty, consumerGroup ?? string.Empty, partitionId ?? string.Empty, errorMessage ?? string.Empty);
}
}

/// <summary>
/// Writes an event with three string arguments and a value type into a stack allocated
/// <see cref="EventData"/> struct to avoid the parameter array allocation on the WriteEvent methods.
/// </summary>
/// <param name="eventId">The event identifier.</param>
/// <param name="arg1">The first argument.</param>
/// <param name="arg2">The second argument.</param>
/// <param name="arg3">The third argument.</param>
/// <param name="arg4">The fourth argument.</param>
[NonEvent]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private unsafe void WriteEvent<TValue1>(int eventId, string arg1, string arg2, string arg3, TValue1 arg4)
where TValue1 : struct
{
fixed (char* arg1Ptr = arg1)
fixed (char* arg2Ptr = arg2)
fixed (char* arg3Ptr = arg3)
{
var eventPayload = stackalloc EventData[4];

eventPayload[0].Size = (arg1.Length + 1) * sizeof(char);
eventPayload[0].DataPointer = (IntPtr)arg1Ptr;

eventPayload[1].Size = (arg2.Length + 1) * sizeof(char);
eventPayload[1].DataPointer = (IntPtr)arg2Ptr;

eventPayload[2].Size = (arg3.Length + 1) * sizeof(char);
eventPayload[2].DataPointer = (IntPtr)arg3Ptr;

eventPayload[3].Size = Unsafe.SizeOf<TValue1>();
eventPayload[3].DataPointer = (IntPtr)Unsafe.AsPointer(ref arg4);

WriteEventCore(eventId, 4, eventPayload);
}
}

/// <summary>
/// Writes an event with four string arguments into a stack allocated <see cref="EventData"/> struct to avoid
/// the parameter array allocation on the WriteEvent methods.
/// </summary>
/// <param name="eventId">The event identifier.</param>
/// <param name="arg1">The first argument.</param>
/// <param name="arg2">The second argument.</param>
/// <param name="arg3">The third argument.</param>
/// <param name="arg4">The fourth argument.</param>
[NonEvent]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private unsafe void WriteEvent(int eventId, string arg1, string arg2, string arg3, string arg4)
{
fixed (char* arg1Ptr = arg1)
fixed (char* arg2Ptr = arg2)
fixed (char* arg3Ptr = arg3)
fixed (char* arg4Ptr = arg4)
{
var eventPayload = stackalloc EventData[4];

eventPayload[0].Size = (arg1.Length + 1) * sizeof(char);
eventPayload[0].DataPointer = (IntPtr)arg1Ptr;

eventPayload[1].Size = (arg2.Length + 1) * sizeof(char);
eventPayload[1].DataPointer = (IntPtr)arg2Ptr;

eventPayload[2].Size = (arg3.Length + 1) * sizeof(char);
eventPayload[2].DataPointer = (IntPtr)arg3Ptr;

eventPayload[3].Size = (arg4.Length + 1) * sizeof(char);
eventPayload[3].DataPointer = (IntPtr)arg4Ptr;

WriteEventCore(eventId, 4, eventPayload);
}
}

/// <summary>
/// Writes an event with five string arguments into a stack allocated <see cref="EventData"/> struct to avoid
/// the parameter array allocation on the WriteEvent methods.
/// </summary>
/// <param name="eventId">The event identifier.</param>
/// <param name="arg1">The first argument.</param>
/// <param name="arg2">The second argument.</param>
/// <param name="arg3">The third argument.</param>
/// <param name="arg4">The fourth argument.</param>
/// <param name="arg5">The fifth argument.</param>
[NonEvent]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private unsafe void WriteEvent(int eventId, string arg1, string arg2, string arg3, string arg4, string arg5)
{
fixed (char* arg1Ptr = arg1)
fixed (char* arg2Ptr = arg2)
fixed (char* arg3Ptr = arg3)
fixed (char* arg4Ptr = arg4)
fixed (char* arg5Ptr = arg5)
{
var eventPayload = stackalloc EventData[5];

eventPayload[0].Size = (arg1.Length + 1) * sizeof(char);
eventPayload[0].DataPointer = (IntPtr)arg1Ptr;

eventPayload[1].Size = (arg2.Length + 1) * sizeof(char);
eventPayload[1].DataPointer = (IntPtr)arg2Ptr;

eventPayload[2].Size = (arg3.Length + 1) * sizeof(char);
eventPayload[2].DataPointer = (IntPtr)arg3Ptr;

eventPayload[3].Size = (arg4.Length + 1) * sizeof(char);
eventPayload[3].DataPointer = (IntPtr)arg4Ptr;

eventPayload[4].Size = (arg5.Length + 1) * sizeof(char);
eventPayload[4].DataPointer = (IntPtr)arg5Ptr;

WriteEventCore(eventId, 5, eventPayload);
}
}

/// <summary>
/// Writes an event with six string arguments into a stack allocated <see cref="EventData"/> struct to avoid
/// the parameter array allocation on the WriteEvent methods.
/// </summary>
/// <param name="eventId">The event identifier.</param>
/// <param name="arg1">The first argument.</param>
/// <param name="arg2">The second argument.</param>
/// <param name="arg3">The third argument.</param>
/// <param name="arg4">The fourth argument.</param>
/// <param name="arg5">The fifth argument.</param>
/// <param name="arg6">The sixth argument.</param>
[NonEvent]
danielmarbach marked this conversation as resolved.
Show resolved Hide resolved
private unsafe void WriteEvent(int eventId, string arg1, string arg2, string arg3, string arg4, string arg5, string arg6)
{
fixed (char* arg1Ptr = arg1)
fixed (char* arg2Ptr = arg2)
fixed (char* arg3Ptr = arg3)
fixed (char* arg4Ptr = arg4)
fixed (char* arg5Ptr = arg5)
fixed (char* arg6Ptr = arg6)
{
var eventPayload = stackalloc EventData[6];

eventPayload[0].Size = (arg1.Length + 1) * sizeof(char);
eventPayload[0].DataPointer = (IntPtr)arg1Ptr;

eventPayload[1].Size = (arg2.Length + 1) * sizeof(char);
eventPayload[1].DataPointer = (IntPtr)arg2Ptr;

eventPayload[2].Size = (arg3.Length + 1) * sizeof(char);
eventPayload[2].DataPointer = (IntPtr)arg3Ptr;

eventPayload[3].Size = (arg4.Length + 1) * sizeof(char);
eventPayload[3].DataPointer = (IntPtr)arg4Ptr;

eventPayload[4].Size = (arg5.Length + 1) * sizeof(char);
eventPayload[4].DataPointer = (IntPtr)arg5Ptr;

eventPayload[5].Size = (arg6.Length + 1) * sizeof(char);
eventPayload[5].DataPointer = (IntPtr)arg6Ptr;

WriteEventCore(eventId, 6, eventPayload);
}
}
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

using System;
using System.Diagnostics.Tracing;
using System.Runtime.CompilerServices;
using Azure.Core.Diagnostics;

namespace Azure.Messaging.EventHubs.Processor.Diagnostics
Expand Down Expand Up @@ -188,5 +190,82 @@ public virtual void ValidationCleanupError(string identifier,
WriteEvent(26, identifier ?? string.Empty, eventHubName ?? string.Empty, consumerGroup ?? string.Empty, errorMessage ?? string.Empty);
}
}

/// <summary>
/// Writes an event with four string arguments into a stack allocated <see cref="EventData"/> struct to avoid
/// the parameter array allocation on the WriteEvent methods.
/// </summary>
/// <param name="eventId">The event identifier.</param>
/// <param name="arg1">The first argument.</param>
/// <param name="arg2">The second argument.</param>
/// <param name="arg3">The third argument.</param>
/// <param name="arg4">The fourth argument.</param>
[NonEvent]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private unsafe void WriteEvent(int eventId, string arg1, string arg2, string arg3, string arg4)
danielmarbach marked this conversation as resolved.
Show resolved Hide resolved
{
fixed (char* arg1Ptr = arg1)
fixed (char* arg2Ptr = arg2)
fixed (char* arg3Ptr = arg3)
fixed (char* arg4Ptr = arg4)
{
var eventPayload = stackalloc EventData[4];

eventPayload[0].Size = (arg1.Length + 1) * sizeof(char);
eventPayload[0].DataPointer = (IntPtr)arg1Ptr;

eventPayload[1].Size = (arg2.Length + 1) * sizeof(char);
eventPayload[1].DataPointer = (IntPtr)arg2Ptr;

eventPayload[2].Size = (arg3.Length + 1) * sizeof(char);
eventPayload[2].DataPointer = (IntPtr)arg3Ptr;

eventPayload[3].Size = (arg4.Length + 1) * sizeof(char);
eventPayload[3].DataPointer = (IntPtr)arg4Ptr;

WriteEventCore(eventId, 4, eventPayload);
}
}

/// <summary>
/// Writes an event with five string arguments into a stack allocated <see cref="EventData"/> struct to avoid
/// the parameter array allocation on the WriteEvent methods.
/// </summary>
/// <param name="eventId">The event identifier.</param>
/// <param name="arg1">The first argument.</param>
/// <param name="arg2">The second argument.</param>
/// <param name="arg3">The third argument.</param>
/// <param name="arg4">The fourth argument.</param>
/// <param name="arg5">The fifth argument.</param>
[NonEvent]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private unsafe void WriteEvent(int eventId, string arg1, string arg2, string arg3, string arg4, string arg5)
{
fixed (char* arg1Ptr = arg1)
fixed (char* arg2Ptr = arg2)
fixed (char* arg3Ptr = arg3)
fixed (char* arg4Ptr = arg4)
fixed (char* arg5Ptr = arg5)
{
var eventPayload = stackalloc EventData[5];

eventPayload[0].Size = (arg1.Length + 1) * sizeof(char);
eventPayload[0].DataPointer = (IntPtr)arg1Ptr;

eventPayload[1].Size = (arg2.Length + 1) * sizeof(char);
eventPayload[1].DataPointer = (IntPtr)arg2Ptr;

eventPayload[2].Size = (arg3.Length + 1) * sizeof(char);
eventPayload[2].DataPointer = (IntPtr)arg3Ptr;

eventPayload[3].Size = (arg4.Length + 1) * sizeof(char);
eventPayload[3].DataPointer = (IntPtr)arg4Ptr;

eventPayload[4].Size = (arg5.Length + 1) * sizeof(char);
eventPayload[4].DataPointer = (IntPtr)arg5Ptr;

WriteEventCore(eventId, 5, eventPayload);
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
<ApiCompatVersion>5.6.2</ApiCompatVersion>
<PackageTags>Azure;Event Hubs;EventHubs;.NET;AMQP;IoT;$(PackageCommonTags)</PackageTags>
<TargetFrameworks>$(RequiredTargetFrameworks)</TargetFrameworks>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>

<ItemGroup>
Expand Down
Loading