Add semaphore example to PerformanceBenchmarks.

This commit is contained in:
sebastianburckhardt 2023-04-04 15:00:17 -07:00
Родитель 985cf72e2b
Коммит aa0740f35e
2 изменённых файлов: 138 добавлений и 0 удалений

Просмотреть файл

@ -0,0 +1,49 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
namespace PerformanceTests.HelloCities
{
using System;
using System.IO;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using System.Collections.Generic;
using Microsoft.Azure.WebJobs.Extensions.DurableTask;
using System.Linq;
using System.Collections.Concurrent;
using System.Threading;
/// <summary>
/// A simple microbenchmark orchestration that some trivial activities in a sequence.
/// </summary>
public static class SemaphoreHttpTriggers
{
[FunctionName(nameof(SemaphoreOrchestration))]
public static async Task<IActionResult> SemaphoreOrchestration(
[HttpTrigger(AuthorizationLevel.Anonymous, "get")] HttpRequest req,
[DurableClient] IDurableClient client,
ILogger log)
{
// start the orchestration
string orchestrationInstanceId = await client.StartNewAsync("OrchestrationWithSemaphore");
// wait for it to complete and return the result
return await client.WaitForCompletionOrCreateCheckStatusResponseAsync(req, orchestrationInstanceId, TimeSpan.FromSeconds(400));
}
[FunctionName(nameof(Semaphore))]
public static async Task<IActionResult> Semaphore(
[HttpTrigger(AuthorizationLevel.Anonymous, "get")] HttpRequest req,
[DurableClient] IDurableClient client,
ILogger log)
{
var response = await client.ReadEntityStateAsync<SemaphoreTest.SemaphoreEntity>(new EntityId("SemaphoreEntity", "MySemaphoreInstance"));
return new OkObjectResult(response);
}
}
}

Просмотреть файл

@ -0,0 +1,89 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
namespace PerformanceTests.HelloCities
{
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Threading;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.DurableTask;
using Microsoft.Extensions.Logging;
/// <summary>
/// A simple microbenchmark orchestration that executes several simple "hello" activities in a sequence.
/// </summary>
public static partial class SemaphoreTest
{
[FunctionName("OrchestrationWithSemaphore")]
public static async Task<string> OrchestrationWithSemaphore([OrchestrationTrigger] IDurableOrchestrationContext context)
{
EntityId semaphore = new EntityId("SemaphoreEntity", "MySemaphoreInstance");
Guid requestId = context.NewGuid();
DateTime startTime = context.CurrentUtcDateTime;
TimeSpan timeOut = TimeSpan.FromMinutes(5);
try
{
while (true)
{
if (await context.CallEntityAsync<bool>(semaphore, "TryAcquire", requestId))
{
break; // we have acquired the semaphore
}
if (context.CurrentUtcDateTime > startTime + timeOut)
{
throw new Exception("timed out while waiting for semaphore");
}
else
{
await context.CreateTimer(context.CurrentUtcDateTime + TimeSpan.FromSeconds(1), CancellationToken.None);
}
}
await context.CallActivityAsync("ActivityThatRequiresSemaphore", null);
return "Completed successfully.";
}
finally
{
context.SignalEntity(semaphore, "Release", requestId);
}
}
[FunctionName("SemaphoreEntity")]
public static Task Run([EntityTrigger] IDurableEntityContext ctx)
=> ctx.DispatchAsync<SemaphoreEntity>();
public class SemaphoreEntity
{
public List<Guid> Requests { get; set; } = new List<Guid>();
public int MaxCount { get; set; } = 50;
public bool TryAcquire(Guid id)
{
int position = this.Requests.IndexOf(id);
if (position == -1)
{
this.Requests.Add(id);
position = this.Requests.Count - 1;
}
return (position < this.MaxCount);
}
public void Release(Guid id)
{
this.Requests.Remove(id);
}
}
[FunctionName("ActivityThatRequiresSemaphore")]
public static Task ActivityThatRequiresSemaphore([ActivityTrigger] IDurableActivityContext context, ILogger logger)
{
logger.LogInformation("Entering");
Thread.Sleep(100);
logger.LogInformation("Exiting");
return Task.CompletedTask;
}
}
}