From 225d35a4924af97c76067a04dc2e3c1832c6acc9 Mon Sep 17 00:00:00 2001 From: mostlikely4r Date: Wed, 9 Oct 2024 15:28:39 +0200 Subject: [PATCH] -Ah performance improvement: Removed direct ah db queries and replaced it with a internal lookup. --- playerbot/RandomPlayerbotMgr.cpp | 37 ++++++++++++++++++-- playerbot/RandomPlayerbotMgr.h | 6 +++- playerbot/TravelMgr.cpp | 1 - playerbot/strategy/actions/AhAction.cpp | 23 +++++++++--- playerbot/strategy/values/ItemUsageValue.cpp | 35 +++++++++++++++--- 5 files changed, 89 insertions(+), 13 deletions(-) diff --git a/playerbot/RandomPlayerbotMgr.cpp b/playerbot/RandomPlayerbotMgr.cpp index 4087cb302..c1fc349a6 100644 --- a/playerbot/RandomPlayerbotMgr.cpp +++ b/playerbot/RandomPlayerbotMgr.cpp @@ -658,6 +658,8 @@ void RandomPlayerbotMgr::UpdateAIInternal(uint32 elapsed, bool minimal) DelayedFacingFix(); + MirrorAh(); + //Ping character database. CharacterDatabase.AsyncPQuery(&RandomPlayerbotMgr::DatabasePing, sWorld.GetCurrentMSTime(), std::string("CharacterDatabase"), "select 1 from dual"); } @@ -698,9 +700,6 @@ void RandomPlayerbotMgr::ScaleBotActivity() out << activityPercentageMod << ","; out << activeBots << ","; out << GetPlayerbotsAmount() << ","; - out << ahQueries << ","; - - ahQueries = 0; float totalLevel = 0, totalGold = 0, totalGearscore = 0; @@ -3818,6 +3817,38 @@ void RandomPlayerbotMgr::Hotfix(Player* bot, uint32 version) bot->GetGUIDLow(), MANGOSBOT_VERSION); } +void RandomPlayerbotMgr::MirrorAh() +{ + sRandomPlayerbotMgr.m_ahActionMutex.lock(); + + ahMirror.clear(); + + std::vector houses = { (AuctionHouseType)0,(AuctionHouseType)1,(AuctionHouseType)2 }; + + //Now loops over all houses. Can probably be faction specific later. + for (auto house : houses) + { + AuctionHouseObject* auctionHouse = sAuctionMgr.GetAuctionsMap(house); + + AuctionHouseObject::AuctionEntryMap const& map = auctionHouse->GetAuctions(); + + for (auto& auction : map) + { + if (!auction.second) + continue; + + if (!auction.second->buyout) + continue; + + if (!auction.second->itemCount) + continue; + + ahMirror[auction.second->itemTemplate].push_back(*auction.second); + } + } + sRandomPlayerbotMgr.m_ahActionMutex.unlock(); +} + typedef std::unordered_map > botPerformanceMetric; std::unordered_map botPerformanceMetrics; diff --git a/playerbot/RandomPlayerbotMgr.h b/playerbot/RandomPlayerbotMgr.h index 1c510b0e2..205e27d67 100644 --- a/playerbot/RandomPlayerbotMgr.h +++ b/playerbot/RandomPlayerbotMgr.h @@ -155,7 +155,7 @@ class RandomPlayerbotMgr : public PlayerbotHolder std::mutex m_ahActionMutex; - uint32 ahQueries = 0; + std::vector GetAhPrices(uint32 itemId) { return ahMirror[itemId]; } protected: virtual void OnBotLoginInternal(Player * const bot); @@ -183,6 +183,7 @@ class RandomPlayerbotMgr : public PlayerbotHolder void PrepareTeleportCache(); typedef void (RandomPlayerbotMgr::*ConsoleCommandHandler) (Player*); + void MirrorAh(); private: PlayerBotMap players; int processTicks; @@ -208,6 +209,9 @@ class RandomPlayerbotMgr : public PlayerbotHolder bool showLoginWarning; std::unordered_map>>> facingFix; + + // itemId, buyout, count + std::unordered_map < uint32, std::vector> ahMirror; }; #define sRandomPlayerbotMgr RandomPlayerbotMgr::instance() diff --git a/playerbot/TravelMgr.cpp b/playerbot/TravelMgr.cpp index 0e7c80497..9baa9c511 100644 --- a/playerbot/TravelMgr.cpp +++ b/playerbot/TravelMgr.cpp @@ -1323,7 +1323,6 @@ void TravelMgr::LoadQuestTravelTable() out << "activityPercentageMod,"; out << "activeBots,"; out << "playerBots.size(),"; - out << "ahqueries,"; out << "totalLevel,"; out << "avarageLevel1-9,"; out << "avarageLevel10-19,"; diff --git a/playerbot/strategy/actions/AhAction.cpp b/playerbot/strategy/actions/AhAction.cpp index c7e419346..6f29d550f 100644 --- a/playerbot/strategy/actions/AhAction.cpp +++ b/playerbot/strategy/actions/AhAction.cpp @@ -83,13 +83,25 @@ bool AhAction::ExecuteCommand(Player* requester, std::string text, Unit* auction if (!pricePerItemCache[proto->ItemId]) { //check current AH listing prices for this item and try to set lower (undercut) + AuctionEntry lowestPrice; - uint32 lowestBuyoutItemPricePerItem = 0; - uint32 lowestBuyoutItemPricePerItemOwnerDbGuid = 0; + lowestPrice.Id = 0; // check for the cheapest listing with the same count // (simple dumping protection, can be improved by comparing listing prices but it's a bit complicated) - sRandomPlayerbotMgr.ahQueries += 1; + + std::vector auctions; + + for (auto& auction : sRandomPlayerbotMgr.GetAhPrices(proto->ItemId)) + { + if (auction.itemCount != item->GetCount()) + continue; + + if (lowestPrice.Id == 0 || float(auction.buyout) / float(auction.itemCount) < float(lowestPrice.buyout) / float(lowestPrice.itemCount)) + lowestPrice = auction; + } + + /* auto lowestBuyoutPriceListing = CharacterDatabase.PQuery( "SELECT buyoutprice, item_count, itemowner FROM auction WHERE item_template = '%u' AND item_count = '%u' ORDER BY buyoutprice / item_count ASC LIMIT 1", item->GetProto()->ItemId, @@ -110,6 +122,9 @@ bool AhAction::ExecuteCommand(Player* requester, std::string text, Unit* auction } } while (lowestBuyoutPriceListing->NextRow()); } + */ + + uint32 lowestBuyoutItemPricePerItem = float(lowestPrice.buyout) / float(lowestPrice.itemCount); // default desired price if there are no item listings // (is the max price because why not? sounds reasonable to try selling at max price if there are no listings) @@ -120,7 +135,7 @@ bool AhAction::ExecuteCommand(Player* requester, std::string text, Unit* auction // check if it would be reasonable to sell lower than current cheapest listing // also check if the item poster is not self to not to undercut yourself - if (lowestBuyoutItemPricePerItem > 0 && lowestBuyoutItemPricePerItemOwnerDbGuid != bot->GetDbGuid()) + if (lowestBuyoutItemPricePerItem > 0 && lowestPrice.owner != bot->GetDbGuid()) { //try to undercut by randomly 1 copper to 10% (may result in not actually undercutting but it's alright, even better) uint32 undercutByMoney = std::max(static_cast(1), static_cast(lowestBuyoutItemPricePerItem * frand(0.0f, 0.1f))); diff --git a/playerbot/strategy/values/ItemUsageValue.cpp b/playerbot/strategy/values/ItemUsageValue.cpp index da30d18e8..a7771869f 100644 --- a/playerbot/strategy/values/ItemUsageValue.cpp +++ b/playerbot/strategy/values/ItemUsageValue.cpp @@ -1097,7 +1097,6 @@ void ItemUsageValue::PopulateReagentItemIdsForCraftableItemIds() void ItemUsageValue::PopulateSoldByVendorItemIds() { - sRandomPlayerbotMgr.ahQueries += 1; if (auto result = WorldDatabase.PQuery("%s", "SELECT item, entry FROM npc_vendor")) { BarGoLink bar(result->GetRowCount()); @@ -1112,7 +1111,6 @@ void ItemUsageValue::PopulateSoldByVendorItemIds() } while (result->NextRow()); } - sRandomPlayerbotMgr.ahQueries += 1; if (auto result = WorldDatabase.PQuery("%s", "SELECT item, entry FROM npc_vendor WHERE maxcount > 0")) { BarGoLink bar(result->GetRowCount()); @@ -1162,7 +1160,21 @@ uint32 ItemUsageValue::GetAHMedianBuyoutPricePerItem(ItemPrototype const* proto) { if (sPlayerbotAIConfig.shouldQueryAHListingsOutsideOfAH) { - sRandomPlayerbotMgr.ahQueries += 1; + std::vector prices; + + for (auto& auction : sRandomPlayerbotMgr.GetAhPrices(proto->ItemId)) + { + prices.push_back((float)auction.buyout / (float)auction.itemCount); + } + + if (prices.empty()) + return 0; + + size_t n = prices.size() / 2; + std::nth_element(prices.begin(), prices.begin() + n, prices.end()); + return prices[n]; + + /* auto query = CharacterDatabase.PQuery( " SELECT item_template, AVG(median)" " FROM (SELECT item_template, (buyoutprice / item_count) median" @@ -1185,6 +1197,7 @@ uint32 ItemUsageValue::GetAHMedianBuyoutPricePerItem(ItemPrototype const* proto) return medianPrice; } while (query->NextRow()); } + */ } return 0; @@ -1194,7 +1207,20 @@ uint32 ItemUsageValue::GetAHListingLowestBuyoutPricePerItem(ItemPrototype const* { if (sPlayerbotAIConfig.shouldQueryAHListingsOutsideOfAH) { - sRandomPlayerbotMgr.ahQueries += 1; + float minPrice = 0; + uint32 minBuyout = 0; + + for (auto& auction : sRandomPlayerbotMgr.GetAhPrices(proto->ItemId)) + { + if (!minBuyout || minBuyout > auction.buyout) + { + minBuyout = auction.buyout; + minPrice = (float)auction.buyout / (float)auction.itemCount; + } + } + + return minBuyout; + /* auto query = CharacterDatabase.PQuery( "SELECT buyoutprice / item_count" " FROM auction" @@ -1214,6 +1240,7 @@ uint32 ItemUsageValue::GetAHListingLowestBuyoutPricePerItem(ItemPrototype const* return lowestBuyoutPrice; } while (query->NextRow()); } + */ } return 0;