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(escapeAllSwigTags): reducing GC overhead #5620

Open
wants to merge 4 commits into
base: master
Choose a base branch
from

Conversation

D-Sketon
Copy link
Member

What does it do?

A large amount of string concatenation can result in numerous consString objects, which cannot be cleared during Scavenge. This leads to old generation expansion.

12x many-posts
before PR
{7542781E-F3A2-469E-8F24-D23D2BD2F2E7}
after PR
{405183C1-BE25-4F12-AB74-3F6AFD5EE625}

12x many-posts concurrency=20
before PR
{078D8B04-6C65-4DC3-824B-8310CFD81762}
after PR
{7CCECB0D-DD2C-4BA3-807D-6C52B52EDB0C}

4x many-posts concurrency=20
before PR
{80FEC4BA-F199-46A7-9B7E-B81BF2ADD67B}

after PR
{28230638-86F6-4081-A1ED-5F6DC02A9506}

1x many-posts concurrency=20
before PR
{CBF42156-63A6-47BC-A8B2-6FA2C0BB5CCC}
after PR
{13F8198A-B0EF-412A-93CE-F21BDA67EDE0}

Screenshots

Pull request tasks

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

Copy link

How to test

git clone -b perf/mem https://github.com/D-Sketon/hexo.git
cd hexo
npm install
npm test

@coveralls
Copy link

coveralls commented Jan 19, 2025

Pull Request Test Coverage Report for Build 12972482668

Details

  • 22 of 23 (95.65%) changed or added relevant lines in 1 file are covered.
  • No unchanged relevant lines lost coverage.
  • Overall coverage remained the same at 99.492%

Changes Missing Coverage Covered Lines Changed/Added Lines %
lib/hexo/post.ts 22 23 95.65%
Totals Coverage Status
Change from base Build 12902994421: 0.0%
Covered Lines: 9606
Relevant Lines: 9655

💛 - Coveralls

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.

I believe that the root cause of the issue is that string concatenation doesn't copy strings; instead, it points to the existing strings using pointers. This is good for performance, so we should retain this behavior.

On the other hand, the concatenated string holds the reference of the old string, preventing the old string from being released.

Instead of manually creating a StringBuilder, you can try replacing return output with return output.replace('#'.repeat(output.length + 1), '') to see if it reduces GC pressure.

See also: https://romgrk.com/posts/optimizing-javascript#8-use-strings-carefully

@D-Sketon
Copy link
Member Author

D-Sketon commented Jan 21, 2025

I tested it briefly and it doesn't seem to make a difference
return output
{AB300490-3FDF-4A72-A222-3B5BBB04242F}
return output.replace('#'.repeat(output.length + 1), '')
{86D9B4DB-361B-4D64-B6F6-29698F88D5DC}
with stringbuilder
{ACE486C0-2961-459A-88F9-1EE38EFBAA66}
I'll follow up with an in-depth investigation.

@D-Sketon
Copy link
Member Author

D-Sketon commented Jan 23, 2025

I might have figured out why there's a memory difference.

Although consString uses references, each consString itself carries a size of 32 bytes.

Assuming each post has 5,000 characters and there are 4,000 posts, consString would occupy an additional 5,000 * 4,000 * 32B = 640MB.

{7EFA2D73-C795-4FD8-AC57-0F0263CC169B}

On the other hand, using StringBuilder would result in each post taking an additional 32 bytes (I’m not entirely sure), totaling an additional 4,000 * 32B = 128KB.

{94E66F92-42A9-4CD3-B8A5-D12EBE15F076}

@D-Sketon
Copy link
Member Author

@SukkaW Using output.charAt(0) seems to be able to flatten the string in Node20, but it doesn't work on node22.
before
{74099CD0-72BE-4EDC-A46A-ED4B15111385}
after
{BF396102-744E-438C-8BE1-36501BB70309}

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.

3 participants