ข้าม​ไป​ยัง​เนื้อหา

เขียน 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 ที่​จัดสรร” อย่าง​เดียว และ​จะ​เขียน​แบบนั้นตรงๆ ทั้ง​แปดบท

  1. ข้อ​สรุป​ว่า “เทคนิค​นี้​ดี​กว่า” ตัดสิน​ด้วย column Allocated เท่านั้น ไม่ใช่ column Mean
  2. ตัวเลข​เวลา​ทุก​ตัว​ต้อง​พ่วง​เครื่อง​ที่​วัด​และ​ค่า​การกระจาย (StdDev หรือ Error) พ่วง​ไม่​ได้ = ตัด​ทิ้ง
  3. byte ที่​ประหยัด​ได้ ไม่​เท่ากับ เวลา​ที่​ประหยัด​ได้ คอร์ส​นี้​ไม่มี​หลักฐาน​เรื่อง​นั้น​และ​จะ​ไม่​อ้าง
  4. “รัน​สอง​รอบ​ได้​เท่า​กัน” ยัง​ไม่​พอ ต้อง​อุ่น​จนถึง 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 physical
Ubuntu 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 บน​สถาปัตยกรรม​อื่น​ตัวเลข​ชุด​นี้​เปลี่ยน