Crusader Kings III

Crusader Kings III

A Culling of the Weak: Performance Improvements
 Denna tråd har blivit fäst, så den är troligtvis viktig
Olympia  [utvecklare] 11 nov @ 13:29
Break Down of Design Decisions
If you're anything like me, you want to know exactly what's beneath the hood of this mod, who it's culling, who it's sparing, and my overall design decisions. Here is a more elaborate and specific breakdown for the curious and bored:

Character Adjustments
AI Characters that are obscured (and all features are enabled)...
  • Have a 75% war chance reduction
  • Have a 5x greater war cool down before declaring more wars
  • Gain a +5 domain limit
  • Gain a +25 Popular Opinion with their counties
  • Elderly Health -2
  • Child Health -1
  • Fertility -25%
  • Does not gain stress
  • Only kings or higher can host activities and make most decisions
  • Only dukes or higher can participate in raids

Why these adjustments?

Based on Paradox's own review[forum.paradoxplaza.com] of what consumes the most CPU resources, I wanted to prioritize the big ticket items: character population, number of rulers, path finding (thus wars, raids, and traveling), activities, and decisions. I have a few other ideas in mind that I'm testing, but I don't want to implement them unless they actually result in tangible changes.
  • War reduction and greater cool down for AI rulers means the AI should be prioritizing the bigger, more important wars (particularly for high ranking rulers), while counts should be engaging in less pointless border squabbles that ultimately make no difference to the player on the other side of the map. This only affects the chance of war, it doesn't disable it. I am currently testing to see if completely disabling wars for Counts makes any difference (so far, not enough to justify the change). Fewer wars means fewer armies making the expensive path finding calculations.

  • Higher popular opinion helps reduce peasant rebellions and, let's be clear, those are really kind of useless and more of a nuisance. These are completely pointless to a player on the other side of the map. I'm tempted to eliminate them completely, but for now, there is just a significantly reduced chance of them starting (but not impossible).

  • A +5 domain limit increase is possibly the only change that tangibly gives distant rulers a huge advantage and may want to be considered carefully, but it also helps cut down on resources considerably. For every one Count eliminated, that's one fewer courts (average about 10 courtiers each), which means fewer schemes, fewer tiny wars, fewer marriages, fewer successions, fewer children to educate, fewer councils to run tasks, etc. And since the AI loses this advantage when they become relevant to players (either because they end up within diplomatic range or they join a war as a secondary participant), it shouldn't unfairly impact the player.

    Consider this: in one 1282 test run with this mod, there were 4,520 landed rulers (2,951 barons and 904 counts) under the domain-adjusted system.

    After removing the domain-increase modifier and allowing the AI to redistribute its excess titles, that number rose to 5,498: 3,497 barons and 1,397 counts, a 21.6% increase overall, driven mostly by a 54% surge in counts (!!!) and an 18.5% rise in barons. While the Barons aren't really that concerning, that increase in counts is. That's almost 500 extra courts, 500 more vassals, all with their own council, weddings, children, schemes, priorities, war capabilities, armies, etc.

    Now, why not just keep raising it? Double it to +10, hell, make it +50! Tempting, but doing so has an unintended consequence: after around +5, any additional increases tends to make the top lieges exponentially richer and monster military powerhouses, so much to the point that when they finally do become diplomatically relevant to a player, they've amassed such a huge war chest and massive army, it becomes asymmetrical warfare (and not the fun, challenging kind). The other issue is that even if you don't go to war right away with the AI as they become relevant, if they've built their economy and military around having huge domain bonuses (+6 or higher), the sudden loss of those domains just because you got closer usually means their economies collapse. And every CK3 player knows the AI is anything but flexible and resilient in times of economic crisis. +5 domain increase is the top limit of where I feel as though we're not setting the AI for failure nor handing them big advantages over players for the sake of performance.

    That all being said... if you increase the domain limit for all rulers (including the player) by 1, 2, 3, 4, 5, or even higher through game rules or mods, you will level the playing field, and could in theory get that number of landed counts and barons down even further without breaking game balance. I didn't test this myself, but logically, it would seem to make sense.

  • Lowering the health of children by 1 (the equivalent of gaining the Ill trait) doesn't cull huge numbers of children automatically, but does make it harder for them to survive other health issues, like sickly or getting a disease. If children are not sick or have some other issue impacting their health, they cannot die from the modifier alone. So it's not like mass infanticide is going on. Honestly, the impact is pretty minimal in my testing, but still enough to justify its place in the mod. If we increase it to 2, then children start dying too often, and many rulers are left without heirs, which creates succession crises, which is more CPU intensive than just have a few more kids chilling in court with their parents.

  • On the other hand, lowering the health of elderly (50+) characters by 2 significantly helps. It cuts out a lot of old characters that usually just sit in courts that players don't care about, accumulating CPU dust. You'll still see some 60, 70, and 80 year olds, but it's rarer, and usually only made possible by the right combination of traits and a well-trained physician. And if these characters die before their 5 year culling event check, that's that many fewer checks the game engine has to run.

  • Removing the AI from gaining stress is primarily there to prevent death cascades caused by the culling of family members, friends, etc. But it also has the added benefit of not firing those events associated with stress. Who cares if that random lowborn courtier in a court on the other side of the map is stressed and gains the drunkard trait?

  • Limiting AI rulers from activities and decision is the single biggest chunk of performance improvement available as a single feature in this mod. The biggest culprit I've been able to identify are feasts and grand tournaments. Feasts are held constantly, meaning characters we just do not care about are constantly traveling (thus path finding), while grand tournaments are held frequently enough that hundreds of characters then travel to them (more path finding). And when rulers leave, they have to setup a regent, which also can be costly if done constantly. I don't eliminate these activities entirely, just make it so that only obscured Kings and higher can host them.

    So how does it work? I hijacked the "is_available_adult" trigger, which is used for a huge chunk of decisions and activities. This has its pros and cons. Biggest pro is that it makes the mod compatible with any other mod that makes changes to activities, decisions, or adds their own. It also means we're not overriding vanilla files, which is always nice. One con is that there are a few decisions that just cannot be taken by characters who are not kings. Tributaries in particular get impacted here, as their response to the demand tribute character interaction basically gets voided. Small price to pay, though, in my mind. And if you are a ruler with tributaries, this wouldn't affect you.

  • Limiting AI rulers and their ability to raid is helpful, as these are also armies being raised, path finding, then moving over and over again, all with their own series of events. And often, the AI raises their own armies to push these raiders back (thus also more path finding), resulting in hundreds of teeny tiny pointless fights. We can't get rid of them entirely, and limiting them to just kings isn't helpful, as most tribal rulers don't get past the duchy level before becoming feudal.

Who is safe from the cull?
Every five years, characters who have not been previously designated as immune (such as your family, house, and dynasty members, depending on the rules you picked) and have the Obscured trait are checked against the trigger list below. If they meet one of the requirements, they're kept safe.
  • A ruler (Mercenary, Adventurer, Baron, Count, Duke, etc.)
  • The head of a noble house
  • A knight that is healthy (3.0+) and has a prowess of 15+ (the AI is pretty terrible at assigning useful knights, so this helps them in a way, but also really helps cut down on useless courtiers with no other reason for existence other than to exist as fodder for a war you will likely never know about)

All conditions below require the character to have fine health (3.0+) in order to be spared.
  • Has any court position
  • Has any council position
  • Is pregnant
  • Is an adventurer
  • Is inspired
  • Has any attribute at 20+ (mostly to help the AI secure good councilors)
  • Has an inheritable genetic trait and is 35 or younger
  • Any close family member (parent, child, grand parents, grand children) is a duke or an adventurer
  • Any spouse is a duke or adventurer
  • They have a claim of a duchy title or higher

Once a character goes into the guest pool, they run through an even tighter, less forgiving gauntlet of triggers. If they don't have fine health or higher, they're removed. Most guests out of range for the players are, well, irrelevant.

What are some other features being tested for more performance impact?
Honestly, at this point, I'm not sure how much more we can squeeze out of the game engine. But there are a few things I'm trying out:
  • Culling Inside Diplomatic Range: The next logical step is to cull characters within diplomatic range, as they're currently immune, no matter how useless or trivial. I haven't pursued this yet for a couple of reasons. First, there are population control mods that would already help with this. Second, and perhaps more importantly, I worry about finding a compromise on just who is worthy of CPU juice and who isn't. Do we just eliminate all useless characters? Does that then make special, valuable characters less special? Do lowborns all go, making high borns the norm? What about lazy, good for nothing noble children with no chance of inheriting anything? If they go, then we just have competent characters everywhere? That doesn't feel very immersive. This is all easy to decide for obscured rulers and their courts, because, let's be real, we don't really care. But in our courts, our vassals courts, and our neighbors courts? Yikes. And yes, I can roll out even more rules to personalize it, but eek. Feels like a trap.

  • Fewer Knights: I am currently testing the effects of reducing the number of knights an obscured ruler has, meaning there are just that fewer amount of characters sitting in court waiting for a war. But so far, despite cutting back on a couple thousand characters, it doesn't seem to help much in performance. The AI mostly assigns knighthood to their counts and barons, and removing them doesn't actually help all that much. I'm also worried about the combat balance of two kingdoms going at one another, with one in diplomatic range (thus, full knights) and another kingdom out of diplomatic range with the player (so fewer knights) and the imbalance that may create.

    Now on the flip side, I could also make it so that rulers (Barons and Counts primarily) cannot be Knights, meaning only courtiers can be knights. This has an interesting side effect of creating fewer successions (because fewer counts are dying, thus cutting back on the game engine calculating heirs and all that, which logically should help). However, because there are 50% fewer counts anyway with the domain adjustments, this doesn't seem to really have a noticeable difference.

  • Increasing obscured ruler health: In tandem with the idea above, if we cut down on the amount of successions being calculated due to the death of a ruler, then that should mean keeping them alive for longer results in a performance bump. In initial tests, it seems to help a little bit, but not enough to justify the buff to the AI. Plus... I don't know... there's something about seeing a bunch of 70 and 80 year old rulers and being like... ugh... Medieval life was rough, unforgiving, and short, and that seems to contradict it a bit.

  • Speeding up sieges and increasing supply amounts for obscured AI: The thinking is that if we have much faster sieges, then what wars the obscured AI runs are shorter, thus less path finding over time. And if we increase the supply amounts, then the AI breaks up its doom stacks less often to avoid attrition. This means larger armies, and fewer smaller armies path finding. I can set it up so that in the event that one ai gets into a war with another ai, and they both don't have these bonuses, then the bonus from the obscured AI is removed. Bonuses are already removed if they get into a war as a secondary participant with players. But if there is a performance edge to be gained with this, I haven't been able to see it yet, unless I significantly ramp up the siege bonuses and supply increase (to like 10x), which really starts to feel like a risk at unbalancing the AI and creating a really gamey environment.

  • Locking army movement: Interestingly, there is a quick way to gain a small boost in performance during wars -- locking army movement at 100% instead of 50%. I'm not entirely sure why this works, but I assume that if you make it so that you have to commit to your army's movement, the game engine has to only calculate the involved path finding once, rather than every time you stop the movement and restart. We've all seen the indecisive AI moving, then stopping, or changing directions depending on the actions of the player. By locking movement to 100%, meaning once you pick a direction, you have to go there, the AI doesn't recalculate. But there's a couple of problems: this is a defines override, so it'd be a game wide change, to the player, diplomatically relevant AI, and those obscured. It's not something I can change with a rule. It'd have to be a separate mod. I also worry that the player could then easily outsmart the AI and pounce, when the AI simply lacks that same ability. It feels like a huge boon for the player to me. Is it worth the 1 to 2% performance boost? Not sure. Might be worth it to look into more ways to discourage the obscured AI from getting into silly wars to just avoid armies being raised altogether.

Performance Measures
I'm reluctant to include this section, but I figure there will be questions. The computer I am running and testing on is beefy: i9-12900KF, SSD, 4900, 32 GB RAM. I share that to emphasize that it's the only setup I've tested this mod on and over several test runs, what I have consistently found is:
  • Anywhere from 20% to a 35% performance increase that seems to become more significant the longer the game goes on for.
  • Roughly about 10,000 fewer characters in any given year compared to vanilla.

But these tests are best case scenarios: small, tall kingdom at one corner of the map (England, Norway, Spain, Japan, etc.), where I do not blob out and have a massive diplomatic range. As I said in the mod description, your mileage is going to vary depending on your hardware, your game setup, what other mods you're running, and how big your "inside diplomatic range" is.

As more players begin to use the mod, I'll be curious to hear about what you're experiencing with your setups!
Senast ändrad av Olympia; 13 nov @ 20:24
< >
Visar 1-1 av 1 kommentarer
Wax 14 nov @ 4:07 
Thanks for the detailed breakdown. I will be running a playthrough with the mod and see how it plays out. Very interesting concept and might even help with obscene border gore in far away lands
< >
Visar 1-1 av 1 kommentarer
Per sida: 1530 50