ทำไม Farseer 2.x จัดเก็บขมับเป็นสมาชิกและไม่อยู่ในสแต็ก (.สุทธิ)


10

UPDATE: คำถามนี้หมายถึง Farseer 2.x 3.x ที่ใหม่กว่าดูเหมือนจะไม่ทำเช่นนี้

ฉันใช้ Farseer Physics Engine อย่างกว้างขวางในขณะนี้และฉันสังเกตเห็นว่าดูเหมือนว่าจะเก็บค่าชั่วคราวจำนวนมากในฐานะสมาชิกของคลาสและไม่ได้อยู่ในสแต็กอย่างที่คาดไว้

นี่คือตัวอย่างจากBodyชั้นเรียน:

private Vector2 _worldPositionTemp = Vector2.Zero;

private Matrix _bodyMatrixTemp = Matrix.Identity;
private Matrix _rotationMatrixTemp = Matrix.Identity;
private Matrix _translationMatrixTemp = Matrix.Identity;

public void GetBodyMatrix(out Matrix bodyMatrix)
{
    Matrix.CreateTranslation(position.X, position.Y, 0, out _translationMatrixTemp);
    Matrix.CreateRotationZ(rotation, out _rotationMatrixTemp);
    Matrix.Multiply(ref _rotationMatrixTemp, ref _translationMatrixTemp, out bodyMatrix);
}

public Vector2 GetWorldPosition(Vector2 localPosition)
{
    GetBodyMatrix(out _bodyMatrixTemp);
    Vector2.Transform(ref localPosition, ref _bodyMatrixTemp, out _worldPositionTemp);
    return _worldPositionTemp;
}

ดูเหมือนว่าเป็นการเพิ่มประสิทธิภาพด้วยมือ แต่ฉันไม่เห็นว่าสิ่งนี้อาจช่วยประสิทธิภาพได้อย่างไร (ถ้ามีอะไรฉันคิดว่ามันจะเจ็บด้วยการทำให้วัตถุมีขนาดใหญ่ขึ้น)

คำตอบ:


6

แม้ว่าในประเภทค่า. NET จะถูกเก็บไว้ในสแต็กทำให้มีค่าใช้จ่ายในการจัดสรรน้อยที่สุด แต่ก็ไม่ได้ลดค่าใช้จ่ายในการเริ่มต้น

ในกรณีนี้เรามีชุดของฟังก์ชั่นที่ใช้เมทริกซ์ชั่วคราวหนึ่งหรือสองตัวซึ่งจะส่งผลให้การเริ่มต้นของ 16-32 ลอยต่อการโทร แม้ว่าวิธีนี้อาจดูไม่สำคัญ แต่ถ้าใช้วิธีการนั้นบ่อยครั้งมากพอ (กล่าวคือพันและพันครั้งต่อเฟรม) ค่าใช้จ่ายโดยรวมอาจมีผลกระทบที่มีความหมาย หากเทคนิคดังกล่าวมีการใช้อย่างเป็นระบบในทุกวิธีดังกล่าวค่าใช้จ่ายในการกำจัดอาจมีจำนวนมาก

ในขณะที่การใช้เทคนิคดังกล่าวช่วยลดความสามารถในการจัดเตรียมความปลอดภัยของเธรดในระดับต่อวัตถุโดยทั่วไปแล้วมันไม่ฉลาดที่จะรับประกันการใช้งานในระดับย่อย


คุณแน่ใจหรือไม่ หนึ่งคิดว่าฉันมีก็คือมันอาจจะหลีกเลี่ยงการโทรก่อสร้าง แต่สำหรับประเภทค่าคุณไม่จำเป็นต้องเรียกตัวสร้าง - รวมถึงตัวสร้างแบบไร้พารามิเตอร์เริ่มต้น - ถ้าคุณจะตั้งสมาชิกทั้งหมด (หรือส่งเป็นoutพารามิเตอร์) ฉันค่อนข้างแน่ใจว่าจุดทั้งหมดของกฎนี้คือเพื่อให้คอมไพเลอร์สามารถข้าม zeroing หน่วยความจำ - ใช่ไหม? (มันคือจริงๆว่าช้าที่จะย้ายตัวชี้สแต็ค?)
แอนดรูรัสเซล

น่าแปลกใจใช่ไหม น่าเสียดายถ้าคุณตรวจสอบ IL ที่สร้างขึ้นเมทริกซ์ชั่วคราวจะเริ่มต้นได้ การทดสอบอย่างรวดเร็วไม่กี่แสดงให้เห็นว่ารุ่นสมาชิกชั่วคราวคือ ~ 10-15% เร็วขึ้น
Jason Kozak

1
ผมตะลึง ใน "การทำความเข้าใจกับ XNA Framework Performance" (GDC2008) Shawn Hargreaves พูดถึง structs: "[JIT] มักจะคิดออก: 'ในบรรทัดถัดไปเขาตั้งค่าทั้งสามฟิลด์ [ของ Vector3] ในทันทีดังนั้นฉันจึงไม่จำเป็นต้อง ในการเริ่มต้นมันเป็นศูนย์" ข้อมูลของฉันมาจากไหน แต่ในการฟังอีกครั้งตอนนี้เขาเพียง แต่บอกว่า "มักจะ" จุดถัดไปในการนำเสนอทันทีคือ JIT ทำงานแตกต่างจาก debugger ที่แนบมาซึ่งส่งผลต่อประสิทธิภาพ (คุณทดสอบอย่างไร) นอกจากนี้: เขากำลังพูดถึง JIT ที่นี่ด้วยดังนั้นบางที IL ก็ยังคง "ดี" (ตรวจสอบได้?)
Andrew Russell

อิลลินอยส์ได้รับการตรวจสอบผ่านทางกระจกสะท้อนแสงและการทดสอบที่ถูกเรียกใช้นอก IDE ที่สร้างขึ้นในรีลีส (บน Windows, ฉันไม่จำเป็นต้องเป็นสมาชิก CC ไปทดสอบกับ)
เจสัน Kozak

1
จากสิ่งนี้ - ฉันสงสัยว่ามันจะดีกว่า (และจะดีกว่านี้อีกหรือไม่) ที่จะทำให้สมาชิกชั่วคราวเหล่านั้นstatic(และ / หรือนำกลับมาใช้อย่างจริงจังมากขึ้น) ตัวอย่างเช่นในBodyชั้นเรียนใน Farseer มีสมาชิก 73 คนที่มีความ "จำเป็น"
Andrew Russell

-1

คำถามที่ดี. ฉันเป็นคน C # /. NET ที่คมชัดและน่าสนใจเล็กน้อยและนี่ดูเหมือนเป็นการตัดสินใจที่ค่อนข้างแปลกสำหรับฉัน สิ่งแรกที่กระโดดออกมาที่ฉันคือรหัสนี้ไม่ด้ายปลอดภัย ฉันไม่รู้ว่านี่เป็นปัญหาในระบบฟิสิกส์หรือไม่ แต่การจัดเก็บข้อมูลชั่วคราวนอกขอบเขตของวิธีการมักเป็นสูตรสำหรับภัยพิบัติ

สุจริตถ้าฉันพบรหัสประเภทนี้เป็นประจำในกรอบงานของ บริษัท อื่นฉันอาจลองค้นหากรอบงานอื่น


3
ไม่ตอบคำถามจริงๆ
Brian Ortiz

ใช่สิ่งที่ดีที่สุดที่ฉันสามารถทำได้คือยืนยันว่าเขาไม่ได้บ้าและดูเหมือนว่าจะไม่ได้รับประโยชน์ใด ๆ จากการใช้รหัสเช่นนั้น ค้นหาเจตนาที่แท้จริงเท่านั้นคือถามคนที่เขียนรหัส :)
Mike Strobel

ขอบคุณไมค์ ฉันเริ่มสงสัยว่านักพัฒนาดั้งเดิมเป็นคนบ้าไม่ใช่ฉัน แต่มันจะช่วยตรวจสอบเสมอ)
Andrew Russell

บางครั้งความปลอดภัยของเธรดสามารถรับประกันค่าใช้จ่ายได้สูงโดยเฉพาะอย่างยิ่งเมื่อเขียนไลบรารีการคำนวณ FP สำหรับแพลตฟอร์มที่ไม่ได้ใช้คำสั่ง SIMD
Jason Kozak

-1

GC ใน 360 นั้นโดยทั่วไปแล้วจะเป็นคอลเลกชัน GEN 2 เท่านั้นซึ่งมีราคาแพงดังนั้นตัวแปรชั่วคราวที่สร้างและลบออกทุกเฟรม (เช่นวัตถุ temp) ทำให้คอลเลกชันทั้งหมดทำงาน

ฉันสงสัยว่าพวกเขาทำเช่นนี้เพื่อนำวัตถุนั้นกลับมาใช้ใหม่และไม่ได้รวบรวม


1
สิ่งนี้เกิดขึ้นกับฉันเช่นกัน แต่สมาชิกชั่วคราวดูเหมือนจะเป็นประเภทค่าดังนั้นพวกเขาจะไม่ถูกจัดสรรในฮีปที่มีการจัดการอยู่แล้ว
Mike Strobel

2
ถูกต้อง แต่ถ้าพวกเขาเป็นสมาชิกชั้นเรียน หากพวกเขาเป็นคนในท้องถิ่น (วิธีการกำหนดขอบเขต) พวกเขาจะได้รับการจัดสรรในกอง คำถามคือทำไมพวกเขาไม่เพียงไปเส้นทางนั้น
Mike Strobel

1
@Blair - ตาม MSDN ( msdn.microsoft.com/en-us/library/bb203912.aspx ) Xbox360 ใช้. NET Compact Framework ดูเหมือนว่าความแตกต่างใน GC นั้นเกี่ยวข้องกับเรื่องนั้นดังนั้นฉันจึงติดตามเรื่องนั้นเพื่อการวิจัยเพิ่มเติมเกี่ยวกับเรื่องนี้
Logan Kincaid

1
@Blair: @Logan Kincaid ถูกต้อง Garbage Collector ของ CF ทำงานแตกต่างจากเฟรมเวิร์กปกติ มีการพูดคุยที่ดีเกี่ยวกับเรื่องนี้ใน XNA Game Studio 3.0 Unleashed - อย่างไรก็ตามหนังสือเล่มนี้จะล้าสมัยเมื่อมีการเปิดตัว 4.0
Steven Evers

1
@Blair: เนื่องจากสภาพแวดล้อมหน่วยความจำที่ จำกัด ของ 360 (และอุปกรณ์ส่วนใหญ่ที่กำหนดเป้าหมายผ่าน CF) จึงใช้ Mark & ​​Sweep GC ด้วยเหตุนี้การจัดสรรขนาดเล็กจำนวนมากจะทำให้เกิดการรวบรวมและเวลาการรวบรวมจะสัมพันธ์กับ # ของการอ้างอิง มีรายละเอียดมากมายที่นี่: download.microsoft.com/.../Mobility/…
Jason Kozak
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.