2

ファイルからデータを取得し、後で使用するために保存するアプリケーションがあります。ファイルの各行は 1 つのオブジェクトに対応します。Fooこのオブジェクトには、1 つの文字で構成され、それぞれが異なる. したがって、このデータを次のように保存します。nBarStringName

Foo extends HashMap<Name, Pair<Bar, Bar>>

whereは、2 つの値を格納し、Pair<A, B>いくつかのメソッド ( など) を提供する独自のクラスです。equalshashcode

私が遭遇した問題は、実際には 25kbytes に近いのに、オブジェクトを保存するときn=114(これはたまたまテストデータの数字です) 、228 バイトを超えないようにする必要があることです。これは、1000 個までのオブジェクトがある場合、228kB ではなく 25MB のメモリが必要であることを意味し、これは実際には受け入れられません。(注: 各オブジェクトのキーは同じです。)PairFooFooFoofooOne.keySet().equals(fooTwo.keySet())

アプリケーションのプロファイリングにVisualVMを使用していますFoo

Field           Type             Retained
-               
this            Foo              24750
...             
v table         HashMap$Entry[]  24662
  v [0]         HashMap$Entry    200
    v value     Pair             156
      v first   Bar              60
        ...
        > code  String           36
      v second  Bar              60
        ...
        > code  String           36
    v key       Name             72
      ...
      > name    String           36
  > [1]         HashMap$Entry    200
  > [2]        <HashMap$Entry>   -
  ...
  > [233]       HashMap$Entry    600
  ...
  > [255]      <HashMap$Entry>   -

ご覧のとおり、有用な情報はすべて、(私にとって) 役に立たないデータに囲まれています。同じデータを持つより少ない、より大きなオブジェクトがあれば、役に立つ:役に立たない比率が良くなることがわかりますが、これを他の方法で実装する方法がわかりません。これほど便利で使いやすく、データを保存できる方法は他にありますか?

編集

私のアプリケーションは、6000 以上のBarインスタンス、場合によってはそれ以上のインスタンスまで拡張可能である必要がありFooます。

4

5 に答える 5

3

あなたの質問が正しいかどうか完全にはわかりませんが、この状況では Flyweights を使用するとうまくいくかもしれません。

フライ級パターン

于 2012-08-07T10:47:38.643 に答える
0

あなたは言う:

ファイルからデータを取得し、後で使用するために保存するアプリケーションがあります

以降(コメント内)

できるだけメモリ効率を上げるように依頼されました

最もメモリ効率の高い解決策は、事前に解析して保存するのではなく、ファイルを保存して要求に応じて解析することだと思います。しかし、本当にこれを実行して、関連するパフォーマンスコストを負担したいですか?あなたの記憶の問題は特に大きなものではないと思いますが、(他の人が述べているように)私はフライウェイトパターンを調査します。

于 2012-08-07T10:58:36.463 に答える
0

こちらをご覧ください。クラス(文字列またはその他)をJVMのヒープに格納するために、思ったよりもはるかに多くのバイトが必要であることがわかります。

1文字の文字列の36バイトは、文字を保持するオブジェクトの多くのメタデータ(UTFエンコーディングを必ず考慮に入れる)と文字列クラスのオーバーヘッドを格納する必要があるため、非常に適切に聞こえます。

于 2012-08-07T11:00:21.900 に答える
0

あなたの問題の多くは、一般的にはオブジェクト指向コードであり、具体的にはUnicode変換であると思います。

Javaでは、文字列内の文字を格納するには2バイトが必要です。したがって、少なくとも、ドライブにファイルを保持する場合と比較して、メモリ使用量が2倍になることが期待できます。

各オブジェクト、各小さな文字列は、JVMがオブジェクトを指す必要があるポインターのために、単語に相当する情報を必要とします。したがって、データの各ペアは、キーの単語と値の単語にそれぞれの実際のサイズを加えたものです。これで、これらのポインターがハッシュに追加されます。ハッシュは、単語を使用してそれ自体を指し、いくつかの単語を使用してエントリセットを指します。そして、それは行きます。これはオブジェクト指向プログラミングです。

これで、コードを変更して、ペアを単純なchar[2]として格納できます。これにより、メモリーフットプリントが削減されます。次に、それを操作したいときに、Pairオブジェクトで配列をラップすることができます。

于 2012-08-07T10:51:08.833 に答える
0

BarオブジェクトとPairオブジェクトを削除して、単純なStringオブジェクトのペアを保存することができます。たとえば、「ab」(「a」、「b」は現在、Bar( "a")とBar( "で構成されるペアに対応します)。 b "))

おそらくFlyweightパターンを使用して、すべてのFooオブジェクトの共通名を共有します。fooOne.keySet().equals(fooTwo.keySet())

于 2012-08-07T10:51:45.307 に答える