偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

一招MAX降低10倍,現(xiàn)在它是我的了

開(kāi)發(fā) 前端
隨著門(mén)店數(shù)據(jù)越來(lái)越多,本地緩存容量逐漸增大到3G左右。雖然對(duì)垃圾回收器和JVM參數(shù)都進(jìn)行調(diào)整,由于本地緩存數(shù)據(jù)量越來(lái)越大,本地緩存數(shù)據(jù)對(duì)于應(yīng)用GC的影響越來(lái)越明顯,YGC平均耗時(shí)100ms,特別是大促期間調(diào)用方接口毛刺感知也越來(lái)越明顯。

一.背景

性能優(yōu)化是一場(chǎng)永無(wú)止境的旅程。

到家門(mén)店系統(tǒng),作為到家核心基礎(chǔ)服務(wù)之一,門(mén)店C端接口有著調(diào)用量高,性能要求高的特點(diǎn)。

C端服務(wù)經(jīng)過(guò)演進(jìn),核心接口先查詢(xún)本地緩存,如果本地緩存沒(méi)有命中,再查詢(xún)Redis。本地緩存命中率99%,服務(wù)性能比較平穩(wěn)。

隨著門(mén)店數(shù)據(jù)越來(lái)越多,本地緩存容量逐漸增大到3G左右。雖然對(duì)垃圾回收器和JVM參數(shù)都進(jìn)行調(diào)整,由于本地緩存數(shù)據(jù)量越來(lái)越大,本地緩存數(shù)據(jù)對(duì)于應(yīng)用GC的影響越來(lái)越明顯,YGC平均耗時(shí)100ms,特別是大促期間調(diào)用方接口毛刺感知也越來(lái)越明顯。

由于本地緩存在每臺(tái)機(jī)器上容量是固定的,即便是將機(jī)器擴(kuò)容,對(duì)與GC毛刺也沒(méi)有明顯效果。

二.初識(shí)此物心已驚-OHC初識(shí)

本地緩存位于應(yīng)用程序的內(nèi)存中,讀取和寫(xiě)入速度非???,可以快速響應(yīng)請(qǐng)求,無(wú)需額外的網(wǎng)絡(luò)通信,但是一般本地緩存存在JVM內(nèi),數(shù)據(jù)量過(guò)多會(huì)影響GC,造成GC頻率、耗時(shí)增加;如果用Redis的話(huà)有網(wǎng)絡(luò)通信的開(kāi)銷(xiāo)。

框架

簡(jiǎn)介

特點(diǎn)

堆外緩存

性能(一般情況)

Guava Cache

Guava Cache是Google的本地緩存庫(kù),提供了基本的緩存功能。它簡(jiǎn)單易用、輕量級(jí),并支持基本的緩存操作。

·支持最大容量限制

·支持兩種過(guò)期刪除策略(插入時(shí)間和訪(fǎng)問(wèn)時(shí)間)

·支持簡(jiǎn)單的統(tǒng)計(jì)功能

·基于LRU算法實(shí)現(xiàn)

不支持

性能中等

Caffeine

Caffeine是一個(gè)高性能的本地緩存庫(kù),提供了豐富的功能和配置選項(xiàng)。它支持高并發(fā)性能、低延遲和一些高級(jí)功能,如緩存過(guò)期、異步刷新和緩存統(tǒng)計(jì)等。

·提供了豐富的功能和配置選項(xiàng);高并發(fā)性能和低延遲;支持緩存過(guò)期、異步刷新和緩存統(tǒng)計(jì)等功能;

·基于java8實(shí)現(xiàn)的新一代緩存工具,緩存性能接近理論最優(yōu)。

·可以看作是Guava Cache的增強(qiáng)版,功能上兩者類(lèi)似,不同的是Caffeine采用了一種結(jié)合LRU、LFU優(yōu)點(diǎn)的算法:W-TinyLFU,在性能上有明顯的優(yōu)越性

不支持

性能出色

Ehcache

Encache是一個(gè)純Java的進(jìn)程內(nèi)緩存框架,具有快速、精干等特點(diǎn),是Hibernate中默認(rèn)的CacheProvider。同Caffeine和Guava Cache相比,Encache的功能更加豐富,擴(kuò)展性更強(qiáng)

·支持多種緩存淘汰算法,包括LRU、LFU和FIFO

·緩存支持堆內(nèi)存儲(chǔ)、堆外存儲(chǔ)、磁盤(pán)存儲(chǔ)(支持持久化)三種

·支持多種集群方案,解決數(shù)據(jù)共享問(wèn)題

支持

性能一般

OHC

OHC(Off-Heap Cache)是一個(gè)高性能的堆外緩存庫(kù),專(zhuān)為高并發(fā)和低延遲而設(shè)計(jì)。它使用堆外內(nèi)存和自定義的數(shù)據(jù)結(jié)構(gòu)來(lái)提供出色的性能

·針對(duì)高并發(fā)和低延遲進(jìn)行了優(yōu)化;使用自定義數(shù)據(jù)結(jié)構(gòu)和無(wú)鎖并發(fā)控制;較低的GC開(kāi)銷(xiāo);

·在高并發(fā)和低延遲的緩存訪(fǎng)問(wèn)場(chǎng)景下表現(xiàn)出色

支持

性能最佳

通過(guò)對(duì)本地緩存的調(diào)研,堆外緩存可以很好兼顧上面的問(wèn)題。堆外緩存把數(shù)據(jù)放在JVM堆外的,緩存數(shù)據(jù)對(duì)GC影響較小,同時(shí)它是在機(jī)器內(nèi)存中的,相對(duì)與Redis也沒(méi)有網(wǎng)絡(luò)開(kāi)銷(xiāo),最終選擇OHC。

三.習(xí)得技能心自安-OHC使用

talk is cheap, show me the code! OCH是騾子是馬我們遛一遛。

1.引入POM

OHC 存儲(chǔ)的是二進(jìn)制數(shù)組,需要實(shí)現(xiàn)OHC序列化接口,將緩存數(shù)據(jù)與二進(jìn)制數(shù)組之間序列化和反序列化。

這里使用的是Protostuff,當(dāng)然也可以使用kryo、Hession等,通過(guò)壓測(cè)驗(yàn)證選擇適合的序列化框架。

<!--OHC相關(guān)-->
<dependency>
	<groupId>org.caffinitas.ohc</groupId>
	<artifactId>ohc-core</artifactId>
	<version>0.7.4</version>
</dependency>

<!--OHC 存儲(chǔ)的是二進(jìn)制數(shù)組,所以需要實(shí)現(xiàn)OHC序列化接口,將緩存數(shù)據(jù)與二進(jìn)制數(shù)組之間序列化和反序列化-->
<!--這里使用的是protostuff,當(dāng)然也可以使用kryo、Hession等,通過(guò)壓測(cè)驗(yàn)證選擇適合的-->
<dependency>
	<groupId>io.protostuff</groupId>
	<artifactId>protostuff-core</artifactId>
	<version>1.6.0</version>
</dependency>
<dependency>
	<groupId>io.protostuff</groupId>
	<artifactId>protostuff-runtime</artifactId>
	<version>1.6.0</version>
</dependency>

2.創(chuàng)建OHC緩存

OHC緩存創(chuàng)建

OHCache<String, XxxxInfo> basicStoreInfoCache = OHCacheBuilder.<String, XxxxInfo>newBuilder()
                    .keySerializer(new OhcStringSerializer()) //key的序列化器
                    .valueSerializer(new OhcProtostuffXxxxInfoSerializer()) //value的序列化器
                    .segmentCount(512) // 分段數(shù)量 默認(rèn)=2*CPU核數(shù)
                    .hashTableSize(100000)// 哈希表大小 默認(rèn)=8192
                    .capacity(1024 * 1024 * 1024) //緩存容量 單位B 默認(rèn)64MB
                    .eviction(Eviction.LRU) // 淘汰策略 可選LRU\W_TINY_LFU\NONE
                    .timeouts(false) //不使用過(guò)期時(shí)間,根據(jù)業(yè)務(wù)自己選擇
                    .build();

自定義序列化器,這里key-String 序列化器,這里直接復(fù)用OCH源碼中測(cè)試用例的String序列化器;

value-自定義對(duì)象序列化器,這里用Protostuff實(shí)現(xiàn),也可以自己選擇使用kryo、Hession等實(shí)現(xiàn);

//key-String 序列化器,這里直接復(fù)用OCH源碼中測(cè)試用例的String序列化器
public class OhcStringSerializer implements CacheSerializer<String> {

    @Override
    public int serializedSize(String value) {
        return writeUTFLen(value);
    }

    @Override
    public void serialize(String value, ByteBuffer buf) {
        // 得到字符串對(duì)象UTF-8編碼的字節(jié)數(shù)組
        byte[] bytes = value.getBytes(Charsets.UTF_8);
        buf.put((byte) ((bytes.length >>> 8) & 0xFF));
        buf.put((byte) ((bytes.length >>> 0) & 0xFF));
        buf.put(bytes);
    }


    @Override
    public String deserialize(ByteBuffer buf) {
        int length = (((buf.get() & 0xff) << 8) + ((buf.get() & 0xff) << 0));
        byte[] bytes = new byte[length];
        buf.get(bytes);
        return new String(bytes, Charsets.UTF_8);
    }
    static int writeUTFLen(String str) {
        int strlen = str.length();
        int utflen = 0;
        int c;

        for (int i = 0; i < strlen; i++) {
            c = str.charAt(i);
            if ((c >= 0x0001) && (c <= 0x007F)){
                utflen++;}
            else if (c > 0x07FF){
                utflen += 3;}
            else{
                utflen += 2;
            }
        }

        if (utflen > 65535) {
            throw new RuntimeException("encoded string too long: " + utflen + " bytes");
        }
        return utflen + 2;
    }
}


//value-自定義對(duì)象序列化器,這里用Protostuff實(shí)現(xiàn),可以自己選擇使用kryo、Hession等實(shí)現(xiàn)
public class OhcProtostuffXxxxInfoSerializer implements CacheSerializer<XxxxInfo> {

    /**
     * 將緩存數(shù)據(jù)序列化到 ByteBuffer 中,ByteBuffer是OHC管理的堆外內(nèi)存區(qū)域的映射。
     */
    @Override
    public void serialize(XxxxInfo t, ByteBuffer byteBuffer) {
        byteBuffer.put(ProtostuffUtils.serialize(t));
    }
    /**
     * 對(duì)堆外緩存的數(shù)據(jù)進(jìn)行反序列化
     */
    @Override
    public XxxxInfo deserialize(ByteBuffer byteBuffer) {
        byte[] bytes = new byte[byteBuffer.remaining()];
        byteBuffer.get(bytes);
        return ProtostuffUtils.deserialize(bytes, XxxxInfo.class);
    }

    /**
     * 計(jì)算字序列化后占用的空間
     */
    @Override
    public int serializedSize(XxxxInfo t) {
        return ProtostuffUtils.serialize(t).length;
    }
}

為了方便調(diào)用和序列化封裝為工具類(lèi),同時(shí)對(duì)代碼通過(guò)FastThreadLocal進(jìn)行優(yōu)化,提升性能。

public class ProtostuffUtils {

    /**
     * 避免每次序列化都重新申請(qǐng)Buffer空間,提升性能
     */
    private static final FastThreadLocal<LinkedBuffer> bufferPool = new FastThreadLocal<LinkedBuffer>() {
        @Override
        protected LinkedBuffer initialValue() throws Exception {
            return LinkedBuffer.allocate(4 * 2 * LinkedBuffer.DEFAULT_BUFFER_SIZE);
        }
    };

    /**
     * 緩存Schema
     */
    private static Map<Class<?>, Schema<?>> schemaCache = new ConcurrentHashMap<>();

    /**
     * 序列化方法,把指定對(duì)象序列化成字節(jié)數(shù)組
     */
    @SuppressWarnings("unchecked")
    public static <T> byte[] serialize(T obj) {
        Class<T> clazz = (Class<T>) obj.getClass();
        Schema<T> schema = getSchema(clazz);
        byte[] data;
        LinkedBuffer linkedBuffer = null;
        try {
            linkedBuffer = bufferPool.get();
            data = ProtostuffIOUtil.toByteArray(obj, schema, linkedBuffer);
        } finally {
            if (Objects.nonNull(linkedBuffer)) {
                linkedBuffer.clear();
            }
        }

        return data;
    }

    /**
     * 反序列化方法,將字節(jié)數(shù)組反序列化成指定Class類(lèi)型
     */
    public static <T> T deserialize(byte[] data, Class<T> clazz) {
        Schema<T> schema = getSchema(clazz);
        T obj = schema.newMessage();
        ProtostuffIOUtil.mergeFrom(data, obj, schema);
        return obj;
    }

    @SuppressWarnings("unchecked")
    private static <T> Schema<T> getSchema(Class<T> clazz) {
        Schema<T> schema = (Schema<T>) schemaCache.get(clazz);
        if (Objects.isNull(schema)) {
            schema = RuntimeSchema.getSchema(clazz);
            if (Objects.nonNull(schema)) {
                schemaCache.put(clazz, schema);
            }
        }

        return schema;
    }
}

3.壓測(cè)及參數(shù)調(diào)整

通過(guò)壓測(cè)并逐步調(diào)整OHC配置常見(jiàn)參數(shù)(segmentCount、hashTableSize、eviction,參數(shù)含義見(jiàn)附錄)

MAX對(duì)比降低10倍

GC時(shí)間對(duì)比降低10倍GC時(shí)間對(duì)比降低10倍

優(yōu)化前

優(yōu)化后

4.OHC緩存狀態(tài)監(jiān)控

OHC緩存的命中次數(shù)、內(nèi)存使用狀態(tài)等存儲(chǔ)在OHCacheStats中,可以通過(guò)OHCache.stats()獲取。

OHCacheStates信息:

hitCount:緩存命中次數(shù),表示從緩存中成功獲取數(shù)據(jù)的次數(shù)。 missCount:緩存未命中次數(shù),表示嘗試從緩存中獲取數(shù)據(jù)但未找到的次數(shù)。 evictionCount:緩存驅(qū)逐次數(shù),表示因?yàn)榫彺婵臻g不足而從緩存中移除的數(shù)據(jù)項(xiàng)數(shù)量。 expireCount:緩存過(guò)期次數(shù),表示因?yàn)榫彺鏀?shù)據(jù)過(guò)期而從緩存中移除的數(shù)據(jù)項(xiàng)數(shù)量。 size:緩存當(dāng)前存儲(chǔ)的數(shù)據(jù)項(xiàng)數(shù)量。 capacity:緩存的最大容量,表示緩存可以存儲(chǔ)的最大數(shù)據(jù)項(xiàng)數(shù)量。 free:緩存剩余空閑容量,表示緩存中未使用的可用空間。 rehashCount:重新哈希次數(shù),表示進(jìn)行哈希表重新分配的次數(shù)。 put(add/replace/fail):數(shù)據(jù)項(xiàng)添加/替換/失敗的次數(shù)。 removeCount:緩存移除次數(shù),表示從緩存中移除數(shù)據(jù)項(xiàng)的次數(shù)。 segmentSizes(#/min/max/avg):段大小統(tǒng)計(jì)信息,包括段的數(shù)量、最小大小、最大大小和平均大小。 totalAllocated:已分配的總內(nèi)存大小,表示為負(fù)數(shù)時(shí)表示未知。 lruCompactions:LRU 壓縮次數(shù),表示進(jìn)行 LRU 壓縮的次數(shù)。

通過(guò)定期采集OHCacheStates信息,來(lái)監(jiān)控本地緩存數(shù)據(jù)、命中率=[命中次數(shù) / (命中次數(shù) + 未命中次數(shù))]等,并添加相關(guān)報(bào)警。同時(shí)通過(guò)緩存狀態(tài)信息,來(lái)判斷過(guò)期策略、段數(shù)、容量等設(shè)置是否合理,命中率是否符合預(yù)期等。

四.剖析根源見(jiàn)真諦-OHC原理

堆外緩存框架(Off-Heap Cache)是將緩存數(shù)據(jù)存儲(chǔ)在 JVM 堆外的內(nèi)存區(qū)域,而不是存儲(chǔ)在 JVM 堆中。在 OHC(Off-Heap Cache)中,數(shù)據(jù)也是存儲(chǔ)在堆外的內(nèi)存區(qū)域。

具體來(lái)說(shuō),OHC 使用 DirectByteBuffer 來(lái)分配堆外內(nèi)存,并將緩存數(shù)據(jù)存儲(chǔ)在這些 DirectByteBuffer 中。

DirectByteBuffer 在 JVM 堆外的內(nèi)存區(qū)域中分配一塊連續(xù)的內(nèi)存空間,緩存數(shù)據(jù)被存儲(chǔ)在這個(gè)內(nèi)存區(qū)域中。這使得 OHC 在處理大量數(shù)據(jù)時(shí)具有更高的性能和效率,因?yàn)樗梢员苊?JVM 堆的垃圾回收和堆內(nèi)存限制。

OHC 核心OHCache接口提供了兩種實(shí)現(xiàn):

?OHCacheLinkedImpl: 實(shí)現(xiàn)為每個(gè)條目單獨(dú)分配堆外內(nèi)存,最適合中型和大型條目。

?OHCacheChunkedImpl:實(shí)現(xiàn)為每個(gè)散列段作為一個(gè)整體分配堆外內(nèi)存,并且適用于小條目。(實(shí)驗(yàn)性的,不推薦,不做關(guān)注)

可以看到OHCacheLinkedImpl中包含多個(gè)段,每個(gè)段用OffHeapLinkedMap來(lái)表示。同時(shí),OHCacheLinkedImpl將Java對(duì)象序列化成字節(jié)數(shù)組存儲(chǔ)在堆外,在該過(guò)程中需要使用用戶(hù)自定義的CacheSerializer。

OHCacheLinkedImpl的主要工作流程如下:

1.計(jì)算key的hash值,根據(jù)hash值計(jì)算段號(hào),確定其所處的OffHeapLinkedMap

2.從OffHeapLinkedMap中獲取該鍵值對(duì)的堆外內(nèi)存地址(指針)

3.對(duì)于get操作,從指針?biāo)赶虻亩淹鈨?nèi)存讀取byte[],把byte[]反序列化成對(duì)象

4.對(duì)于put操作,把對(duì)象序列化成byte[],并寫(xiě)入指針?biāo)赶虻亩淹鈨?nèi)存

可以將OHC理解為一個(gè)key-value結(jié)果的map,只不過(guò)這個(gè)map數(shù)據(jù)存儲(chǔ)是指向堆外內(nèi)存的內(nèi)存指針。

指針在堆內(nèi),指針指向的緩存數(shù)據(jù)存儲(chǔ)在堆外。那么OHC最核心的其實(shí)就是對(duì)堆外內(nèi)存的地址引用的put和get以及發(fā)生在其中內(nèi)存空間的操作了。

對(duì)OHCacheLinkedImpl的put、get本地調(diào)試

1.put

put核心操作就是put核心操作就是

1.申請(qǐng)堆外內(nèi)存

2.將申請(qǐng)地址存入map;

3.異常時(shí)釋放內(nèi)存

第2步其實(shí)就是map數(shù)據(jù)更新、擴(kuò)容等的一些實(shí)現(xiàn)這里不在關(guān)注,我們重點(diǎn)關(guān)注怎么申請(qǐng)和釋放內(nèi)存的

1.申請(qǐng)內(nèi)存

通過(guò)深入代碼發(fā)現(xiàn)是調(diào)用的IAllocator接口的JNANativeAllocator實(shí)現(xiàn)類(lèi),最后調(diào)用的是com.sun.jna.Native#malloc實(shí)現(xiàn)

2.釋放內(nèi)存

通過(guò)上面可知釋放內(nèi)存操作的代碼

3.get

4.Q&A

在put操作時(shí),上面看到IAllocator有兩個(gè)實(shí)現(xiàn)類(lèi),JNANativeAllocator和UnsafeAllocator兩個(gè)實(shí)現(xiàn)類(lèi),他們有什么區(qū)別?為什么使用JNANativeAllocator?

區(qū)別:UnsafeAllocator對(duì)內(nèi)存操作使用的是Unsafe類(lèi)

為什么使用JNANativeAllocator:Native比Unsafe性能更好,差3倍左右,OHC默認(rèn)使用JNANativeAllocator;

在日常我們知道通過(guò)ByteBuffer#allocateDirect(int capacity)也可以直接申請(qǐng)堆外內(nèi)存,通過(guò)ByteBuffer源碼可以看到內(nèi)部使用的就是Unsafe類(lèi)

可以看到,同時(shí)DirectByteBuffer內(nèi)部會(huì)調(diào)用 Bits.reserveMemory(size, cap);

Bits.reserveMemory方法中,當(dāng)內(nèi)存不足時(shí)可能會(huì)觸發(fā)fullgc,多個(gè)申請(qǐng)內(nèi)存的線(xiàn)程同時(shí)遇到這種情況時(shí),對(duì)于服務(wù)來(lái)說(shuō)是不能接受的,所以這也是OHC自己進(jìn)行堆外內(nèi)存管理的原因。

如果自己進(jìn)行實(shí)現(xiàn)堆外緩存框架,要考慮上面這種情況。

五.總結(jié)

1.OHC使用建議

1.對(duì)于OHC的參數(shù)配置、序列化器的選擇,沒(méi)有固定的推薦??梢酝ㄟ^(guò)壓測(cè)逐步調(diào)整到最優(yōu)。

2.由于OHC需要把key和value序列化成字節(jié)數(shù)組存儲(chǔ)到堆外,因此需要選擇合適的序列化工具。

3.在存儲(chǔ)每個(gè)鍵值對(duì)時(shí),會(huì)調(diào)用CacheSerializer#serializedSize計(jì)算序列化后的內(nèi)存空間占用,從而申請(qǐng)堆外內(nèi)存。另外,在真正寫(xiě)入堆外時(shí),會(huì)調(diào)用CacheSerializer#serialize真正進(jìn)行序列化。因此,務(wù)必在這兩個(gè)方法中使用相同的序列化方法,防止序列化的大小與計(jì)算出來(lái)的大小不一致,導(dǎo)致內(nèi)存存不下或者多申請(qǐng),浪費(fèi)內(nèi)存空間。

2.緩存優(yōu)化建議

1.當(dāng)本地緩存影響GC時(shí),可以考慮使用OHC減少本地緩存對(duì)GC的影響;

2.區(qū)分熱點(diǎn)數(shù)據(jù),對(duì)緩存數(shù)據(jù)進(jìn)行多級(jí)拆分,如堆內(nèi)->堆外->分布式緩存(Reids )等;

3.將較大緩存對(duì)象拆分或者按照業(yè)務(wù)維度將不同熱點(diǎn)數(shù)據(jù)緩存到不同介質(zhì)中,減少單一存儲(chǔ)介質(zhì)壓力;

4.減小緩存對(duì)象大小,如緩存JSON字符,可對(duì)字段名進(jìn)行縮寫(xiě) ,減少存儲(chǔ)數(shù)據(jù)量,降低傳輸數(shù)據(jù)量,同時(shí)也能保證數(shù)據(jù)一定的私密性。

對(duì)象:{"paramID":1,"paramName":"John Doe"} 正常JSON字符串:{"paramID":1,"paramName":"John Doe"} 壓縮字段名JSON字符串:{"a":1,"b":"John Doe"}

Hold hold , One more thing....

在使用Guava時(shí),存儲(chǔ)25w個(gè)緩存對(duì)象數(shù)據(jù)占用空間485M

使用OHCache時(shí),儲(chǔ)存60w個(gè)緩存對(duì)象數(shù)據(jù)占用數(shù)據(jù)387M

為什么存儲(chǔ)空間差別那么多吶?

Guava 存儲(chǔ)的對(duì)象是在堆內(nèi)存中的,對(duì)象在 JVM 堆中存儲(chǔ)時(shí),它們會(huì)占用一定的內(nèi)存空間,并且會(huì)包含對(duì)象頭、實(shí)例數(shù)據(jù)和對(duì)齊填充等信息。對(duì)象的大小取決于其成員變量的類(lèi)型和數(shù)量,以及可能存在的對(duì)齊需求。同時(shí)當(dāng)對(duì)象被頻繁創(chuàng)建和銷(xiāo)毀時(shí),可能會(huì)產(chǎn)生內(nèi)存碎片。

而 OHC 它將對(duì)象存儲(chǔ)在 JVM 堆外的直接內(nèi)存中。由于堆外內(nèi)存不受 Java 堆內(nèi)存大小限制,OHC 可以更有效地管理和利用內(nèi)存。此外,OHC 底層存儲(chǔ)字節(jié)數(shù)組,存儲(chǔ)字節(jié)數(shù)組相對(duì)于直接存儲(chǔ)對(duì)象,可以減少對(duì)象的創(chuàng)建和銷(xiāo)毀,在一些場(chǎng)景下,直接操作字節(jié)數(shù)組可能比操作對(duì)象更高效,因?yàn)樗苊饬藢?duì)象的額外開(kāi)銷(xiāo),如對(duì)象頭和引用,減少額外的開(kāi)銷(xiāo)。同時(shí)將對(duì)象序列化為二進(jìn)制數(shù)組存儲(chǔ),內(nèi)存更加緊湊,減少內(nèi)存碎片的產(chǎn)生。

綜上所述,OHC 在存儲(chǔ)大量對(duì)象時(shí)能夠更有效地利用內(nèi)存空間,相對(duì)于 Guava 在內(nèi)存占用方面具有優(yōu)勢(shì)。

另外一個(gè)原因,不同序列化框架性能不同,將對(duì)象序列化后的占用空間的大小也不同。


參考及附錄

1.OHC常見(jiàn)參數(shù)

name

默認(rèn)值

描述

keySerializer

需要開(kāi)發(fā)者實(shí)現(xiàn)

Key序列化實(shí)現(xiàn)

valueSerializer

需要開(kāi)發(fā)者實(shí)現(xiàn)

Value序列化實(shí)現(xiàn)

capacity

64MB

緩存容量單位B

segmentCount

2倍CPU核心數(shù)

分段數(shù)量

hashTableSize

8192

哈希表的大小

loadFactor

0.75

負(fù)載因子

maxEntrySize

capacity/segmentCount

緩存項(xiàng)最大字節(jié)限制

throwOOME

false

內(nèi)存不足是否拋出OOM

hashAlgorighm

MURMUR3

hash算法,可選性MURMUR3、 CRC32, CRC32C (Jdk9以上支持)

unlocked

false

讀寫(xiě)數(shù)據(jù)是否加鎖,默認(rèn)是加鎖

eviction

LRU

驅(qū)逐策略,可選項(xiàng):LRU、W_TINY_LFU、NONE

frequencySketchSize

hashTableSize數(shù)量

W_TINY_ LFU frequency sketch 的大小

edenSize

0.2

W_TINY_LFU 驅(qū)逐策略下使用

2.JNI faster than Unsafe?

https://mail.openjdk.org/pipermail/hotspot-dev/2015-February/017089.html

3.OHC源碼

https://github.com/snazy/ohc

4.參考文檔

?序列化框架對(duì)比

?Java堆外緩存OHC在馬蜂窩推薦引擎的應(yīng)用

?“堆外緩存”這玩意是真不錯(cuò),我要寫(xiě)進(jìn)簡(jiǎn)歷了。

責(zé)任編輯:武曉燕 來(lái)源: 今日頭條
相關(guān)推薦

2024-01-15 08:28:31

Spring事件

2021-12-03 22:57:50

彈窗廣告電腦進(jìn)程

2019-01-23 10:11:43

Python爬蟲(chóng)IP

2013-07-30 11:24:33

SAP“簡(jiǎn)化IT 一招

2015-08-03 14:02:37

Windows 10升級(jí)

2021-11-22 11:30:37

JavaScript代碼瀏覽器

2021-04-19 05:44:18

顯示器Twinkle Tra亮度調(diào)節(jié)

2013-05-03 11:21:27

2012-06-04 09:05:13

2022-05-30 08:53:47

PycharmPython

2011-04-19 09:47:14

2023-03-03 13:14:46

2012-02-01 15:41:42

2018-08-20 09:11:14

企業(yè)專(zhuān)業(yè)能力

2022-09-06 11:53:00

開(kāi)發(fā)計(jì)算

2021-06-28 20:01:07

電腦性能Windows 7

2018-03-18 23:34:57

2024-05-17 08:19:53

jackson數(shù)組切片

2010-08-19 15:07:26

DB2 -964

2020-12-31 13:17:57

手機(jī)電腦多屏協(xié)同
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)