吞吐量与延迟的权衡
平衡每秒完成的总工作量(吞吐量)与每个项目所需的时间(延迟):比较逐项处理、批处理和并行度调节。
吞吐量与延迟的权衡 是 CoddyKit 上的免费 C# Academy 课时。 这是第 3 节课,共 3 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 C# Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 C# Academy 课程共包含 3 节课。
吞吐量与延迟
定义:
- 吞吐量:每秒处理的项目数
- 延迟:完成一个项目所需的时间
- 权衡:批处理和更高的并行度可能提高吞吐量,但会延迟单个项目的处理
逐项处理模式
项目到达后立即逐个处理:每个项目的等待时间最短,但每个项目都会重复产生开销。
using System;
using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;
public class Program
{
// Simulate small per-item cost
static void HandleItem(int x)
{
// Fixed overhead per item
Thread.SpinWait(20000); // tiny CPU work
}
public static void Main(string[] args)
{
int n = 200;
Stopwatch sw = Stopwatch.StartNew();
for (int i = 0; i < n; i++)
{
HandleItem(i); // process immediately (no batching)
// emit result right away (low latency style)
}
sw.Stop();
Console.WriteLine("Per-item style: {0} ms for {1} items", sw.ElapsedMilliseconds, n);
}
}
批处理模式
批处理可以减少重复开销并提高吞吐量,但较早到达的项目需要等待批次填满(延迟更高)。
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Threading;
public class Program
{
static void ProcessBatch(List<int> batch)
{
// Amortize overhead across the whole batch
Thread.SpinWait(20000); // one-time overhead
for (int i = 0; i < batch.Count; i++)
{
// small per-record work
int val = batch[i] * 2;
if (val == int.MinValue) { } // keep compiler from dropping work
}
}
public static void Main(string[] args)
{
int n = 200;
int batchSize = 20;
List<int> current = new List<int>(batchSize);
Stopwatch sw = Stopwatch.StartNew();
for (int i = 0; i < n; i++)
{
current.Add(i);
if (current.Count == batchSize)
{
ProcessBatch(current);
current.Clear(); // emit results after the batch finishes
}
}
if (current.Count > 0) ProcessBatch(current);
sw.Stop();
Console.WriteLine("Batch style: {0} ms for {1} items (batch={2})", sw.ElapsedMilliseconds, n, batchSize);
}
}
并行度调优
调节 MaxDegreeOfParallelism 可以提高受 CPU 限制的工作的吞吐量;但数值过高可能因上下文切换而降低性能。
using System;
using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;
public class Program
{
static void Work(int x)
{
// CPU-bound unit
Thread.SpinWait(40000);
}
public static void Main(string[] args)
{
int[] data = new int[200];
for (int i = 0; i < data.Length; i++) data[i] = i;
foreach (int dop in new int[] { 1, 2, 4 })
{
var opt = new ParallelOptions();
opt.MaxDegreeOfParallelism = dop;
Stopwatch sw = Stopwatch.StartNew();
Parallel.ForEach(data, opt, Work);
sw.Stop();
Console.WriteLine("DOP={0} -> {1} ms", dop, sw.ElapsedMilliseconds);
}
}
}
微批处理思路
微批次可以平衡两个目标:吞吐量优于逐项处理,延迟低于超大批次。
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;
public class Program
{
static void ProcessBatch(List<int> batch)
{
Thread.SpinWait(15000); // small shared overhead
for (int i = 0; i < batch.Count; i++) Thread.SpinWait(2000);
}
public static void Main(string[] args)
{
int n = 200;
int micro = 5; // micro-batch size
List<int> buf = new List<int>(micro);
Stopwatch sw = Stopwatch.StartNew();
for (int i = 0; i < n; i++)
{
buf.Add(i);
if (buf.Count == micro)
{
ProcessBatch(buf);
buf.Clear(); // emit more frequently than big batches
}
}
if (buf.Count > 0) ProcessBatch(buf);
sw.Stop();
Console.WriteLine("Micro-batch (size={0}): {1} ms", micro, sw.ElapsedMilliseconds);
}
}
调优提示
调优指南:
- 同时测量每项毫秒数和每秒项目数
- 先尝试微批次
- 逐步提高并行度;观察 CPU 和上下文切换
- 使用有界队列,避免长时间等待和内存增长
吞吐量与延迟的权衡
回顾
回顾:逐项处理 = 低延迟、较低吞吐量。大批次/高 DOP = 更高吞吐量、更高延迟。微批次和谨慎调节 DOP 有助于平衡两者。
常见问题解答
「吞吐量与延迟的权衡」课时是免费的吗?
是的 — 「吞吐量与延迟的权衡」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 C# Academy 课程的其余内容,请升级到 CoddyKit PRO。 C# Academy 课程共包含 3 节课。
「吞吐量与延迟的权衡」这节课中我会学到什么?
平衡每秒完成的总工作量(吞吐量)与每个项目所需的时间(延迟):比较逐项处理、批处理和并行度调节。 你通过在浏览器中直接运行的动手代码来练习 C# Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 C# Academy 需要有经验吗?
无需任何先前经验。CoddyKit 上的 C# Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 3 节课,共 3 节。
「吞吐量与延迟的权衡」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 C# Academy 课中编写并运行代码吗?
能。每节 C# Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。