Skip to content

Conversation

@xezon
Copy link

@xezon xezon commented Nov 26, 2025

THE FIRST COMMIT IS FROM #1916

This change removes superfluous AsciiString allocations for name key lookups. It was applied by hand.

It cuts many allocations and can help loading and runtime performance a bit.

NAMEKEY and nameToKey variants for AsciiString have been deleted to discourage their use and to make the programmer think if he wants to pass a C string from AsciiString and if he really needed to allocate that.

Adjacent to Name Key, some functions that only did Name Key lookups and needed no AsciiString have been changed to take const char* instead of AsciiString.

The identified and affected functions are:

  • DamageFXStore::findDamageFX
  • UpgradeCenter::findUpgrade
  • ImageCollection::findImageByName
  • ArmorStore::findArmorTemplate
  • WeaponStore::findWeaponTemplate

There are probably plenty more functions of this kind but this change is already large enough as is and this seemed to be all directly related to Name Key things.

TODO

  • Replicate in Generals

@xezon xezon added Minor Severity: Minor < Major < Critical < Blocker Performance Is a performance concern Refactor Edits the code with insignificant behavior changes, is never user facing labels Nov 26, 2025
/**
Find the Armor with the given name. If no such Armor exists, return null.
*/
const ArmorTemplate* findArmorTemplate(AsciiString name) const;
Copy link

Choose a reason for hiding this comment

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

it would have been better to just alter these to pass by reference.

Copy link
Author

Choose a reason for hiding this comment

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

I disagree, because these functions need no AsciiString and passing const char* is better, because it allows to pass string literals without AsciiString middle-man allocation.

There are a lot of call sites that pass string literals to these. For example in INI parse functions.

Copy link

Choose a reason for hiding this comment

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

The ascii string variant will be hit the most during runtime as the upgrade names in thing data will be an ascii string.
it could be handled with and overloaded function that passes an ascii string reference then calls the const char* implementation with the stored string.

Copy link
Author

Choose a reason for hiding this comment

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

To me it looked 50/50. Some callsites come with AsciiString, others with C strings. The goal here is to discourage passing AsciiString to avoid unnecessary allocations where not necessary.

AsciiString can be passed on callsite with myAscii.str()

When you look through this refactor, you will see a lot of places where allocations have been eliminated.

Copy link

Choose a reason for hiding this comment

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

Yeah it should be fine in the end having looked back over it.

Copy link
Author

Choose a reason for hiding this comment

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

After reviewing the NameKeyGenerator class one more time I realized this change is not optimal either.

What NameKeyGenerator lookups with AsciiString essentially did:

Take AsciiString, pass on into sub functions as C string, then eventually allocate a new AsciiString from that C string if it created a new NameKey entry, otherwise just use the C string for the lookup.

This duplicate AsciiString allocation can be avoided by passing the original AsciiString into the creation of the new NameKey entry. This was done with change #1959 and that should be optimal now.

Closing.

@xezon xezon force-pushed the xezon/refactor-asciistring-unicodestring-instance-2 branch from f024f01 to 1df46e0 Compare December 1, 2025 19:13
@xezon
Copy link
Author

xezon commented Dec 1, 2025

Rebased on main

Copy link

@Mauller Mauller left a comment

Choose a reason for hiding this comment

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

Looks okay overall.

Image *Enum(unsigned index)
{
for (std::map<unsigned,Image *>::iterator i=m_imageMap.begin();i!=m_imageMap.end();++i)
for (ImageMap::iterator i=m_imageMap.begin();i!=m_imageMap.end();++i)
Copy link

Choose a reason for hiding this comment

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

This is one of those times when Auto would have been fine instead of a typedef :P but VC6 so not much we can do yet.


const char * upgradeAlt = getCommandSetUpgradeModuleData()->m_triggerAlt.str();
const UpgradeTemplate *upgradeTemplate = TheUpgradeCenter->findUpgrade( upgradeAlt );
AsciiString upgradeAlt = getCommandSetUpgradeModuleData()->m_triggerAlt;
Copy link

Choose a reason for hiding this comment

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

You could probably revert this one since it's going to cause the reference count to get touched.

Copy link
Author

Choose a reason for hiding this comment

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

Fixed.

@xezon xezon force-pushed the xezon/refactor-asciistring-unicodestring-instance-2 branch from 95cfbb7 to a961400 Compare December 7, 2025 10:32
@xezon xezon closed this Dec 7, 2025
@xezon xezon deleted the xezon/refactor-asciistring-unicodestring-instance-2 branch December 7, 2025 12:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Minor Severity: Minor < Major < Critical < Blocker Performance Is a performance concern Refactor Edits the code with insignificant behavior changes, is never user facing

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants