I failed!

I’ve spent the last four years building an open-source, declarative performance testing tool that requires zero coding.

The idea was simple: help QAs and performance engineers build and run performance tests without dealing with the complexity of writing scripts.

It can do many of the things scripting-based tools can do, but without requiring you to write code.

The tool has so many nice ideas to help engineers analyze bottlenecks so quick with a built-in live dashboard.

And yet… I failed to convince QAs and performance engineers to use it.

What makes this harder is that I don’t really know why.

I’m not getting enough feedback to understand what I got wrong.

So I’m asking this community:

Why do you think I failed?

Is it the problem I’m solving?
The way I’m approaching it?
The lack of scripting?
The tool itself?
Or simply that engineers don’t need another performance testing tool?

I genuinely want honest feedback, even if it’s harsh.

I can’t include the link here because Reddit considers it self-promotion, and the post would likely be removed. But I’d really appreciate your perspective on why a tool like this might fail to gain adoption.

I feel so bad for the years I spent on it and was always saying it is not mature yet! Even though I got a lot of experience out of it, but it is really a hard feeling to fail!

reddit.com
u/Spiritual_Ratio_277 — 4 days ago

SNAT Port Exhaustion: When Your Machine Runs Out of Breath

Everything looks fine — until suddenly, nothing works.

You’ve deployed your application. It’s humming along beautifully. Then, without warning, errors start creeping in:

🔴 connection failed
🔴 socket exception

Your first instinct? The remote server must be down. But you check — it’s perfectly healthy. So what’s going on?

Welcome to SNAT Port Exhaustion: the silent killer of outbound connections.

What Is SNAT, anyway?

Every time your machine sends a request to an external server, it needs to pick a source port to identify that outgoing connection. This happens through a process called SNAT — Source Network Address Translation.

The operating system assigns a temporary (ephemeral) port from a limited pool. That pool is not unlimited. For any given destination (same IP + port combination), you typically get:

  • Around 16,000 ports in a standard setup
  • Only ~1,024 SNAT ports per VM if you’re behind an Azure Load Balancer

That’s it. That’s your budget.

What Happens When You Run Out?

Here’s the sequence when port exhaustion hits:

  1. Your application tries to open a new TCP connection
  2. The OS sends a SYN packet
  3. It searches for an available source port — and finds none
  4. The connection fails before it ever reaches the remote server

The remote server didn’t reject you. You couldn’t even say hello.

How to Spot It

Port exhaustion doesn’t announce itself with a clear error message. Instead, you’ll see symptoms like:

  • Failed to establish connection
  • Socket exhaustion
  • Intermittent, seemingly random failures on outbound requests

The randomness is the giveaway. If connections fail inconsistently under load, and the destination server looks healthy, your ports are likely the culprit.

Why Cloud Environments Make It Worse

On cloud platforms like Azure, traffic often flows through a shared Load Balancer. The LB allocates a fixed number of SNAT ports per VM — and that number can be surprisingly small.

If your service makes many concurrent outbound connections to the same destination (think: a high-throughput API client, a connection-heavy microservice, or a busy database proxy), you can exhaust your port allocation faster than you’d expect.

How to Fix It

Use Connection Pooling

Don’t open a new connection for every request. Reuse existing ones. Connection pooling is the single most effective fix — it dramatically reduces how many ports you consume at any given moment.

Reduce Connection Timeouts

Long-lived idle connections hold onto ports even when they’re doing nothing. Tighten your timeout settings so ports are released promptly.

Monitor Your Open Connections

Use netstat or ss to see what’s happening in real time:

# Count established connections by destination
ss -s
# See all connections with port details
netstat -an | grep ESTABLISHED | wc -l

Catching port pressure early prevents a full exhaustion event.

Scale Your Public IPs (Azure-specific)

If you’re on Azure and hitting LB SNAT limits:

  • Add more Public IPs to your Load Balancer to increase the port pool
  • Switch to NAT Gateway — unlike a Load Balancer, which pre-assigns a fixed number of SNAT ports per VM, NAT Gateway dynamically allocates ports on demand. This is the fundamental difference: there’s no static budget per VM to exhaust. It’s Microsoft’s recommended solution for outbound connectivity at scale, and you can attach up to 16 public IPs or a /28 prefix to it if you need even more capacity

The Bigger Picture

SNAT Port Exhaustion is dangerous precisely because it’s quiet. There’s no crash, no obvious error, no stack trace pointing at the real cause. Your application just… starts failing. Intermittently. Mysteriously.

The fix isn’t complicated — but you have to know what you’re looking for.

Three things to take away:

  1. Monitor how your application opens connections — every one costs a port
  2. Design for port efficiency — pooling and timeouts aren’t optional, they’re hygiene
  3. Keep an eye on your network layer — especially in cloud environments where limits are lower than you think

Summary:

https://preview.redd.it/znalzpva3dih1.png?width=800&format=png&auto=webp&s=5ab77cdf1dccc25159a8e785c7f5cfd455f052ec

Have you run into SNAT Port Exhaustion in a production system? What was the hardest part to diagnose? Share your experience in the comments.

References

reddit.com
u/Spiritual_Ratio_277 — 11 days ago
▲ 0 r/dotnet

LINQ Performance Pitfalls Every C# Developer Should Know

>Two subtle choices —IEnumerable vs IQueryable, and Func vs Expression— can mean the difference between a fast query and a silent disaster.

LINQ is one of C#’s most expressive features. But with that expressiveness comes a trap that even experienced developers fall into: writing queries that look correct, compile without warnings, and silently destroy your application’s performance at scale.

In this article, we’ll look at two specific decisions that have an outsized impact on how your LINQ queries actually execute.

Part 1: IEnumerable vs IQueryable

Both interfaces let you write LINQ queries with the same familiar syntax. The difference is in where the work happens.

IEnumerable — works in memory

When you filter, sort, or project over an IEnumerable<T>, all that work happens in your application's memory. If you're using it against a database, that means Entity Framework will fetch every row first, then apply your filters in C#.

IQueryable — works at the source

IQueryable<T> is designed for external data sources like SQL databases. Instead of running logic in memory, it builds up a query expression that gets translated into SQL and executed inside the database — where it belongs.

>Key rule: when working with a database through Entity Framework, always operate on IQueryable<T>. Filtering happens in SQL, not in RAM.

The practical consequence is significant. Suppose you call AsEnumerable() before filtering:

// All rows fetched from DB first, then filtered in memory
var result = dbContext.Users
    .AsEnumerable()
    .Where(u => u.Age > 30);

The generated SQL is effectively SELECT * FROM Users — no WHERE clause. The filtering happens after all that data lands in your application.

Compare that to staying on IQueryable:

// Filter pushed into SQL — only matching rows are returned
var result = dbContext.Users
    .Where(u => u.Age > 30);

This generates SELECT * FROM Users WHERE Age > 30. The database does the heavy lifting.

A quick note on AsQueryable(): calling it on an in-memory collection like a List<T> does wrap it in an IQueryable, but there's no SQL provider behind it. No translation occurs — everything still runs in memory. The translation only happens when a real query provider, like Entity Framework, is in the picture.

Part 2: Func vs Expression<Func>

This is where things get subtle — and where most developers get burned.

Both Func&lt;T, bool&gt; and Expression&lt;Func&lt;T, bool&gt;&gt; look almost identical when you write a lambda. But they are fundamentally different things at runtime.

Func — a compiled black box

A Func is a compiled delegate. By the time it reaches Entity Framework, it's already been compiled into IL bytecode. EF has no way to look inside it. It cannot read the logic, inspect the conditions, or translate them to SQL. It just sees: "here is a method, call it."

Expression<Func> — a readable data structure

An Expression&lt;Func&lt;T, bool&gt;&gt; is not compiled code — it's a description of code, stored as an expression tree. It's a data structure that EF can walk, inspect, and translate into a SQL WHERE clause.

Think of it like this:

  • Expression&lt;Func&gt; → a recipe written on paper. Entity Framework can read it and cook it inside the database.
  • Func → a meal already cooked. EF can't "uncook" it to figure out what ingredients were used.

What this looks like in practice

// Problematic — Func is a compiled delegate, EF can't translate it
Func&lt;User, bool&gt; filter = u =&gt; u.Age &gt; 30;
var result = dbContext.Users.Where(filter);
// SQL generated: SELECT * FROM Users
// All rows fetched, filter runs in memory

// Correct — Expression tree, EF translates it to SQL
Expression&lt;Func&lt;User, bool&gt;&gt; filter = u =&gt; u.Age &gt; 30;
var result = dbContext.Users.Where(filter);
// SQL generated: SELECT * FROM Users WHERE Age &gt; 30

>Important: the compiler will not warn you about this. Both versions compile cleanly. The performance difference only shows up at runtime — and if your table has millions of rows, that difference is catastrophic.

The reason the compiler stays silent is that IQueryable&lt;T&gt; has overloads for both Where(Func&lt;T, bool&gt;) and Where(Expression&lt;Func&lt;T, bool&gt;&gt;). Passing a Func is syntactically valid — it just forces EF to fall back to in-memory evaluation by first loading all data internally.

Summary

Choice Where filter runs Good for Performance at scale
IEnumerable In memory (RAM) In-memory collections Poor with DB
IQueryable In the database EF / SQL data sources Excellent
Func&lt;T, bool&gt; In memory (RAM) In-memory filtering Poor with DB
Expression&lt;Func&gt; In the database EF queries Excellent

Quick rules to remember

  • When querying a database with EF, always work with IQueryable, not IEnumerable.
  • Pass Expression&lt;Func&lt;T, bool&gt;&gt; to Where() — never a bare Func.
  • AsEnumerable() is a signal that everything after it runs in memory — use it deliberately, not by accident.
  • If something compiles cleanly but seems slow, check whether your filters are actually reaching SQL.
reddit.com
u/Spiritual_Ratio_277 — 11 days ago

Pre-Production Performance Checklist Summary

I’m sharing a few performance checks you should consider running before deploying a new release.

Key Takeaways

  • Core Purpose: To evaluate whether a software change will make a system slower, less scalable, or more resource-intensive under realistic traffic.
  • Standardized Structure: Every potential failure is evaluated by its primary failure mode, the specific test shape required to catch it, its affected secondary resource, and the resulting user impact.

Core Components

1. Common Load Test Shapes

The guide defines 17 specific load-testing profiles to expose targeted system bottlenecks (rather than just generically increasing traffic):

  • Scale & Volume: Gradual, Peak, Burst, Spike, Sustained, Payload scaling, Data volume scaling.
  • State & Reliability: Soak (hours long), Concurrent, Mixed CPU+I/O, Cold cache, Cache expiry burst, Hot key load, Queue overload, large file/data workload.
  • Dependency Reliability: Dependency latency injection, Dependency failure injection.

2. Categorized Failure Scenarios

The checklist breaks down common performance traps across 10 technical domains:

  • CPU-Bound Work: High-cost compute like file parsing, video transcoding, or heavy batching (watch for processing time and peak memory).
  • Memory Pressure: Inefficient allocations, large payloads, or unbounded caches (watch for GC pauses, heap growth, and OOM crashes).
  • Database Performance: N+1 queries, deep pagination, missing indexes, and write contention on hot rows.
  • Connection Pools: Exhaustion of reusable client/backend connections caused by high request volume, slow database/cache writes or reads, slow external API calls, or long-running transactions.
  • Thread/Worker Starvation: Blocked workers causing high latency even while CPU usage remains low.
  • Network & Payload Inefficiency: Excessive serialization, chatty microservices (fan-out), and bloated response sizes.
  • Disk/Storage I/O: Storage bottlenecks caused by heavy logging, file exports, or database disk scans.
  • Cache Failures: Cold caches after deploys, stampedes upon TTL expiration, and hot keys overwhelming specific shards.
  • Queue & Backlog Issues: Job producers outpacing background consumers, retry storms, and message bloat.
  • Nonlinear Scaling: Systems where small increases in data size cause exponential increases in latency/cost (super-linear growth curves).

3. Secondary Resource Classification Reference

Categorizes resource bottlenecks to help identify the primary fix target: CPU, Memory, Disk I/O, Network I/O, Threads/Workers, Connection Pools, DB CPU, DB I/O, DB Locks, Cache Capacity, Queue Capacity, and External Dependencies.

Quick Decision Mapping

Change Type Key Checks Recommended Test Shape
API / Service Logic CPU, memory, payload size, nonlinear growth Sustained load, Gradual load, Payload scaling
Database / Schema Query execution plans, query counts (N+1), pagination Data volume scaling, Concurrent load
Caching Layer Cache hit rates, cold cache behavior, stampedes, hot keys Cold cache load, Cache expiry burst, Hot key load
Queues / Background Workers Processing throughput, backlog growth, memory stability Queue overload, Soak test
External API Calls Latency tolerance, call volume, connection pool utilization Dependency latency / failure injection
File Import / Export Disk throughput, peak memory usage, CPU load Large file/data workload, Payload scaling
reddit.com
u/Spiritual_Ratio_277 — 12 days ago

Performance troubleshooting using sliced metrics

One of my favorite metrics introduced in the #LPS tool for #PerformanceTesting is the Max Concurrent Requests, along with windowed metrics. Max Concurrent Requests is one of the clearest indicators of server or network health.

If it unexpectldy spikes without an increase in load, it usually means requests are taking longer than expected, causing them to accumulate in flight. Unlike cumulative metrics, windowed metrics calculate statistics over short time intervals (for example, every 5 seconds).

Each window is calculated independently, published to the dashboard in real time. Because these metrics represent only a small slice of time, they provide immediate visibility into performance changes as they happen, making short-lived issues much easier to detect than with cumulative statistics.

In the example attached, the spike in concurrent requests aligns with increased latency specifically higher TLS handshake and TTFB times. That quickly points the investigation in the right direction.

My next step would be to check server metrics such as CPU, memory, thread pools, and queues health. If everything looks healthy and there are no intermediaries (load balancers, proxies, firewalls, etc.) introducing delays, I'd move on to network traces.

Sometimes, a single metric is enough to tell you exactly where to start looking.

LPS Installation:

# 1) Verify .NET 8 is installed

dotnet --list-sdks

# 2) Install the LPS .NET global tool

dotnet tool install --global lps

# 3) Check the tool is available

lps --help

Run a quick test:

lps --url https://www.example.com --numberofclients 1000 --arrivaldelay 100

#LoadTesting #PerformanceEngineering #Observability #DevOps #DotNet

u/Spiritual_Ratio_277 — 17 days ago

QA Engineers: What load/performance testing scenarios do you typically work on?

I'm curious how performance and load testing is used in real-world QA teams.

If performance testing is part of your job, I'd love to hear about the kinds of scenarios you typically build and run.

Some questions I'm interested in:

* What is the most common load or performance tests you perform? * Do you mostly test APIs, web applications, mobile apps, databases, or something else? * Are your tests focused on validating SLAs, finding bottlenecks, capacity planning, or regression detection? * How do you usually model user behavior? (steady load, ramp-up, spike tests, stress tests, soak tests, etc.) * How realistic are your workloads? Do you simulate full business workflows or mostly individual endpoints? * Do you generate test data dynamically, or use predefined datasets? * How often do you run these tests? (before releases, nightly, in CI/CD, on demand, etc.) * What are the biggest challenges you face when creating or maintaining performance tests? * What features or capabilities do you wish existed in the tools you use today?

It would also be helpful if you could mention:

* Your industry (finance, e-commerce, healthcare, gaming, SaaS, etc.) * Team size * The tools you use (JMeter, k6, Gatling, Locust, LoadRunner, or others)

I'm mainly trying to understand common real-world testing patterns and workflows across different organizations.

Thanks!

reddit.com
u/Spiritual_Ratio_277 — 1 month ago

QA Engineers: What load/performance testing scenarios do you typically work on?

I'm curious how performance and load testing is used in real-world QA teams.

If performance testing is part of your job, I'd love to hear about the kinds of scenarios you typically build and run.

Some questions I'm interested in:

  • What is the most common load or performance tests you perform?
  • Do you mostly test APIs, web applications, mobile apps, databases, or something else?
  • Are your tests focused on validating SLAs, finding bottlenecks, capacity planning, or regression detection?
  • How do you usually model user behavior? (steady load, ramp-up, spike tests, stress tests, soak tests, etc.)
  • How realistic are your workloads? Do you simulate full business workflows or mostly individual endpoints?
  • Do you generate test data dynamically, or use predefined datasets?
  • How often do you run these tests? (before releases, nightly, in CI/CD, on demand, etc.)
  • What are the biggest challenges you face when creating or maintaining performance tests?
  • What features or capabilities do you wish existed in the tools you use today?

It would also be helpful if you could mention:

  • Your industry (finance, e-commerce, healthcare, gaming, SaaS, etc.)
  • Team size
  • The tools you use (JMeter, k6, Gatling, Locust, LoadRunner, or others)

I'm mainly trying to understand common real-world testing patterns and workflows across different organizations.

Thanks!

reddit.com
u/Spiritual_Ratio_277 — 1 month ago

عملت تطبيق مهام لأنه أغلب التطبيقات الحالية بدها تسجيل دخول و مش كل المزايا بتهمني

من فترة وأنا بجرب تطبيقات تنظيم ومهام،
بس دايمًا نفس المشكلة: بدهم تسجيل دخول، أو اشتراك أو واجهة مش مناسبة لي.

بالآخر قررت أعمل تطبيق بسيط يمشي معي أنا و بمساعدة حبيبنا كلود.

هيك طلع Dashora.

فكرته باختصار:

  • بدون حساب
  • بدون اشتراك
  • خفيف وواضح

فيه:

  • Boards للمهام وBoards للملاحظات/المراجع
  • To Do / In Progress / Done
  • Due dates ومهام متكررة
  • تنبيهات أوضح وقت الموعد
  • Auto backups to restore the board and tasks if the local cache gets cleared as it mainly stores everything on the local cache
  • وإمكانية تحمي نسخ احتياطية معينة من الحذف التلقائي لأنه بسمخ ب 3 نسخ إحتياطية فقط

الصراحة، وجود أدوات الذكاء الإصطناعي ساعدني كثير أخلصه بسرعة وأضبطه على احتياجي، بدل ما أضطر ألتزم بتطبيقات جاهزة و هذا اللي بخلي الحدود بين الفكرة و تطبيقها شبه معدوم حاليا

رابطه:
https://dashora.netlify.app/

إذا جربته، يهمني أعرف رأيك خصوصًا بالتنبيهات والواجهة.

reddit.com
u/Spiritual_Ratio_277 — 1 month ago

لدعم منتجاتنا العربية

السلام عليكم , منتجاتنا العربية تواجه منافسة غير عادلة في السوق نظرا للدعم غير المحدود للمنتجات الغربية و من هون حابب أشاركم بالتالي

في منصة إسمها قبيلة تحاول أن تكون البديل العربي للنكد إن و أنا متابعهم من سنتين و الشباب شغالين شغل كويس و مؤخرا أطلقوا هكثون للمشاريع العربية للي حابب يشارك أو يشوف الأفكار و المنتجات المشاركة من شبابنا العربي

أنا شاركت بتطبيقي الخاص بقياس أداء التطبيقات اللي بتمني أنكم تدعموني و تصوتون لي فيه و أيضا تأخذون نظرة على مختلف المشاريع و الحماس الموجود عند الشباب العربي

https://qabilah.com/hackathon/255665101472799432/projects/257121251644936192

التسجيل في قبيلة سهل و ممكن يأخذ بروفايلك بلنكد إن و يحوله لبروفايل في قبيلة

u/Spiritual_Ratio_277 — 2 months ago

What is compiled regex, and when should it be used?

This question is meant to explore how developers think about compiled regex, and I’m interested in your answers before I turn it into an article.

reddit.com
u/Spiritual_Ratio_277 — 2 months ago

كيف عم تستخدم الذكاء الإصطناعي في عملك اليومي؟

السلام عليكم؟

كيف عم تستخدموا الذكاء الإصطناعي في عملكم اليومي؟ للتعلم, لكتابة الكود و هل عم تعملوا مراجعة للكود اللي بكتبه؟ كم نسبة الأخطاء اللي عم تمسكوها له؟

reddit.com
u/Spiritual_Ratio_277 — 3 months ago
▲ 0 r/dotnet

Concurrency &amp; Parallelism in C# — From Threads to TPL

You can read the article well formatted from here

https://medium.com/@mahdi.com.haidar/concurrency-parallelism-in-c-from-threads-to-tpl-ac08a7a2d4c9

1. Process vs Thread

A Process is the running application itself. A Thread is a path of execution running inside it.

Code example:

using System;

using System.Diagnostics;

using System.Threading;

// This program, once running, is a Process

class Program {

static void Main() {

// Spawning a new Thread (worker) inside this Process

Thread worker = new Thread(() => {

Console.WriteLine("I'm a Thread running inside this Process!");

});

worker.Start();

}

}

2. Multi-threading vs Asynchronous

Multi-threading: Runs code simultaneously by spawning additional OS threads.

Async (smart waiting): Frees the current thread from blocking while waiting for data — no new thread needed.

Full side-by-side example

using System;

using System.Net.Http;

using System.Threading;

using System.Threading.Tasks;

class Program

{

static async Task Main()

{

Console.WriteLine($"[Main] Running on Thread: {Thread.CurrentThread.ManagedThreadId}");

// ───────────────────────────────────────────

// Approach 1: Multi-threading

// ───────────────────────────────────────────

// A brand-new OS thread is created - it has its own stack (~1MB) and creation cost.

// Main won't freeze, but we've "spent" a real thread for the entire wait duration.

Thread t = new Thread(() =>

{

Console.WriteLine($"[Thread] Started on Thread: {Thread.CurrentThread.ManagedThreadId}");

Thread.Sleep(2000); // simulate heavy work or a network wait

Console.WriteLine($"[Thread] Finished on Thread: {Thread.CurrentThread.ManagedThreadId}");

});

t.Start();

Console.WriteLine("[Main] Keeps working while the Thread runs in the background...");

t.Join(); // wait for the thread to finish

Console.WriteLine();

// ───────────────────────────────────────────

// Approach 2: Async / Await

// ───────────────────────────────────────────

// No new thread! The Main thread is released and can do other work

// while the OS waits for the network response - then resumes right where it left off.

Console.WriteLine($"[Main] Before await - Thread: {Thread.CurrentThread.ManagedThreadId}");

var loadDataTask = LoadDataAsync();

Console.WriteLine($"[Main] Do Work While Data Loading");

await loadDataTask;

Console.WriteLine($"[Main] After await - Thread: {Thread.CurrentThread.ManagedThreadId}");

}

static async Task LoadDataAsync()

{

Console.WriteLine($" [Async] Sending request on Thread: {Thread.CurrentThread.ManagedThreadId}");

using var client = new HttpClient();

// At the await: the thread is released back to the thread pool - nobody is blocked!

string data = await client.GetStringAsync("https://jsonplaceholder.typicode.com/todos/1");

// When the response arrives, execution resumes on a thread pool thread

// (may or may not be the same thread ID as before)

Console.WriteLine($" [Async] Resumed on Thread: {Thread.CurrentThread.ManagedThreadId}");

Console.WriteLine($" [Async] First 50 chars: {data[..50]}...");

}

}

Why is Async better than Multi-threading for I/O?

Multi-threading:

Threads used: one new OS thread per operation

Memory cost: ~1MB stack per thread

1,000 concurrent requests: 1,000 threads — a disaster!

Best for: CPU-heavy computation

Async/Await:

Threads used: same thread, released during the wait

Memory cost: nearly zero

1,000 concurrent requests: handled by a small pool of threads

Best for: network, database, file I/O.

Bottom line: Both approaches avoid freezing Main, but async is far more efficient because it doesn’t “waste” a real thread sitting idle during the wait. Imagine 10,000 HTTP requests — with threads you’d need 10,000 of them; with async, a handful is enough.

3. Concurrency vs Parallelism

Concurrency: Rapidly switching between tasks — like a mother managing her household: washing, cooking, doing the dishes, and looking after the kids, moving between them so quickly it looks like she’s doing everything at once, when in reality she’s switching between them.

Parallelism: Truly executing tasks at the exact same moment (like you cooking while a friend washes the dishes — two people, two things simultaneously).

Concurrency example — overlapping tasks on one or a few threads:

using System;

using System.Threading;

using System.Threading.Tasks;

class ConcurrencyExample

{

static async Task Main()

{

Console.WriteLine("=== Concurrency: launching 3 tasks together without waiting for each ===\n");

// Fire all three tasks at once - we don't await each one before starting the next.

// This is concurrency: coordinating tasks that overlap in time.

Task task1 = SimulateWork("API Request", delaySeconds: 3);

Task task2 = SimulateWork("File Read", delaySeconds: 1);

Task task3 = SimulateWork("DB Query", delaySeconds: 2);

Console.WriteLine("[Main] All three tasks launched - now waiting for all to finish...\n");

// Wait for all of them - actual execution may be on one thread or a few

await Task.WhenAll(task1, task2, task3);

Console.WriteLine("\n[Main] All tasks completed!");

// Notice: total time is ~3s (the slowest task), not 6s (the sum of all)

}

static async Task SimulateWork(string taskName, int delaySeconds)

{

Console.WriteLine($" [{taskName}] Started... (takes {delaySeconds}s)");

await Task.Delay(TimeSpan.FromSeconds(delaySeconds)); // simulate I/O wait

Console.WriteLine($" [{taskName}] ✓ Done after {delaySeconds}s");

}

}

// Expected output:

// [API Request] Started... (takes 3s)

// [File Read] Started... (takes 1s)

// [DB Query] Started... (takes 2s)

// [Main] All three tasks launched - now waiting for all to finish...

// [File Read] ✓ Done after 1s ← finishes first

// [DB Query] ✓ Done after 2s

// [API Request] ✓ Done after 3s

// [Main] All tasks completed! ← after ~3s total, not 6s

Parallelism example — truly using multiple CPU cores at once

using System;

using System.Threading;

using System.Threading.Tasks;

class ParallelismExample

{

static void Main()

{

Console.WriteLine("=== Parallelism: spreading computation across CPU cores ===\n");

int[] numbers = new int[12]; // 12 items to process

// Parallel.For distributes iterations across available cores automatically.

// Each iteration may run on a different core at the exact same moment.

Parallel.For(0, numbers.Length, i =>

{

int threadId = Thread.CurrentThread.ManagedThreadId;

numbers[i] = HeavyCalculation(i);

Console.WriteLine($" Item [{i:D2}] = {numbers[i]:D6} | Core/Thread: {threadId}");

});

Console.WriteLine($"\nAll done! Results: {string.Join(", ", numbers)[..40]}...");

}

// A CPU-intensive calculation

static int HeavyCalculation(int n)

{

int result = 0;

for (int i = 0; i < 1_000_000; i++)

result += (n + i) % 7;

return result;

}

}

// Expected output (order varies each run - notice different Thread IDs working simultaneously):

// Item [00] = 142857 | Core/Thread: 4

// Item [01] = 142858 | Core/Thread: 6 ← different thread, same moment!

// Item [02] = 142859 | Core/Thread: 5

// Item [03] = 142860 | Core/Thread: 4

// ...

Key differences between the two

Concurrency:

What actually happens: tasks interleaved over time

Threads used: can be a single thread (with async)

Best for: I/O — network, files, database

Example: Task.WhenAll for multiple API calls

Parallelism:

What actually happens: tasks executing at the exact same instant

Threads used: multiple cores/threads

Best for: CPU — computation, image processing,

compression

Example: Parallel.For for data processing

4. Task Parallel Library (TPL)

TPL makes concurrent programming easier by working with Tasks instead of managing raw Threads directly.

Code example (using Task):

using System.Threading.Tasks;

class TPL_Example {

static async Task Main() {

// Spin up a task easily

Task<int> task = Task.Run(() => {

// Some long-running work

return 42;

});

// Do other work here while the task runs...

// Get the result when it's ready

int result = await task;

Console.WriteLine($"Result: {result}");

}

}

When to use each TPL tool

Parallel.ForEach — you have thousands of items and want maximum throughput (Data Parallelism)

Task.Run — you need to run a heavy operation in the background to keep the UI responsive

Task.WhenAll — you want to fire off multiple requests simultaneously and wait for all of them

Developer tip: Always reach for TPL (Tasks) first — it’s the modern and most efficient way to manage concurrency in .NET. TPL efficiently manages work scheduling and ThreadPool usage for you, reducing the complexity of manual thread management. Only drop down to raw Thread in rare, advanced scenarios where you need direct control over thread lifecycle or priority.

reddit.com
u/Spiritual_Ratio_277 — 3 months ago

Load testing is not about the number of requests — it's about the pattern.

Some people treat load testing as "throw as many requests as possible at the system."

But 10,000 requests over an hour vs 10,000 requests in 10 seconds are completely different tests.

What tends to matter more is *how* the load behaves:

* Gradual ramp-up vs instant spikes

* Think time between actions

* Actual user flows (login → browse → checkout)

* Irregular traffic bursts (sales, news events, viral traffic)

That’s usually where bottlenecks, latency issues, and unexpected behavior tend to appear.

Of course, realism alone isn't enough either. You still need enough load to stress thread pools, memory, connection pools, and get meaningful latency distributions (p95/p99).

The rough formula I try to follow is:

* Realistic traffic patterns

* Enough volume to hit system limits

* Long enough duration to expose degradation / leaks

I've been thinking about this quite a bit while building a load-testing tool (LPS), because modeling realistic user behavior often turns out to be harder than simply generating traffic.

Curious how others handle complex user journeys in practice.

Do you mostly script everything manually, or do you prefer more declarative / scenario-driven approaches?

For anyone interested in concrete examples of what I mean by traffic patterns / staged ramping, here are a few references from my experiments and tooling work (not required reading — mainly context for the discussion):

* Example of staged ramping & patterns: https://lpsload.io/docs/examples/11.RampingWithStages.html

* Project / implementation details: https://github.com/mohaidr/lps

*Comparison with k6 and JMeter: https://medium.com/@mahdi.com.haidar/lps-vs-k6-vs-jmeter-a-practical-comparison-2dd7989b7f23

*Monitoring and Observability Comparison: https://medium.com/@mahdi.com.haidar/monitoring-and-observability-in-load-testing-lps-vs-k6-vs-jmeter-b85e4548b05e

LPS Read Me: https://lpsload.io/docs/readme.html

Understand LPS: https://lpsload.io/docs/understanding-lps.html

reddit.com
u/Spiritual_Ratio_277 — 3 months ago

كيف ممكن نساعد بعض بنشر ادواتنا العربية بشكل عام و الاردنية بشكل خاص في السوق العالمي

اسمي محمد حيدر، مهندس في شركة مايكروسوفت الاردن.

قبل اربع سنين بدأت بتطوير أداة load and performance testing تنافس الادوات الكبيرة الموجودة بالسوق و بخبرة كبيرة في مجال ال API management and security من مايكروسوفت بس عانيت و ما زلت اعاني في نشرها داخل مجتمعاتنا العربية و الاغلب بس يشوف المطور عربي لا يعير انتباه للاداة و يتجاهل حتى التجربة.

اعلم بان هذا التجاهل هو نتيجة تجارب كثيرة سيئة لمنتجات عربية و لكن اعتقد بان سوقنا الاردني و العربي بشكل عام اصبح اكثر نضوجا و وعيا و عندنا مهندسين على اعلى المستويات.

برأيكم ايش افضل طريقة نساعد فيها بعض و كيف بنقدر نشتغل على تغيير هذه النظرة لمنتجاتنا؟

الاداة مفتوحة المصدر للي حابب يجربها و تنزيلها سهل كثير

https://github.com/mohaidr/lps

و هذا ال full documentation لها

https://lpsload.io/docs/readme.html

u/Spiritual_Ratio_277 — 3 months ago

Frustrated with heavy/complex load testing tools, I built an open-source alternative. Would love some QA feedback.

Hey everyone,

Like many of you who handle performance and stress testing, I’ve spent years working with the standard industry tools. While JMeter is incredibly powerful, it often feels bloated, heavy on resources, and a bit dated. On the flip side, while modern tools like k6 or Artillery are great, they still come with their own learning curves, specific scripting requirements.

I wanted something lightweight, fast, and dead-simple to spin up.

I actually started building a solution to solve this for my own workflows back in mid-2022. I recently made the decision to transition it to a fully open-source project on GitHub to give back to the community. It's called (LPS) which stands for Load, Perform and Stress.

I'm sharing it here because I genuinely want the perspective of seasoned QA and performance engineers.

What makes it different?

Zero Bloat & Lightweight: Designed to execute high-concurrency stress tests without eating up all your testing machine's resources, making it highly efficient compared to traditional Java-based runners.

Streamlined Learning Curve: The tool is declerative, you don't need to spend time configuring complex XMLs or writing boilerplate scripts just to get a baseline load test running.

Built for Fast Iteration: Ideal for developers and QA engineers who want to quickly benchmark endpoints and catch performance degradation early in the pipeline. You can see the full architectural breakdown and syntax in the LPS Documentation.

The Challenge:

For me, one of the toughest parts of building a load tester from scratch has been handling concurrent virtual users accurately without thread contention skewing the latency metrics. I put a lot of work into optimizing the execution engine to ensure the reporting stays highly accurate even under heavy stress.

Looking for your feedback (and code reviews!)

The project is entirely open-source, and my goal right now is purely to make it better. I would love it if you could take a look at the design, try running a quick test, or tear the code apart.

What missing features would prevent you from using a tool like this in your daily workflow?

How can I improve the reporter/metrics output to make it more useful for QA teams?

GitHub Repo: https://github.com/mohaidr/lps

Full Documentation: https://lpsload.io/docs/readme.html

Thanks for reading, and I'm looking forward to your feedback!

reddit.com
u/Spiritual_Ratio_277 — 3 months ago