ホームページ  >  記事  >  バックエンド開発  >  Go でポインターやガベージ コレクションを使用する場合、メモリ使用量を効果的に管理し、ガベージの生成を防ぐにはどうすればよいですか?

Go でポインターやガベージ コレクションを使用する場合、メモリ使用量を効果的に管理し、ガベージの生成を防ぐにはどうすればよいですか?

Patricia Arquette
Patricia Arquetteオリジナル
2024-10-31 18:36:02832ブラウズ

How can I effectively manage memory usage and prevent garbage creation when working with pointers and garbage collection in Go?

Go のガベージ コレクションとポインター: データ構造マッピングの包括的なガイド

はじめに

Python、Ruby、JavaScript では、ポインターの動作が異なります。囲碁よりも。 Go のガベージ コレクターはメモリを自動的に解放するため、メモリ消費を最適化し、不必要なガベージの作成を防ぐためにポインタの使用法を理解することが不可欠です。

例: 画像 URL へのタグのマッピング

タグが関連付けられた画像のデータセット。各タグを対応する画像 URL のリストにマップするデータ構造を作成することを目的としています。

<code class="python">{
    "ocean": [
        "https://c8.staticflickr.com/4/3707/11603200203_87810ddb43_o.jpg"
    ],
    "water": [
        "https://c8.staticflickr.com/4/3707/11603200203_87810ddb43_o.jpg",
        "https://c3.staticflickr.com/1/48/164626048_edeca27ed7_o.jpg"
    ],
    ...
}</code>

ポインターの使用 (バージョン 1)

このマッピングを表す 1 つの方法は、ポインターを使用することです。画像構造体の URL フィールド:

<code class="go">tagToUrlMap := make(map[string][]*string)

for _, image := range result {
    for _, tag := range image.Tags {
        tagToUrlMap[tag.Name] = append(tagToUrlMap[tag.Name], &image.URL)
    }
}</code>

結果:

  • 画像 URL 文字列フィールドは、結果のデータ構造とともにメモリに保存されます。
  • 結果のデータ構造は、そのメンバーが参照されるため、プログラムの終了までメモリ内に残ります。

中間変数の使用 (バージョン 2)

代替アプローチ中間変数を使用し、その変数へのポインタを格納します。

<code class="go">tagToUrlMap := make(map[string][]*string)

for _, image := range result {
    imageUrl = image.URL
    for _, tag := range image.Tags {
        tagToUrlMap[tag.Name] = append(tagToUrlMap[tag.Name], &imageUrl)
    }
}</code>

結果:

  • 中間の imageUrl 変数のみがメモリに残り、画像 URL 文字列フィールド。
  • 結果のデータ構造は正しくガベージ コレクションできます。

画像構造体の文字列へのポインタを使用する

別のオプションは次のとおりです。画像構造体の文字列へのポインタを使用します:

<code class="go">type Image struct {
    URL *string
    Description string
    Tags []*Tag
}</code>

考慮事項:

  • 他の方法と比較して追加のメモリ節約はありません。
  • 複雑さと間接性が追加されました。

最適な解決策: 文字列インターニング

メモリ効率の最適な解決策は、一意の文字列値のインスタンスを 1 つだけ確保する文字列インターニングを使用することです。

<code class="go">var cache = map[string]string{}

func interned(s string) string {
    if s2, ok := cache[s]; ok {
        return s2
    }
    cache[s] = s
    return s
}</code>

実装:

<code class="go">tagToUrlMap := make(map[string][]string)

for _, image := range result {
    imageURL := interned(image.URL)

    for _, tag := range image.Tags {
        tagName := interned(tag.Name)
        tagToUrlMap[tagName] = append(tagToUrlMap[tagName], imageURL)
    }
}</code>

結論

  • 文字列値は Go のポインタのように機能し、 *文字列は不要です。
  • メンバーへのポインターが保存されている場合、結果のデータ構造はメモリ内に残ります。
  • フィールドまたは配列要素のアドレスの保存は、メモリの断片化を避けるために注意して行う必要があります。
  • 文字列インターニングは、メモリ消費量を削減するための最適なソリューションです。
  • さらに最適化するには、append() を使用して作成されたスライスから余分な容量をトリミングします。

以上がGo でポインターやガベージ コレクションを使用する場合、メモリ使用量を効果的に管理し、ガベージの生成を防ぐにはどうすればよいですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。