Skip to content

perf(cache): Improve cache, Reduce Memory Usages#3756

Merged
SukkaW merged 5 commits into
hexojs:masterfrom
dailyrandomphoto:improve-cache
Oct 10, 2019
Merged

perf(cache): Improve cache, Reduce Memory Usages#3756
SukkaW merged 5 commits into
hexojs:masterfrom
dailyrandomphoto:improve-cache

Conversation

@dailyrandomphoto

Copy link
Copy Markdown
Member

What does it do?

Hexo uses a lot of memory to make a huge site.
This PR will reduce memory usages by modifying the usage of the unnecessary cache.
It can help with the "out of memory" related issues. (e.g., #3350 #3311 #1769 #1763 #1735 #1529)

There are two kinds of caches that hexo using

I've found something that can be improved a little bit to reduce memory usages.

Before

Mode Use Cache Of Rendered HTML Use Fragment Cache
generate true true
generate + watch false false
server(watch) false false
  1. In generate mode, Use Cache Of Rendered HTML should be false, since each route just be called once. The unnecessary cache uses a lot of memory.
    On the other hand, in server mode, Use Cache Of Rendered HTML should be true, since each route will be called several times. After enabling the cache, the route will respond more quickly from second requests.

  2. In generate + watch mode, generating a huge site will be slower than generate mode since Use Fragment Cache is disabled. Use Fragment Cache should always be enabled to speed up generating.

After

This PR will change the usages of caches to

Mode Use Cache Of Rendered HTML Use Fragment Cache
generate false true
generate + watch false true
server(watch) true true

How to test

git clone -b improve-cache https://github.com/dailyrandomphoto/hexo.git
cd hexo
npm install
npm test

Compare: Before vs. After

Before

git clone https://github.com/dailyrandomphoto/hexo-huge-site-test.git
cd hexo-huge-site-test
npm install
npm run g

Environment & Result

After

change the hexo dependency to dailyrandomphoto/hexo#improve-cache in package.json

npm install dailyrandomphoto/hexo#improve-cache
npm run g

Environment & Result

Screenshots

Before

2019100901

After

2019100902

Pull request tasks

  • Add test cases for the changes.
  • Passed the CI test.

@coveralls

coveralls commented Oct 9, 2019

Copy link
Copy Markdown

Coverage Status

Coverage decreased (-0.02%) to 97.273% when pulling 1ff8265 on dailyrandomphoto:improve-cache into d2662d4 on hexojs:master.

@SukkaW

SukkaW commented Oct 9, 2019

Copy link
Copy Markdown
Member

LGTM. I will run a benchmark on this.

@SukkaW

SukkaW commented Oct 9, 2019

Copy link
Copy Markdown
Member

With fragment cache enabled:

NodeJS 8 NodeJS 10 NodeJS 12
Hexo (master) 10s 9.39s 9.4s
This PR 11s 9.33s 9.38s

With fragment cache disabled:

NodeJS 8 NodeJS 10 NodeJS 12
Hexo (master) 15.5s 15s 15s
This PR 16s 15s 14.5s

I can see this PR has its generation speed more or less as same as the current master branch. I am wonder why @tommy351 implement Cache Of Rendered HTML at the beginning.

SukkaW
SukkaW previously approved these changes Oct 9, 2019
@SukkaW SukkaW added this to the v4.0.0 milestone Oct 9, 2019
@curbengh

Copy link
Copy Markdown
Contributor

Fragment cache reminds me of this issue #2503, specifically this comment (I highlighted the last line):

Can you confirm whether you have a layout file that is using the {cache:true} option set on the partial that loads the open_graph tag? I had the same issue, and then realized I was caching the partial that was loading my header which then caused this issue. Take a look, that might also have been your issue! hexo s must not respect the cache:true?

By enabling Fragment Cache for every mode, I believe this PR is also an improvement to the Different result between hexo g and hexo s of roadmap. If Fragment Cache was the sole cause, this PR can even fully fix it; though I suspect there might be other cause.

Comment thread lib/plugins/helper/fragment_cache.js Outdated
const cache = {};
let cache = {};

ctx.on('generateBefore', function() {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think can use arrow function?

@dailyrandomphoto

Copy link
Copy Markdown
Member Author

@SukkaW

I am wonder why @tommy351 implement Cache Of Rendered HTML at the beginning.

For server mode, Cache Of Rendered HTML can make the route respond more quickly from second requests.

At the beginning, Cache Of Rendered HTML was enabled for server mode. commit

hexo/lib/hexo/index.js

Lines 362 to 367 in e8e45ed

return self.execFilter('template_locals', locals, {context: self})
.then(function(locals){
route.set(path, function(){
if (cache != null) return cache;
var view, name;

But from this commit it was disabled by options.cache option value.

hexo/lib/hexo/index.js

Lines 362 to 368 in c313b5f

return self.execFilter('template_locals', locals, {context: self})
.then(function(locals){
route.set(path, function(){
if (options.cache && cache != null) return cache;
var view, name;

I think @tommy351 wants to disable it for watch mode, however it was disabled for server mode also.

If this feature useful for server mode only(if my guess is not wrong), I think it is better to refactoring as implement cache on the hexo-server repository as a filter or on a separate plugin.

@dailyrandomphoto

dailyrandomphoto commented Oct 10, 2019

Copy link
Copy Markdown
Member Author

Fragment Cache(introduced in #637) can improve performance a lot.
as @tommy351 said,

The effect of fragment cache is remarkable. I used fragment_cache helper in sidebar to reduce database queries. It only took less than 10 seconds to generate 1000+ static files. The original elapsed time is 10 minutes, which means is at least 60x faster.

However, some partial which output is different between pages should turn it off.
e.g.

  • head: title, og tags, meta tags should diffrent
  • toc
  • etc.

Like these partial(widget) can turn it on:

  • footer
  • tag, tagcloud
  • category
  • archives
  • etc.

@SukkaW SukkaW left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

@SukkaW SukkaW merged commit 6f6084c into hexojs:master Oct 10, 2019
@NoahDragon NoahDragon mentioned this pull request Oct 14, 2019
53 tasks
thom4parisot referenced this pull request in thom4parisot/hexo Jan 17, 2020
* 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/hexo@e8e45ed#diff-b9bb6fa7bb069bab9948daba90c6c3b2). Should enable save cache for rendered contents when run server mode.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants