Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Merged
merged 5 commits into from
Oct 10, 2019

Conversation

dailyrandomphoto
Copy link
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
Copy link

coveralls commented Oct 9, 2019

Coverage Status

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

@SukkaW
Copy link
Member

SukkaW commented Oct 9, 2019

LGTM. I will run a benchmark on this.

@SukkaW
Copy link
Member

SukkaW commented Oct 9, 2019

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
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.

const cache = {};
let cache = {};

ctx.on('generateBefore', function() {
Copy link
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
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
Copy link
Member Author

dailyrandomphoto commented Oct 10, 2019

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.

Copy link
Member

@SukkaW SukkaW left a comment

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 pushed a commit to thom4parisot/hexo that referenced this pull request 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@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