プロジェクトファイルのusesにFastMM4を追加して使います。
MLホームページ: http://www.freeml.com/delphi-users
----------------------------------------------------------------------
動画など大きいファイルもMLメンバーにカンタンに共有!
http://ad.freeml.com/cgi-bin/sa.cgi?id=fkfwL
-----------------------------------------------------[freeml by GMO]--
> 下記、環境でDBアクセスを含む重い処理を大量・長時間実行していると「メモリ不足です」と表示され、処理が中断されてしまいます。
> メモリリークについては、EurekaLogによる検出はありません。
> また、メモリ不足です(EOutOfMemory)の発生箇所は、EurekaLogのレポートによれば、IB.pas-IBAllocで毎回発生しています。
> いろいろ試したところ、下記のようなテーブル(※)へ、TIBSQLでSELECT文(選択リストは3つ)を実行している箇所をコメントアウトすると、正常に終了することが分かっています。
> (※、カラム数35(VARCHARとDOUBLE)、行数3万)
UniDirectionalプロパティがデフォルトのFalseになっているのが
原因ではないでしょうか?IBXは双方向カーソルを実現するために
各レコードをキャッシュするようになっており、それが原因で
メモリ不足が発生することがあります。単一方向にしか移動しない
(Nextのみ)のであればUniDirectionalをTrueにすることで問題を
回避できると思います。
---
東洋テクニカルシステム株式会社 システム開発部 福士 光
Hikaru Fukushi (Toyo Technical System Inc.)
mailto:fuk...@tts-inc.co.jp
MLホームページ: http://www.freeml.com/delphi-users
----------------------------------------------------------------------
自分好みのMLを作成して気の合う仲間と情報を共有しよう♪
http://ad.freeml.com/cgi-bin/sa.cgi?id=fkhIV
> 同じ処理で、TIBDataSetに大きなデータをよみこんでいるため、ご指摘の可能性が高いかもしれません。
> しかし、仕組み的に難しく、検証して確認するには至っておりません。
> また、双方向である必要もあるため、単方向への変更もできません。
> 読み込むデータ量を減らすなどしての対応しかないでしょうか?
前回も書きましたが、IBXはUniDirectionalプロパティがFalseの
ときに、本来単方向にしか移動できないデータセットに対して
双方向の移動を可能にするために、通過したレコードをキャッシュ
するようになっています。このときキャッシュに使用するメモリを
BufferChunks毎に再アロケートして内容をコピーするため、例えば
10MBのデータがキャッシュされた状況で次のレコードに移動すると
一時的に20MBのメモリを必要とするような状況が起きていたような
気がします。
# エラーとなるIB.IBAllocの呼び出し元はIBCustomDataSet.
# TIBCustomDataSet.AdjustPositionでしょうか?
hirariさんの回答にあったFastMMである程度問題が解決したと
いうことであれば、FastMM採用以前のDelphi標準のメモリ
マネージャの持つ問題が関係しているのかもしれません。解決策は
お勧め順に
1.BufferChunksを大きくしてメモリの再アロケートを減らす。
2.メモリマネージャを変更する(例えばFastMMを使用する)。
3.IBXを使うのをやめる(DBXなどに移行する)。
4.UniDirectionalをTrueにして単方向でのみ動作させる。
といったところでしょうか。参考にしてください。
# BufferChunksはキャッシュサイズの直接的な増分なので、大きめな
# 値を指定することで問題が起きにくくなるはずですが、確か4KBが
# メモリマネージャのストラテジ切り替えの閾値だったような…。
---
東洋テクニカルシステム株式会社 システム開発部 福士 光
Hikaru Fukushi (Toyo Technical System Inc.)
mailto:fuk...@tts-inc.co.jp
MLホームページ: http://www.freeml.com/delphi-users
----------------------------------------------------------------------
春に新しいことを始めるなら♪MLも作成して活用しよう!
http://ad.freeml.com/cgi-bin/sa.cgi?id=fkrzS
福士様
詳しい説明ありがとうございます。
># エラーとなるIB.IBAllocの呼び出し元はIBCustomDataSet.
># TIBCustomDataSet.AdjustPositionでしょうか?
はい、その通りです。
> >1.BufferChunksを大きくしてメモリの再アロケートを減らす。
> 下記の値に変えて、試してみましたがうまくいきませんでした。
> 1500、2000、4000
もっと大きな値、例えば32768とか65536とか(実行環境のメモリに
余裕があるならもっと思い切って大きな値、最初からキャッシュ
データが全て入りきって再アロケートの起きる恐れのないサイズの
ほうがいいのかもしれません)を指定したらどうでしょう?少なく
とも4096以下は意味がないと思います。
> >2.メモリマネージャを変更する(例えばFastMMを使用する)。
> 将来的に採用したいと思いますが、すぐに採用はできません。
> 稼働中のシステムなので、すぐ対応が必要なためです。
それほど大きな問題だとは思わないのですが。既にDelphi 2007
以降で使用されていることで実績はありますし(FastMMはDelphi
2006以降の標準メモリマネージャです)。
# 単なるメモリマネージャの入れ替えなのでプログラムに手を
# 入れるよりは安全かと。
まぁBufferChunksの変更で解決すればベストですが。
---
東洋テクニカルシステム株式会社 システム開発部 福士 光
Hikaru Fukushi (Toyo Technical System Inc.)
mailto:fuk...@tts-inc.co.jp
MLホームページ: http://www.freeml.com/delphi-users
----------------------------------------------------------------------
お花見や旅行♪MLメンバーと撮った写真はみんなで楽しもう!
http://ad.freeml.com/cgi-bin/sa.cgi?id=fkywe
> BufferChunksについてですが、
> 詳しくないので間違っているかもしれませんが、値は行数の指定でないでしょうか。
あー、そうですね。失礼しました。IBCustomDataSet.pasをちょっと
追ってみましたが、キャッシュサイズ(FCacheSize)の初期値は
TIBCustomDataSet.InternalOpen内で
| FBufferChunkSize := FRecordBufferSize * BufferChunks;
で計算されたFBufferChunkSizeと同じ値で、以後FBufferChunkSizeだけ
増えてゆくため、BufferChunksを当該SELECT文で取得されるレコードの
最大想定数として再アロケートが発生しないようにするのがいいように
思います。
ただその時点でFCacheSize分のまとまったメモリが確保できない
ような状況(標準の(FastMM系でない)メモリマネージャだとヒープ
エリアが断片化しやすく、まとまったサイズのブロックが確保
できなくなることがある)だとまずいので、そのような状況が発生
するのであれば、やはりメモリマネージャを変更する必要があるの
かもしれません。
# BufferChunksが適切でないと何度も再アロケートが発生してしまい、
# 自分で断片化の原因を作って嵌まってしまうことに…。
---
東洋テクニカルシステム株式会社 システム開発部 福士 光
Hikaru Fukushi (Toyo Technical System Inc.)
mailto:fuk...@tts-inc.co.jp
MLホームページ: http://www.freeml.com/delphi-users
----------------------------------------------------------------------
自分好みのMLを作成して気の合う仲間と情報を共有しよう♪
http://ad.freeml.com/cgi-bin/sa.cgi?id=fkzhx