-
Notifications
You must be signed in to change notification settings - Fork 218
Use StringView and Span in Player #2293
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
Conversation
e61c30e to
af8c97b
Compare
|
Here are performance numbers for with with So 30% of the time in this function was being spent just allocating and freeing temporary arrays. |
Eliminates string copies in the replacement set
Eliminates memory allocations from temporary vectors
This makes WordWrap function zero-copy internally
|
Played some rm2k games with the battle system testing the changes to wordwrap and replaceplaceholders. Everything seem fine. |
Ghabry
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also have to learn about span, never used them before.
| * @return The async request. | ||
| */ | ||
| FileRequestAsync* RequestFile(const std::string& folder_name, const std::string& file_name); | ||
| FileRequestAsync* RequestFile(StringView folder_name, StringView file_name); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Question: So, a string view is always used when the target function does not take ownership on the string?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wish I could tell you yes, replace all const std::string& with StringView. Unfortunately this is C++ so there is always one big caveat.
StringView is not null terminated, so if at the end of your call stack you end up calling a C library which requires null terminated const char*, you'll end up having to make a copy so you can get a new string with a null byte at the end.
Aside from that caveat, yes use StringView where-ever you need a non-owning reference. Not only is it a generic adapter but the calling convention used is faster (see below).
Span does not have this caveat, fortunately so you can use it anywhere you'd pass a vector by reference.
Performance Note
const string& if you think about it in C terms, is essentially a double pointer const char**. The reference is a pointer to the string object, which contains another pointer to the bytes.
When you pass a StringView you're passing a const char*, removing one level of indirection. In some cases this can help the optimizer with it's aliasing analysis to produce faster code.
The same rule applies to vector and Span.
src/cache.cpp
Outdated
| std::string MakeHashKey(const std::string& folder_name, const std::string& filename, bool transparent) { | ||
| return folder_name + ":" + filename + ":" + (transparent ? "T" : " "); | ||
| std::string MakeHashKey(StringView folder_name, StringView filename, bool transparent) { | ||
| return std::string(folder_name) + ":" + std::string(filename) + ":" + (transparent ? "T" : " "); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Question: Couldn't you also use ToString() here instead of std::string(). Does it make a difference?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ahh this was from the other PR before I added ToString. Will fix.
They do the same thing in this case, but ToString is easier to grep for.
| {'V', 'U'}, | ||
| {std::to_string(exp), lcf::Data::terms.exp_short} | ||
| Utils::MakeArray('V', 'U'), | ||
| Utils::MakeSvArray(std::to_string(exp), lcf::Data::terms.exp_short) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Question: What's the advantage of using Make*()?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So I don't have to say std::array<char,2>('V', 'U')
This was actually supposed to go in the standard library, but they dropped it after adding deduction guides in C++17.
Depends on: EasyRPG/liblcf#384
This adds StringView in many places to make code generic to different string types.
Utils::ReplacePlaceholdershas been greatly optimizing by removing all unnecessary copies from it's interface.