Go が長さ 100k の配列よりも長さ 100k のスライスの方が使用するメモリが少ないのはなぜですか?
Go 言語がスライスと配列を処理する場合、長さ 100k のスライスは長さ 100k の配列よりもメモリ使用量が少なくなります。これは、スライスでは基礎となる実装でポインタと長さの組み合わせが使用されるのに対し、配列ではデータを格納するために連続したメモリ領域が必要になるためです。スライスの長さは可変であるため、メモリは動的に割り当ておよび解放できますが、配列は宣言時に固定長を指定する必要があります。したがって、大量のデータを処理する場合、スライスを使用するとメモリ空間をより効率的に使用し、メモリ使用量を削減できます。これは、大規模なデータを処理する場合の Go 言語の利点の 1 つでもあります。
質問の内容
次のコードを考えてみましょう。それぞれ長さ 100k の 4000 個の配列を割り当てました。 リーリー
プログラムをローカルで実行してメモリ使用量を分析すると、2 GB を超えるメモリが使用され始めます。ここで、コードを少し変更して、次のように配列スライス (ただし長さは 100k) を使用するとします。
リーリー
私のマシンでは、メモリは約 73mb でピークに達しました。 ###何故ですか?次の理由により、両方のフラグメントがほぼ同じメモリを使用すると思います:
どちらの場合も、go ランタイムは
- parentmap
- の値をヒープに割り当てます。 go がこれを行うのは、これらの値をスタックに割り当てると、現在の関数がスコープ外になると
parentmap
の値がすべてクリアされるためです。 - そして、2 番目のフラグメントは、ヒープ上に 4k スライス ヘッダーを割り当てます。各スライス ヘッダーには、サイズ 100k の一意の配列 (ヒープ上にもあります) へのポインターがあります。
- どちらの場合も、サイズ 100k のヒープ上に 4k の配列があります。したがって、どちらの場合もほぼ同じ量のメモリを使用する必要があります。
- 読みました: https://go.dev/blog/slices-intro。しかし、これを説明する実装の詳細は見つかりません。
回避策
スライスを使用するバージョンでは、遅延割り当ての利点が得られる可能性があります。これらのスライスのいずれかにあるデータ バッファーへの書き込みは何も試行されないため、実際に書き込みが試行されるまで、オペレーティング システムはこれらのバッファーに実際にメモリを割り当てなくても構いません。 (オペレーティング システムは、割り当てが強制されないようにバッファのゼロ初期化を遅らせることもできます。)
一方、配列を使用するバージョンでは、配列を実際にマップにコピーする必要があります。これは、実際に書き込みを実行することを意味します。書き込まれた値がすべて 0 であっても、それらは書き込みであることに変わりはないため、オペレーティング システムは書き込まれるデータ用にメモリを実際に割り当てる必要があります。
これらのスライスにデータを書き込もうとすると、スライスされたバージョンもギガバイトのメモリを占有するはずです。 (メモリのページごとに 1 つの値で十分だと思いますが、スライスに
1 を設定する方が簡単かもしれません。)
以上がGo が長さ 100k の配列よりも長さ 100k のスライスの方が使用するメモリが少ないのはなぜですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

ホットAIツール

Undresser.AI Undress
リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover
写真から衣服を削除するオンライン AI ツール。

Undress AI Tool
脱衣画像を無料で

Clothoff.io
AI衣類リムーバー

AI Hentai Generator
AIヘンタイを無料で生成します。

人気の記事

ホットツール

メモ帳++7.3.1
使いやすく無料のコードエディター

SublimeText3 中国語版
中国語版、とても使いやすい

ゼンドスタジオ 13.0.1
強力な PHP 統合開発環境

ドリームウィーバー CS6
ビジュアル Web 開発ツール

SublimeText3 Mac版
神レベルのコード編集ソフト(SublimeText3)

ホットトピック









Go Crawler Collyのキュースレッドの問題は、Go言語でColly Crawler Libraryを使用する問題を調査します。 �...

大企業または有名なオープンソースプロジェクトによって開発されたGOのどのライブラリが開発されていますか? GOでプログラミングするとき、開発者はしばしばいくつかの一般的なニーズに遭遇します...

GO言語で構造を定義する2つの方法:VARとタイプのキーワードの違い。構造を定義するとき、GO言語はしばしば2つの異なる執筆方法を見ます:最初...

Go言語での文字列印刷の違い:printlnとstring()関数を使用する効果の違いはGOにあります...

redisstreamを使用してGo言語でメッセージキューを実装する問題は、GO言語とRedisを使用することです...

Golandのカスタム構造ラベルが表示されない場合はどうすればよいですか?ゴーランドを使用するためにGolandを使用する場合、多くの開発者はカスタム構造タグに遭遇します...

ポインター構文とviperライブラリの使用における問題への取り組みGO言語でプログラミングするとき、特にポインターの構文と使用を理解することが重要です...
