MyBB Community Forums

Full Version: Ban Cache Optimisations
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
Can you please add performance and security thread prefixes? Toungue
PHP arrays aren't really arrays, they're a weird mix of lists and maps, but I'll call them that since that's the usual terminology.

The current system involves storing every banned user every in a forum in a giant array, serializing it, and storing it in memcached (or the datacache table, if you don't have a cache setup). MyBB will load this giant string on every page-load for users, attempts to deserialize it into a giant array, looks the current user up in this giant array, retrieves the cached ban table row from it, and checks if they have a live ban.

This process is extremely, extremely inefficient and will get slower and slower as the number of banned users on your forum increases, particularly on big boards. In fact, I discovered this issue thanks to a big board owner who ran into performance problems with a different cache and pointed this one out to me as another potential issue.

The first solution to the problem is one which I've already implemented locally, minus the upgrader portions.
It consists of adding a banExpiry column to the users table. 0 would signify that you aren't banned, -1 would represent a permanent ban, and anything over 0 would represent the date the user's ban expires on.

Edit: Option b was terrible in hindsight, so removed.

Edit 2: Ah wait, users are loaded on requests with a join to the groups table, duh. Okay, good idea.

I also looked into an alternate solution, as Euan kindly reminded me that the first solution would lead to a length upgrade process.
The alternate solution involves the ban cache being removed entirely and bans being managed entirely by the task system.
Once every fifteen minutes, the task system would go through all the bans which have expired and restore the user's original groups. It is extremely unlikely that an admin would issue a ban shorter than an hour and we don't really need a high degree of accuracy for ban expiries.
(2017-11-28, 02:52 AM)Azah Wrote: [ -> ]Basically, the ban cache would be removed and ban expiries would be managed solely by the task system which would run once every 15 minutes. It's extremely unlikely that an admin would assign a ban under an hour in length and ban expiries generally don't need an extremely high accuracy.

Just run it once a day. You should ban outright for longer than that anyway. Gets rid of the time issue. Runs at Midnight (local time - or better yet, GMT+0), problem solved.
The problem with running it once a day is that if someone is really unlucky, then they could end up being banned for 23 hours longer than they should have been. It's possible that someone could use a ban as a warning with a lot more oomph to drive the point home than as a proper ban lasting who knows how many weeks.

I've modmined (half-admin / half-mod) a Discord which at it's peak had over 30 thousand users, we use hour long bans (more like mutes) all the time there. It can be useful for when you want someone to chill out and come back after they've calmed down.
(2017-11-28, 03:15 AM)Azah Wrote: [ -> ]I've modmined (half-admin / half-mod) a Discord which at it's peak had over 30 thousand users, we use hour long bans (more like mutes) all the time there. It can be useful for when you want someone to chill out and come back after they've calmed down.

Live chat is not a forum; Discord is not really relevant here.

Full forum bans should only really be used when (something like) Topic Reply bans don't work
It's not up to the software to dictate how people should use it, I gave a perfectly reasonable use case.

Discord is totally relevant here, although the volume of the messages is far higher than a forum with messages pouring in every second. You literally can't afford to mess around with "warnings" in that environment. One thing we noticed is that people generally don't take you seriously, unless you smack them down and it sets an example for everyone else.

Please don't do that is as ineffective as can be, people don't know or care about your problems, I think your viewpoint stems from forums in general being nearly dead and difficult to use, thus people don't go through the hassle of using them.
That said, a query running once every fifteen minutes would have an infinitesimally small performance impact, particularly if the task system is properly optimised, in addition to that, it's extremely unlikely that anything under an hour would actually useful.

Far, far heavier queries are run every *request* in comparison to what could be essentially an o(1) check every 15 minutes.
The cache does seem rather pointless. All it does is serialize the entire mybb_banned table?

It looks like it could simply be piggy backed onto the query same way it's already done for userfields ( https://github.com/mybb/mybb/blob/featur...#L127-L133 ) then it's the database's problem to provide the banned data performantly. (Which it does, provided the relevant indexes are in place).
Account ban cache Issue for MyBB 1.8: https://github.com/mybb/mybb/issues/3878
IP, e-mail ban caches Issue for MyBB 1.9: https://github.com/mybb/mybb/issues/3876
Old thread but still relevant.

On my site years ago I noticed this problem and ended up making a Closed group that essentially was a zero access account similar to a permanent ban. It solves the problem actually. I almost think that MyBB should have a group such as that by default.

The solution by dvz will also probably work more efficiently too. Nice job.