โครงการนี้ไม่ได้รับการดูแลอีกต่อไป !!!
OHC จะให้ประสิทธิภาพที่ดีทั้งในฮาร์ดแวร์สินค้าโภคภัณฑ์และระบบใหญ่โดยใช้สถาปัตยกรรมที่ไม่สม่ำเสมอ
ยังไม่มีผลการทดสอบประสิทธิภาพ - คุณอาจลองใช้เครื่องมือ - เบี้ยประกัน OHC ดูคำแนะนำด้านล่าง ความประทับใจขั้นพื้นฐานเกี่ยวกับความเร็วอยู่ในส่วน _benchmarking_
Java 8 VM ที่รองรับ 64 บิตและมี sun.misc.Unsafe
(Oracle JVMs บน X64 Intel CPU)
OHC มีเป้าหมายสำหรับ Linux และ OSX ควร ทำงานบน Windows และ UNIX OSS อื่น ๆ
OHC มีการใช้งานสองอย่างสำหรับคุณลักษณะรายการแคชที่แตกต่างกัน: - การใช้งาน _linked_ จัดสรรหน่วยความจำนอกกองสำหรับแต่ละรายการแต่ละรายการและทำงานได้ดีที่สุดสำหรับรายการขนาดกลางและขนาดใหญ่ - การใช้งาน _chunked_ จัดสรรหน่วยความจำนอกกองสำหรับแต่ละเซ็กเมนต์แฮชโดยรวมและมีไว้สำหรับรายการเล็ก ๆ
จำนวนเซ็กเมนต์ได้รับการกำหนดค่าผ่าน org.caffinitas.ohc.OHCacheBuilder
ค่าเริ่มต้นเป็น # of cpus * 2
และต้องเป็นพลังของ 2 รายการจะถูกกระจายไปทั่วเซ็กเมนต์โดยใช้บิตที่สำคัญที่สุดของรหัสแฮช 64 บิต การเข้าถึงในแต่ละเซ็กเมนต์จะถูกซิงโครไนซ์
แต่ละรายการแฮช-แมปจะถูกจัดสรรเป็นรายบุคคล รายการจะเป็นอิสระ (จัดการ) เมื่อพวกเขาไม่ได้อ้างอิงโดยแผนที่นอกกองเองหรือการอ้างอิงภายนอกใด ๆ เช่น org.caffinitas.ohc.DirectValueAccess
หรือ org.caffinitas.ohc.CacheSerializer
การออกแบบการใช้งานนี้จะช่วยลดเวลาที่ล็อคไว้ของเซ็กเมนต์ในเวลาอันสั้น ใส่/แทนที่การดำเนินการจัดสรรหน่วยความจำก่อนโทร org.caffinitas.ohc.CacheSerializer
เพื่อทำให้เป็นอนุกรมและค่าจากนั้นใส่รายการที่เตรียมไว้อย่างเต็มที่ในเซ็กเมนต์
การขับไล่ดำเนินการโดยใช้อัลกอริทึม LRU รายการที่เชื่อมโยงผ่านองค์ประกอบที่แคชทั้งหมดต่อเซ็กเมนต์ใช้เพื่อติดตามรายการคนโต
การจัดสรรหน่วยความจำแบบปิดการใช้งานนอกกอง
วัตถุประสงค์ของการใช้งานนี้คือการลดค่าใช้จ่ายสำหรับรายการแคชที่ค่อนข้างเล็กเมื่อเทียบกับการใช้งานที่เชื่อมโยงเนื่องจากหน่วยความจำสำหรับส่วนทั้งหมดถูกจัดสรรล่วงหน้า การใช้งานนี้เหมาะสำหรับรายการขนาดเล็กที่มีการใช้งานแบบอนุกรม Fast (DE) ของ org.caffinitas.ohc.CacheSerializer
การแบ่งส่วนเป็นเช่นเดียวกับในการใช้งานที่เชื่อมโยง จำนวนเซ็กเมนต์ได้รับการกำหนดค่าผ่าน org.caffinitas.ohc.OHCacheBuilder
ค่าเริ่มต้นเป็น # of cpus * 2
และต้องเป็นพลังของ 2 รายการจะถูกกระจายไปทั่วเซ็กเมนต์โดยใช้บิตที่สำคัญที่สุดของรหัสแฮช 64 บิต การเข้าถึงในแต่ละเซ็กเมนต์จะถูกซิงโครไนซ์
แต่ละเซ็กเมนต์แบ่งออกเป็นหลาย ๆ ชิ้น แต่ละเซ็กเมนต์มีหน้าที่รับผิดชอบส่วนหนึ่งของกำลังการผลิตทั้งหมด (capacity / segmentCount)
จำนวนหน่วยความจำนี้ได้รับการจัดสรรเมื่อล่วงหน้าระหว่างการเริ่มต้นและแบ่งออกเป็นจำนวนมากของชิ้นที่กำหนดค่าได้ ขนาดของแต่ละก้อนถูกกำหนดค่าโดยใช้ตัวเลือก chunkSize
ใน org.caffinitas.ohc.OHCacheBuilder
เช่นเดียวกับการใช้งานที่เชื่อมโยงรายการแฮชจะถูกทำให้เป็นแบบต่อเนื่องเป็นบัฟเฟอร์ชั่วคราวก่อนก่อนที่จะใส่ลงในเซ็กเมนต์ที่เกิดขึ้นจริง
รายการใหม่จะถูกวางลงในก้อนเขียนปัจจุบัน เมื่อก้อนนั้นเต็มก้อนที่ว่างเปล่าถัดไปจะกลายเป็นชิ้นเขียนใหม่ เมื่อชิ้นทั้งหมดเต็มรูปแบบที่ใช้น้อยที่สุดเมื่อเร็ว ๆ นี้รวมถึงรายการทั้งหมดที่มีอยู่จะถูกขับไล่
การระบุคุณสมบัติตัวสร้าง fixedKeyLength
และ fixedValueLength
จะช่วยลดอัตราการถือครองหน่วยความจำได้ 8 ไบต์ต่อรายการ
การทำให้เป็นอนุกรมการเข้าถึงโดยตรงและฟังก์ชั่น get-with-loader ไม่ได้รับการสนับสนุนในการใช้งานนี้
ในการเปิดใช้งานการใช้งาน chunked ให้ระบุ chunkSize
ใน org.caffinitas.ohc.OHCacheBuilder
หมายเหตุ: การใช้งานแบบ chunked ควรได้รับการพิจารณาการทดลอง
OHC สนับสนุนอัลกอริทึมการขับไล่สามครั้ง:
ใช้คลาส OHCacheBuilder
เพื่อกำหนดค่าพารามิเตอร์ที่จำเป็นทั้งหมดเช่น
โดยทั่วไปคุณควรทำงานกับตารางแฮชขนาดใหญ่ ยิ่งตารางแฮชที่ใหญ่ขึ้นเท่าไหร่รายการที่เชื่อมโยงในแต่ละพาร์ติชันแฮช-นั่นหมายถึงการเดินเชื่อมโยงที่เชื่อมโยงน้อยลงและประสิทธิภาพที่เพิ่มขึ้น
จำนวนเงินทั้งหมดของหน่วยความจำปิดฮีปคือตาราง ความจุ รวมบวกกับ ตารางแฮช แต่ละถังแฮช (ปัจจุบัน) ต้องใช้ 8 ไบต์ - ดังนั้นสูตรคือ capacity + segment_count * hash_table_size * 8
OHC จัดสรรหน่วยความจำนอกกองโดยผ่านข้อ จำกัด หน่วยความจำนอกกองของ Java โดยตรง ซึ่งหมายความว่าหน่วยความจำทั้งหมดที่จัดสรรโดย OHC ไม่ได้นับรวม -XX:maxDirectMemorySize
เนื่องจากการใช้งานที่เชื่อมโยงโดยเฉพาะอย่างยิ่งดำเนินการจัดสรร/ฟรีสำหรับแต่ละรายการให้พิจารณาว่าการกระจายตัวของหน่วยความจำสามารถเกิดขึ้นได้
ยังออกจากห้องส่วนหัวเนื่องจากการจัดสรรบางอย่างอาจยังคงอยู่ในเที่ยวบินและ "สิ่งอื่น ๆ " (ระบบปฏิบัติการ, JVM, ฯลฯ ) ต้องการหน่วยความจำ ขึ้นอยู่กับรูปแบบการใช้งานที่จำเป็นต้องใช้ห้องหัวเท่าไหร่ โปรดทราบว่าการใช้งานที่เชื่อมโยงจะจัดสรรหน่วยความจำในระหว่างการดำเนินการเขียน _Before_ มันถูกนับไปยังเซ็กเมนต์ซึ่งจะขับไล่รายการเก่า ซึ่งหมายความว่า: อย่าอุทิศหน่วยความจำที่มีอยู่ทั้งหมดให้กับ OHC
เราขอแนะนำให้ใช้ Jemalloc เพื่อให้การกระจายตัวต่ำ ในระบบปฏิบัติการ UNIX, preload jemalloc
OSX มักจะไม่ต้องการ Jemalloc ด้วยเหตุผลด้านประสิทธิภาพ ตรวจสอบให้แน่ใจว่าคุณกำลังใช้ Jemalloc เวอร์ชันล่าสุด - การแจกแจง Linux บางส่วนยังคงให้รุ่นเก่าแก่
ในการโหลด jemalloc บน linux ให้ใช้ export LD_PRELOAD=<path-to-libjemalloc.so
เพื่อ preload jemalloc บน OSX ใช้ export DYLD_INSERT_LIBRARIES=<path-to-libjemalloc.so
เทมเพลตสคริปต์สำหรับการโหลดล่วงหน้าสามารถดูได้ที่โครงการ Apache Cassandra
Quickstart:
OHCACHE OHCACHE = OHCACHEBUILDER.NEWBUILDER () .KeySerializer (YoukeySerializer) .Valueserializer (YourValueserializer) .สร้าง();
QuickStart นี้ใช้การกำหนดค่าเริ่มต้นน้อยที่สุด:
ดู Javadoc ของ CacheBuilder
สำหรับรายการตัวเลือกที่สมบูรณ์
คีย์และค่า serializers จำเป็นต้องใช้อินเทอร์เฟซ CacheSerializer
อินเทอร์เฟซนี้มีสามวิธี:
int serializedSize(T t)
เพื่อส่งคืนขนาดที่เป็นอนุกรมของวัตถุที่กำหนดvoid serialize(Object obj, DataOutput out)
เพื่อทำให้เป็นอนุกรมวัตถุที่กำหนดไปยังเอาต์พุตข้อมูลT deserialize(DataInput in)
เพื่อ deserialize วัตถุจากอินพุตข้อมูล โคลน GIT repo ไปยังเครื่องในพื้นที่ของคุณ ใช้สาขาหลักที่มีเสถียรภาพหรือแท็กปล่อย
git clone https://github.com/snazy/ohc.git
คุณต้องใช้ OpenJDK 11 หรือใหม่กว่าเพื่อสร้างจากแหล่งที่มา เพียงแค่ดำเนินการ
mvn clean install
คุณต้องสร้าง OHC จากแหล่งที่มาเพราะสิ่งประดิษฐ์เกณฑ์มาตรฐานขนาดใหญ่ไม่ได้อัปโหลดไปยัง Maven Central
ดำเนินการ java -jar ohc-benchmark/target/ohc-benchmark-0.7.1-SNAPSHOT.jar -h
(เมื่อสร้างจากแหล่งที่มา) เพื่อรับข้อมูลความช่วยเหลือ
โดยทั่วไปเครื่องมือเบนช์มาร์กจะเริ่มเธรดพวงและดำเนินการ _get_ และ _put_ การดำเนินการพร้อมกันโดยใช้การแจกแจงคีย์ที่กำหนดค่าได้สำหรับการดำเนินการ _get_ และ _put_ ต้องกำหนดค่าการกระจายขนาดของมูลค่า
ตัวเลือกบรรทัดคำสั่งที่มีอยู่:
-CAP <Arg> ขนาดของแคช -D <gr> ระยะเวลามาตรฐานในไม่กี่วินาที -H ช่วยพิมพ์คำสั่งนี้ -lf <gr> ปัจจัยโหลดตารางแฮช -r <gr> การปันส่วนอ่าน-เขียน (เป็นสองเท่า 0..1 แสดงโอกาสในการอ่าน) -rkd <gr> การแจกแจงการใช้คีย์ฮอต - ค่าเริ่มต้น: เครื่องแบบ (1..10000) -sc <gr> จำนวนเซ็กเมนต์ (จำนวนของแมปที่ไม่ได้ใช้งานแต่ละตัว) -t <rarg> เธรดสำหรับการดำเนินการ -VS <gr> ขนาดของค่า - ค่าเริ่มต้น: แก้ไข (512) -wkd <gr> การแจกแจงการใช้คีย์ฮอต - ค่าเริ่มต้น: เครื่องแบบ (1..10000) -wu <gr> อุ่นเครื่อง-<Work-Secs>, <Selecs> -z <gr> ขนาดตารางแฮช -CS <ARG> ขนาดก้อน - ถ้าระบุจะใช้การใช้งาน "chunked" -FKS <gr> ขนาดคีย์คงที่ในไบต์ -FVS <gr> ขนาดของค่าคงที่ในไบต์ -MES <ARG> ขนาดรายการสูงสุดในไบต์ -ไม่ได้ใช้การล็อค -เฉพาะเจาะจงสำหรับโหมดเธรดเดี่ยว -HM <gr> อัลกอริทึมแฮชที่จะใช้ - MURMUR3, XX, CRC32 -bh แสดง Bucket Historgram ในสถิติ -kl <gr> เปิดใช้งานฮิสโตแกรมถัง ค่าเริ่มต้น: FALSE
การแจกแจงสำหรับคีย์อ่านปุ่มเขียนและขนาดค่าสามารถกำหนดค่าได้โดยใช้ฟังก์ชั่นต่อไปนี้:
exp (min..max) การแจกแจงแบบเอ็กซ์โปเนนเชียลในช่วง [min..max] Extreme (min..max, Shape) การกระจายค่าสุดขีด (weibull) ในช่วง [min..max] QExtreme (min..max, Shape, Quantas) ค่าสุดขีดแบ่งออกเป็น Quantas ภายในซึ่งโอกาสในการเลือกเป็นเครื่องแบบ Gaussian (min..max, stdvrng) การแจกแจงแบบเกาส์/ปกติโดยที่ค่าเฉลี่ย = (ขั้นต่ำ+สูงสุด)/2 และ stdev คือ (ค่าเฉลี่ย)/stdvrng Gaussian (min..max, mean, stdev) การแจกแจงแบบเกาส์/ปกติโดยมีค่าเฉลี่ยที่กำหนดไว้อย่างชัดเจนและ stdev เครื่องแบบ (min..max) การกระจายที่สม่ำเสมอในช่วง [min, max] แก้ไข (val) การแจกแจงแบบคงที่มักจะส่งคืนค่าเดียวกัน ก่อนหน้าชื่อที่มี ~ จะกลับการกระจายเช่น ~ exp (1..10) จะให้ 10 ส่วนใหญ่แทนที่จะเป็นอย่างน้อยบ่อยครั้ง นามแฝง: Ext, Qextr, Gauss, Normal, Norm, Weibull
(หมายเหตุ: สิ่งเหล่านี้คล้ายกับเครื่องมือความเครียด Apache Cassandra - ถ้าคุณรู้จักคุณรู้ทั้งสองอย่าง;)
ตัวอย่างด่วนพร้อมอัตราส่วนการอ่าน/เขียนที่ .9
, ความจุสูงสุด 1.5GB, 16 เธรดที่ทำงานเป็นเวลา 30 วินาที:
java -jar ohc-benchmark/target/ohc-benchmark-0.5.1-snapshot.jar
(โปรดทราบว่าเวอร์ชันในชื่อไฟล์ JAR อาจแตกต่างกัน)
บนระบบ 2.6GHz Core i7 (OSX) ตัวเลขต่อไปนี้เป็นเรื่องปกติที่ใช้งานมาตรฐานด้านบน (.9 อัตราส่วนการอ่าน/เขียน):
เมื่อใช้วัตถุจำนวนมากในกองขนาดใหญ่มากเครื่องเสมือนจะได้รับความดัน GC ที่เพิ่มขึ้นเนื่องจากโดยทั่วไปจะต้องตรวจสอบแต่ละวัตถุและทุกวัตถุไม่ว่าจะสามารถรวบรวมได้และต้องเข้าถึงหน้าหน่วยความจำทั้งหมด แคชจะต้องทำให้ชุดของวัตถุร้อนสามารถเข้าถึงได้อย่างรวดเร็ว (เช่นดิสก์ละเว้นหรือเครือข่ายไปกลับ) ทางออกเดียวคือการใช้หน่วยความจำแบบดั้งเดิม - และที่นั่นคุณจะได้รับตัวเลือกให้ใช้รหัสดั้งเดิม (C/C ++) ผ่าน JNI หรือใช้การเข้าถึงหน่วยความจำโดยตรง
รหัสดั้งเดิมที่ใช้ C/C ++ ผ่าน JNI มีข้อเสียเปรียบที่คุณต้องเขียนโค้ด C/C ++ ตามธรรมชาติสำหรับแต่ละแพลตฟอร์ม แม้ว่า UNIX OS ส่วนใหญ่ (Linux, OSX, BSD, Solaris) ค่อนข้างคล้ายกันเมื่อจัดการกับสิ่งต่าง ๆ เช่นการเปรียบเทียบและสลับหรือ POSIX ไลบรารีคุณมักจะต้องการรองรับแพลตฟอร์มอื่น ๆ (Windows)
ทั้งโค้ดเนทีฟและการเข้าถึงหน่วยความจำโดยตรงมีข้อเสียเปรียบที่พวกเขาต้อง "ปล่อย" บริบท JVM "" - ต้องการบอกว่าการเข้าถึงหน่วยความจำปิดกองช้ากว่าการเข้าถึงข้อมูลในกอง Java และการโทร JNI แต่ละครั้งมีบางอย่าง " หลบหนีจากบริบท JVM "
แต่การปิดหน่วยความจำกองนั้นยอดเยี่ยมเมื่อคุณต้องจัดการกับหน่วยความจำแคชจำนวนมาก/จำนวนมากเนื่องจาก DOS นั้นไม่ได้กดดันนักสะสมขยะ Java ให้ Java GC ทำงานสำหรับแอปพลิเคชันที่ห้องสมุดนี้ทำงานสำหรับข้อมูลแคช
TL; DR การจัดสรรหน่วยความจำนอกกองโดยตรงและข้าม ByteBuffer.allocateDirect
การจัดวางไดเร็คนั้นอ่อนโยนต่อ GC และเรามีการควบคุมการจัดสรรหน่วยความจำอย่างชัดเจนและที่สำคัญกว่านั้นฟรี การใช้งานสต็อกใน Java ทำให้หน่วยความจำปิดกองในระหว่างการรวบรวมขยะ-นอกจากนี้: หากไม่มีหน่วยความจำนอกกองอยู่อีกต่อไปมันน่าจะทำให้เกิด GC เต็มรูปแบบซึ่งเป็นปัญหาหากหลายเธรดทำงานในสถานการณ์นั้นพร้อมกันเพราะมันหมายถึงล็อตล็อต ของ GCs เต็มตามลำดับ นอกจากนี้การใช้งานสต็อกใช้รายการที่เชื่อมโยงกันทั่วโลกเพื่อติดตามการจัดสรรหน่วยความจำนอก
นี่คือเหตุผลที่ OHC จัดสรรหน่วยความจำนอกกองโดยตรงและแนะนำให้โหลด jemalloc บนระบบ Linux เพื่อปรับปรุงประสิทธิภาพการจัดการหน่วยความจำ
OHC ได้รับการพัฒนาในปี 2014/58 สำหรับ Apache Cassandra 2.2 และ 3.0 เพื่อใช้เป็นแบ็กเอนด์แถวใหม่
เนื่องจากไม่มีการใช้งานแคชปิดกองเต็มที่เหมาะสมจึงมีการตัดสินใจที่จะสร้างใหม่อย่างสมบูรณ์ - และนั่นคือ OHC แต่มันกลับกลายเป็นว่า OHC เพียงอย่างเดียวอาจใช้งานได้สำหรับโครงการอื่น ๆ - นั่นเป็นสาเหตุที่ OHC เป็นห้องสมุดแยกต่างหาก
'ขอบคุณ' ที่ยิ่งใหญ่ต้องไปที่เบเนดิกต์เอลเลียตสมิ ธ และเอเรียลไวส์เบิร์กจาก DataStax เพื่อรับอินพุตที่มีประโยชน์มากไปยัง OHC!
Ben Manes ผู้แต่งคาเฟอีนแคชบนกองที่สามารถกำหนดค่าได้สูงโดยใช้ W-tiny LFU
นักพัฒนา: Robert Stupp
ลิขสิทธิ์ (C) 2014 Robert Stupp, Koeln, Germany, Robert-Stupp.de
ได้รับใบอนุญาตภายใต้ใบอนุญาต Apache เวอร์ชัน 2.0 ("ใบอนุญาต"); คุณไม่สามารถใช้ไฟล์นี้ยกเว้นตามใบอนุญาต คุณอาจได้รับสำเนาใบอนุญาตที่
http://www.apache.org/licenses/license-2.0
เว้นแต่ว่ากฎหมายที่บังคับใช้หรือตกลงเป็นลายลักษณ์อักษรซอฟต์แวร์ที่แจกจ่ายภายใต้ใบอนุญาตจะถูกแจกจ่ายตาม "ตามพื้นฐาน" โดยไม่มีการรับประกันหรือเงื่อนไขใด ๆ ไม่ว่าจะโดยชัดแจ้งหรือโดยนัย ดูใบอนุญาตสำหรับภาษาเฉพาะที่ควบคุมการอนุญาตและข้อ จำกัด ภายใต้ใบอนุญาต