CSC367 NET Centric Computing

NET Centric ComputingUnit 107 min read

Async/Await, Performance Tuning & Real-World Web Speed

Unit 10 of NET Centric Computing explores asynchronous programming in C (async/await), its architecture, performance optimization techniques, and real-world impacts on web apps—with examples from Nepalese platforms like eSewa and Daraz.

TAKEAWAYS:

  • Async/await enables non-blocking I/O operations, improving scalability for web apps handling thousands of requests (e.g., Daraz’s order processing).
  • The Task class and async/await keywords replace callback hell with sequential-looking code that runs concurrently.
  • Performance bottlenecks in web apps (CPU-bound vs. I/O-bound) require different optimization strategies (e.g., async DB queries vs. parallel loops).
  • Real-world examples: eSewa’s payment processing uses async to handle simultaneous transactions; YouTube’s video streaming relies on async to buffer chunks without freezing.
  • Common pitfalls include deadlocks (e.g., ConfigureAwait(false)) and improper cancellation token usage.
  • Optimization techniques like caching (Redis) and async I/O reduce server load by 40–60% in high-traffic apps.

Core Concepts: Why Async Matters in Web Apps

1. Blocking vs. Non-Blocking I/O: The CPU’s Dilemma

Web servers spend 90% of their time waiting for I/O operations (database queries, file reads, API calls). Traditional synchronous code blocks the thread while waiting, wasting CPU cycles. Async programming lets threads handle other requests instead.

flowchart TD
    A["Synchronous Code\n(Blocking)"] -->|"Thread waits"| B["CPU Idle\n(No work)"]
    C["Asynchronous Code\n(Non-Boking)"] -->|"Thread freed"| D["CPU Handles\nOther Requests"]
    B -->|"Wasted cycles"| E["Slow Response"]
    D -->|"Faster throughput"| F["Handles 1000+ req/sec"]

2. The Task Class: The Backbone of Async

The Task<T> class represents an asynchronous operation. It can be in one of 5 states:

  • Created: Initialized but not started.
  • WaitingForActivation: Scheduled but not running.
  • Running: Executing.
  • WaitingForCompletion: Awaited but not finished.
  • RanToCompletion: Done successfully (or faulted/canceled).
// Example: Async file read
Task<string> fileTask = Task.Run(() => File.ReadAllTextAsync("data.txt"));
string content = await fileTask; // Non-blocking wait

Why Task?

  • Composition: Combine multiple Tasks with Task.WhenAll().
  • Cancellation: Use CancellationToken to abort long-running ops.
  • Error Handling: try-catch works with await (exceptions propagate).

3. Async/Await Syntax: How It Works Under the Hood

When you write await, the compiler:

  1. Suspends the method until the Task completes.
  2. Yields the thread back to the thread pool.
  3. Resumes execution when the Task finishes.
sequenceDiagram
    participant Thread as Main Thread
    participant Task as Async Task
    Thread->>Task: Start File.ReadAsync()
    Task-->>Thread: Yield (non-blocking)
    Thread->>Other: Handle other requests
    Task-->>Thread: Complete (data ready)
    Thread->>Task: Resume & process data

Key Rules:

  • Only async methods can use await.
  • await can only be used inside async methods.
  • No async void (except event handlers)—it breaks error handling.

Real-World Applications in Nepalese Tech

1. eSewa: Handling 10,000+ Transactions/Second

  • Problem: Synchronous payment processing would freeze the server during peak hours (e.g., Dashain/Tihar).
  • Solution: Async I/O for:
    • Database writes (SQL queries).
    • Third-party API calls (e.g., Ncell/Khalti gateways).
    • File logging (transaction records).
  • Result: eSewa processes ~12,000 transactions/minute without timeouts.

2. Daraz: Order Queue Optimization

  • Problem: During sales (e.g., 11.11), synchronous order processing caused 500+ms delays.
  • Solution: Async pipeline:
    flowchart LR
      A["User Clicks Buy"] --> B["Async Order Validation"]
      B --> C["Async Inventory Check"]
      C --> D["Async Payment Processing"]
      D --> E["Async Email/SMS"]
      E --> F["User Sees 'Order Confirmed'"]
  • Impact: Reduced average response time from 800ms → 150ms.

3. NTC’s Website: Async Database Queries

  • Problem: Synchronous SqlConnection calls blocked threads during traffic updates.
  • Solution: Replace with ExecuteReaderAsync():
    var command = new SqlCommand("SELECT * FROM TrafficData", connection);
    var reader = await command.ExecuteReaderAsync(); // Non-blocking
    
  • Result: Page load time dropped from 2.5s → 400ms.

Performance Optimization Techniques

1. CPU-Bound vs. I/O-Bound Workloads

Type Example Optimization Async Benefit
I/O-Bound DB queries, API calls async/await, Task.Run Threads freed for other work
CPU-Bound Heavy computations Parallel.For, PLINQ Multi-core utilization

2. Common Pitfalls & Fixes

Issue Cause Solution
Deadlocks ConfigureAwait(true) + sync code Use ConfigureAwait(false)
Memory Leaks Unobserved Tasks Attach to TaskScheduler.UnobservedTaskException
Fire-and-Forget Task.Run without await Use FireAndForget helper or BackgroundService

Example: Deadlock Fix

// BAD: Deadlock risk
public async Task ProcessOrder()
{
    var order = await _db.GetOrderAsync(); // ConfigureAwait(true) by default
    _cache.Set(order.Id, order); // Sync code blocks thread
}

// GOOD: Avoids deadlock
public async Task ProcessOrder()
{
    var order = await _db.GetOrderAsync().ConfigureAwait(false);
    _cache.Set(order.Id, order); // Safe
}

3. Advanced Patterns

A. Async Stream Processing

public async IAsyncEnumerable<int> StreamData()
{
    using var reader = new StreamReader("largefile.txt");
    while (!reader.EndOfStream)
    {
        var line = await reader.ReadLineAsync();
        yield return int.Parse(line);
    }
}

Use Case: NEPSE’s real-time stock data feed.

B. Async Cancellation

public async Task ProcessWithTimeout(CancellationToken token)
{
    using var cts = CancellationTokenSource.CreateLinkedTokenSource(token);
    cts.CancelAfter(TimeSpan.FromSeconds(10));

    try
    {
        await _service.DoWorkAsync(cts.Token);
    }
    catch (OperationCanceledException)
    {
        Console.WriteLine("Timed out!");
    }
}

Use Case: Pathao’s ride cancellation if the driver doesn’t respond.


Exam Tip: What to Focus On

  1. Define Key Terms:

    • Async/await: "Compiler-generated state machines that yield control during I/O."
    • Task: "Represents an asynchronous operation with a result or exception."
    • ConfigureAwait(false): "Prevents deadlocks by avoiding synchronization context."
  2. Code Examples:

    • Always show before/after async conversions (e.g., sync File.ReadAllText → async File.ReadAllTextAsync).
    • Include error handling (try-catch with await).
  3. Real-World Scenarios:

    • Explain how eSewa/Khalti use async for payment gateways.
    • Compare synchronous vs. async DB queries (show SQL command timing).
  4. Common Mistakes:

    • Async void: "Only use in event handlers; otherwise, exceptions are lost."
    • Blocking calls: "Never use .Result or .Wait()—they cause deadlocks."
  5. Performance Metrics:

    • Know that async can reduce server load by 50% for I/O-bound apps.
    • Mention thread pool starvation if too many async ops block threads.

Final Note: Async programming is not about speeding up single operations but about scaling the entire system. Master this, and you’ll design web apps that handle Nepal’s traffic spikes (like during festivals) without crashing.

Based on the TU BSc CSIT syllabus for NET Centric Computing (CSC367), unit 10.

Discussion

Loading…