Czysta ciekawość skłoniła mnie do sprawdzenia pewnej rzeczy. Czy przechowywanie kilku stringów w jednym std::string
będzie miało jakieś plusy w porównaniu do wektora stringów?
Przyznam, że spodziewałem się iż co najmniej wyszukiwanie będzie szybsze z powodu 'biegania' po ciągłym bloku pamięci a nie skakaniu po pamięci.
#include <string>
#include <string_view>
#include <vector>
#include <chrono>
#include <algorithm>
using namespace std;
constexpr string base{"veryveryverylonglonglongstring_"};
constexpr string_view to_find{"veryveryverylonglonglongstring_915000"};
constexpr size_t max_size = 1000000u;
void multi_string()
{
string storage;
for (auto i = 0u; i < max_size; ++i) {
storage += string{base + std::to_string(i) + '\0'};
}
auto currptr = storage.data();
auto fin = storage.data() + storage.length();
auto start = chrono::steady_clock::now();
while (currptr < fin) {
string_view current{currptr};
if (current == to_find) {
break;
}
currptr += current.length() + 1;
}
auto elapsed = chrono::duration_cast<chrono::milliseconds>(chrono::steady_clock::now() - start);
cout << "Multistring -> " << elapsed.count() << "\n":
}
void vector_string()
{
vector<string> storage;
for (auto i = 0u; i < max_size; ++i) {
storage.push_back(string{base + to_string(i)});
}
auto start = chrono::steady_clock::now();
auto iter = std::find(storage.begin(), storage.end(), to_find);
auto elapsed = chrono::duration_cast<chrono::milliseconds>(chrono::steady_clock::now() - start);
cout << "Vector -> " << elapsed.count() << "\n":
}
int main(int argc, char** argv)
{
multi_string();
vector_string();
return 0;
}
Wyniki:
Multistring -> 42
Vector -> 17
VS2017, release x64 + optymalizacja O2
Dlaczego skakanie po wskaźnikach z std::string
jest ponad 2x szybsze niż iterowanie po ciągłym bloku? Gdzieś się machnąłem?