您的位置:首页 > 运维架构 > Nginx

Nginx初步-5:用SWIG为PHP写个C++的扩展

2013-12-29 17:11 316 查看
PHP-GD的性能

在写这章之前,先运行一段PHP脚本。如下:

$src = "test.jpg"; // 图像优化里用到的图片
$dst = "upload/gray.jpg"; // 保存的结果
$totalTime = 0;
$testCount = 32; // 只能用这么小的值,否则运行超过30秒
$count = 0;

// 尝试使用PHP-GD
for($i = 0; $i < $testCount; $i++)
{
	$start = getNanos();
	$im = imagecreatefromjpeg($src);
	
	imagefilter($im, IMG_FILTER_GRAYSCALE);	
	
	imagegd($im, $dst);
	
	imagedestroy($im);
	$stop = getNanos();

	$time = (max($start, $stop) - min($start, $stop)) / (1000 * 1000);

	if ($time > 500.0)
	{
		//continue;
	}
	else
	{
		$count++;

		$totalTime += $time;
	}
}

if ($count == 0)
	$count = 1;

echo "Perf:" . $totalTime / $count . "ms<br />";


先不要管getNano(),这个在后面会给出实现。这段程序运行的结果表明,对于test.jpg这样图片处理,GD需要差不多半秒。这个性能不能说很差,毕竟对大图的直接操作很少见。但想想《图像处理的简单优化》中得出的结果,GD还是很不给力。所以,就需要将快速的处理引入到PHP中,也就需要用到swig了。

编写PHP的扩展,提升性能

毫无疑问,这个扩展要命名为igame。

仿照GD的函数,简单定义了swig的接口文件,如下所示:

%module igame

%include <const.i>
%include <std_string.i>

%{
	
#include "igame.h"
#include "image.h"

unsigned int getNanos();
int grayscaleJpeg(char* src, char* dst);

Image* createImageFromJpeg(const std::string& filename);
Image* createImageJpeg(unsigned int width, unsigned int height);
int applyImageEffect(Image* img);
int imageSaveAsJpeg(Image* img, const std::string& filename);
void destroyImage(Image* img);
%}

extern unsigned int getNanos();
extern int grayscaleJpeg(char* src, char* dst);

class Image
{
public:
	Image();
	Image(unsigned int width, unsigned int height);
	Image(const std::string& filename);
	virtual ~Image();

public:
	virtual bool create(unsigned int width, unsigned int height);
	virtual bool save(const std::string& filename) = 0;
	virtual bool load(const std::string& filename) = 0;
	virtual bool close();
	virtual bool available();
	virtual unsigned int width();
	virtual unsigned int height();
	virtual unsigned int stride();
	virtual unsigned int bytesPerPixel();
	virtual bool applyEffect(Effect* effect);
}; // class

extern Image* createImageFromJpeg(const std::string& filename);
extern Image* createImageJpeg(unsigned int width, unsigned int height);
extern int applyImageEffect(Image* img);
extern int imageSaveAsJpeg(Image* img, const std::string& filename);
extern void destroyImage(Image* img);


注意,这里的Image类导出有问题,无法调用类的方法。后续再处理吧,现在用做容器还是可以的。

实现文件如下:

igame.h

#ifndef IGAME_H
#define IGAME_H

#include "image.h"

unsigned int getNanos();
int grayscaleJpeg(char* src, char* dst);
Image* createImageFromJpeg(const std::string& filename);
Image* createImageJpeg(unsigned int width, unsigned int height);
int applyImageEffect(Image* img);
int imageSaveAsJpeg(Image* img, const std::string& filename);
void destroyImage(Image* img);
#endif
igame.cpp

#include "igame.h"
#include "jpeg.h"
#include "grayscale.h"

#include <time.h>

unsigned int getNanos()
{
	struct timespec time;

	clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &time);

	return time.tv_sec * 1000 * 1000 + time.tv_nsec;
}

int grayscaleJpeg(char* src, char* dst)
{
	Jpeg myjpg;

	if (myjpg.load(src))
	{
		Grayscale grayscale;

		if (myjpg.applyEffect(&grayscale))
		{
			if (myjpg.save(dst))
				return true;
		}
	}

	return false;
}

Image* createImageFromJpeg(const std::string& filename)
{
	return new Jpeg(filename);
}

Image* createImageJpeg(unsigned int width, unsigned int height)
{
	return new Jpeg(width, height);
}

int applyImageEffect(Image* img)
{
	Grayscale grayscale;
	return img->applyEffect(&grayscale);
}

int imageSaveAsJpeg(Image* img, const std::string& filename)
{
	return img->save(filename);
}

void destroyImage(Image* img)
{
	delete img;
}


修改PHP.INI,使之能够使用扩展包。再编写相同的测试页面,最后得出结果:136.494ms。大致是GD的3倍多。

相较于GD的可怜性能,这才是自己开发扩展的用意。

完整的eclipse工程可以从这里下载
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: