场景问题

最近在做大模型的加载,加载文件的时候会解析出这个文件有多少个mesh, line, parameter, 而后都会存在一个变量中去保护这个关系:

const detailedList = {   mesh: Array,   line: Array,   parameter: Array}

这样会导致这个内存吃紧,毕竟间接存了好几G的数据信息。
那还有一种说法是, 文件加载过去间接就渲染不就行了吗?
然而这样会导致DC过多, CPU吃不消。

IndexDB

应用indexDB来充当一个相似内存的性能, 我把数据选择性的存在indexDB中,须要的时候再拿,这样会大大缓解内存压力。indexDB相似NOSQL,并不是MYSQL这种二维表构造, 取数据的速度是飞快的。

结构一个Store

和大部分前端我的项目一样,我也结构了一个store.

enum StoreType {    MEMORY,    INDEXDB}class Store {    /**     * 寄存在内存中的数据     */    private memory: Map<string, any>    private readonly dbVersion: number;    /**     * indexDB     */    private db: IDBDatabase;    private isReady: boolean;    /**     * 贮存的value多大才应用indexDB贮存,反之应用map     */    private readonly limitForDB: number;    /**     * 达到贮存下限后一次性删除多少条数据     */    private readonly deleteCount: number;    /**     * 贮存下限     */    private readonly upperStorageLimit: number;    constructor(dbVersion = 1, limitForDB?: number) {        this.isReady = false        this.dbVersion = dbVersion        this.initIndexDB()        this.memory = new Map()        this.limitForDB = limitForDB || 30        this.upperStorageLimit = 10000        this.deleteCount = 20    }    set(key: string, value: any, type?: StoreType) {        const intoMemory = () => {            this.memory.set(key, value)        }        const intoIndexDB = () => {            const objectStore = this.getObjectStore();            objectStore.put({id: key, value}, key);            this.calculationTimesAndDelete();        }        if (typeof type !== 'undefined') {            type === StoreType.INDEXDB ? intoIndexDB() : intoMemory()        } else {            if (Store.sizeOf(value) > this.limitForDB) {                // indexDB加之前删除map中存在的key                this.clear(key, StoreType.MEMORY)                intoIndexDB()            } else {                // 退出map之前删除indexDB中存在的key                this.clear(key, StoreType.INDEXDB)                intoMemory()            }        }    }    get(key: string, type?: StoreType): Promise<any> {        return new Promise((resolve, reject) => {            const fromMemory = (key) => {                resolve(this.memory.get(key))            }            const fromIndexDB = (key) => {                const objectStore = this.getObjectStore();                const index = objectStore.index("id");                const res = index.get(key);                res.onsuccess = (e) => {                    // @ts-ignore                    resolve(e.target.result.value)                }                res.onerror = (e) => {                    reject(e)                }            }            if (typeof type !== 'undefined') {                type === StoreType.INDEXDB ? fromIndexDB(key) : fromMemory(key)            } else {                this.memory.has(key) ? fromMemory(key) : fromIndexDB(key)            }        })    }    /**     * 查询数据库条数     */    calculationTimesAndDelete() {        const result = this.getObjectStore().count()        result.onsuccess = (e) => {            // @ts-ignore            if (e.result > this.upperStorageLimit) {                this.deleteFromPrevious()            }        }    }    /**     * 达到阈值后删除最开始建设的数据     * @description 避免数据收缩     */    deleteFromPrevious() {        const objectStore = this.getObjectStore()        const request = objectStore.openCursor();        let count = 0        request.onsuccess = (event) => {            // @ts-ignore            const cursor = event.target.result            if (cursor) {                if (count === this.deleteCount) return;                count++;                objectStore.delete(cursor.key)                cursor.continue()            }        }    }    getObjectStore() {        const transaction = this.db.transaction(["store"], "readwrite");        return transaction.objectStore("store")    }    clear(key: string, type?: StoreType) {        const fromMemoryDel = () => this.memory.delete(key)        const fromIndexDBDel = () => {            const objectStore = this.getObjectStore();            objectStore.delete(key)        }        if (typeof type !== 'undefined') {            type === StoreType.INDEXDB ? fromIndexDBDel() : fromMemoryDel()        } else {            this.memory.has(key) ? fromMemoryDel() : fromIndexDBDel()        }    }    initIndexDB() {        // @ts-ignore        const indexedDB = window.indexedDB || window.webkitIndexedDB || window.mozIndexedDB || window.OIndexedDB || window.msIndexedDB        if (!indexedDB) {            alert('indexDB被浏览器禁止!')            throw new Error('indexDB forbidden in the browser!')        }        const request = indexedDB.open("elephantFiles", this.dbVersion)        request.onerror = function () {            throw new Error('Error creating/accessing IndexedDB database');        }        request.onsuccess = event => {            // @ts-ignore            this.db = event.target.result as IDBDatabase;            this.isReady = true        }        request.onupgradeneeded = (event) => {            console.log('database upgradeneeded!')            // @ts-ignore            const db = event.target.result as IDBDatabase;            if (!db.objectStoreNames.contains('store')) {                const store = db.createObjectStore('store')                store.createIndex('id', 'id')            }        }    }    /**     * @description 不确认是否初始化结束时 将查问赋值等操作包裹在此     */    ready(callback: Function) {        const step = () => {            if (this.isReady) {                callback && callback()                return;            }            window.requestAnimationFrame(step)        }        window.requestAnimationFrame(step)    }    /**     * @description 估算字节大小, 疏忽key的长度, 如果是object只计算value, 比JSON.stringify更快     */    static sizeOf(value): number {        const typeSizes = {            "undefined": () => 0,            "boolean": () => 4,            "number": () => 8,            "string": item => 2 * item.length,            "object": item => !item ? 0 : Object                .keys(item)                .reduce((total, key) => size(key) + size(item[key]) + total, 0)        };        const size = value => typeSizes[typeof value](value);        return size(value)    }}export {StoreType, Store}

应用

const a = new Store();a.ready(() => {  a.set('a', { k: 'dsdsdsdsdssdsd', p: [123, 'sdsdsdsdsdsdsdvvvvvvvvv'] })  a.set('b', 123)  a.get('b')  a.get('a')})

依据客户的客户端条件适当调节limitForDBupperStorageLimit