Hi and marry christmas.
Working on a problem on FreeBSD hosting i see a big difference in the processing through the php5-gd extension. As i browse source code of php5-gd - nothing Linux-specified code.
To demonstrate, I specifically created a large jpeg file and upload to http://81.176.66.218/test1.jpg (8 MB)
Both station (FreeBSD and Linux) is 64-bit, php5-gd compiling identically (t1lib, truetype support..)
On the Linux host:
imgresize.php php.ini
linux:/tmp/test$ wget http://81.176.66.218/test1.jpg
Result: All perfect - Linux take 700 Kbytes only.
Ok, FreeBSD host now:
Result: Fatal error, not enough memory ;(
examining the system calls, see only that both machines use the mmap(2) (Linux - mmap2(2)). But FreeBSD is not asked getrlimit(2) limits and does not use brk(2). On the other hand - the file has only 8 megabytes - that's not enough for the projection of a memory or a problem elsewhere?
Linux syscall: http://81.176.66.218/straceme.log
FreeBSD syscall: http://81.176.66.218/trussme.log
PS: I try three FreeBSD hosts for test: - 7.4 amd64, 8.2 amd64 and 9.0-current (snap from 10/26/2010). Different versions of PHP in BSD also try: php4 + php4-gd, php52 + php52-gd, php5-php5-gd - ports on the 26.10.2010. But with no difference.
PS2: Content of imgresize.php
Working on a problem on FreeBSD hosting i see a big difference in the processing through the php5-gd extension. As i browse source code of php5-gd - nothing Linux-specified code.
To demonstrate, I specifically created a large jpeg file and upload to http://81.176.66.218/test1.jpg (8 MB)
Both station (FreeBSD and Linux) is 64-bit, php5-gd compiling identically (t1lib, truetype support..)
On the Linux host:
$ ls
imgresize.php php.ini
$ grep ^memory_limit php.ini
Code:
memory_limit = 32M
$ php -v
Code:
PHP 5.3.3-1ubuntu9.1 with Suhosin-Patch (cli) (built: Oct 15 2010 14:00:18)
Copyright (c) 1997-2009 The PHP Group
Zend Engine v2.3.0, Copyright (c) 1998-2010 Zend Technologies
$ strace -o /tmp/straceme.log php -c ./php.ini imgresize.php test1.jpg
Code:
crop: Memory usage: 679752
Memory usage: 675784
Memory peak usage: 767856
$ uname -rm
Code:
2.6.35-24-generic x86_64
$ cat /etc/lsb-release
Code:
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=10.10
DISTRIB_CODENAME=maverick
DISTRIB_DESCRIPTION="Ubuntu 10.10"
Result: All perfect - Linux take 700 Kbytes only.
Ok, FreeBSD host now:
# grep ^memory php.ini
Code:
memory_limit = 288M
# truss -o /tmp/trussme.log php -c ./php.ini imgresize.php test1.jpg
Code:
PHP Fatal error: Allowed memory size of 301989888 bytes exhausted (tried to allocate 18892 bytes) in /tmp/test/imgresize.php on line 49
Result: Fatal error, not enough memory ;(
examining the system calls, see only that both machines use the mmap(2) (Linux - mmap2(2)). But FreeBSD is not asked getrlimit(2) limits and does not use brk(2). On the other hand - the file has only 8 megabytes - that's not enough for the projection of a memory or a problem elsewhere?
Linux syscall: http://81.176.66.218/straceme.log
FreeBSD syscall: http://81.176.66.218/trussme.log
PS: I try three FreeBSD hosts for test: - 7.4 amd64, 8.2 amd64 and 9.0-current (snap from 10/26/2010). Different versions of PHP in BSD also try: php4 + php4-gd, php52 + php52-gd, php5-php5-gd - ports on the 26.10.2010. But with no difference.
PS2: Content of imgresize.php
Code:
<?php
function resize($img, $preset, $recache=false) {
$imginfo = pathinfo($img);
//Check if GD extension is loaded
if (!extension_loaded('gd') && !extension_loaded('gd2')){
trigger_error("GD is not loaded", E_USER_WARNING);
return false;
}
$newfilename='';
$preset['addpath'] = isset($preset['addpath'])?$preset['addpath']:'';
$newfilename = '/tmp/'.$imginfo['basename'];
//Get Image size info
list($width_orig, $height_orig, $image_type) = getimagesize($img);
switch ($image_type) {
case 1: $im = imagecreatefromgif($img); break;
case 2: $im = imagecreatefromjpeg($img); break;
case 3: $im = imagecreatefrompng($img); break;
default:
$err = 'Unsupported filetype: ' . $img;
trigger_error($err, E_USER_WARNING);
throw new Exception($err);
break;
}
if (!$im) {
return false;
}
if ($preset['height'] == 'auto') {
$aspect_ratio = (float) $width_orig / $preset['width'];
$preset['height'] = ceil($height_orig / $aspect_ratio);
}
if (isset($preset['maxheight']) && $preset['height'] > $preset['maxheight']) {
$preset['height'] = $preset['maxheight'];
}
if (isset($preset['maxwidth']) && $preset['width'] > $preset['maxwidth']) {
$preset['width'] = $preset['maxwidth'];
}
$ratio = array($width_orig / $height_orig, $preset['width'] / $preset['height']);
if ($ratio[0] != $ratio[1] && isset($preset['crop']) && $preset['crop'] == 1)
{
$scale = min((float)($width_orig / $preset['width']), (float)($height_orig / $preset['height']));
$cropX = (float)($width_orig - ($scale * $preset['width']));
$cropY = (float)($height_orig - ($scale * $preset['height']));
// cropped image size
$cropW = (float)($width_orig - $cropX);
$cropH = (float)($height_orig - $cropY);
$crop = ImageCreateTrueColor($cropW, $cropH);
// crop the middle part of the image to fit proportions
ImageCopy($crop, $im, 0, 0, (int)($cropX / 2), (int)($cropY / 2), $cropW, $cropH);
echo "crop: Memory usage: " . memory_get_usage() . "\n";
}
$newImg = imagecreatetruecolor($preset['width'], $preset['height']);
/* Check if this image is PNG or GIF, then set if Transparent*/
if(($image_type == 1) OR ($image_type==3))
{
imagealphablending($newImg, false);
imagesavealpha($newImg,true);
$transparent = imagecolorallocatealpha($newImg, 255, 255, 255, 127);
imagefilledrectangle($newImg, 0, 0, $preset['width'], $preset['height'], $transparent);
}
if (isset($crop)) { // been cropped
ImageCopyResampled($newImg, $crop, 0, 0, 0, 0, $preset['width'], $preset['height'], $cropW, $cropH);
ImageDestroy($crop);
} else {
imagecopyresampled($newImg, $im, 0, 0, 0, 0, $preset['width'], $preset['height'], $width_orig, $height_orig);
}
//Generate the file, and rename it to $newfilename
switch ($image_type)
{
case 1: $result = imagegif($newImg,$newfilename); break;
case 2: $result = imagejpeg($newImg,$newfilename); break;
case 3: $result = imagepng($newImg,$newfilename); break;
default: trigger_error('Failed resize image!', E_USER_WARNING); break;
}
if (!@$result) {
//trigger_error("cacher error saving image", E_USER_WARNING);
return false;
}
//cacher::imageServersUploadQueue($newfilename);
return $newfilename;
}
$preset = array(
'width' => 168,
'height' => 'auto',
'maxheight' => 300,
'crop' => 1,
'addpath' => 'upic168',
'name' => 'avatar'
);
if (!file_exists($argv[1])) {
echo "Gimme filename\n";
die();
}
resize($argv[1], $preset, true);
echo "Memory usage: " . memory_get_usage() . "\n";
echo "Memory peak usage: " . memory_get_peak_usage() . "\n";