[Strings] Split String Optimizations (#1325)

* Switch the 2 split calls to SplitString

* Nuke duplicate split in favor of SplitString #1263

* Add a test for SplitString

* Optimize SplitString

Benchmarking:
--------------------------------------------------------------
Benchmark                       Time           CPU Iterations
--------------------------------------------------------------
bench_oldsplit               5201 ns       5201 ns     129500
bench_split                  1269 ns       1269 ns     548906

This is splitting a VERY long SpecialAbilities string. This is ~75%
speed up.
This commit is contained in:
Michael Cook (mackal) 2021-04-23 00:36:39 -04:00 committed by GitHub
parent 00fb9bc9f9
commit dba3010c89
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 24 additions and 24 deletions

View File

@ -74,18 +74,6 @@ const std::string str_tolower(std::string s)
return s; return s;
} }
std::vector<std::string> split(std::string str_to_split, char delimiter)
{
std::stringstream ss(str_to_split);
std::string item;
std::vector<std::string> exploded_values;
while (std::getline(ss, item, delimiter)) {
exploded_values.push_back(item);
}
return exploded_values;
}
const std::string str_toupper(std::string s) const std::string str_toupper(std::string s)
{ {
std::transform( std::transform(
@ -113,15 +101,18 @@ const std::string StringFormat(const char *format, ...)
return output; return output;
} }
std::vector<std::string> SplitString(const std::string &str, char delim) { std::vector<std::string> SplitString(const std::string &str, const char delim) {
std::vector<std::string> ret; std::vector<std::string> ret;
std::stringstream ss(str); std::string::size_type start = 0;
std::string item; auto end = str.find(delim);
while (end != std::string::npos) {
while(std::getline(ss, item, delim)) { ret.emplace_back(str, start, end - start);
ret.push_back(item); start = end + 1;
end = str.find(delim, start);
} }
// this will catch the last word since the string is unlikely to end with a delimiter
if (str.length() > start)
ret.emplace_back(str, start, str.length() - start);
return ret; return ret;
} }

View File

@ -39,7 +39,6 @@
const std::string str_tolower(std::string s); const std::string str_tolower(std::string s);
const std::string str_toupper(std::string s); const std::string str_toupper(std::string s);
const std::string ucfirst(std::string s); const std::string ucfirst(std::string s);
std::vector<std::string> split(std::string str_to_split, char delimiter);
const std::string StringFormat(const char* format, ...); const std::string StringFormat(const char* format, ...);
const std::string vStringFormat(const char* format, va_list args); const std::string vStringFormat(const char* format, va_list args);
std::vector<std::string> wrap(std::vector<std::string> &src, std::string character); std::vector<std::string> wrap(std::vector<std::string> &src, std::string character);
@ -177,7 +176,7 @@ std::vector<std::string> join_tuple(const std::string &glue, const std::pair<cha
return output; return output;
} }
std::vector<std::string> SplitString(const std::string &s, char delim); std::vector<std::string> SplitString(const std::string &s, const char delim = ',');
std::string::size_type search_deliminated_string(const std::string &haystack, const std::string &needle, const char deliminator = ','); std::string::size_type search_deliminated_string(const std::string &haystack, const std::string &needle, const char deliminator = ',');
std::string EscapeString(const char *src, size_t sz); std::string EscapeString(const char *src, size_t sz);
std::string EscapeString(const std::string &s); std::string EscapeString(const std::string &s);

View File

@ -30,6 +30,7 @@ public:
TEST_ADD(StringUtilTest::EscapeStringTest); TEST_ADD(StringUtilTest::EscapeStringTest);
TEST_ADD(StringUtilTest::EscapeStringMemoryTest); TEST_ADD(StringUtilTest::EscapeStringMemoryTest);
TEST_ADD(StringUtilTest::SearchDeliminatedStringTest); TEST_ADD(StringUtilTest::SearchDeliminatedStringTest);
TEST_ADD(StringUtilTest::SplitStringTest);
} }
~StringUtilTest() { ~StringUtilTest() {
@ -108,6 +109,15 @@ public:
TEST_ASSERT(search_deliminated_string(h, "bef") == std::string::npos); TEST_ASSERT(search_deliminated_string(h, "bef") == std::string::npos);
TEST_ASSERT(search_deliminated_string(h, "wwi") == std::string::npos); TEST_ASSERT(search_deliminated_string(h, "wwi") == std::string::npos);
} }
void SplitStringTest() {
std::string s = "123,456,789,";
auto v = SplitString(s, ',');
TEST_ASSERT(v.size() == 3);
TEST_ASSERT(v[0] == "123");
TEST_ASSERT(v[1] == "456");
TEST_ASSERT(v[2] == "789");
}
}; };
#endif #endif

View File

@ -557,7 +557,7 @@ inline std::string WriteDisplayInfoSection(
* "total_to_hit" = "Total To Hit" * "total_to_hit" = "Total To Hit"
*/ */
if (attribute_name.find('_') != std::string::npos) { if (attribute_name.find('_') != std::string::npos) {
std::vector<std::string> split_string = split(attribute_name, '_'); auto split_string = SplitString(attribute_name, '_');
std::string new_attribute_name; std::string new_attribute_name;
for (std::string &string_value : split_string) { for (std::string &string_value : split_string) {
new_attribute_name += ucfirst(string_value) + " "; new_attribute_name += ucfirst(string_value) + " ";

View File

@ -93,7 +93,7 @@ void ZoneEventScheduler::Process(Zone *zone, WorldContentService *content_servic
} }
if (e.event_type == ServerEvents::EVENT_TYPE_RULE_CHANGE) { if (e.event_type == ServerEvents::EVENT_TYPE_RULE_CHANGE) {
auto params = split(e.event_data, '='); auto params = SplitString(e.event_data, '=');
auto rule_key = params[0]; auto rule_key = params[0];
auto rule_value = params[1]; auto rule_value = params[1];
if (!rule_key.empty() && !rule_value.empty()) { if (!rule_key.empty() && !rule_value.empty()) {