Skip to content
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

[8_12] improve strategy of expanding string for performance #341

Merged
merged 3 commits into from
Jul 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 50 additions & 12 deletions Kernel/Types/string.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,11 @@ round_length (int n) {
return i;
}

string_rep::string_rep (int n2)
: n (n2),
a ((n == 0) ? ((char*) NULL) : tm_new_array<char> (round_length (n))) {}
string_rep::string_rep (int n2) : n (n2), a_N (round_length (n2)), a (nullptr) {
if (a_N != 0) {
a= tm_new_array<char> (a_N);
}
}

void
string_rep::resize (int m) {
Expand All @@ -42,17 +44,53 @@ string_rep::resize (int m) {
if (mm != nn) {
if (mm != 0) {
if (nn != 0) {
a= tm_resize_array<char> (mm, a);
a_N= mm;
a = tm_resize_array<char> (mm, a);
}
else {
a= tm_new_array<char> (mm);
a_N= mm;
a = tm_new_array<char> (mm);
}
}
else if (nn != 0) tm_delete_array (a);
else if (nn != 0) {
tm_delete_array (a);
a_N= 0;
a = NULL;
};
}
n= m;
}

int
string_rep::expand_or_shrink_by (int delta) {
int old_n= n;
n+= delta;
reserve (n);
return old_n;
}

void
string_rep::reserve (int new_n) {
int old_size= a_N;
if (new_n != 0) {
if (old_size == 0) {
a_N= round_length (new_n);
a = tm_new_array<char> (a_N);
}
else if (old_size < new_n) {
a_N= round_length (new_n);
a = tm_resize_array<char> (a_N, a);
}
}
else {
if (old_size != 0) {
tm_delete_array (a);
a = NULL;
a_N= 0;
};
}
}

string::string (char c) {
rep = tm_new<string_rep> (1);
rep->a[0]= c;
Expand Down Expand Up @@ -138,17 +176,17 @@ copy (string s) {

string&
operator<< (string& a, char x) {
a->resize (N (a) + 1);
a[N (a) - 1]= x;
int old_a_N= a->expand_or_shrink_by (1);
a[old_a_N] = x;
return a;
}

string&
operator<< (string& a, string b) {
int i, k1= N (a), k2= N (b);
a->resize (k1 + k2);
for (i= 0; i < k2; i++)
a[i + k1]= b[i];
int b_N = N (b);
int old_a_N= a->expand_or_shrink_by (b_N);
for (int i= 0; i < b_N; i++)
a[i + old_a_N]= b[i];
return a;
}

Expand Down
26 changes: 24 additions & 2 deletions Kernel/Types/string.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,37 @@ class string;
class string_rep : concrete_struct {
int n;
char* a;
int a_N;

public:
inline string_rep () : n (0), a (NULL) {}
inline string_rep () : n (0), a_N (0), a (NULL) {}
string_rep (int n);
inline ~string_rep () {
if (n != 0) tm_delete_array (a);
if (a_N != 0) tm_delete_array (a);
}
/**
* @brief expand (or shrink) string by delta, but do not release memory when
* string is shrinked.
*
* @return string length before expansion
*/
int expand_or_shrink_by (int delta);

/**
* @brief expand (or shrink) string to given length n, and try to release
* memory when string is shrinked.
*
* @note expand_or_shrink_by may be faster if memory space is reserved
*/
void resize (int n);

/**
* @brief reserve memory space to contain at least n word in the whole string.
* Do not affect length of string, and do not release memory when n is smaller
* than current space.
*/
void reserve (int n);

friend class string;
friend inline int N (string a);
};
Expand Down
2 changes: 1 addition & 1 deletion bench/Kernel/Types/string_bench.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ static ankerl::nanobench::Bench bench;
int
main () {
lolly::init_tbox ();
bench.minEpochTime (std::chrono::milliseconds (20));
bench.run ("construct string", [&] {
string ("abc");
string ();
Expand Down Expand Up @@ -43,7 +44,6 @@ main () {
static string a ("abcdefgh");
a (1, 6);
});
bench.minEpochIterations (40000);
bench.run ("concat string", [&] {
static string a ("abc"), b ("de");
a* b;
Expand Down
75 changes: 75 additions & 0 deletions tests/Kernel/Types/string_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,81 @@ TEST_CASE ("test append") {
CHECK_EQ (str == string ("xyz"), true);
}

TEST_CASE ("test append") {
auto str= string ();
str << 'x';
CHECK (str == "x");
str << string ("yz");
CHECK (str == "xyz");
}

TEST_CASE ("test reserve along with append") {

SUBCASE ("reserved more space") {
auto str= string ();
str->reserve (6);
str << 'x';
CHECK_EQ (str == "x", true);
str << string ("yz");
CHECK_EQ (str == "xyz", true);
str << string (": larger than reserved space");
CHECK_EQ (str == "xyz: larger than reserved space", true);
}
SUBCASE ("reserved the same space") {
auto str= string ("abc");
str->reserve (3);
CHECK_EQ (str == "abc", true);
}
SUBCASE ("reserved less space should take no effect") {
auto str= string ("abc");
str->reserve (2);
CHECK_EQ (str == "abc", true);
}
}

TEST_CASE ("test expand_or_shrink_by along with sub index") {

SUBCASE ("expand") {
auto str = string ("abc");
int previous_n= str->expand_or_shrink_by (1);
CHECK_EQ (previous_n, 3);
str[3]= 'd';
CHECK_EQ (str == "abcd", true);
}
SUBCASE ("shrink") {
auto str = string ("abc");
int previous_n= str->expand_or_shrink_by (-1);
CHECK_EQ (previous_n, 3);
CHECK_EQ (str == "ab", true);
}
SUBCASE ("delta 0 takes no effect") {
auto str = string ("abc");
int previous_n= str->expand_or_shrink_by (0);
CHECK_EQ (previous_n, 3);
CHECK_EQ (str == "abc", true);
}
}

TEST_CASE ("test resize") {

SUBCASE ("expand") {
auto str= string ("abc");
str->resize (4);
str[3]= 'd';
CHECK_EQ (str == "abcd", true);
}
SUBCASE ("shrink") {
auto str= string ("abc");
str->resize (2);
CHECK_EQ (str == "ab", true);
}
SUBCASE ("delta 0 takes no effect") {
auto str= string ("abc");
str->resize (3);
CHECK_EQ (str == "abc", true);
}
}

/******************************************************************************
* Conversions
******************************************************************************/
Expand Down
Loading