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

feat(Core/AuctionHouse): Rework auctionhouse search threading #20830

Merged
merged 23 commits into from
Dec 18, 2024

Conversation

Takenbacon
Copy link
Contributor

@Takenbacon Takenbacon commented Dec 3, 2024

Complete rework of the auctionhouse search threading as the old system has been proven to be obviously very unsafe (#20538).

Simple model, spawns a configurable number of worker threads that each contain a pointer to a shared copy of AuctionEntry with an almost completely decoupled data structure (except for a pointer to ItemTemplate, which will be fine as long as we don't actively invalidate ItemTemplate data during run time. This can be "fixed" if needed by copying relevant item template data at the cost of increased memory usage and inability to modify existing data).

Scales well and is safe. I have used a similar model on servers with xx,xxx+ players and 150k+ auctions, however the implementation is quite different. I have done some initial local testing but I would highly recommend more testing before any merging. No danger to auctionhouse item data integrity during as we do not modify any auction entry data. Compile tested using MSVC only currently, GCC/Clang untested.

The auctionhouse system itself could use more changes but I kept the scope of this PR limited to just the searches.

Changes Proposed:

This PR proposes changes to:

  • Core (units, players, creatures, game systems).
  • Scripts (bosses, spell scripts, creature scripts).
  • Database (SAI, creatures, etc).

Issues Addressed:

SOURCE:

The changes have been validated through:

  • Live research (checked on live servers, e.g Classic WotLK, Retail, etc.)
  • Sniffs (remember to share them with the open source community!)
  • Video evidence, knowledge databases or other public sources (e.g forums, Wowhead, etc.)
  • The changes promoted by this pull request come partially or entirely from another project (cherry-pick). Cherry-picks must be committed using the proper --author tag in order to be accepted, thus crediting the original authors, unless otherwise unable to be found

Tests Performed:

This PR has been:

  • Tested in-game by the author.
  • Tested in-game by other community members/someone else other than the author/has been live on production servers.
  • This pull request requires further testing and may have edge cases to be tested.

How to Test the Changes:

  • This pull request can be tested by following the reproduction steps provided in the linked issue
  • This pull request requires further testing. Provide steps to test your changes. If it requires any specific setup e.g multiple players please specify it as well.
  1. Simply use the auctionhouse (specifically anything related to searches, owned and bidded auction lists)

Known Issues and TODO List:

None currently.

  • [ ]
  • [ ]

How to Test AzerothCore PRs

When a PR is ready to be tested, it will be marked as [WAITING TO BE TESTED].

You can help by testing PRs and writing your feedback here on the PR's page on GitHub. Follow the instructions here:

http://www.azerothcore.org/wiki/How-to-test-a-PR

REMEMBER: when testing a PR that changes something generic (i.e. a part of code that handles more than one specific thing), the tester should not only check that the PR does its job (e.g. fixing spell XXX) but especially check that the PR does not cause any regression (i.e. introducing new bugs).

For example: if a PR fixes spell X by changing a part of code that handles spells X, Y, and Z, we should not only test X, but we should test Y and Z as well.

Always update worker threads to prevent possible resource leaks on empty/idle servers
Remove redundant SearchableAuctionEntry list from AuctionHouseSearcher
These changes, while good, aren't currently necessary. Restore back to original to limit scope of PR. Will reimplement later with some changes.
and a little bit of misc refactoring to standardize some notation
@github-actions github-actions bot added CORE Related to the core file-cpp Used to trigger the matrix build labels Dec 3, 2024
@heyitsbench
Copy link
Contributor

Looks like this also closes #5068.

@Takenbacon
Copy link
Contributor Author

Looks like I finally got most of the build check issues resolved, only problem remaining appears to be a couple small compatibility issues with ahbot, in which it'd probably be best just to update the ahbot module.

@sudlud
Copy link
Member

sudlud commented Dec 4, 2024

Thanks for the update, could you please also prepare a PR for ahbot? Then we could get both merged when everything's ready :)

Copy link
Contributor

@walkline walkline left a comment

Choose a reason for hiding this comment

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

I think you already know that I love this implementation 😁 I just have a few small nitpicks (some of them related to the old code).

Comment on lines 2341 to 2342
METRIC_TIMER("world_update_time", METRIC_TAG("type", "Update expired auctions"));
sAuctionMgr->Update(diff);
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 we still need to put this code in an anonymous scope to measure the metric correctly.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done. 6cb4d9c


AuctionSearcherResponse* searchResponse = new AuctionSearcherResponse();
searchResponse->playerGuid = searchBidderListRequest.ownerGuid;
searchResponse->packet.Initialize(SMSG_AUCTION_BIDDER_LIST_RESULT, (4 + 4 + 4) + 30000); // pussywizard: ensure there is enough memory
Copy link
Contributor

Choose a reason for hiding this comment

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

I know that this change (upfront allocation of 30 012 bytes) doesn't come from your side, but does it make sense to you? I thought the average bidder list shouldn't be that long.
On the other hand, I think upfront allocation can be useful for getAll requests.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I did see that but opted to not change it at the time, but yes, it's a bit excessive and ultimately useless. At 148 bytes per auction entry it's effectively preallocating the buffer size for ~202 bidder auction entries which is unlikely to be the case 99% of the time. It's a bit insane to pre-optimize for ultra edge cases especially when the optimization is overall extremely insignificant. Also, we don't do the same for either SMSG_AUCTION_OWNER_LIST_RESULT or SMSG_AUCTION_LIST_RESULT. As such, I have now removed it ed83ecd

Comment on lines 284 to 287
{
for (auto const& pair : auctionMap)
auctionEntries.push_back(pair.second.get());
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Small nitpick: if we add return here, we can get rid of the else statement below.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done. f2e9608

else
{
CreatureData const* auctioneerData = sObjectMgr->GetCreatureData(creature->GetSpawnId());
if (!auctioneerData)
{
LOG_ERROR("network.opcode", "Data for auctioneer not found ({})", auctioneer.ToString());
delete AH;
Copy link
Contributor

Choose a reason for hiding this comment

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

Good catch!

Comment on lines -746 to -749
const Milliseconds delay = 2s;
const Milliseconds now = GameTime::GetGameTimeMS();
Milliseconds diff = GetMSTimeDiff(_lastAuctionListItemsMSTime, now);
if (diff > delay)
Copy link
Contributor

Choose a reason for hiding this comment

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

I was thinking maybe we could add rate limiter for some auction house opcodes somewhere here. What do you think? Maybe we can address it in a separate PR if needed.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The auction list opcodes definitely should be throttled, in fact there's even a blizzlike client side delay that we add to the list packets (now defined as AUCTION_SEARCH_DELAY) but that's obviously only on the client side. Personally, I've seen the antidos system and I can't say I'm a huge fan of how it works for a variety of reasons that would take too long to elaborate on, but I suppose it's the best we have for now. It could still use some refinement if we had a better system but as a temporary measure I've added them 2a51d56

CMSG_AUCTION_LIST_ITEMS is still lacking the blizzlike throttle for "getAll" requests (something around ~15 minutes if I recall correctly?). I don't believe it to be too important at the moment but it should also be implemented at some point. (Note: If someone other than me eventually implements it, there's a "gotcha" that CMSG_AUCTION_LIST_ITEMS is currently handled as PROCESS_THREADSAFE, any global containers used in the handler must be locked or the opcode moved to PROCESS_THREADUNSAFE)

Copy link
Contributor

Choose a reason for hiding this comment

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

Yeah, agree. Thanks for addressing the comments!

@TheSCREWEDSoftware
Copy link
Contributor

@Takenbacon just so I know if i need to update the labels. Is this ready to be tested or still being changed/developed?

@Takenbacon
Copy link
Contributor Author

@Takenbacon just so I know if i need to update the labels. Is this ready to be tested or still being changed/developed?

Ready to be tested, nothing left on my end except for any requested changes during reviews/testing that may come up.

@walkline
Copy link
Contributor

walkline commented Dec 8, 2024

I ran a small smoke test - no issues were found.

@Grimdhex
Copy link
Contributor

Why use std::wstring instead string ? Most of the core manipulate char and not wchar_t. Even with OS differences, that shouldn't be an issue ? Does I'm wrong ?

@Takenbacon
Copy link
Contributor Author

Why use std::wstring instead string ? Most of the core manipulate char and not wchar_t. Even with OS differences, that shouldn't be an issue ? Does I'm wrong ?

Mostly because that is what was there in the original implementation. Use of a wide string is not new from this PR.

if (!Utf8toWStr(_searchedname, wsearchedname))

Now, why we use a wide string in general? It's going to be for supporting the various languages/character encoding inputs received from the client. But, I couldn't really give you the specifics and I can't say I've bothered to really look into it. Character encoding is not a particular strong suit of mine as it is a confusing mess and varies significantly. You'll notice Utf8toWStr has quite a few uses in the codebase, mostly converting client string inputs (who list, channels, chat, etc)

@Nyeriah
Copy link
Member

Nyeriah commented Dec 12, 2024

Please check the merge conflicts
Also we need someone to please take a look into the AH bot module so we can merge it (the CI is failing)

@Takenbacon
Copy link
Contributor Author

Takenbacon commented Dec 12, 2024

Please check the merge conflicts
Also we need someone to please take a look into the AH bot module so we can merge it (the CI is failing)

Conflicts resolved.

@Grimdhex Grimdhex mentioned this pull request Dec 18, 2024
8 tasks
@sudlud sudlud merged commit 4d349e8 into azerothcore:master Dec 18, 2024
12 of 13 checks passed
@Kitzunu
Copy link
Member

Kitzunu commented Dec 18, 2024

Awesome sauce

@Nyeriah
Copy link
Member

Nyeriah commented Dec 19, 2024

https://github.com/azerothcore/mod-eluna needs an update

xpdemon pushed a commit to xpdemon/azerothcore-wotlk that referenced this pull request Dec 25, 2024
skelUA added a commit to skelUA/wotlk that referenced this pull request Jan 19, 2025
skelUA added a commit to skelUA/wotlk that referenced this pull request Jan 24, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
CORE Related to the core file-cpp Used to trigger the matrix build Ready to be Reviewed Waiting to be Tested
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Feature: Rewrite Auction House search
8 participants