[解決済み] libc++の短い文字列の最適化の仕組みとは?
質問
この回答 は、短い文字列の最適化 (SSO) の素晴らしいハイレベルな概要を提供しています。しかし、私はそれが実際にどのように動作するのか、特に libc++ の実装においてより詳細に知りたいと思います。
-
SSO のために修飾するために、文字列はどのくらい短くなければならないのでしょうか。 これはターゲットとなるアーキテクチャに依存するのでしょうか。
-
文字列データにアクセスする際、実装はどのように短い文字列と長い文字列を区別しているのでしょうか? を区別しているのでしょうか?単純に
m_size <= 16
なのか、それとも他のメンバ変数の一部であるフラグなのでしょうか?(I 想像するにm_size
またはその一部もまた 文字列データを格納するために使用されるかもしれません)。
libc++ が SSO を使用することを知っているので、私はこの質問を特に libc++ に対して行いました。 libc++ ホームページ .
以下は ソース :
libc++ は文字列クラスに対して、2 つの微妙に異なるメモリレイアウトでコンパイルすることができます。
_LIBCPP_ALTERNATE_STRING_LAYOUT
フラグによって決定されます。どちらのレイアウトもリトルエンディアンとビッグエンディアンのマシンを区別しており、合計で 4 種類の異なるレイアウトがあります。以下では、quot;normal" レイアウトとリトルエンディアンを仮定します。
さらに次のように仮定します。
size_type
が4バイトであり
value_type
が1バイトの場合、文字列の最初の4バイトはメモリ上でこのように表示されます。
// short string: (s)ize and 3 bytes of char (d)ata
sssssss0;dddddddd;dddddddd;dddddddd
^- is_long = 0
// long string: (c)apacity
ccccccc1;cccccccc;cccccccc;cccccccc
^- is_long = 1
短い文字列のサイズは上位7ビットであるため、アクセスする際にシフトする必要があります。
size_type __get_short_size() const {
return __r_.first().__s.__size_ >> 1;
}
同様に、長い文字列の容量を表すゲッターとセッターは
__long_mask
を回避するために
is_long
ビットを回避することができます。
私はまだ最初の質問に対する答えを探しています、つまり、どのような値で
__min_cap
はどのような値をとるのでしょうか。
他の標準ライブラリの実装
この回答
の概要を説明しています。
std::string
メモリレイアウトの概要を説明しています。
どのように解決するのですか?
libc++ の
basic_string
は
sizeof
3語で、すべてのアーキテクチャで
sizeof(word) == sizeof(void*)
. long/short フラグ、および short フォームのサイズ フィールドを正しく分解しています。
短い文字列の容量である __min_cap は、異なるアーキテクチャに対してどのような値を取るのでしょうか?
短い形式では、扱う単語は3つです。
- 1ビットはロング/ショートのフラグになります。
- 7ビットがサイズになります。
-
仮定すると
char
と仮定すると、1 バイトが末尾の null になります(libc++ は常にデータの後ろに末尾の null を格納します)。
これは、短い文字列を格納するために3ワードから2バイトを引いたものです(つまり、最大の
capacity()
アロケーションなし)。
32ビットマシンでは、短い文字列に10文字が収まります。 sizeof(string)は12です。
64ビットマシンでは、22文字が短い文字列に収まります。
主要な設計目標は
sizeof(string)
を最小化し、内部バッファを可能な限り大きくすることでした。 その根拠は、手の構築と手の割り当てを高速化するためです。 より大きな
sizeof
が大きいほど、移動の構築や移動の割り当ての間に移動しなければならない単語が多くなります。
長い形式では、データポインタ、サイズ、および容量を格納するために最低3つの単語が必要です。 したがって、私は短いフォームをこれらと同じ 3 つの単語に制限しました。 4 ワードの sizeof がより良い性能を持つかもしれないことが示唆されています。 私はその設計選択をテストしていません。
_libcpp_abi_alternate_string_layout
という設定フラグがあります。
_LIBCPP_ABI_ALTERNATE_STRING_LAYOUT
から "ロングレイアウト" に変わるように、データメンバーを並べ替えます。
struct __long
{
size_type __cap_;
size_type __size_;
pointer __data_;
};
になります。
struct __long
{
pointer __data_;
size_type __size_;
size_type __cap_;
};
この変更の動機は、このように
__data_
を最初に置くことで、より良いアライメントによるパフォーマンスの利点があると考えたからです。 パフォーマンスの利点を測定する試みがなされましたが、測定するのは困難でした。 パフォーマンスを悪化させることはなく、わずかに良くなるかもしれません。
このフラグは注意して使用する必要があります。 これは異なるABIであり、誤ってlibc++と混同すると
std::string
の異なる設定でコンパイルされた
_LIBCPP_ABI_ALTERNATE_STRING_LAYOUT
はランタイムエラーを発生させます。
このフラグは、libc++のベンダによってのみ変更されることをお勧めします。
関連
-
[解決済み】リンカーエラーです。"リンカ入力ファイルはリンクが行われていないため未使用"、そのファイル内の関数への未定義参照
-
[解決済み】#include<iostream>は存在するのですが、「識別子 "cout "は未定義です」というエラーが出ます。なぜですか?
-
[解決済み] 配列のベクトルを扱う正しい方法
-
[解決済み] 変数サイズのオブジェクトが初期化されないことがある c++
-
[解決済み] C#のStringとstringの違いは何ですか?
-
[解決済み] explicit キーワードの意味は?
-
[解決済み] 文字列の単語を反復処理するにはどうすればよいですか?
-
[解決済み] ルール・オブ・スリーとは?
-
[解決済み] コピーアンドスワップ慣用句とは?
-
[解決済み】C/C++の"-->"演算子とは何ですか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み] エラーが発生する。ISO C++は型を持たない宣言を禁じています。
-
[解決済み】C++でユーザー入力を待つ【重複あり
-
[解決済み】C++コンパイルタイムエラー:数値定数の前に期待される識別子
-
[解決済み】 != と =! の違いと例(C++の場合)
-
[解決済み】デバッグアサーションに失敗しました。C++のベクトル添え字が範囲外
-
[解決済み】fpermissiveフラグは何をするのですか?
-
[解決済み】指定範囲内の乱数で配列を埋める(C++)
-
[解決済み】std::cin.getline( ) vs. std::cin
-
[解決済み】システムが指定されたファイルを見つけられませんでした。
-
[解決済み] std::stringの文脈における頭文字SSOの意味