เหตุใดสถานะที่แชร์จึงทำให้ประสิทธิภาพลดลง


19

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

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

คำถามคือ ... เนื่องจากไม่มีการล็อคทำไมการแนะนำซิงเกิลตันนี้จึงสร้างผลงานได้อย่างยอดเยี่ยม? เกิดอะไรขึ้นภายใต้ฝาครอบที่สามารถอธิบายสิ่งนี้ได้?

เพื่อยืนยันการเข้าถึงซิงเกิลใหม่นี้เป็นการเปลี่ยนแปลงเพียงอย่างเดียวและฉันสามารถสร้างสิ่งนี้ได้อย่างน่าเชื่อถือเพียงแค่แสดงความคิดเห็นการเรียกไปยังแคช


8
คุณชี้ profiler ที่รหัสหรือไม่
Timo Geusch

2
การทำโปรไฟล์ไม่น่าจะตอบคำถามนี้เว้นแต่ว่าคุณกำลังทำโปรไฟล์ CLR และอาจเป็นเคอร์เนลของ windows (ไม่ใช่เรื่องง่ายสำหรับโปรแกรมเมอร์ทั่วไป)
Igby Largeman

1
@JoeGeeky เอาล่ะฉันเดาว่าสิ่งเดียวที่จะทำให้ฉันที่นี่คือ +1 และเป็นที่ชื่นชอบ! ดูเหมือนว่าแปลกเพราะทั้งคู่อยู่ในระดับเดียวกันในทางอ้อมและควรใส่ในแคชโปรเซสเซอร์ต่อไป ฯลฯ ...
สูงสุด

2
FWIT ฉันวางไข่สองสามครั้งและใช้ตัวนับจำนวนหนึ่ง ฉันสร้างอินสแตนซ์ของคลาส singleton, lockedSingleton และ dict <string, string> หลังจากการเริ่มต้นครั้งแรกของแต่ละครั้งการรันต่อเนื่องจะใช้เวลาประมาณ 2000ns สำหรับวัตถุที่กำหนด พจนานุกรมวิ่งช้าลง 2x อาจเกิดจากรหัสคอนสตรัคเตอร์ ... มันช้ากว่าการล็อคด้วยตัวเอง เมื่อพิจารณาถึง GC ทั้งหมด, การจัดการ OS ของเธรดคิวและค่าใช้จ่ายอื่น ๆ ... ไม่แน่ใจว่าใครสามารถตอบคำถามนี้ได้อย่างแท้จริง แต่จากผลลัพธ์ของฉันฉันไม่เชื่อว่าปัญหาเกี่ยวข้องกับ Singletons ไม่ใช่ถ้ามันถูกนำไปใช้เหมือนใน MSDN ไม่รวมการปรับให้เหมาะสมของคอมไพเลอร์
P.Brian.Mackey

1
@JoeGeeky - ความคิดอื่น: การใช้แคชเพิ่มระดับของการอ้อมหรือไม่? หากเข้าถึงบ่อยการไล่ล่าตัวชี้พิเศษ deref (หรือ MSIL equiv) สามารถเพิ่มเวลาผ่านการคัดลอกทางอ้อมน้อยกว่าแบบโลคอล
sdg

คำตอบ:


8

อาจเป็นไปได้ว่ารัฐที่ไม่เปลี่ยนรูปแบบนั้นจะแชร์แคชไลน์กับบางสิ่งที่ไม่แน่นอน ในกรณีนี้การเปลี่ยนแปลงสถานะที่ไม่แน่นอนที่อยู่ใกล้เคียงอาจมีผลบังคับใช้การ resynch ของแคชบรรทัดนี้ข้ามคอร์ซึ่งอาจทำให้ประสิทธิภาพลดลง


3
ดูเหมือนว่าfalse sharingสถานการณ์ที่คุณอธิบายไว้ เพื่อแยกว่าฉันจะต้องโปรไฟล์ L2 แคช โชคไม่ดีที่เหล่านี้เป็นประเภทการอ้างอิงดังนั้นการเพิ่มพื้นที่บัฟเฟอร์จะไม่เป็นตัวเลือกหากนี่คือสิ่งที่เกิดขึ้นจริง
JoeGeeky

3

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

หากโอกาสของคุณคือกุญแจคุณอาจมี: ข่าวลือว่าสตริงนั้นทำตัวเหมือนวัตถุที่ไม่เปลี่ยนรูป แต่เพื่อประโยชน์ในการปรับแต่งบางอย่างพวกมันจะถูกนำไปใช้ในรูปแบบที่ไม่แน่นอนด้วยทุกสิ่งที่เกี่ยวข้องกับมัลติเธรด .

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

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

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

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.