0. 원본 코드
std::string remove_ctrl(std::string s){
std::string result;
for(int i = 0; i < s.length(); ++i){
if(s[i] > 0x20)
result = result + s[i];
}
}
result : 24.8 us
1. += 연산자 사용.
기존의 코드는 매번 임시 문자열 객체를 생성함.
result += s[i];
result : 1.62 us
2. reserve() 사용
result.reserve(s.length());
result : 1.47 us
3. call by reference
std::string remove_ctrl(const std::string& s){
...
}
result : 1.60 us
2번에 비해 시간이 늘어났는데, 이는 s가 참조이기때문에 매 루프마다 s를 역참조하느라 성능이 저하된 것임.
4. iterator 사용 + s.end() 미리 초기화
for(auto it = s.begin(), end = s.end(); it != end; ++it){
if (*it >= 0x20)
result += *it;
}
result : 1.04 us
5. out parameter(복사 생성을 생략하는 방법 중 하나)
void remove_ctrl(const std::string& s, std::string& result){
...
}
result : 1.02 us
6. c style
void remove_ctrl(const char* src, char* dst, size_t size){
for(size_t i = 0; i < size; ++i){
if(src[i] >= 0x20)
*dst++ = src[i];
}
}
result : 0.15 us
함수 호출을 없애고, cache locality를 향상시킨 결과.
7. break, substr
std::string remove_ctrl(std::string s){
std::string result;
for(size_t b = 0, i = b, e = s.length(); b < e ; b = i + 1){
for (i = b; i < e; ++i){
if (s[i] < 0x20)
break;
}
result = result + s.substr(b, i - b);
}
}
result : 2.91 us
8. break, append
result = result + s.substr(b, i - b);
result : 0.65 us
해당 함수에 2~5번을 적용하면 0.43 us까지 호출 시간이 감소한다.
9. erase
std::string romove_ctrl(std::string s){
for(size_t i = 0; i < s.length();){
if(s[i] < 0x20)
s.erase(i, 1);
else
++i;
}
return s;
}
result : 0.81 us
정보 감사합니다.