3

我编写了一个自动化脚本来解析本地的 XML 文件,从 XML 中提取一些 url,然后下载 url 指向的文件并存储数据(所有 jpg 的)。每次后续迭代逐渐花费越来越长的时间。最终,脚本只是挂起,没有任何反应。哦,内存使用量似乎保持不变。XML 解析工作正常,所以请不要过多关注。如果我在脚本完全停止的游戏中启动脚本,则会在一秒钟内将文件保存到磁盘,因为这是脚本所做的第一次保存。这是什么原因造成的?这是代码:

    <?php

$xml = simplexml_load_file('./playfin.xml', null, LIBXML_NOCDATA);

echo("Getting urls from the XML...\n");
$data = array();
foreach($xml->game as $game) {
  $smlBox = $game->small_boxshot_image->url;
  $lrgBox = $game->large_boxshot_image->url;

  foreach($game->screenshots->screenshot_image as $image) {
    $scrShots[] = array(
      'smlScr' => (string)$image->small_screenshot_image->url,
      'lrgScr' => (string)$image->large_screenshot_image->url  
    );
  }
  $data[] = array(
    'id' => (int)$game->game_id,
    'smlBox' => (string)$smlBox,
    'lrgBox' => (string)$lrgBox,
    'scrShots' => $scrShots
  );
} 
echo("Done pulling urls from XML...\n");

echo("Storing picture data to disk...\n");
$start = time();
$total = 0;
$now = 0;
for($i = 0; $i < count($data); $i++) {
  $total += $now;
  $now = time() - $start - $total;
  echo("Writing game id: ".$data[$i]['id']. 
    ." to disk at time=".(string)$now."          seconds.\n");
  echo("Memory usage: ".(string)memory_get_usage(true)."\n\n");
  $smlBoxStr = '%s_49_60.jpg';
  $lrgBoxStr = '%s_160_189.jpg';
  $smlScrStr = '%s_115_86_%d.jpg';
  $lrgScrStr = '%s_300_300_%d.jpg';

  writeData($data[$i]['smlBox'], sprintf($smlBoxStr, $data[$i]['id']), 'boxshot');
  writeData($data[$i]['lrgBox'], sprintf($lrgBoxStr, $data[$i]['id']), 'boxshot');
  for($j = 0; $j < count($data[$i]['scrShots']); $j++) {
    writeData(
      $data[$i]['scrShots'][$j]['smlScr'], 
      sprintf($smlScrStr, $data[$i]['id'], $j),
      'screenshot'
    );
    writeData(
      $data[$i]['scrShots'][$j]['lrgScr'], 
      sprintf($lrgScrStr, $data[$i]['id'], $j),
      'screenshot'
    );
  }  
}
echo("Done storing!\n");
echo("Done!\n");

function writeData($url, $file, $type) {
  $headers = get_headers($url, 1);
  $awayPic = fopen($url, 'rb');
  $localPic = fopen("./$type/$file", 'wb');
  while($picData = fread($awayPic, (int)$headers['Content-Length'])) {
    fwrite($localPic, $picData);
  }
  fclose($awayPic);
  fclose($localPic);
}  

?>

这是生成的日志文件:

从 XML 中获取 url... 完成从 XML 中提取 url... 将图片数据存储到磁盘... 在 time=0 秒时将游戏 id: 671850 写入磁盘。内存使用量:77856768

在 time=0 秒时将游戏 id: 730950 写入磁盘。内存使用量:77856768

在 time=1 秒时将游戏 id: 621650 写入磁盘。内存使用量:77856768

在 time=1 秒时将游戏 id: 687250 写入磁盘。内存使用量:77856768

在时间 = 7 秒时将游戏 ID:633950 写入磁盘。内存使用量:77856768

在 time=2 秒时将游戏 id: 633850 写入磁盘。内存使用量:77856768

在 time=2 秒时将游戏 id: 720950 写入磁盘。内存使用量:77856768

在 time=3 秒时将游戏 id: 572250 写入磁盘。内存使用量:77856768

在 time=3 秒时将游戏 id: 674950 写入磁盘。内存使用量:77856768

在 time=3 秒时将游戏 id: 731450 写入磁盘。内存使用量:77856768

在 time=4 秒时将游戏 id: 656350 写入磁盘。内存使用量:77856768

在 time=4 秒时将游戏 id: 653550 写入磁盘。内存使用量:77856768

在时间 = 4 秒时将游戏 ID:585550 写入磁盘。内存使用量:77856768

在 time=5 秒时将游戏 id: 736750 写入磁盘。内存使用量:77856768

在时间 = 5 秒时将游戏 ID:671350 写入磁盘。内存使用量:77856768

在 time=5 秒时将游戏 id: 696250 写入磁盘。内存使用量:77856768

在时间 = 6 秒时将游戏 ID:645550 写入磁盘。内存使用量:77856768

在 time=6 秒时将游戏 id: 625650 写入磁盘。内存使用量:77856768

在 time=6 秒时将游戏 id: 696850 写入磁盘。内存使用量:77856768

在时间 = 7 秒时将游戏 ID:709550 写入磁盘。内存使用量:77856768

在时间 = 7 秒时将游戏 ID:575750 写入磁盘。内存使用量:77856768

在时间 = 7 秒时将游戏 ID:651950 写入磁盘。内存使用量:77856768

在时间 = 8 秒时将游戏 ID:685350 写入磁盘。内存使用量:77856768

在时间 = 9 秒时将游戏 ID:724150 写入磁盘。内存使用量:77856768

在时间 = 8 秒时将游戏 ID:522250 写入磁盘。内存使用量:77856768

在时间 = 10 秒时将游戏 ID:610350 写入磁盘。内存使用量:77856768

在时间 = 9 秒时将游戏 ID:645050 写入磁盘。内存使用量:77856768

在时间 = 9 秒时将游戏 ID:716950 写入磁盘。内存使用量:77856768

在 time=10 秒时将游戏 id: 672750 写入磁盘。内存使用量:77856768

在时间 = 11 秒时将游戏 ID:568650 写入磁盘。内存使用量:77856768

在时间 = 11 秒时将游戏 ID:668650 写入磁盘。内存使用量:77856768

在时间 = 11 秒时将游戏 ID:417950 写入磁盘。内存使用量:77856768

在时间 = 13 秒时将游戏 ID:497950 写入磁盘。内存使用量:77856768

在时间 = 12 秒时将游戏 ID:567950 写入磁盘。内存使用量:77856768

在时间 = 13 秒时将游戏 ID:692350 写入磁盘。内存使用量:77856768

在时间 = 13 秒时将游戏 ID:450950 写入磁盘。内存使用量:77856768

在时间 = 14 秒时将游戏 ID:452750 写入磁盘。内存使用量:77856768

在时间 = 14 秒时将游戏 ID:666450 写入磁盘。内存使用量:77856768

在时间 = 15 秒时将游戏 ID:754550 写入磁盘。内存使用量:77856768

在时间 = 15 秒时将游戏 ID:659050 写入磁盘。内存使用量:77856768

在时间 = 15 秒时将游戏 ID:712350 写入磁盘。内存使用量:77856768

在时间 = 16 秒时将游戏 ID:719250 写入磁盘。内存使用量:77856768

在时间 = 15 秒时将游戏 ID:529250 写入磁盘。内存使用量:77856768

在时间 = 17 秒时将游戏 ID:685150 写入磁盘。内存使用量:77856768

在时间 = 17 秒时将游戏 ID:736450 写入磁盘。内存使用量:77856768

在时间 = 17 秒时将游戏 ID:252750 写入磁盘。内存使用量:77856768

在时间 = 17 秒时将游戏 ID:719150 写入磁盘。内存使用量:77856768

在时间 = 18 秒时将游戏 ID:461150 写入磁盘。内存使用量:77856768

在时间 = 18 秒时将游戏 ID:699450 写入磁盘。内存使用量:77856768

在时间 = 18 秒时将游戏 ID:523550 写入磁盘。内存使用量:77856768

在 time=20 秒时将游戏 id: 451050 写入磁盘。内存使用量:77856768

在时间 = 19 秒时将游戏 ID:768350 写入磁盘。内存使用量:77856768

在 time=20 秒时将游戏 id: 724650 写入磁盘。内存使用量:77856768

在 time=21 秒时将游戏 id: 676550 写入磁盘。内存使用量:77856768

在时间 = 21 秒时将游戏 ID:730850 写入磁盘。内存使用量:77856768

在时间 = 22 秒时将游戏 ID:558250 写入磁盘。内存使用量:77856768

在时间 = 22 秒时将游戏 ID:674750 写入磁盘。内存使用量:77856768

在 time=22 秒时将游戏 id: 695450 写入磁盘。内存使用量:77856768

在时间 = 22 秒时将游戏 ID:682950 写入磁盘。内存使用量:77856768

在时间 = 24 秒时将游戏 ID:706450 写入磁盘。内存使用量:77856768

在时间 = 24 秒时将游戏 ID:546450 写入磁盘。内存使用量:77856768

在时间 = 24 秒时将游戏 ID:575350 写入磁盘。内存使用量:77856768

在时间 = 25 秒时将游戏 ID:616550 写入磁盘。内存使用量:77856768

在 time=26 秒时将游戏 id: 648250 写入磁盘。内存使用量:77856768

在时间 = 25 秒时将游戏 ID:763750 写入磁盘。内存使用量:77856768

在 time=26 秒时将游戏 id: 613850 写入磁盘。内存使用量:77856768

在时间 = 25 秒时将游戏 ID:645450 写入磁盘。内存使用量:77856768

在时间 = 33 秒时将游戏 ID:695950 写入磁盘。内存使用量:77856768

在时间 = 27 秒时将游戏 ID:661050 写入磁盘。内存使用量:77856768

在时间 = 27 秒时将游戏 ID:461050 写入磁盘。内存使用量:77856768

在时间 = 29 秒时将游戏 ID:693150 写入磁盘。内存使用量:77856768

谢谢!

4

2 回答 2

3

问题是您在$scrShots解析 XML 时没有清除外部循环。因此,每次迭代不仅包含当前游戏的屏幕截图,还包含之前所有游戏的屏幕截图。(这样,你从第一场比赛下载图像,然后从第一场比赛的图像加上第二场比赛的图像,然后从第一场比赛加上第二场比赛加上第三场比赛,依此类推,当然这需要越来越长的时间。)

在添加下一轮之前尝试清除数组:

$scrShots = array();
foreach($game->screenshots->screenshot_image as $image) {
    $scrShots[] = array(
    ...
于 2012-12-19T21:27:37.657 回答
0

除了 Wolfgang 发现的问题(主要问题)之外,您还错误地计算了时间(次要问题)。

Writing game id: 687250 to disk at time=1 seconds. Memory usage: 77856768
Writing game id: 633950 to disk at time=7 seconds. Memory usage: 77856768
Writing game id: 633850 to disk at time=2 seconds. Memory usage: 77856768

让我们假设 $start 从 1000 开始,每次迭代需要 1 秒

for($i = 0; $i < count($data); $i++) {
    $total += $now;
    $now = time() - $start - $total;

那么这将是您在每次循环迭代之后的值

1: $total: 0, $now: 1000 - 1000 - 0 = 0
2: $total: 0, $now: 1001 - 1000 - 0 = 1
3: $total: 1, $now: 1002 - 1000 - 1 = 1
4: $total: 1, $now: 1003 - 1000 - 1 = 2
5: $total: 2, $now: 1004 - 1000 - 2 = 2
6: $total: 2, $now: 1005 - 1000 - 2 = 3
7: $total: 3, $now: 1006 - 1000 - 3 = 3
7: $total: 3, $now: 1007 - 1000 - 3 = 4

这绝对不是你想要的。不知道您为什么使用总计来计算您的 $now。:)

我想这就是你想要的。

for($i = 0; $i < count($data); $i++) {
    $now = time() - $start;
    ...
}

$total = $now - $start;
于 2012-12-19T21:34:32.137 回答