.NET Fiddle

CSharp · Console

/Program.cs

using System;
using System.Threading;
using System.Threading.Tasks;

public static class Program
{
    static async Task Main()
    {
        await TestAsync("Using Task<object>", true, TaskLoop);
        await TestAsync("Using ValueTask<object>", true, ValueTaskLoop);
        await TestAsync("Using Task<object>", false, TaskLoop);
        await TestAsync("Using ValueTask<object>", false, ValueTaskLoop);
    }

    static async Task TestAsync(string title, bool asynchronous,
        Func<bool, CancellationToken, Task<int>> loop)
    {
        GC.Collect();
        long mem0 = GC.GetTotalAllocatedBytes(true);
        var cts = new CancellationTokenSource(1000);
        int count = await loop(asynchronous, cts.Token);
        long mem1 = GC.GetTotalAllocatedBytes(true);
        Console.WriteLine($"{title} - " + 
            (asynchronous ? "Asynchronous" : "Synchronous") + " completion");
        Console.WriteLine($"- Loops: {count:#,0}");
        Console.WriteLine($"- Allocations: {mem1 - mem0:#,0} bytes");
        double perLoop = (mem1 - mem0) / (double)count;
        Console.WriteLine($"- Allocations per loop: {perLoop:#,0} bytes");
        Console.WriteLine();
    }

    static async Task<object> TaskOne(bool asynchronous)
    {
        if (asynchronous) await Task.Yield();
        return new object();
    }

    static async ValueTask<object> ValueTaskOne(bool asynchronous)
    {
        if (asynchronous) await Task.Yield();
        return new object();
    }

    static async Task<int> TaskLoop(bool asynchronous, CancellationToken token)
    {
        int count = 0;
        while (!token.IsCancellationRequested)
        {
            var result = await TaskOne(asynchronous);
            count++;
            if (result == null) break; // Make sure that the result is not optimized out
        }
        return count;
    }

    static async Task<int> ValueTaskLoop(bool asynchronous, CancellationToken token)
    {
        int count = 0;
        while (!token.IsCancellationRequested)
        {
            var result = await ValueTaskOne(asynchronous);
            count++;
            if (result == null) break; // Make sure that the result is not optimized out
        }
        return count;
    }
}
;