Php 显示1x1 GIF(跟踪像素、网络信标)的最有效方式
我正在构建一个基本的分析服务,理论上基于Google analytics的工作原理,但是我没有请求实际的图像,而是将图像请求路由到一个脚本,该脚本接受数据,然后输出图像。由于浏览器在每次加载时都会请求此图像,因此每毫秒都很重要 我正在寻找一个文件从PHP脚本输出gif文件的最有效方法。到目前为止,我已经确定了3种主要方法 有没有更有效的方法从PHP脚本中输出1x1 GIF文件?如果不是,以下哪项是最高效和可扩展的? 三种确定的方法 PHP图像构建库Php 显示1x1 GIF(跟踪像素、网络信标)的最有效方式,php,javascript,image,performance,analytics,Php,Javascript,Image,Performance,Analytics,我正在构建一个基本的分析服务,理论上基于Google analytics的工作原理,但是我没有请求实际的图像,而是将图像请求路由到一个脚本,该脚本接受数据,然后输出图像。由于浏览器在每次加载时都会请求此图像,因此每毫秒都很重要 我正在寻找一个文件从PHP脚本输出gif文件的最有效方法。到目前为止,我已经确定了3种主要方法 有没有更有效的方法从PHP脚本中输出1x1 GIF文件?如果不是,以下哪项是最高效和可扩展的? 三种确定的方法 PHP图像构建库 $im = imagecreatetrueco
$im = imagecreatetruecolor(1, 1);
imagefilledrectangle($im, 0, 0, 0, 0, 0xFb6b6F);
header('Content-Type: image/gif');
imagegif($im);
imagedestroy($im);
文件\u获取\u内容
服务器上的图像并将其输出
$im = file_get_contents('raw.gif');
header('Content-Type: image/gif');
echo $im;
base64\u解码图像
header('Content-Type: image/gif');
echo base64_decode("R0lGODdhAQABAIAAAPxqbAAAACwAAAAAAQABAAACAkQBADs=");
(我的直觉是base64将是最快的,但我不知道该功能的资源密集度有多高;而且由于它添加了另一个文件系统操作,文件内容的扩展性可能会较差。)
作为参考,我使用的GIF如下:
编辑
因此,我提供此图像的原因是我的分析库构建了一个查询字符串并将其附加到此图像请求。我没有解析日志,而是将请求路由到一个PHP脚本,该脚本处理数据并用图像响应,这样最终用户的浏览器就不会挂起或抛出错误。我的问题是,如何在脚本的范围内最好地服务于该图像
header('Content-Type: image/gif');
header("Content-Length: " . filesize("image.gif"));
$f = fopen('image.gif', 'rb');
fpassthru($f);
fclose($f);
对于磁盘上的映像,可能是最快的,但是(特别是如果您使用字节码缓存),对于预先知道的小映像,我认为base64方式将是最快的。发送内容长度
也可能是一个好主意,对于小图像,浏览器在大多数情况下不会在收到字节后等待任何内容,因此虽然服务器会花费同样多的时间,但使用体验会明显更好
另一种方法是让Apache/lighttpd/nginx为映像提供服务,记录访问和脱机解析 也许吧
header('Content-Type: image/gif');
//equivalent to readfile('pixel.gif')
echo "\x47\x49\x46\x38\x37\x61\x1\x0\x1\x0\x80\x0\x0\xfc\x6a\x6c\x0\x0\x0\x2c\x0\x0\x0\x0\x1\x0\x1\x0\x0\x2\x2\x44\x1\x0\x3b";
这将输出与1x1透明gif的二进制文件内容相同的二进制字符串。我声称这是有效的,因为它不做任何缓慢的IO,比如读取文件,也不调用任何函数
如果您想制作上述十六进制字符串的自己版本,也许是为了更改颜色,您可以使用它为echo语句生成php代码
printf('echo "%s";', preg_replace_callback('/./s', function ($matches) {
return '\x' . dechex(ord($matches[0]));
}, file_get_contents('https://upload.wikimedia.org/wikipedia/en/d/d0/Clear.gif')));
与其动态生成/输出图像,为什么不直接重定向到静态图像
<?php
// process query param stuff
header('Location: pixel.gif');
exit();
?>
使用Laravel:
$pixel = "\x47\x49\x46\x38\x39\x61\x1\x0\x1\x0\x80\x0\x0\xff\xff\xff\x0\x0\x0\x21\xf9\x4\x1\x0\x0\x0\x0\x2c\x0\x0\x0\x0\x1\x0\x1\x0\x0\x2\x2\x44\x1\x0\x3b";
return response($pixel,200,[
'Content-Type' => 'image/gif',
'Content-Length' => strlen($pixel),
]);
如果有人出于某种原因想要的话
或者,如果您不喜欢代码中的长(ish)十六进制字符串:
base64_decode('R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw')
如果您的目的真的是提供1x1像素的GIF,只需让您的Web服务器静态提供即可。如果您真的想为一个更大的、动态构造的映像提供服务,那么您也应该使用代表性数据进行基准测试。@保存Internet很难模拟成百上千个查询的效果,但是是的,一些基准测试可能是合适的。我也在问是否还有其他可能更好的方法。@Thomas 1x1图像只是为了不挂起请求;我将分析信息附加到请求的查询字符串,并将其用作数据收集的基础。我实际上没有在页面中使用图像。这是Google Analytics使用的方法,它比其他一些选项(即隐藏的iframe)更加优雅和高效。@yc:好吧,你仍然可以通过Web服务器提供服务,并在后台分析日志。。。我现在明白了。我以为你在画图表什么的。不要介意!嗯,增加内容长度会使整个系统的加载时间减少10%+1个月的时间。:)是的,考虑到伐木路线。如果我这样做,我可能会切换到S3以提高性能并使用它们的日志记录。这绝对是一个选项。在测试它之前,我的直觉是,这可能效率较低。这将强制浏览器发出第二个HTTP请求(因为第一个请求将是302/301'ed)。额外的HTTP请求通常对性能非常不利。为什么它应该是最好的解决方案?这根绳子是什么?请改进这个答案…非常好的解决方案。一个小问题是生成的gif不透明。。。如何从现有的gif文件中生成这样的字符串?PHP中的“\x1”
是“\x01”
的缩写吗?我正在尝试将这个像素调整为Python,它似乎不支持单位数十六进制代码。@CarlG是的。只是为了确定一下。文档在x
之后明确指出1或2个字符。FWIWbase64_decode
比我在速度测试中编码的十六进制字符串慢5倍