Skip to main content

Command Palette

Search for a command to run...

Day 20 of 30-Day .NET Challenge: Task vs. ValueTask

Heap allocations aren’t entirely bad but when an object is allocated on a heap it contributes to the garbage collection cycles which in turn reduces o

Published
2 min read
Day 20 of 30-Day .NET Challenge: Task vs. ValueTask
S

Hi there 👋 I'm Sukhpinder Singh, a passionate self-taught .Net developer from India. Worked on 10+ projects for SQL database design. Developed and maintained over 20 .NET websites with 100% client satisfaction.

Skills C# | Microsoft Certified | Medium Blogger | .Net Core | Xamarin | ASP.Net | Angular


Introduction

One approach to optimize resource usage in async code is by using ValueTask<TResult> syntax to minimize heap allocations, which in turn reduces pressure on garbage collection and enhances overall performance.

Learning Objectives

  • The Problem with Heap Allocations

  • Optimizing with ValueTask<TResult>

  • When to Use ValueTask<TResult>

Prerequisites for Developers

  • Basic understanding of C# programming language.

Getting Started

Heap allocations aren’t entirely bad but when an object is allocated on a heap it contributes to the garbage collection cycles which in turn reduces overall application performance. In case of excessive heap allocation, the garbage collector can lead to GC pauses.

Bad Practice: Excessive Use of Task<TResult>

Let’s consider a common asynchronous pattern that developers commonly use:

public async Task<string> ReadDataAsync()
{
    var data = await ReadFromStreamAsync(_stream);
    return ProcessData(data);
}

If the above-mentioned method is called more frequently, each request results in a new Task instance being allocated on heap memory. Over time, it leads to increased garbage collection overhead.

Optimizing with ValueTask<TResult>

By changing the return type from Task<TResult> to ValueTask<TResult>, we can reduce heap allocations

public async ValueTask<string> ReadDataAsync()
{
    var data = await ReadFromStreamAsync(_stream);
    return ProcessData(data);
}

The aforementioned optimization is beneficial for high-frequency async operations or methods which are expected to complete synchronously in a significant portion of time.

When to Use ValueTask<TResult>

  • High-frequency methods

  • Performance-sensitive code

  • Methods that often complete synchronously

Create another class named TaskVsValueTask and add the following code snippet

public static class TaskVsValueTask
{
    public static async Task<string> FetchDataAsync()
    {
        // Simulate a delay to mimic fetching data
        await Task.Delay(1000);
        return "Data fetched using Task";
    }

    public static async ValueTask<string> FetchDataValueTaskAsync()
    {
        // Simulate a delay to mimic fetching data
        await Task.Delay(1000); // Note: Use Task.Delay for the sake of example.
        return "Data fetched using ValueTask";
    }
}

Execute from the main method as follows

#region Day 20: Task vs. Value Task
static async Task<string> ExecuteDay20()
{
    Console.WriteLine("Fetching data with Task...");
    string result = await TaskVsValueTask.FetchDataAsync();
    Console.WriteLine(result);

    Console.WriteLine("Fetching data with ValueTask...");
    string resultValueTask = await TaskVsValueTask.FetchDataValueTaskAsync();
    Console.WriteLine(resultValueTask);

    return "Executed Day 20 successfully..!!";
}
#endregion

Console Output

Fetching data with Task...
Data fetched using Task
Fetching data with ValueTask...
Data fetched using ValueTask

Complete Code on GitHub

GitHub — ssukhpinder/30DayChallenge.Net
Contribute to ssukhpinder/30DayChallenge.Net development by creating an account on GitHub.github.com


C# Programming🚀

Thank you for being a part of the C# community! Before you leave:

Follow us: Youtube | X | LinkedIn | Dev.to
Visit our other platforms: GitHub
More content at C# Programming

30 Day C# Challenge

Part 11 of 30

The series consists of a 30-day code challenge where I'll be diving deep into a different C# concept every single day. 🌟 I'll also be sharing my learnings and insights through engaging articles.

Up next

Day 19 of 30-Day .NET Challenge: Stack vs. Heap Allocation

The article demonstrates the idea of memory allocations to be used for vibrant and high-performance applications.