เขียน C#/.NET ให้เร็ว: struct, zero allocation, Span
ชั้น PERFORMANCE ของ domain Order: คอร์ส #8–#11 สร้าง domain ฟู้ดเดลิเวอรีขึ้นมา #19 สอนให้มองเห็นมันตอนรัน คอร์สนี้ทำให้มันเร็วขึ้น — โดยมีหลักฐาน ทั้งคอร์สเดินบน hot path เดียวกันเส้นเดียว (parse บรรทัดออร์เดอร์ → รวมยอด → พิมพ์ใบเสร็จ) แล้วไล่ปรับทีละชั้น: เริ่มจากการวัดให้เป็นก่อน เพราะตัวเลข allocation ขยับได้เองตาม tier ของ JIT และ object ที่ไม่หลุดออกนอก method ก็หายไปเงียบๆ ได้ด้วย escape analysis → struct กับ class และสำเนาที่ compiler แอบสร้างให้ (defensive copy) → boxing ที่เป็นคุณสมบัติของ code ที่ JIT ปล่อยออกมา ไม่ใช่ของซอร์ส → Span กับ stackalloc ที่มอง buffer เดิมโดยไม่คัดลอก → ArrayPool ที่แลก allocation กับสัญญาที่ผู้ยืมต้องรักษาเอง → งาน string (interpolated string handler, GetAlternateLookup, SearchValues) → ValueTask กับสิ่งที่ลบ allocation ได้จริงบนเส้นทางที่ suspend → ปิดท้ายด้วย capstone ที่วัดได้ว่าลดจาก 12,272 byte ต่อ batch เหลือ 0 byte ขณะที่ทั้ง 7 version ยังพิมพ์ผลลัพธ์ตรงกันทุก byte (982 byte) เส้นขอบเขตของคอร์สประกาศไว้ตั้งแต่บทแรกและบังคับใช้อีกเจ็ดบท: byte คือหลักฐาน นาโนวินาทีไม่ใช่ ทุกข้อสรุปตัดสินด้วย column Allocated ไม่ใช่ column Mean และทุกตัวเลขวัดจริงบนเครื่องเดียว ไม่มีเลขที่แต่งขึ้น 8 บทลงมือจริง
ความคืบหน้า0 / 8 บทเรียน
ก่อนเริ่ม — สิ่งที่ควรมีมาก่อน
หัวข้อที่มีชื่อว่า “ก่อนเริ่ม — สิ่งที่ควรมีมาก่อน”- C# ระดับใช้งานจริง อ่าน code ที่มี generic, interface และ async ออกโดยไม่ต้องหยุดคิด ถ้ายังไม่ถึงจุดนั้น คอร์ส เขียน C# สมัยใหม่ด้วย domain Order คือ on-ramp ที่ตรงที่สุด
- คุ้น domain Order ระดับอ่าน code ออก จะผ่าน bounded-contexts-integration หรือ efcore-persistence มาก็ได้ อย่างใดอย่างหนึ่งก็พอ และไม่บังคับ เพราะทุกบทพิมพ์ข้อมูลตั้งต้นให้ครบก่อนแสดงตัวเลขเสมอ
- feature C# 11–14 ไม่ต้องรู้มาก่อน แต่คอร์สนี้จะ ใช้ มันโดยไม่หยุดอธิบาย ถ้าเจอไวยากรณ์ที่ไม่คุ้น ให้เปิด C# 8 → 14: อะไรเปลี่ยนไปบ้าง ควบคู่ไป — บทความ จัดชั้น feature คอร์สนี้ สอนใช้
- .NET SDK 10 บนเครื่องของคุณ ถ้าอยากรันตาม ทุกบทรันได้จริง ไม่มีบทไหนที่อ่านอย่างเดียว
เส้นขอบเขตของคอร์ส — byte คือหลักฐาน นาโนวินาทีไม่ใช่
หัวข้อที่มีชื่อว่า “เส้นขอบเขตของคอร์ส — byte คือหลักฐาน นาโนวินาทีไม่ใช่”คอร์สนี้วัด “จำนวน byte ที่จัดสรร” อย่างเดียว และจะเขียนแบบนั้นตรงๆ ทั้งแปดบท
- ข้อสรุปว่า “เทคนิคนี้ดีกว่า” ตัดสินด้วย column Allocated เท่านั้น ไม่ใช่ column Mean
- ตัวเลขเวลาทุกตัวต้องพ่วงเครื่องที่วัดและค่าการกระจาย (StdDev หรือ Error) พ่วงไม่ได้ = ตัดทิ้ง
- byte ที่ประหยัดได้ ไม่เท่ากับ เวลาที่ประหยัดได้ คอร์สนี้ไม่มีหลักฐานเรื่องนั้นและจะไม่อ้าง
- “รันสองรอบได้เท่ากัน” ยังไม่พอ ต้องอุ่นจนถึง tier-1 จริงก่อนจึงจะอ่านตัวเลขได้
สิ่งที่คอร์สนี้ ไม่รับปาก: GC pause, throughput, working set, tail latency หรือ latency ของ app จริง และ allocation ไม่เท่ากับ residency — byte ที่จัดสรรกับ byte ที่ยังค้างอยู่ในหน่วยความจำเป็นคนละเรื่องกัน
เครื่องที่วัดตัวเลขทั้งหมด
หัวข้อที่มีชื่อว่า “เครื่องที่วัดตัวเลขทั้งหมด”ทุกตัวเลขในคอร์สนี้มาจากเครื่องเดียวกันเครื่องนี้ ไม่มีเลขที่แต่งขึ้นและไม่มีเลขที่ยกมาจากที่อื่น
Intel Core i7-7700 3.60GHz (Kaby Lake) · 8 logical / 4 physicalUbuntu 24.04.4 LTS (WSL2) · linux-x64.NET SDK 10.0.302 / runtime Microsoft.NETCore.App 10.0.10 · RyuJIT AVX2 (x86-64-v3)workstation non-concurrent GC (ServerGC=false, ConcurrentGC=false)BenchmarkDotNet 0.15.2 / 0.15.4 / 0.15.8ตัวเลขโครงสร้างทุกตัวผูกกับ x64 (IntPtr = 8): object header 16 byte · reference 8 byte · array header 24 byte · string header 22 byte บนสถาปัตยกรรมอื่นตัวเลขชุดนี้เปลี่ยน