mem模块 缓存模块

5 篇文章 0 订阅
2 篇文章 0 订阅

mem模块

mem的github地址

作用

缓存函数的运行结果,当参数一样的时候,不再运行,直接读取缓存值

使用

const mem = require('mem');
const m = mem(fn[,options]);
fn:你想运行的函数
options:mem的设置,包括设置缓存时间、缓存key值算法、缓存存储、统计等

具体请参见文档

同步使用
const mem = require('mem');

let i = 0;

function sum() {
  ++i;
}

const m = mem(sum);

m('h');//i=1
m('h');//i=1
m('m');//i=2
m('m');//i=2
异步使用
const mem = require('mem');

let i = 0;

async function sum() {
  ++i;
}

const m = mem(sum);

(async function () {
  await m();//i=1
  await m();//i=1
  await m('i');//i=2
})();

源码学习

源码暴露出两个函数:

  • mem:主函数
  • clear :清除缓存函数
主函数

主函实现:

  • 计算key值,将数据存储于Map中
  • 数据去重,不存储已经存在过的key值
  • 超过设置maxAge时间清除缓存
  • 将函数作为key值,存入WeekMap中
1、计算key值
// 默认使用defaultCacheKey函数
const defaultCacheKey = (...args) => {
	if (args.length === 0) {
		return '__defaultKey';
	}

	if (args.length === 1) {
		const [firstArgument] = args;
		if (
			firstArgument === null ||
			firstArgument === undefined ||
			(typeof firstArgument !== 'function' && typeof firstArgument !== 'object')
		) {
			return firstArgument;
		}
	}

	return JSON.stringify(args);
};

如上是作者计算缓存key的函数,将计算后的key做为cache的键。当然也可以自己传入key的计算函数:

const mem = require('mem');
const m = mem(fn,{
	cacheKey:fn //此处可以传入计算key的函数
});

计算key的时候,判断有些不严谨

  • 传入值 于 期望返回的不符:当传入NaN、Object类型时,可能会造成与期望不符,例如:
const mem = require('mem');

let i = 0;

function sum() {
  ++i;
}

const m = mem(sum);

m(NaN);// i=1
m(NaN);// i=1
m({ a: 1 });// i=2
m({ a: 1 });// i=3
// 但是 NaN是不等于NaN,{a:1}也不等于{a:1},而他们的得到值是一样的
  • 某些值使用JSON.stringfy()会出现问题:如正则表达式和函数
m(function b() {});// i=1
m(function a() {});// i=1
m(/a/);// i=2
m(/b/);// i=2
2、数据去重
const memoized = function (...args) {
		const key = options.cacheKey(...args);

		if (cache.has(key)) {
			const c = cache.get(key);

			return c.data;
		}

		const ret = fn.call(this, ...args);

		setData(key, ret);

		if (isPromise(ret) && options.cachePromiseRejection === false) {
			// Remove rejected promises from cache unless `cachePromiseRejection` is set to `true`
			ret.catch(() => cache.delete(key));
		}

		return ret;
	};
	// 作者使用Map的has方法判断去重
	// 	cache(Map类型)在这里充当存储空间,是优于Object的,因为Map可以存储任意类型的key值,而Object只能存储字符串和数字的key值
3、maxAge实现
// mem/index.js文件中
const mapAgeCleaner = require('map-age-cleaner');
...
  if (typeof options.maxAge === 'number') {
    mapAgeCleaner(options.cache);
  }
...
// 使用mapAgeCleaner函数,覆盖了Map.set()方法,调用了cleanup()方法。

在cleanup内部有如下判断超时的机制
...
// map-age-cleaner/index.js文件中
   const delay = item[ 1 ][ property ] - Date.now();
      if (delay <= 0) {  // 此处判断是否超时
        // Remove the item immediately if the delay is equal to or below 0
        map.delete(item[ 0 ]);// 超时了则删除当前key的数据
        processingDeferred.resolve();
        return;
      }
...
4、缓存函数
...
	mimicFn(memoized, fn);

	cacheStore.set(memoized, options.cache);
...
// 以函数做为键名,cache作为值,存入cacheStore(weekMap类型)中
// cacheStore是weekMap类型,在此处使用该类型的作用时,weekMap内部的key值是弱引用,当外部引用消失的时候,自动销毁内部对应的键值,防止内存溢出。
清除函数

调用clear方法,手动清楚缓存

module.exports.clear = fn => {
	const cache = cacheStore.get(fn);

	if (cache && typeof cache.clear === 'function') {
		cache.clear();
	}
};

结论

优点:

  • 快速缓存函数运行结果

不足:

  • 在key计算时,不够严谨
  • 未设置默认的maxAge时间(当未设置maxAge则为永久缓存),可能会造成内存泄漏
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
引用\[2\]中提到,Python的内存管理机制主要涉及对象的存储问题。Python会为对象分配一块内存空间来存储。对于整数和短小的字符等,Python会执行缓存机制,即将这些对象进行缓存,不会为相同的对象分配多个内存空间。而对于容器对象,如列表、元组、字典等,存储的是其他对象的引用,而不是这些对象本身。此外,Python还使用了对象池来优化内存管理。其中,小整数池是为了避免频繁申请和销毁内存空间,Python对于范围在\[-5, 257)的整数使用同一个对象。而字符串驻留机制则通过维护一个字符串常量池,尽量只保存唯一的字符串对象,以达到高效和节省内存的目的。 引用\[3\]中提到,Python中的每一个东西都是对象,它们的核心是结构体PyObject。当一个对象的引用计数为0时,该对象的生命周期就结束了。引用计数机制会记录对象引用自己的对象的个数,每增加一个引用,个数+1,每减少一个引用,个数-1。可以使用sys模块中的getrefcount(对象)方法来查看对象的引用个数。 综上所述,Python的内存管理机制主要包括引用计数机制和垃圾回收机制。引用计数机制通过记录对象的引用个数来管理内存,当引用个数为0时,对象被销毁。而垃圾回收机制则负责回收无法通过引用计数机制释放的内存。 #### 引用[.reference_title] - *1* *2* *3* [【python】46_python内存管理机制](https://blog.csdn.net/potizo/article/details/107489307)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值