약어의 의미 std :: string
에서 최적화 및 코드 스타일에 대한 C ++ 질문 몇 가지 답변의 사본을 최적화의 맥락에서 "SSO"라고 std::string
. 그 맥락에서 SSO는 무엇을 의미합니까?
"단일 사인온"이 아닙니다. 아마도 "공유 문자열 최적화"일까요?
배경 / 개요
자동 변수 ( malloc
/에서 호출하지 않고 만드는 변수 인 "스택에서" new
)에 대한 작업은 일반적으로 사용 가능한 저장소 ( "힙",을 사용하여 만든 변수)와 관련된 작업보다 훨씬 빠릅니다 new
. 그러나 자동 배열의 크기는 컴파일 타임에 고정되지만 무료 저장소의 배열 크기는 고정되지 않습니다. 또한 스택 크기는 제한적이며 (일반적으로 몇 MiB), 무료 저장소는 시스템 메모리에 의해서만 제한됩니다.
SSO는 Short / Small String Optimization입니다. A는 std::string
일반적으로 통화에 것처럼 비슷한 성능 특성을 제공하는 무료 저장 ( "힙")에 대한 포인터로 문자열을 저장합니다 new char [size]
. 이렇게하면 매우 큰 문자열의 스택 오버플로가 방지되지만 특히 복사 작업의 경우 속도가 느려질 수 있습니다. 최적화로서, 많은 구현은 std::string
다음과 같은 작은 자동 배열 을 만듭니다 char [20]
. 문자열이 20 자 이하인 경우 (이 예제에서는 실제 크기가 다름) 해당 배열에 직접 저장합니다. 이렇게하면 전화 new
를 전혀 하지 않아도되므로 속도가 약간 빨라집니다.
편집하다:
나는이 답변이 그렇게 인기가있을 것으로 기대하지는 않았지만, 실제로는 "실제로"SSO의 구현을 전혀 읽지 않았다는 경고와 함께보다 현실적인 구현을하겠습니다.
구현 세부 사항
최소한 std::string
다음 정보를 저장해야합니다.
- 크기
- 용량
- 데이터의 위치
크기는 std::string::size_type
또는 끝에 대한 포인터로 저장 될 수 있습니다 . 유일한 차이점은 사용자가 호출 할 때 두 개의 포인터를 빼야하는지 size
또는 사용자가 호출 할 때 포인터 에 a size_type
를 추가 해야하는지 end
입니다. 용량은 어느 쪽이든 저장할 수 있습니다.
사용하지 않는 것에 대해서는 비용을 지불하지 않습니다.
먼저 위에서 설명한 내용을 기반으로 순진한 구현을 고려하십시오.
class string {
public:
// all 83 member functions
private:
std::unique_ptr<char[]> m_data;
size_type m_size;
size_type m_capacity;
std::array<char, 16> m_sso;
};
64 비트 시스템의 경우 일반적으로 std::string
문자열 당 24 바이트의 '오버 헤드'와 SSO 버퍼에 대한 16 바이트 (패딩 요구 사항으로 인해 20 대신 16이 선택됨)를 의미합니다. 간단한 예제 에서처럼이 세 가지 데이터 멤버와 로컬 문자 배열을 저장하는 것은 실제로 의미가 없습니다. 인 경우 m_size <= 16
모든 데이터를에 넣을 m_sso
것이므로 이미 용량을 알고 있으므로 데이터에 대한 포인터가 필요하지 않습니다. 이면 m_size > 16
필요하지 않습니다 m_sso
. 내가 그들 모두를 필요로하는 곳은 겹치지 않습니다. 공간을 낭비하지 않는 똑똑한 솔루션은 다음과 같이 보일 것입니다 (예상되지 않은 예시 목적으로 만).
class string {
public:
// all 83 member functions
private:
size_type m_size;
union {
class {
// This is probably better designed as an array-like class
std::unique_ptr<char[]> m_data;
size_type m_capacity;
} m_large;
std::array<char, sizeof(m_large)> m_small;
};
};
대부분의 구현은 다음과 같다고 가정합니다.
SSO는 "작은 문자열 최적화"의 약자로, 작은 문자열이 별도로 할당 된 버퍼를 사용하는 대신 문자열 클래스의 본문에 포함되는 기술입니다.
다른 답변에서 이미 설명한 것처럼 SSO는 Small / Short String Optimization을 의미 합니다. 이 최적화의 동기는 일반적으로 응용 프로그램이 긴 문자열보다 훨씬 짧은 문자열을 처리한다는 명백한 증거입니다.
데이비드 스톤 설명한 바와 같이 위의 그의 대답에서 의 std::string
클래스는 주어진 길이로 저장 내용에 대한 내부 버퍼까지를 사용하고,이을 제거해은 할 필요 동적으로 메모리를 할당합니다. 이것은 코드를 보다 효율적 이고 빠르게 만듭니다.
This other related answer clearly shows that the size of the internal buffer depends on the std::string
implementation, which varies from platform to platform (see benchmark results below).
Benchmarks
Here is a small program that benchmarks the copy operation of lots of strings with the same length. It starts printing the time to copy 10 million strings with length = 1. Then it repeats with strings of length = 2. It keeps going until the length is 50.
#include <string>
#include <iostream>
#include <vector>
#include <chrono>
static const char CHARS[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
static const int ARRAY_SIZE = sizeof(CHARS) - 1;
static const int BENCHMARK_SIZE = 10000000;
static const int MAX_STRING_LENGTH = 50;
using time_point = std::chrono::high_resolution_clock::time_point;
void benchmark(std::vector<std::string>& list) {
std::chrono::high_resolution_clock::time_point t1 = std::chrono::high_resolution_clock::now();
// force a copy of each string in the loop iteration
for (const auto s : list) {
std::cout << s;
}
std::chrono::high_resolution_clock::time_point t2 = std::chrono::high_resolution_clock::now();
const auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(t2 - t1).count();
std::cerr << list[0].length() << ',' << duration << '\n';
}
void addRandomString(std::vector<std::string>& list, const int length) {
std::string s(length, 0);
for (int i = 0; i < length; ++i) {
s[i] = CHARS[rand() % ARRAY_SIZE];
}
list.push_back(s);
}
int main() {
std::cerr << "length,time\n";
for (int length = 1; length <= MAX_STRING_LENGTH; length++) {
std::vector<std::string> list;
for (int i = 0; i < BENCHMARK_SIZE; i++) {
addRandomString(list, length);
}
benchmark(list);
}
return 0;
}
If you want to run this program, you should do it like ./a.out > /dev/null
so that the time to print the strings isn't counted. The numbers that matter are printed to stderr
, so they will show up in the console.
I have created charts with the output from my MacBook and Ubuntu machines. Note that there is a huge jump in the time to copy the strings when the length reaches a given point. That's the moment when strings don't fit in the internal buffer anymore and memory allocation has to be used.
Note also that on the linux machine, the jump happens when the length of the string reaches 16. On the macbook, the jump happens when the length reaches 23. This confirms that SSO depends on the platform implementation.
참고URL : https://stackoverflow.com/questions/10315041/meaning-of-acronym-sso-in-the-context-of-stdstring
'development' 카테고리의 다른 글
.toArray (new MyClass [0]) 또는 .toArray (new MyClass [myList.size ()])? (0) | 2020.06.21 |
---|---|
java.exe와 javaw.exe의 차이점 (0) | 2020.06.21 |
반환 값 또는 매개 변수 중 어느 것이 더 낫습니까? (0) | 2020.06.21 |
파이썬 : iterable의 내용을 세트에 추가하는 방법? (0) | 2020.06.21 |
Objective-C 용 JSON 구문 분석기 (JSON 프레임 워크, YAJL, TouchJSON 등) 비교 (0) | 2020.06.20 |