std::string의 컨텍스트에서 약자 SSO의 의미
최적화와 코드 스타일에 대한 C++ 질문에서, 몇몇 답변들은 복사본을 최적화하는 맥락에서 "SSO"를 언급했습니다.std::string
맥락에서 SSO는 그러한 맥락에서 무엇을 의미합니까?
분명히 "싱글 사인 온"은 아닙니다."공유 문자열 최적화"?
배경 / 개요
호출하지 않고 생성하는 변수인 자동 변수("스택에서")에 대한 작업malloc
/new
)는 일반적으로 다음을 사용하여 생성되는 변수인 free store("heap")와 관련된 것보다 훨씬 빠릅니다.new
의 크기는 되어 있지 .) 단, 자동 배열의 크기는 컴파일 타임에 고정되어 있지만, 프리 스토어에서 제공하는 배열의 크기는 고정되어 있지 않습니다.또한 스택 크기는 제한적이며(일반적으로 몇 개의 MiB), 무료 저장소는 시스템의 메모리에 의해서만 제한됩니다.
SSO는 숏/스몰 스트링 최적화입니다 Astd::string
일반적으로 문자열을 무료 저장소("heap")의 포인터로 저장합니다. 이는 마치 호출하는 것처럼 유사한 성능 특성을 제공합니다.new char [size]
이렇게 매우 큰할 수 가 느려질 수 이렇게 하면 매우 큰 문자열에 대한 스택 오버플로를 방지할 수 있지만, 특히 복사 작업의 경우에는 더 느려질 수 있습니다.최적화를 위해, 많은 구현이std::string
작은 자동 배열을 만듭니다.char [20]
인 경우가 다양함) 문자열이 20자 이하인 경우(이 예에서는 실제 크기가 다양함) 해당 배열에 직접 저장됩니다.이렇게 하면 전화할 필요가 없습니다.new
일이 좀 빨라지는 것 같아요
편집:
저는 이 답변이 그렇게 인기가 있을 줄은 예상하지 못했지만, 실제로 "야생에서" SSO의 구현을 읽어본 적이 없다는 점에 주의하면서, 좀 더 현실적인 구현을 해보겠습니다.
구현내역
, a.std::string
다음 정보를 저장해야 합니다.
- 사이즈를
- 용량을
- 데이터 위치
사이즈는 a로 저장할 수 있었습니다.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는 "Small String Optimization"의 줄임말로, 작은 문자열이 별도로 할당된 버퍼를 사용하지 않고 문자열 클래스 본문에 포함되는 기법입니다.
다른 답변에서 이미 설명한 바와 같이 SSO는 Small/Short String Optimization을 의미합니다.이러한 최적화의 동기는 일반적으로 애플리케이션이 긴 문자열보다 훨씬 짧은 문자열을 더 많이 처리한다는 부인할 수 없는 증거입니다.
데이비드 스톤이 위의 답변에서 설명한 바와 같이,std::string
class는 내부 버퍼를 사용하여 주어진 길이까지 콘텐츠를 저장하므로 동적으로 메모리를 할당할 필요가 없습니다.이렇게 하면 코드가 더 효율적이고 빨라집니다.
이 다른 관련 답변은 내부 버퍼의 크기가 다음에 따라 달라진다는 것을 명확하게 보여줍니다.std::string
플랫폼마다 다른 구현(아래 벤치마크 결과 참조).
벤치마크
여기 길이가 같은 많은 문자열의 복사 작업을 벤치마크하는 작은 프로그램이 있습니다.길이가 = 1인 1000만 문자열 복사 시간 인쇄를 시작합니다.그런 다음 길이 = 2의 문자열로 반복합니다.길이가 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;
}
이 프로그램을 실행하려면 다음과 같이 해야 합니다../a.out > /dev/null
문자열을 인쇄하는 시간이 계산되지 않도록 해야 합니다.중요한 숫자가 인쇄되어 있습니다.stderr
, 콘솔에 나타날 겁니다
MacBook과 Ubuntu 머신의 출력으로 차트를 만들었습니다.길이가 지정된 지점에 도달하면 문자열을 복사하는 시간이 크게 증가합니다.내부 버퍼에 더 이상 문자열이 들어가지 않고 메모리 할당을 사용해야 하는 순간입니다.
또한 리눅스 머신에서는 문자열의 길이가 16에 도달할 때 점프가 발생합니다.맥북에서는 길이가 23이 되면 점프가 일어납니다.이는 SSO가 플랫폼 구현에 따라 다름을 확인해 줍니다.
언급URL : https://stackoverflow.com/questions/10315041/meaning-of-acronym-sso-in-the-context-of-stdstring
'sourcecode' 카테고리의 다른 글
Excel에서 csv 빈 행 문제 발생 (0) | 2023.11.05 |
---|---|
Swift 4에서 Json 문자열을 Json 개체로 변환 (0) | 2023.10.31 |
sequelize Unknown 열 '*.createdAt'이 '필드 목록'에 있습니다. (0) | 2023.10.31 |
문자열에서 새 줄(\n)을 사용하고 HTML에서 동일하게 렌더링 (0) | 2023.10.31 |
자바스크립트:변수에 할당된 콜백 함수에 변수를 전달할 수 있습니까? (0) | 2023.10.31 |