Skip to content

Conversation

@WhatCats
Copy link
Contributor

@WhatCats WhatCats commented Nov 2, 2025

I believe a Set would be better suited for the private member _roles collection.
I think the role cache getters will perform better by iterating over the _roles subset instead of every guild role.

Context: Trying to do stuff with the roles of every guild member in a guild with 20000 members and 200 roles.

Status and versioning classification:

  • I know how to update typings and have done so, or typings don't need updating

@vercel
Copy link

vercel bot commented Nov 2, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

2 Skipped Deployments
Project Deployment Preview Comments Updated (UTC)
discord-js Ignored Ignored Preview Nov 9, 2025 10:47am
discord-js-guide Ignored Ignored Preview Nov 9, 2025 10:47am

Copy link
Member

@kyranet kyranet left a comment

Choose a reason for hiding this comment

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

The changes in GuildEmojiRoleManager#cache and GuildMemberRoleManager#cache are solid and definitely will see an improvement since it's not running a nested iteration anymore, however...

Changing GuildMember#_roles to be a Set<Snowflake> rather than a Snowflake[], whilst it's true it'll see performance gains in large datasets, the average role count is more like 2-3 roles (tested in my bot, 3_296_963 GuildMember instances, 6_291_128 member roles excluding everyone), therefore making a negligible CPU performance difference.

The memory usage does increase by replacing Array with Set substantially, see below.

Data

For 1 million sets of 5 entries each (which is above average anyways), the memory usage for Set is substantially higher:

  • Array:

    • Empty: 40.47 MB | 71.21 MB
    • 5 values: 40.47 MB | 71.46 MB (doesn't change because capacity)
  • Set:

    • Empty: 154.91 MB | 187.46 MB
    • 5 values: 231.21 MB | 265.71 MB
  • The above numbers are the difference between the start and the end.

  • globalThis.gc() is called before and after each test, using --expose-gc.

  • Tested on Node.js v22.14.0

While we welcome performance improvements, specially when they make internal code easier to read, sometimes such improvement comes at the cost of higher memory usage, and this is a case where the impact is just too large to accept it. We can keep the #cache improvements nevertheless, those should work as-is without changes!

@github-project-automation github-project-automation bot moved this from Todo to Review in Progress in discord.js Nov 9, 2025
@Jiralite Jiralite removed the in review label Nov 9, 2025
@WhatCats WhatCats force-pushed the feat/optimize-role-manager branch from e6c026c to e4c2ba9 Compare November 9, 2025 02:14
@Jiralite Jiralite self-requested a review November 9, 2025 10:43
@github-project-automation github-project-automation bot moved this from Review in Progress to Review Approved in discord.js Nov 9, 2025
@kodiakhq kodiakhq bot merged commit c85f18c into discordjs:main Nov 9, 2025
7 checks passed
@github-project-automation github-project-automation bot moved this from Review Approved to Done in discord.js Nov 9, 2025
Jiralite pushed a commit that referenced this pull request Nov 9, 2025
Co-authored-by: Almeida <github@almeidx.dev>
@Jiralite Jiralite changed the title feat: optimize role manager cache getter perf: optimize role manager cache getter Nov 19, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

5 participants