5 คะแนน โดย GN⁺ 2025-12-29 | 1 ความคิดเห็น | แชร์ทาง WhatsApp
  • MacThrottle คือ แอปบนพื้นฐาน SwiftUI ที่จะแจ้งให้เห็นบนแถบเมนูแบบภาพเมื่อ Mac จำกัดประสิทธิภาพเพราะเครื่องร้อนเกินไป - โอเพนซอร์ส
  • เปรียบเทียบ API ProcessInfo.thermalState ของ macOS กับคำสั่ง powermetrics เพื่อสำรวจวิธีตรวจจับสถานะความร้อนจริงของระบบให้แม่นยำ
  • สุดท้ายได้ใช้ การแจ้งเตือนที่ thermald เผยแพร่ไปยังระบบ notifyd ของ Darwin เพื่ออ่านสถานะความร้อนโดยไม่ต้องใช้สิทธิ์ root
  • แอปรวม กราฟอุณหภูมิ·ความเร็วพัดลม, ไอคอนเปลี่ยนสีตามสถานะ, และ การแจ้งเตือนของ macOS พร้อมรองรับการเปิดอัตโนมัติเมื่อเข้าสู่ระบบ
  • เป็นเครื่องมือสำหรับ ตรวจสอบสถานะการจัดการความร้อนของ Apple Silicon Mac แบบเรียลไทม์ ที่มีประโยชน์ต่อทั้งนักพัฒนาและผู้ใช้ระดับ power user ในการวินิจฉัยระบบ

การรับรู้ปัญหา thermal throttling บน Mac

  • เมื่อใช้จอภายนอก 4K 120Hz กับ M2 MacBook Air พบว่าเกิด ประสิทธิภาพตกและการตอบสนองหน่วง
    • แม้ไม่มีพัดลมจึงไม่สามารถสังเกตจากเสียงได้ แต่พบว่าขณะ CPU ใช้งาน 100% การใช้พลังงานกลับลดลง
  • ใช้ iStat Menus และ MX Power Gadget เพื่อตรวจสอบ ความถี่ CPU และกำลังไฟที่ลดลง และวินิจฉัยว่าเป็น thermal throttling
  • พบอาการเดียวกันใน M4 Max MacBook Pro เช่นกัน โดยกล่าวถึงว่าเป็นปัญหาจาก ข้อจำกัดด้านการออกแบบความร้อน ของรุ่น 14 นิ้ว
  • แม้ Apple Silicon จะยังมีประสิทธิภาพต่อวัตต์สูง แต่ก็ต้องการหา วิธีตรวจจับสถานะความร้อนโดยตรง

การตรวจสอบสถานะความร้อนบน macOS แบบโปรแกรม

  • macOS เปิดเผยสถานะความร้อนออกมาหลายวิธี แต่ ขาดความสม่ำเสมอ
  • วิธีที่ Apple แนะนำคือใช้ ProcessInfo.thermalState ของ Foundation
    • ตัวอย่างผลลัพธ์: nominal, fair, serious, critical
  • คำสั่ง powermetrics -s thermal ที่ต้องใช้สิทธิ์ root ก็ให้ข้อมูลเดียวกันเช่นกัน แต่
    ระดับการแบ่งสถานะของทั้งสองวิธีต่างกัน
    • เช่น fair ครอบคลุมทั้งสถานะ moderate และ heavy ของ powermetrics
  • ช่วงเวลาที่เกิด throttling จริงจะแสดงเป็น heavy ใน powermetrics แต่ ProcessInfo แยกไม่ออก

การใช้ thermald และระบบแจ้งเตือน Darwin

  • ข้อมูลของ powermetrics มาจาก ดีมอน thermald และ
    thermald จะเผยแพร่สถานะ thermal pressure ปัจจุบันเป็น เหตุการณ์ของระบบ notifyd
  • สามารถตรวจสอบสถานะได้ด้วยคำสั่ง notifyutil -g com.apple.system.thermalpressurelevel
  • ระดับ thermal pressure ที่นิยามไว้ในเฮดเดอร์ OSThermalNotification.h:
    • nominal, moderate, heavy, trapping, sleeping
  • ใช้โค้ด Swift เรียก notify_register_check และ notify_get_state เพื่อทำให้
    อ่านสถานะความร้อนแบบเรียลไทม์ได้โดยไม่ต้องใช้สิทธิ์ root

การพัฒนาแอป MacThrottle

  • ใช้ SwiftUI และ MenuBarExtra สร้างแอปสำหรับแถบเมนูโดยเฉพาะ
    • แสดงสถานะด้วยสีของไอคอนรูปเทอร์โมมิเตอร์ (เขียว→แดง)
    • ตั้งค่า LSUIElement ใน Info.plist เป็น true เพื่อปิดการแสดงไอคอนใน Dock

แนวทางเริ่มต้น: powermetrics พร้อม root helper

  • ช่วงแรกเพื่อใช้งาน powermetrics ที่ต้องใช้สิทธิ์ root
    จึงสร้าง helper process ด้วย LaunchDaemon และสคริปต์ bash
    • /usr/local/bin/mac-throttle-thermal-monitor จะบันทึกสถานะลงไฟล์ใน /tmp ทุก 10 วินาที
    • แอปจะอ่านไฟล์นั้นเป็นระยะเพื่อนำมาแสดงผล

การปรับปรุง: ใช้การแจ้งเตือน IPC ของ thermald

  • เปลี่ยนมาใช้วิธี subscribe เหตุการณ์ notifyd โดยตรง
    • ไม่ต้องใช้สิทธิ์ root และทำให้โค้ดเรียบง่ายขึ้น

การแสดงอุณหภูมิและความเร็วพัดลม

  • แสดงกราฟอุณหภูมิ CPU/GPU และความเร็วพัดลม
  • ตอนแรกเมื่อใช้ API ภายในของ IOKit อุณหภูมิที่แสดงต่ำกว่าความจริง (~80°C)
  • อ้างอิงโปรเจกต์โอเพนซอร์ส Stats แล้วเปลี่ยนไปใช้ อินเทอร์เฟซ SMC
    • ต้องใช้คีย์ต่างกันตามรุ่นของ SoC เช่น Tp0D, Tf0E เป็นต้น
  • หาก SMC ใช้งานไม่ได้จะ fallback ไปใช้ IOKit

การทำกราฟบนแถบเมนู

  • กราฟจะแสดงข้อมูล 3 อย่างพร้อมกัน
    • สีพื้นหลัง: สถานะความร้อน (เขียว~แดง)
    • เส้นทึบ: อุณหภูมิ CPU
    • เส้นประ: สัดส่วนความเร็วพัดลม
  • เก็บข้อมูลทุก 2 วินาที และคงประวัติไว้ 10 นาที
  • ใช้ onContinuousHover เพื่อแสดง tooltip และ
    เพิ่ม .drawingGroup เพื่อให้ เรนเดอร์ด้วย GPU และแสดงผลลื่นไหลแม้บนจอ 120Hz

การแจ้งเตือน macOS และการเปิดอัตโนมัติ

  • เพิ่ม ฟังก์ชันส่งการแจ้งเตือน เมื่อสถานะความร้อนเปลี่ยน
    • สามารถแจ้งเตือนเมื่อเปลี่ยนเป็นสถานะที่กำหนดหรือเมื่อกลับสู่สภาพปกติ
  • รองรับการตั้งค่าเปิดอัตโนมัติเมื่อเข้าสู่ระบบด้วย API SMAppService
    • ควบคุมผ่านเมธอด register() / unregister() / status

การแจกจ่ายและการใช้งาน

  • เนื่องจากไม่มีบัญชี Apple Developer จึงไม่สามารถทำ notarization อย่างเป็นทางการ ได้
    • เมื่อติดตั้งจาก GitHub Releases ต้องไปอนุมัติด้วยตนเองใน Privacy and Security
    • บน Mac บางเครื่องอาจต้อง build ด้วย Xcode ด้วยตนเอง จึงจะรันได้
  • วิธีติดตั้งและ build ระบุไว้ใน README ของ GitHub

บทสรุป

  • MacThrottle เป็นเครื่องมือขนาดเล็กสำหรับ เฝ้าดูสถานะ thermal throttling ของ Apple Silicon Mac แบบเรียลไทม์
  • ทำงานได้โดยไม่ต้องใช้สิทธิ์ root และมอบ ฟีดแบ็กแบบภาพ·การแจ้งเตือน·กราฟ เพื่อช่วยให้
    นักพัฒนาและผู้ใช้ที่ทำงานหนักกับเครื่องเข้าใจ สถานะความร้อนของระบบ

1 ความคิดเห็น

 
GN⁺ 2025-12-29
ความคิดเห็นจาก Hacker News
  • เคยใช้ MacBook Pro i9 รุ่นปี 2019 และคิดว่าฟังก์ชันตรวจจับ thermal throttling น่าจะเขียนง่ายแค่นี้

    function isThermalThrottling() {
      return true;
    }
    

    พูดเล่นนะ แต่ตอนนั้นผิดหวังพอสมควรที่ซื้อ CPU i9 ราคาแพงมาแล้วกลับได้ประสิทธิภาพแย่กว่า i7

    • ฉันก็ใช้รุ่นเดียวกัน และแก้ปัญหาได้ด้วยการชาร์จจากพอร์ตด้านขวาเท่านั้น
      ไม่รู้เหมือนกันว่าทำไม แต่พอทำแบบนั้นแล้วอาการ throttling ก็หายไป
      ถึงอย่างนั้นก็ยังใช้อยู่เพราะคุ้นกับ workflow บน macOS และ Logic
      จะย้ายไป Linux ก็ได้ แต่ตอนนี้มันก็ยังเป็นเครื่องที่ใช้งานได้ดีพอสมควร
    • ฉันก็เคยใช้รุ่น 2019 i9 เหมือนกัน และพอติด thermal pad ที่โมดูล VRM แล้วมันเหมือนได้คอมเครื่องใหม่ไปเลย
      ก่อนหน้านั้นเวลาใช้จอนอกสองจอพร้อม Adobe Creative Suite จะ throttling หนักมาก แต่ pad นี้ช่วยแก้ได้
      ข้อเสียคือใต้เครื่องจะร้อนจนวางบนตักลำบาก แต่ก็ไม่เสียใจเลย
      ตอนนี้เปลี่ยนมาใช้ M3 MacBook Air (RAM 24GB) แล้วและพอใจมาก
      ถ้าใครยังใช้รุ่นปี 2019 อยู่ แนะนำให้ลองพิจารณาดัดแปลงใส่ VRM thermal pad จริงๆ
    • จริงๆ แล้วฉันคิดว่า i9 เองก็เป็น CPU ที่ไม่เหมาะกับโน้ตบุ๊ก ตั้งแต่แรก
      ฝั่ง Dell ก็เหมือนกัน พอเปลี่ยนจาก i9 เป็น i7 แล้วดีขึ้นเยอะ
      เรียกได้ว่าโดนการตลาดแบบ “เลขใหญ่กว่า = CPU ดีกว่า” หลอก
    • ฉันก็เจอปัญหาเดียวกัน โดยเฉพาะตอนต่อ จอนอกสองจอ
      หลังจากนั้นพอเปลี่ยนไป M1 Max ก็เหมือนคนละโลก
      ตอนนี้อัปเกรดเป็น M3 Max แล้ว และคิดว่า Apple Silicon น่าจะใช้งานได้ยาวๆ
    • โน้ตบุ๊กเครื่องนั้นคือ คอมพิวเตอร์ที่แย่ที่สุด ที่ฉันเคยใช้
      เปิดเครื่องปุ๊บพัดลมก็ดังทันที และพอต่ออุปกรณ์ Thunderbolt ก็มักเจอ kernel panic บ่อยๆ
      ส่วน M1 Max MBP ที่ใช้อยู่ตอนนี้เสถียรสมบูรณ์แบบ
  • โปรเจ็กต์นี้ดูดีทีเดียว
    แต่การพัฒนาบน macOS ก็ยากขึ้นเรื่อยๆ และถึงจะตรวจจับ throttling ได้ ก็ยังสงสัยว่า จะทำอะไรต่อได้จริงแค่ไหน
    เพราะปรับรอบพัดลมก็ไม่ได้ และ undervolt ก็คงทำไม่ได้ไม่ใช่หรือ?

    • สำหรับฉันใช้ iStat Menus ปรับ fan curve เอง
      เพราะค่าเริ่มต้นมันช้าเกินไปจน throttling เกิดก่อน
      บน Apple Silicon ถ้าใช้ High Power Mode พัดลมจะหมุนเร็วขึ้น
      ตอนนี้ฉันไม่ได้ใช้ curve แบบปรับเองแล้ว แต่บน 14" M4 Max มันค่อนข้างเสียงดัง
      ส่วน MacBook Air ไม่มีพัดลม ก็ทำได้แค่หาทางระบายความร้อนออกไป
    • ฉันใช้ Macs Fan Control เพื่อปรับ RPM พัดลมตามอุณหภูมิ CPU
      ค่าปกติมันขึ้นไปเกิน 90 องศา เลยตั้งให้ conservative มากขึ้น
      ลิงก์ GitHub
    • แอปแบบนี้จำเป็นมาก และตอนนี้ก็มีแล้ว
      บางครั้งโปรเซสบางตัวทำงานหนักผิดปกติจนเกิด throttling แต่กว่าจะสังเกตได้ แบตเตอรี่ก็ลดไปครึ่งหนึ่งแล้ว
    • สุดท้ายแล้วสิ่งที่ทำได้ก็มีแค่ ปิดแอปหรือพักเครื่องสักครู่
      ปัญหาแบบนี้เกิดบ่อยเวลามีแอปทำงานอยู่เบื้องหลังเยอะๆ
  • ถ้าเอาเข้า Homebrew ก็จะได้ code signing และ notarization ฟรี
    ถ้าปล่อยแจกแบบนั้นได้ก็คงดีมาก

    • ข้อมูลดีมาก อยากรู้เหมือนกันว่ามี วิธีเซ็นสำหรับ Windows แบบฟรี หรือเปล่า
    • อ้อ ไม่เคยรู้มาก่อน นึกว่าขึ้นอยู่กับการตั้งค่าของนักพัฒนา เดี๋ยวต้องไปหาข้อมูลเพิ่ม
  • สมมติฐานของฉันคือปัญหาไม่ได้อยู่ที่ CPU แต่เป็น คอนโทรลเลอร์ USB ที่ทำให้ความร้อนสะสมจนเต็ม
    ไม่ใช่ CPU/GPU ที่ร้อน แต่เป็นตัวเครื่องที่ร้อนเกินจนระบายความร้อนต่อไม่ได้ สุดท้ายเลยเกิด throttling
    น่าจะต้องลองทดสอบกับอะแดปเตอร์หรือจออื่นดู

    • ฉันก็ใช้ 2019 i9 และพอ เปลี่ยนพอร์ตชาร์จ แล้วอาการ throttling ก็หายไป
      ดูเหมือนที่คุณพูดจะถูก
    • ฉันยังเข้าใจไม่หมด แต่ M2 Air ของฉันก็มีอาการคล้ายกัน
      ถ้าต่อกับจอ 4K 144Hz แล้วเปิด Zoom หรือสตรีมวิดีโอหลายรายการพร้อมกัน เครื่องจะร้อนมาก
      เลยมองว่าน่าจะเป็นเพราะภาระงานสูงเฉยๆ มากกว่าจะเป็นคอนโทรลเลอร์ USB
    • ปรากฏการณ์แบบนี้เรียกว่า thermal soaking
  • เหมือนเว็บจะล่มเพราะทราฟฟิกพุ่ง
    ส่วนรีโพอยู่ที่ angristan/MacThrottle

    • แก้เรียบร้อยแล้ว Cloudflare Workers ถูกตั้งเป็นโหมด fail closed เลยบล็อกทราฟฟิกอยู่
  • ใน iStat Menus ถ้า CPU ใช้ 100% แต่การใช้พลังงานต่ำ ก็อาจคิดได้ว่าเป็น throttling
    แต่ถ้าต่อกับ ที่ชาร์จ USB-C กำลังต่ำ ก็จะเกิดอาการเดียวกันได้
    น่าจะดีถ้าเพิ่มฟีเจอร์ตรวจจับกำลังไฟของที่ชาร์จ

    • ฉันก็เคยเจอปัญหาเดียวกันตอนเล่น D&D บน M1 MacBook Air
      ตอนเสียบชาร์จเครื่องจะร้อนขึ้นและ throttling หนัก แต่พอชาร์จไว้ล่วงหน้าก่อนเริ่มเซสชันก็หาย
    • เมื่อก่อนฉันเคยเจอ อะแดปเตอร์ไฟจ่ายไม่พอ จนตอนเล่นเกมแบตหมดแล้วเครื่องดับ
      หลังจากนั้นก็เข้าใจเลยว่าทำไมรุ่นถัดๆ มาถึงมีอะแดปเตอร์ที่ใหญ่ขึ้น
    • ถ้าอย่างนั้นก็สงสัยว่าทำไม การดูแค่อุณหภูมิของคอร์ถึงใช้ตัดสิน throttling ไม่ได้
      อุณหภูมิควรเป็นตัวแปรควบคุมโดยตรงไม่ใช่หรือ?
    • iStat Menus แสดงกำลังไฟของที่ชาร์จได้ก็จริง แต่ก็ยังสงสัยอยู่ดีว่าทำไมปรากฏการณ์นี้ถึงเกิดขึ้น
  • ถ้าเอา การใช้ CPU และพลังงานของระบบไปแสดงบนแถบเมนู ก็จะเห็นความผิดปกติได้ทันที
    exelban/stats

    • ฉันก็เริ่มสงสัยว่าเป็น throttling ครั้งแรกจากวิธีนี้
      เพราะเห็นว่า CPU ใช้สูง แต่การใช้พลังงานกลับลดลง
  • หวังว่า MacBook Air M5 รุ่นถัดไปจะมี ระบบระบายความร้อนแบบ Vapor Chamber
    ตอนนี้เหมือน Apple ให้ความสำคัญกับการลดเสียงมากกว่าการระบายความร้อน
    เลยบังคับความเร็วพัดลมขั้นต่ำไว้ต่ำมาก

    • Vapor Chamber ดีสำหรับ กระจายความร้อนแบบฉับพลัน แต่สุดท้ายความร้อนก็ต้องถูกส่งไปที่ ตัวเครื่องอะลูมิเนียม อยู่ดี
      พอตัวเครื่องเข้าสู่สมดุลความร้อนกับสภาพแวดล้อมแล้ว ปริมาณการระบายก็จะชนเพดาน
      ถ้ามีพัดลม แผ่นทองแดงกับลมก็ช่วยแก้ได้เพียงพอ
      สุดท้ายแล้วมันคือปัญหาเรื่อง การอนุรักษ์พลังงาน
  • ดูเหมือนจะมี บั๊กการแจ้งเตือน thermal pressure
    เลยอยากรู้ว่าในแอปเจอปัญหาแบบนั้นไหม
    ประเด็นที่เกี่ยวข้อง

    • ฉันก็เคยเห็นตอนใช้ ProcessInfo.processInfo.thermalState ว่าสถานะไม่อัปเดต
      แต่กับ วิธีแจ้งเตือนผ่าน thermald ที่ใช้อยู่ตอนนี้ไม่มีปัญหาแบบนั้น
  • สงสัยว่าทำไมถึงประกาศ Darwin API โดยตรง ด้วย @_silgen_name
    ใช้ import Darwin แล้วเข้าถึงไม่ได้หรือ?

    • ดูเหมือนว่าแม้จะ import Darwin อย่างเดียว ก็ยังไม่ expose API ตัวนั้นออกมา