我有一個將csv檔案寫入磁盤的php腳本,這是一個函式:
function fputcsv_content($fp, $array, $delimiter=", "/span>, $eol="
") {
$line = " ";
foreach($array as $value) {
$value = trim($value)。
$value = str_replace("
", "
", $value)。)
if(preg_match("/[$delimiter"
]/"/span>, $value)) {
$value = ' "'. str_replace('"', '"', $value).'"'。
}
$line .= $value.$delimiter;
}
$eol = str_replace("/span>, "
", $eol)。)
$eol = str_replace("n"/span>, "
"/span>, $eol)。)
$line = substr($line, 0, (strlen($delimiter) * -1) ) 。
$line .= $eol;
return fputs($fp, $line) 。
服務器是AWS實體,CentOS 7,PHP版本為7.2
。服務器規格。 4GB記憶體 32GB SWAP 2個核心,2.5GHZ
當檔案很大時,(3GB,4GB)寫入程序很慢,(每2或3秒1MB)。在php.ini或apache配置中是否有任何設定來控制這個fputs/fwrite功能?
我在php.ini中看到一個output_buffer的設定(目前設定為4096),但我懷疑這和它有關系。
謝謝!
uj5u.com熱心網友回復:
不要使用.=來追加一行。使用一個陣列,將值添加到陣列中,然后將陣列內爆。你現在正在用不斷丟棄的字串填充你的記憶體。
每次你做.=時,舊的字串被保留在堆疊中,而新的空間被保留給新的字串,GC只在函式準備好時運行。
對于一個3-4gb的檔案來說,這可能最終會成為許多倍,這導致行程使用交換作為額外的記憶體,這很慢。
嘗試將其重構為一個陣列方法,通過使用一些節省記憶體的技術,看看是否能緩解你的問題。
我加入了靜態函式變數的使用,因此它們只被分配一次,而不是每次迭代,這也節省了少量的記憶體,這也是拋開php可能或不可能做的優化。
在線查看。https://ideone.com/dNkxIE
function fputcsv_content($fp, $array, $delimiter=", "/span>, $eol="
")
{
static $find = ["
","
"] 。
static $replace = ["
"/span>,"
"]。
static $cycles_count = 0;
$cycles_count ;
$array = array_map(function($value) use($delimiter) {
return clean_value($value, $delimiter)。
}, $array)。)
$eol = str_replace($find, $replace, $eol)。
$line = implode($delimiter, $array) . $eol;
$return_value = fputs($fp, $line) 。
/**特意釋放了RAM **/。
$line = null;
$eol = null;
$array = null;
/** 觸發 gc_collect_cycles() 每250次呼叫此方法 **/
if($cycles_count % 250 ==0) gc_collect_cycles();
return $return_value。
}
/** 使用第二個函式,以便在這里觸發GC。
*當它回傳的值和所有的中間值都是免費的。
*/
function clean_value($value, $delimeter)
{
/**。
* 使用靜態值來防止將相同的
* 的值重復分配到堆疊中。
*/
static $regex = []。
static $find = "
"。
static $replace = "
"。
static $quote = ' "';
if(!isset($regex[$delimeter]) {
$regex[$delimeter] = "/[$delimiter"
]/"。
}
$value = trim($value)。
$value = str_replace($find, $replace, $value)。
if(preg_match($regex[$delimeter], $value) {
$value = $quote. str_replace($quote, '"', $value) .$quote。
}
return $value。
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/309426.html
標籤:
