1

私のアプリケーションは、多数のグラフを含む pdf ファイルを生成する必要があります。

状況: PDF 生成には FPDF を使用し、グラフには JpGraph を使用しています。私のコードは、データベースからグラフ データを取得し、設定、グラフのスタイル設定、およびサーバー上のキャッシュ フォルダーに png ファイルとしてキャッシュするためのすべての JpGraph コードを含む各グラフの関数を呼び出して繰り返し処理します。次に、FPDF はこれらの画像を PDF に配置し、ブラウザに提供します。

問題: グラフの数が特定の数を超えると、PHP のメモリ不足エラーが発生します。AFAICTこれはFPDFの問題ではありません。問題を診断しようとして、より多くの(事前に生成された)グラフと同等のサイズの画像を含むはるかに大きなドキュメントを生成しました。問題は、グラフレンダリング関数でグラフをレンダリングするために使用されたメモリが、関数が完了したときに解放されていないようです。これは、関数内で memory_get_peak_usage を呼び出すと、関数が呼び出されるたびに 1 つずつ、関数が停止する 64MB の制限まで、一連の増加する数値が得られるという事実に基づいています。

私のグラフ生成スクリプトは次のようになります。

function barChart($filename, $ydata, $xdata){

// Create the graph. These two calls are always required
$graph = new Graph(900,500);
$graph->SetScale('textlin');

//(bunch of styling stuff)

// Create the bar plot
$bplot=new BarPlot($ydata);

// Add the plot to the graph
$graph->Add($bplot);

//(more styling stuff)


// Display the graph
$graph->Stroke($filename);

$graph = null;
$bplot = null;

unset($graph);
unset($bplot);

echo "<br><br>".(memory_get_peak_usage(true)/1048576)."<br><br>";
}

ご覧のとおり、グラフと bplot オブジェクトの設定を解除して無効にしようとしましたが、これは必要ないはずだと理解しています。関数が終了したときに、Graph および Bplot インスタンスによって使用されるすべてのメモリを解放するべきではありませんか? それとも、これはおそらく JpGraph のメモリ リークですか? (私は高低を検索しましたが、これについて不平を言う人は他に見つかりません)。これは、リモートでリソースを大量に使用する PHP プロジェクトとしては初めてなので、明らかな何かが欠けている可能性があります。

4

3 に答える 3

8

私は同じ問題を抱えていて、わずか1時間ほどで解決策を見つけました.

問題は、グラフが作成されるたびに jpgraph がデフォルトのフォント ファイル セットをロードすることです。フォントをアンロードする方法が見つからなかったので、フォントを 1 回だけロードするように少し変更しました。

インストールを修正するには、「gd_image.inc.php」を次のように編集します。

ファイルの先頭付近 (CLASS イメージの直前) に次の行を追加します。

// load fonts only once, and define a constant for them
define("GD_FF_FONT0", imageloadfont(dirname(__FILE__) . "/fonts/FF_FONT0.gdf"));
define("GD_FF_FONT1", imageloadfont(dirname(__FILE__) . "/fonts/FF_FONT1.gdf"));
define("GD_FF_FONT2", imageloadfont(dirname(__FILE__) . "/fonts/FF_FONT2.gdf"));
define("GD_FF_FONT1_BOLD", imageloadfont(dirname(__FILE__) . "/fonts/FF_FONT1-Bold.gdf"));
define("GD_FF_FONT2_BOLD", imageloadfont(dirname(__FILE__) . "/fonts/FF_FONT2-Bold.gdf"));

次に、Image クラス コンストラクターの最後 (91 ~ 95 行目) で、これを置き換えます。

$this->ff_font0 =  imageloadfont(dirname(__FILE__) . "/fonts/FF_FONT0.gdf");
$this->ff_font1 =  imageloadfont(dirname(__FILE__) . "/fonts/FF_FONT1.gdf");
$this->ff_font2 =  imageloadfont(dirname(__FILE__) . "/fonts/FF_FONT2.gdf");
$this->ff_font1_bold =  imageloadfont(dirname(__FILE__) . "/fonts/FF_FONT1-Bold.gdf");
$this->ff_font2_bold =  imageloadfont(dirname(__FILE__) . "/fonts/FF_FONT2-Bold.gdf");

これとともに:

$this->ff_font0 =  GD_FF_FONT0;
$this->ff_font1 =  GD_FF_FONT1;
$this->ff_font2 =  GD_FF_FONT2;
$this->ff_font1_bold =  GD_FF_FONT1_BOLD;
$this->ff_font2_bold =  GD_FF_FONT2_BOLD;

複数のバージョンの php または jpgraph でこれをテストしていませんが、正常に動作するはずです。ymmv。

于 2012-12-13T19:48:45.360 に答える
3

PHP >= 5.3 ガベージ コレクションを使用してみることができます

gc_enable()+gc_collect_cycles()

http://php.net/manual/en/features.gc.php

于 2012-11-06T14:43:53.767 に答える