2011-10-11 8 views
6

従来のDelphi 7プログラムの一部のコードを見直しながら、どこにでもpackedと記されているレコードがあることに気付きました。これは、もちろん、レコードがバイト単位で格納され、CPUがアクセスするためにより速くなるようにアライメントされていないことを意味します。パッキングは、コンパイラや何かの裏をかくための試みとして、盲目的に行われているようだ - たとえばレコード基本的に代わりに高速アクセスのメモリの数バイトを大切「パックされた」レコード以外のものは修正する必要がありますか?

TFooTypeRec = packed record 
    RID     : Integer; 
    Description   : String; 
    CalcInTotalIncome : Boolean; 
    RequireAddress  : Boolean; 
end; 

私はこの問題を解決すべきであり、すべてのレコードを正常にするか、あるいは「梱包しない」ようにしますか?あるいは、現代のCPUとメモリでは、これはごくわずかですが、恐らく時間の無駄でしょうか?開梱によって何か問題がありますか?

+2

この例でも、アンパックを実行してもアクセスが高速になるわけではありません。最初の2つのフィールドはすでに整列されており、ブール値はバイトであり、整列する必要はありません。そして、より大きなスキームでは、データがCPUキャッシュにもはや適合しなくなった場合、より大きな整列構造の効率が低下する可能性があります(L1は現在のCPUではわずか数十キロバイトです)。したがって、潜在的にパフォーマンスが低下する可能性があるコードを破る危険性があります。 –

答えて

21

これらのパックされたレコードのそれぞれがアプリケーションコードでどのように使用されているかを完全に理解していなければ、この質問に答える方法はありません。これは、 "この変数宣言をInt64からByteに変更する必要がありますか?"という質問と同じです。

答えを維持するために期待される変数の値がわかっていなくても、はいの可能性があります。それともいいえ。

あなたの場合も同様です。レコードがの場合、がパックされている必要があります。は、となります。梱包する必要がない場合は、梱包しても害はありません。あなたが確信が持てない、あるいは伝えられない場合は、一番安全なコースはそれらをそのまま残すことです。レコードのパッキングが必要または推奨され、この決意をするためのガイドとして

(続行することを決定しなければならない)、状況は次のとおりです。レコードの

  • 持続性は、[潜在]でレコード値の
  • 共有値意図的に異なる構造のメモリ上型レイアウトを覆う外部で定義された構造
  • と異なるコンパイルされたコード
  • 厳密互換

は、これは必ずしも完全なリストではなく、どのようなこれらすべて共通しているのです。そして任意の潜在的な生産や消費者が依拠することができなければならない隣接バイト単位で一連の値を含ん

  • 記録コンパイラからの干渉やその他の要因の可能性のないレコードの

私が推薦することで、それぞれの場合に機能しますどのような目的の梱包を決定し、レコードの宣言にその旨を文書を追加する(可能かつ実用的であれば)ということです同じ質問をして将来誰でも

type 
    TSomeRecordType = packed record 
     // This record must be packed as it is used for persistence 
     .. 
    end; 

    TSomeExternType = packed record 
     // This record must be packed as it is required to be compatible 
     // in memory with an externally defined struct (ref: extern code docs) 
     .. 
    end; 
+0

+1優れた回答 –

7

パックされたレコードを使用する主なアイデアは、ではなく、で、数バイトのメモリを節約できます。代わりに、変数がメモリ内にあると予想される場所にあることを保証することです。そのような保証がなければ、ヒープ上で手動でメモリを管理したり、ファイルに書き込んだり読み込んだりすることは、不可能(または少なくとも難しい)になります。

したがって、レコードをアンパックすると、プログラムが誤動作する可能性があります。

+7

+1。あなたが完全な回帰テストを利用できる場合を除いて、レガシーコードを不必要に使い果たしてはいけません。 –

1

レコードがパックされているとみなされるレシーバにパックされたり、転送されたりする場合は、変更しないでください。

更新:

あなたの例では文字列型が宣言されています。バイナリファイルにレコードを格納しても文字列の内容は保持されないため、疑わしいようです。

+0

主にこれらのレコードは、いくつかの情報を保存し、異なるクラス間でプログラム内でそれを渡すために使用されます。各バイトの実際の順序に依存するコードの一部が存在する可能性がありますが、すべてのレコードをパックする必要はないことがわかります – Earlz

+1

とにかく、パックされた宣言に触れない方がいいです。何の利益もなく、このように宣言された重要な理由を見落とす危険性があります。 –

+0

「重要な理由」の欠如のために、容易に説明できない「副作用」があるかもしれません。 –

0
  • パックレコードはメンバーのように正確に大きさがある長さを持っている:例えば、その発見プロセスを通過する必要があります。
  • パフォーマンスを向上させるために、パックされたレコードは最適化されていません(その結果、結果がより高くなります)。
関連する問題