Skip to content

Commit

Permalink
perf(cache): improve cache and reduce Memory Usages (hexojs#3756)
Browse files Browse the repository at this point in the history
* test(cache): verify whether the cache works properly
* fix(fragment_cache): reset the cache on generateBefore event so we can enable cache on watch mode.
* fix(cache): disable save cache for rendered contents when generate files. Added at (hexojs@e8e45ed#diff-b9bb6fa7bb069bab9948daba90c6c3b2). Should enable save cache for rendered contents when run server mode.
  • Loading branch information
dailyrandomphoto authored and Thomas Parisot committed Jan 17, 2020
1 parent b497321 commit 223f2c6
Show file tree
Hide file tree
Showing 4 changed files with 75 additions and 14 deletions.
18 changes: 14 additions & 4 deletions lib/hexo/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ function Hexo(base = process.cwd(), args = {}) {
silent: Boolean(args.silent),
env: process.env.NODE_ENV || 'development',
version: pkg.version,
cmd: args._ ? args._[0] : '',
init: false
};

Expand Down Expand Up @@ -253,11 +254,16 @@ Hexo.prototype.load = function(callback) {
this.source.process(),
this.theme.process()
]);
}).then(() => this._generate({cache: true})).asCallback(callback);
}).then(() => this._generate({cache: false})).asCallback(callback);
};

Hexo.prototype.watch = function(callback) {
this._watchBox = debounce(() => this._generate({cache: false}), 100);
let useCache = false;
if (this.env.cmd.startsWith('s')) {
// enable cache when run hexo server
useCache = true;
}
this._watchBox = debounce(() => this._generate({cache: useCache}), 100);

return loadDatabase(this).then(() => {
this.log.info('Start processing');
Expand All @@ -270,7 +276,7 @@ Hexo.prototype.watch = function(callback) {
this.source.on('processAfter', this._watchBox);
this.theme.on('processAfter', this._watchBox);

return this._generate({cache: false});
return this._generate({cache: useCache});
}).asCallback(callback);
};

Expand Down Expand Up @@ -345,6 +351,8 @@ const createLoadThemeRoute = function(generatorResult, locals, ctx) {
const layout = unique(castArray(generatorResult.layout));
const layoutLength = layout.length;

// allways use cache in fragment_cache
locals.cache = true;
return () => {
if (useCache && routeCache.has(generatorResult)) return routeCache.get(generatorResult);

Expand All @@ -355,7 +363,9 @@ const createLoadThemeRoute = function(generatorResult, locals, ctx) {
if (view) {
log.debug(`Rendering HTML ${name}: ${chalk.magenta(path)}`);
return view.render(locals).tap(result => {
routeCache.set(generatorResult, result);
if (useCache) {
routeCache.set(generatorResult, result);
}
}).tapCatch(err => {
log.error({ err }, `Render HTML failed: ${chalk.magenta(path)}`);
});
Expand Down
5 changes: 4 additions & 1 deletion lib/plugins/helper/fragment_cache.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
'use strict';

module.exports = ctx => {
const cache = {};
let cache = {};

// reset cache for watch mode
ctx.on('generateBefore', () => { cache = {}; });

return function fragmentCache(id, fn) {
if (this.cache && cache[id] != null) return cache[id];
Expand Down
11 changes: 10 additions & 1 deletion test/scripts/helpers/fragment_cache.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
'use strict';

describe('fragment_cache', () => {
const fragment_cache = require('../../../lib/plugins/helper/fragment_cache')();
const Hexo = require('../../../lib/hexo');
const hexo = new Hexo(__dirname);
const fragment_cache = require('../../../lib/plugins/helper/fragment_cache')(hexo);

fragment_cache.call({cache: true}, 'foo', () => 123);

Expand All @@ -12,4 +14,11 @@ describe('fragment_cache', () => {
it('cache disabled', () => {
fragment_cache.call({cache: false}, 'foo', () => 456).should.eql(456);
});

it('should reset cache on generateBefore', () => {
fragment_cache.call({cache: true}, 'foo', () => 789).should.eql(456);
// reset cache
hexo.emit('generateBefore');
fragment_cache.call({cache: true}, 'foo', () => 789).should.eql(789);
});
});
55 changes: 47 additions & 8 deletions test/scripts/hexo/hexo.js
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ describe('Hexo', () => {
silent: false,
env: process.env.NODE_ENV || 'development',
version,
cmd: '',
init: false
});
hexo.config_path.should.eql(pathFn.join(__dirname, '_config.yml'));
Expand Down Expand Up @@ -452,17 +453,41 @@ describe('Hexo', () => {
it('_generate() - reset cache for new route', () => {
let count = 0;

hexo.theme.setView('test.swig', '{{ page.count }}');
hexo.theme.setView('test.swig', '{{ page.count() }}');

hexo.extend.generator.register('test', () => ({
path: 'test',
layout: 'test',
data: {count: count++}
data: {count: () => count++}
}));

// First generation
return hexo._generate({cache: true}).then(() => checkStream(route.get('test'), '0')).then(() => // Second generation
hexo._generate({cache: true})).then(() => checkStream(route.get('test'), '1'));
return hexo._generate({cache: true})
.then(() => checkStream(route.get('test'), '0'))
.then(() => checkStream(route.get('test'), '0')) // should return cached result
.then(() => hexo._generate({cache: true})) // Second generation
.then(() => checkStream(route.get('test'), '1'))
.then(() => checkStream(route.get('test'), '1')); // should return cached result
});

it('_generate() - cache disabled and use new route', () => {
let count = 0;

hexo.theme.setView('test.swig', '{{ page.count() }}');

hexo.extend.generator.register('test', () => ({
path: 'test',
layout: 'test',
data: {count: () => count++}
}));

// First generation
return hexo._generate({cache: false})
.then(() => checkStream(route.get('test'), '0'))
.then(() => checkStream(route.get('test'), '1'))
.then(() => hexo._generate({cache: false})) // Second generation
.then(() => checkStream(route.get('test'), '2'))
.then(() => checkStream(route.get('test'), '3'));
});

it('_generate() - cache disabled & update template', () => {
Expand All @@ -473,10 +498,24 @@ describe('Hexo', () => {
layout: 'test'
}));

return hexo._generate({cache: false}).then(() => checkStream(route.get('test'), '0')).then(() => {
hexo.theme.setView('test.swig', '1');
return checkStream(route.get('test'), '1');
});
return hexo._generate({cache: false})
.then(() => checkStream(route.get('test'), '0'))
.then(() => hexo.theme.setView('test.swig', '1'))
.then(() => checkStream(route.get('test'), '1'));
});

it('_generate() - cache enabled & update template', () => {
hexo.theme.setView('test.swig', '0');

hexo.extend.generator.register('test', () => ({
path: 'test',
layout: 'test'
}));

return hexo._generate({cache: true})
.then(() => checkStream(route.get('test'), '0'))
.then(() => hexo.theme.setView('test.swig', '1'))
.then(() => checkStream(route.get('test'), '0')); // should return cached result
});

it('execFilter()', () => {
Expand Down

0 comments on commit 223f2c6

Please sign in to comment.