เผยแพร่
Android 11 (API ระดับ 30) - Thermal API
Android 12 (API ระดับ 31) - API ของ NDK
(ตัวอย่าง) Android 15 (DP1) - getThermalHeadroomThresholds()
ประสิทธิภาพที่อาจเกิดขึ้นของแอปจะถูกจำกัดโดยสถานะความร้อนของ อุปกรณ์ ซึ่งอาจแตกต่างกันไปตามลักษณะต่างๆ เช่น สภาพอากาศ การใช้งานล่าสุด และการออกแบบการระบายความร้อนของอุปกรณ์ อุปกรณ์จะรักษาประสิทธิภาพในระดับสูงได้เพียงระยะเวลาหนึ่งเท่านั้นก่อนที่จะถูกจำกัดความร้อน เป้าหมายหลักของการติดตั้งใช้งานควรเป็นการบรรลุเป้าหมายด้านประสิทธิภาพโดยไม่เกินข้อจำกัดด้านความร้อน Thermal API ช่วยให้ทำได้โดยไม่ต้อง มีการเพิ่มประสิทธิภาพเฉพาะอุปกรณ์ นอกจากนี้ เมื่อแก้ไขข้อบกพร่องด้านประสิทธิภาพ การทราบว่าสถานะความร้อนของอุปกรณ์จำกัดประสิทธิภาพหรือไม่ก็เป็นสิ่งสำคัญ
โดยปกติแล้ว Game Engine จะมีพารามิเตอร์ประสิทธิภาพรันไทม์ที่สามารถปรับ ภาระงานที่ Engine ใส่ไว้ในอุปกรณ์ได้ เช่น พารามิเตอร์เหล่านี้สามารถตั้งค่า จำนวนเทรดของผู้ปฏิบัติงาน ความสัมพันธ์ของเทรดของผู้ปฏิบัติงานสำหรับคอร์ขนาดใหญ่และขนาดเล็ก ตัวเลือกความเที่ยงตรงของ GPU และความละเอียดของเฟรมบัฟเฟอร์ ใน Unity Engine นักพัฒนาเกมสามารถปรับปริมาณงานได้โดยการเปลี่ยนการตั้งค่าคุณภาพโดยใช้ปลั๊กอิน Adaptive Performance สำหรับ Unreal Engine ให้ใช้การตั้งค่าความสามารถในการปรับขนาดเพื่อปรับ ระดับคุณภาพแบบไดนามิก
เมื่ออุปกรณ์เข้าใกล้สถานะความร้อนที่ไม่ปลอดภัย เกมจะหลีกเลี่ยงการถูกควบคุมได้โดยการลดภาระงานผ่านพารามิเตอร์เหล่านี้ คุณควรตรวจสอบสถานะความร้อนของอุปกรณ์และปรับปริมาณงานของเอนจินเกม ล่วงหน้าเพื่อหลีกเลี่ยงการควบคุมปริมาณ
เมื่ออุปกรณ์ร้อนเกินไป ภาระงานจะต้อง ลดลงต่ำกว่าระดับประสิทธิภาพที่ยั่งยืนเพื่อระบายความร้อน หลังจาก ส่วนต่างของอุณหภูมิลดลงไปอยู่ในระดับที่ปลอดภัยมากขึ้นแล้ว เกมจะเพิ่ม การตั้งค่าคุณภาพได้อีกครั้ง แต่โปรดตรวจสอบว่าได้ตั้งค่าคุณภาพในระดับที่ยั่งยืนเพื่อ เวลาในการเล่นที่เหมาะสม
คุณตรวจสอบสถานะความร้อนของอุปกรณ์ได้โดยการสำรวจเมธอด
getThermalHeadroom วิธีนี้จะคาดการณ์ระยะเวลาที่อุปกรณ์จะ
รักษาระดับประสิทธิภาพปัจจุบันได้โดยไม่ร้อนเกินไป หากเวลาเหลือน้อยกว่าเวลาที่จำเป็นในการเรียกใช้เวิร์กโหลด เกมควรลดเวิร์กโหลดลงให้อยู่ในระดับที่ยั่งยืน เช่น เกมอาจเปลี่ยนไปใช้คอร์ขนาดเล็ก
ลดอัตราเฟรม หรือลดความเที่ยงตรง
ดาวน์โหลด Thermal Manager
หากต้องการใช้ Thermal API คุณจะต้องรับ Thermal Manager ก่อน
C++
AThermalManager* thermal_manager = AThermal_acquireManager();
Java
PowerManager powerManager = (PowerManager)this.getSystemService(Context.POWER_SERVICE);
คาดการณ์ Thermal Headroom ล่วงหน้า x วินาทีเพื่อควบคุมได้มากขึ้น
คุณขอให้ระบบคาดการณ์อุณหภูมิในอีก x วินาทีข้างหน้าได้โดยใช้ ปริมาณงานปัจจุบัน ซึ่งช่วยให้คุณควบคุมได้อย่างละเอียดมากขึ้นและมีเวลาตอบสนองมากขึ้น โดยการลดปริมาณงานเพื่อป้องกันไม่ให้เกิดการควบคุมความร้อน
ผลลัพธ์มีตั้งแต่ 0.0f (ไม่มีการจำกัดอัตรา
THERMAL_STATUS_NONE)
เป็น 1.0f (การควบคุมปริมาณอย่างหนัก
THERMAL_STATUS_SEVERE)
หากเกมของคุณมีระดับคุณภาพกราฟิกที่แตกต่างกัน คุณสามารถทำตามหลักเกณฑ์เกี่ยวกับส่วนต่างของอุณหภูมิ
C++
float thermal_headroom = AThermal_getThermalHeadroom(0);
ALOGI("ThermalHeadroom: %f", thermal_headroom);
Java
float thermalHeadroom = powerManager.getThermalHeadroom(0);
Log.d("ADPF", "ThermalHeadroom: " + thermalHeadroom);
หรือจะดูสถานะความร้อนเพื่อความชัดเจนก็ได้
อุปกรณ์แต่ละรุ่นอาจได้รับการออกแบบแตกต่างกัน อุปกรณ์บางเครื่องอาจระบายความร้อนได้ดีกว่า จึงทนต่อส่วนต่างของอุณหภูมิที่สูงขึ้นได้ก่อนที่จะถูกจำกัด หากต้องการอ่านการจัดกลุ่มช่วงของ ส่วนต่างอุณหภูมิที่ง่ายขึ้น ให้ตรวจสอบสถานะความร้อนเพื่อทำความเข้าใจค่า ส่วนต่างอุณหภูมิในอุปกรณ์ปัจจุบัน
C++
AThermalStatus thermal_status = AThermal_getCurrentThermalStatus(thermal_manager);
ALOGI("ThermalStatus is: %d", thermal_status);
Java
int thermalStatus = powerManager.getCurrentThermalStatus();
Log.d("ADPF", "ThermalStatus is: " + thermalStatus);
รับการแจ้งเตือนเมื่อสถานะความร้อนเปลี่ยนแปลง
นอกจากนี้ คุณยังหลีกเลี่ยงการสำรวจthermalHeadroomจนกว่าthermalStatusจะถึงระดับหนึ่งได้ด้วย (เช่น
THERMAL_STATUS_LIGHT)
โดยลงทะเบียนการเรียกกลับเพื่อให้ระบบแจ้งเตือนคุณทุกครั้งที่สถานะมีการเปลี่ยนแปลง
C++
int result = AThermal_registerThermalStatusListener(thermal_manager, callback);
if ( result != 0 ) {
// failed, check whether you have previously registered callback that
// hasn’t been unregistered
}
Java
// PowerManager.OnThermalStatusChangedListener is an interface, thus you can
// also define a class that implements the methods
PowerManager.OnThermalStatusChangedListener listener = new
PowerManager.OnThermalStatusChangedListener() {
@Override
public void onThermalStatusChanged(int status) {
Log.d("ADPF", "ThermalStatus changed: " + status);
// check the status and flip the flag to start/stop pooling when
// applicable
}
};
powerManager.addThermalStatusListener(listener);
อย่าลืมนำ Listener ออกเมื่อเสร็จสิ้น
C++
int result = AThermal_unregisterThermalStatusListener(thermal_manager, callback);
if ( result != 0 ) {
// failed, check whether the callback has been registered previously
}
Java
powerManager.removeThermalStatusListener(listener);
ทำความสะอาดข้อมูล
เมื่อเสร็จแล้ว คุณจะต้องล้างข้อมูล thermal_manager ที่คุณได้รับ หากคุณใช้ Java ระบบจะรวบรวมข้อมูลอ้างอิง PowerManager ให้คุณโดยอัตโนมัติ แต่หากคุณใช้ Java API ผ่าน JNI และเก็บข้อมูลอ้างอิงไว้ โปรดอย่าลืมล้างข้อมูลอ้างอิง
C++
AThermal_releaseManager(thermal_manager);
ดูคำแนะนำฉบับสมบูรณ์เกี่ยวกับวิธีใช้ Thermal API ในเกม C++ แบบเนทีฟโดยใช้ทั้ง C++ API (NDK API) และ Java API (ผ่าน JNI) ได้ที่ส่วนผสานรวม Thermal API ในส่วนCodelab เกี่ยวกับความสามารถในการปรับตัว
หลักเกณฑ์เกี่ยวกับส่วนต่างของอุณหภูมิ
คุณตรวจสอบสถานะความร้อนของอุปกรณ์ได้โดยการสำรวจเมธอด
getThermalHeadroom
วิธีนี้จะคาดการณ์ระยะเวลาที่อุปกรณ์จะรักษาระดับประสิทธิภาพปัจจุบันได้ก่อนที่จะถึงTHERMAL_STATUS_SEVERE
เช่น หาก getThermalHeadroom(30) แสดงผล 0.8 แสดงว่าในอีก 30 วินาที
คาดว่าเฮดรูมจะอยู่ที่ 0.8 ซึ่งอยู่ห่างจากขีดจำกัดการควบคุมอย่างรุนแรงหรือ 1.0 เป็นระยะทาง 0.2 หากเวลาที่เหลืออยู่น้อยกว่าเวลาที่จำเป็นในการเรียกใช้ภาระงาน เกมของคุณควรลดภาระงานลงให้อยู่ในระดับที่ยั่งยืน ตัวอย่างเช่น เกมสามารถลดอัตราเฟรม ลดความเที่ยงตรง หรือ
ลดการทำงานของการเชื่อมต่อเครือข่าย
สถานะความร้อนและความหมาย
- หากอุปกรณ์ไม่ได้ถูกจำกัดความเร็วเนื่องจากความร้อน ให้ทำดังนี้
- มีการจำกัดอัตรา แต่ไม่มีผลกระทบต่อประสิทธิภาพอย่างมีนัยสำคัญ
- การควบคุมปริมาณที่ส่งผลต่อประสิทธิภาพอย่างมาก
ข้อจำกัดของอุปกรณ์ใน Thermal API
API ความร้อนมีข้อจำกัดที่ทราบหรือข้อกำหนดเพิ่มเติมบางอย่างเนื่องจากการติดตั้งใช้งาน API ความร้อนในอุปกรณ์รุ่นเก่า ข้อจำกัดและวิธี แก้ไขมีดังนี้
- อย่าเรียกใช้ API
GetThermalHeadroom()บ่อยเกินไป หากดำเนินการดังกล่าว API จะแสดงNaNคุณไม่ควรเรียกใช้มากกว่า 1 ครั้งทุกๆ 10 วินาที - หลีกเลี่ยงการเรียกจากหลายเธรด เนื่องจากจะทำให้ควบคุมความถี่ในการเรียกได้ยากขึ้น และอาจทำให้ API แสดงผล
NaN - หากค่าเริ่มต้นของ
GetThermalHeadroom()เป็น NaN แสดงว่า API ไม่พร้อมใช้งานในอุปกรณ์ - หาก
GetThermalHeadroom()แสดงค่าสูง (เช่น 0.85 ขึ้นไป) และGetCurrentThermalStatus()ยังคงแสดงTHERMAL_STATUS_NONEอยู่ สถานะ อาจยังไม่อัปเดต ใช้ฮิวริสติกเพื่อประมาณสถานะการควบคุมอุณหภูมิที่ถูกต้อง หรือใช้getThermalHeadroom()โดยไม่มีgetCurrentThermalStatus()
ตัวอย่างการคาดคะเน
- ตรวจสอบว่าอุปกรณ์รองรับ Thermal API
isAPISupported()จะตรวจสอบค่าของการเรียกครั้งแรกไปยังgetThermalHeadroomเพื่อให้แน่ใจว่าค่าดังกล่าวไม่ใช่ 0 หรือ NaN และ ข้ามการใช้ API หากค่าแรกเป็น 0 หรือ NaN - หาก
getCurrentThermalStatus()แสดงผลค่าอื่นที่ไม่ใช่THERMAL_STATUS_NONEแสดงว่าอุปกรณ์กำลังถูกจำกัดความเร็วเนื่องจากความร้อน - หาก
getCurrentThermalStatus()แสดงTHERMAL_STATUS_NONEต่อไปเรื่อยๆ ไม่ได้หมายความว่าอุปกรณ์ไม่ได้ถูกจำกัดความเร็วเนื่องจากความร้อน ซึ่งอาจหมายความว่าอุปกรณ์ไม่รองรับgetCurrentThermalStatus()ตรวจสอบค่าที่ส่งคืนของgetThermalHeadroom()เพื่อให้แน่ใจว่าอุปกรณ์มีสภาพเป็นไปตามที่ระบุ - หาก
getThermalHeadroom()แสดงค่า > 1.0 สถานะอาจเป็นTHERMAL_STATUS_SEVEREหรือสูงกว่า ให้ลดภาระงานทันที และคงภาระงานไว้ในระดับต่ำจนกว่าgetThermalHeadroom()จะแสดงค่าที่ต่ำกว่า - หาก
getThermalHeadroom()แสดงค่า 0.95 สถานะอาจเป็นTHERMAL_STATUS_MODERATEหรือสูงกว่านั้น ลดภาระงานทันทีและคอยสังเกตเพื่อป้องกันไม่ให้ค่าสูงขึ้น - หาก
getThermalHeadroom()แสดงค่า 0.85 สถานะอาจเป็นTHERMAL_STATUS_LIGHTโปรดระมัดระวังและลดภาระงานหากเป็นไปได้
Pseudocode:
bool isAPISupported() {
float first_value_of_thermal_headroom = getThermalHeadroom();
if ( first_value_of_thermal_headroom == 0 ||
first_value_of_thermal_headroom == NaN ) {
// Checked the thermal Headroom API's initial return value
// it is NaN or 0,so, return false (not supported)
return false;
}
return true;
}
if (!isAPISupported()) {
// Checked the thermal Headroom API's initial return value, it is NaN or 0
// Don’t use the API
} else {
// Use thermalStatus API to check if it returns valid values.
if (getCurrentThermalStatus() > THERMAL_STATUS_NONE) {
// The device IS being thermally throttled
} else {
// The device is not being thermally throttled currently. However, it
// could also be an indicator that the ThermalStatus API may not be
// supported in the device.
// Currently this API uses predefined threshold values for thermal status
// mapping. In the future you may be able to query this directly.
float thermal_headroom = getThermalHeadroom();
if ( thermal_headroom > 1.0) {
// The device COULD be severely throttled.
} else if ( thermal_headroom > 0.95) {
// The device COULD be moderately throttled.
} else if ( thermal_headroom > 0.85) {
// The device COULD be experiencing light throttling.
}
}
}
แผนภาพ