이 프로젝트는 더 이상 유지되지 않습니다 !!!
OHC는 불균일 한 메모리 아카데프를 사용하여 상품 하드웨어 및 대형 시스템 모두에서 우수한 성능을 제공해야합니다.
아직 사용할 수있는 성능 테스트 결과가 없습니다. OHC -Benchmark 도구를 사용해 볼 수 있습니다. 아래 지침을 참조하십시오. 속도에 대한 매우 기본적인 인상은 _benchmarking_ 섹션에 있습니다.
64 비트를 지원하고 sun.misc.Unsafe
(X64 Intel CPU의 Oracle JVMS)를 지원하는 Java 8 VM.
OHC는 Linux 및 OSX를 대상으로합니다. Windows 및 기타 유닉스 OSS에서 작동 해야합니다 .
OHC는 다른 캐시 입력 특성에 대한 두 가지 구현을 제공합니다 .- _linked_ 구현은 각 항목에 대해 오프 haep 메모리를 개별적으로 할당하고 중간 및 큰 항목에 가장 적합합니다. - _chunked_ 구현은 각 해시 세그먼트에 대해 오프 하모 메모리를 할당하며 작은 항목을위한 것입니다.
세그먼트 수는 org.caffinitas.ohc.OHCacheBuilder
를 통해 구성되며 # of cpus * 2
기본값은 2의 전원이어야합니다. 항목은 64 비트 해시 코드의 가장 중요한 비트를 사용하여 세그먼트에 배포됩니다. 각 세그먼트의 액세스는 동기화됩니다.
각 해시 맵 항목은 개별적으로 할당됩니다. org.caffinitas.ohc.DirectValueAccess
또는 org.caffinitas.ohc.CacheSerializer
와 같은 외부지도 자체 또는 외부 참조로 더 이상 참조되지 않을 때는 항목이 무료 (거래)됩니다.
이 구현의 설계는 세그먼트의 잠긴 시간을 매우 짧은 시간으로 줄입니다. 작업/교체 작업을 먼저 메모리 할당하고 org.caffinitas.ohc.CacheSerializer
호출하여 키와 값을 직렬화 한 다음 완전히 준비된 항목을 세그먼트에 넣습니다.
퇴거는 LRU 알고리즘을 사용하여 수행됩니다. 모든 캐시 된 요소 자격을 통한 링크 된 목록은 가장 오래된 항목을 추적하는 데 사용됩니다.
청크 메모리 할당 오프-해당 구현.
이 구현의 목적은 전체 세그먼트에 대한 메모리가 사전 할당되기 때문에 연결된 구현과 비교하여 비교적 작은 캐시 항목의 오버 헤드를 줄이는 것입니다. 이 구현은 org.caffinitas.ohc.CacheSerializer
의 빠른 (DE) 직렬화 구현이있는 소규모 항목에 적합합니다.
세분화는 연결된 구현과 동일합니다. 세그먼트 수는 org.caffinitas.ohc.OHCacheBuilder
를 통해 구성되며 # of cpus * 2
기본값은 2의 전원이어야합니다. 항목은 64 비트 해시 코드의 가장 중요한 비트를 사용하여 세그먼트에 배포됩니다. 각 세그먼트의 액세스는 동기화됩니다.
각 세그먼트는 여러 덩어리로 나뉩니다. 각 세그먼트는 총 용량 (capacity / segmentCount)
의 일부를 담당합니다. 이 메모리의 양은 초기화 중에 한 번 선형으로 할당되며 논리적으로 구성 가능한 수의 덩어리로 나뉩니다. 각 청크의 크기는 org.caffinitas.ohc.OHCacheBuilder
의 chunkSize
옵션을 사용하여 구성됩니다.
연결된 구현과 마찬가지로, 해시 항목은 먼저 세그먼트에 들어가기 전에 (세그먼트 작업이 동기화되기 전에) 임시 버퍼로 직렬화됩니다.
새로운 항목이 현재 쓰기 청크에 배치됩니다. 그 청크가 가득 차면 다음 빈 덩어리는 새로운 쓰기 청크가됩니다. 모든 청크가 가득 차면, 모든 항목을 포함하여 가장 최근에 사용 된 청크는 퇴거됩니다.
fixedKeyLength
및 fixedValueLength
Builder 속성을 지정하면 항목 당 메모리 풋 프린트가 8 바이트 씩 줄어 듭니다.
이 구현에서는 직렬화, 직접 액세스 및 Get-Loader 기능이 지원되지 않습니다.
청크 구현을 가능하게하려면 org.caffinitas.ohc.OHCacheBuilder
에 chunkSize
지정하십시오.
참고 : 청크 구현은 여전히 실험적인 것으로 간주되어야합니다.
OHC는 세 가지 퇴거 알고리즘을 지원합니다.
클래스 OHCacheBuilder
사용하여 필요한 모든 매개 변수를 구성하십시오.
일반적으로 큰 해시 테이블로 작업해야합니다. 해시 테이블이 클수록 각 해시 파티션의 링크 목록이 짧아서 링크 링크 워크가 줄어들고 성능이 향상됩니다.
필요한 힙 메모리의 총량은 총 용량 + 해시 테이블 입니다. 각 해시 버킷 (현재)에는 8 바이트가 필요하므로 공식은 capacity + segment_count * hash_table_size * 8
.
OHC는 Java의 heap 메모리 제한을 직접 우회하지 않는 메모리를 할당합니다. 즉, OHC에 의해 할당 된 모든 메모리는 -XX:maxDirectMemorySize
에 계산되지 않음을 의미합니다.
특히 연결된 구현은 각 개별 항목에 대해 Alloc/Free 작업을 수행하므로 메모리 조각화가 발생할 수 있습니다.
또한 일부 할당이 여전히 비행 중일 수 있고 "다른 물건"(운영 체제, JVM 등)은 메모리가 필요하기 때문에 헤드 룸을 떠납니다. 사용 패턴에 따라 필요한 헤드 룸의 양에 따라 다릅니다. 링크 된 구현은 쓰기 작업 중에 메모리를 할당 _before_ 세그먼트에 계산하여 이전 항목을 퇴거시킵니다. 이것은 이용 가능한 모든 메모리를 OHC에 전념하지 마십시오.
Jemalloc을 사용하여 단편화를 낮게 유지하는 것이 좋습니다. UNIX 운영 체제에서 Jemalloc 예압.
OSX는 일반적으로 성능의 이유로 Jemalloc을 요구하지 않습니다. 또한 최근 버전의 Jemalloc을 사용하고 있는지 확인하십시오. 일부 Linux 배포판은 여전히 오래된 버전을 제공합니다.
Linux에서 Jemalloc을 예압하려면 export LD_PRELOAD=<path-to-libjemalloc.so
를 사용하여 OSX에서 Jemalloc을 사전로드하고 export DYLD_INSERT_LIBRARIES=<path-to-libjemalloc.so
사용하십시오. 예압을위한 스크립트 템플릿은 Apache Cassandra 프로젝트에서 찾을 수 있습니다.
QuickStart :
OHCACHE OHCACHE = OHCACHEBUILDER.NEWBUILDER () .keyserializer (yourkeyserializer) .Valueserializer (YourValueserializer) .짓다();
이 QuickStart는 최소한 기본 구성을 사용합니다.
전체 옵션 목록은 CacheBuilder
의 Javadoc을 참조하십시오.
키 및 값 시리얼 라이저는 CacheSerializer
인터페이스를 구현해야합니다. 이 인터페이스에는 세 가지 방법이 있습니다.
int serializedSize(T t)
void serialize(Object obj, DataOutput out)
T deserialize(DataInput in)
git repo를 로컬 컴퓨터로 복제하십시오. 안정적인 마스터 브랜치 또는 릴리스 태그를 사용하십시오.
git clone https://github.com/snazy/ohc.git
소스에서 구축하려면 OpenJDK 11 이상이 필요합니다. 그냥 실행하십시오
mvn clean install
큰 벤치 마크 아티팩트가 Maven Central에 업로드되지 않기 때문에 소스에서 OHC를 구축해야합니다.
java -jar ohc-benchmark/target/ohc-benchmark-0.7.1-SNAPSHOT.jar -h
(소스에서 빌드 할 때)를 실행하여 도움 정보를 얻으십시오.
일반적으로 벤치 마크 도구는 많은 스레드를 시작하고 _get_ 및 _put_ 작업에 대한 구성 가능한 키 분포를 사용하여 _get_ 및 _put_ 작업을 동시에 수행합니다. 값 크기 분포도 구성해야합니다.
사용 가능한 명령 줄 옵션 :
-CAP <Arg> 캐시의 크기 -D <Arg> 초의 벤치 마크 기간 -H 도움,이 명령을 인쇄하십시오 -LF <Arg> 해시 테이블로드 계수 -R <Arg> 읽기 쓰기 배급 (읽기 기회를 나타내는 이중 0..1) -rkd <Arg> 핫 키 사용 분포 - 기본값 : 균일 (1..10000) -Sc <Arg> 세그먼트 수 (개별 오프 하이프 맵 수) -t <Arg> 실행을위한 스레드 -vs <arg> 값 크기 - 기본값 : 고정 (512) -wkd <Arg> 핫 키 사용 분포 - 기본값 : 균일 (1..10000) -wu <arg> 워밍업-<work-secs>, <sleep-secs> -z <Arg> 해시 테이블 크기 -cs <arg> 청크 크기 - 지정된 경우 "청크"구현을 사용합니다. -fks <arg> 키 크기가 바이트에서 고정되었습니다 -fvs <Arg> 바이트의 고정 값 크기 -MES <Arg> 바이트의 최대 항목 크기 -UNL 잠금을 사용하지 않습니다 -단일 스레드 모드에 대해서만 적절합니다. -hm <arg> 사용 할 해시 알고리즘 -Murmur3, XX, CRC32 -BH 통계의 버킷 히스토그인을 보여줍니다 -kl <arg> 버킷 히스토그램 활성화. 기본값 : False
읽기 키, 쓰기 키 및 값 크기의 분포는 다음 기능을 사용하여 구성 할 수 있습니다.
exp (min..max) 범위에 대한 지수 분포 [min..max] 극단 (Min..Max, Shape) 범위에 대한 극단적 인 값 (Weibull) 분포 [Min..Max] QEXTREME (Min....MAX, Shape, Quantas) 극단적 인 값, Quantas로 나뉘어지면서 선택 가능성이 균일합니다. 가우스 (min..max, stdvrng) 가우시안/정규 분포, 여기서 평균 = (min+max)/2, stdev는 (평균 min)/stdvrng입니다. 가우스 (Min..Max, Mean, STDEV) 가우스/정규 분포, 명시 적으로 정의 된 평균 및 stdev 균일 (Min..Max) 범위에 걸친 균일 분포 [Min, Max] 고정 (val) 고정 분포로 항상 동일한 값을 반환합니다 ~의 이름은 ~가 분포를 반전합니다. 예를 들어 ~ exp (1..10) 별칭 : Ext, Qextr, Gauss, Normal, Norm, Weibull
(참고 : 이들은 Apache Cassandra 스트레스 도구와 유사합니다. 하나를 알고 있다면 둘 다 알고 있습니다.)
읽기/쓰기 비율이 .9
, 약 1.5GB 최대 용량, 30 초 동안 실행되는 16 개의 스레드의 빠른 예 :
Java -Jar OHC-Benchmark/Target/OHC-Benchmark-0.5.1-snapshot.jar
(JAR 파일 이름의 버전은 다를 수 있습니다.)
2.6GHz 코어 i7 시스템 (OSX)에서 다음 숫자는 위의 벤치 마크 (.9 읽기/쓰기 비율)를 실행하는 일반적인 것입니다.
매우 큰 힙에 매우 많은 수의 물체를 사용하는 경우 가상 머신은 기본적으로 각 객체가 수집 할 수 있고 모든 메모리 페이지에 액세스 해야하는지 검사해야하기 때문에 GC 압력 증가로 어려움을 겪게됩니다. 캐시는 빠른 액세스를 위해 핫 객체 세트에 액세스 할 수 있어야합니다 (예 : 디스크 또는 네트워크 왕복 생략). 유일한 해결책은 기본 메모리를 사용하는 것입니다. 그리고 거기서 JNI를 통해 일부 기본 코드 (C/C ++)를 사용하거나 직접 메모리 액세스를 사용하는 선택으로 끝납니다.
JNI를 통해 C/C ++를 사용하는 기본 코드에는 각 플랫폼마다 C/C ++ 코드를 자연스럽게 작성 해야하는 단점이 있습니다. 대부분의 UNIX OS (Linux, OSX, BSD, Solaris)는 비교 및 스웨이 또는 POSIX 라이브러리와 같은 것들을 다룰 때 상당히 유사하지만 일반적으로 다른 플랫폼 (Windows)도 지원하려고합니다.
기본 코드와 직접 메모리 액세스는 모두 "JVM"컨텍스트 "를"떠나야한다 "는 단점이 있습니다. 힙 메모리에 대한 액세스에 대한 액세스는 Java 힙의 데이터에 대한 액세스보다 느리게 진행되며 각 JNI 호출은 일부가 있다고 말하고 싶습니다." JVM 컨텍스트에서 탈출 "비용.
그러나 힙 메모리는 Java Garbage Collector에 압력을 가하지 않기 때문에 엄청난 양의 여러 GB의 캐시 메모리를 처리해야 할 때 좋습니다. Java GC 가이 라이브러리가 캐시 된 데이터에 대한 작업을 수행하는 응용 프로그램을 위해 작업을 수행하도록하십시오.
TL; Dr. 오프 eap 메모리를 직접 할당하고 ByteBuffer.allocateDirect
우회하는 DR은 GC에 매우 온화하며 메모리 할당을 명시 적으로 제어하고 더 중요한 것은 무료입니다. 가비지 컬렉션 중에 Java의 재고 구현은 쓰레기 수집 중에 메모리를 해제합니다. 또한 : 더 이상 오프 HEAP 메모리를 사용할 수 없다면 전체 GC를 트리거 할 수 있습니다. 전체 GC의 순차적으로. 또한, 주식 구현은 전역의 동기화 된 링크 된 링크 목록을 사용하여 오프 하모 메모리 할당을 추적합니다.
그렇기 때문에 OHC가 오프 eap 메모리를 직접 할당하고 Linux 시스템에서 Jemalloc을 예비로드하여 메모리 관리 성능을 향상시키는 권장입니다.
OHC는 2014/15 년 Apache Cassandra 2.2 및 3.0을 위해 새로운 Row-Cache 백엔드로 사용되었습니다.
사용 가능한 적절한 완전히 오프 헤어 캐시 구현이 없기 때문에 완전히 새로운 것을 구축하기로 결정했습니다. 그리고 그것은 OHC입니다. 그러나 OHC만으로는 다른 프로젝트에서도 사용할 수 있다는 것이 밝혀졌습니다. 그래서 OHC는 별도의 라이브러리입니다.
큰 '감사합니다'는 Datastax의 Benedict Elliott Smith와 Ariel Weisberg에게 OHC에 매우 유용한 입력을해야합니다!
Caffeine의 저자 인 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
해당 법률에 의해 요구되거나 서면에 동의하지 않는 한, 라이센스에 따라 배포 된 소프트웨어는 명시 적 또는 묵시적 보증 또는 조건없이 "그대로"기준으로 배포됩니다. 라이센스에 따른 특정 언어 통치 권한 및 제한 사항에 대한 라이센스를 참조하십시오.