intervention/image 中的一個小坑及其破解之法

田勇發表於2017-11-13

事實上 intervention/iamge 用了很有些時日了,它的 api 設計得很簡潔,文件也很全面,用起來相當順手。

不過最近無意間發現了一個小坑。因為需要合成帶微信頭像的二維碼,我使用 Image::make($avatarUrl) (這裡的 $avatarUrl 是微信頭像的連結)來產生頭像,然後合成到二維碼影像中去(還包括一些其它操作,比如使用模板背景、寫入文字)。

寫完之後一執行,發現相當慢,平均耗時 23 秒左右。起初以為是因為合成過程中進行的操作比較多、尺寸比較大,本來就應該是這個速度。不過後來閒下來,開始試著優化,即使不能提升速度,至少也搞清楚到底是什麼原因這麼耗時。

這一通折騰下來,發現真相竟然與合成操作的多少、尺寸沒有多大關係。而關鍵在於我建立頭像資料的姿勢。

為了說明這個問題,特意寫了下面的程式碼進行對比。

// 記錄開始時間
$startTimestamp = microtime(true);

$url = 'http://wx.qlogo.cn/mmopen/XxT9TiaJ1ibf06TNRCMjQADS4opDHvQLguLZHpqkRlvuJYZicvJW4iaOalPsKIs0kpZ3F6864ZzibyObYiaucUQSrdp4pFTNDyIpxw/0';

$avatar = \Image::make($url);

// 記錄結束時間
$endTimestamp = microtime(true);

info($startTimestamp);
info($endTimestamp);
info($endTimestamp - $startTimestamp);

file

上面這段程式碼使用 Image::make($url) 的形式,直接從 url 生成頭像。從記錄的日誌資料來看,耗時基本上在 16 秒左右。

後來,想到了一個新姿勢,其實也就是在嘗試優化的過程中折騰時想到的。見下面程式碼:

$startTimestamp = microtime(true);

$client = new \GuzzleHttp\Client();

$url = 'http://wx.qlogo.cn/mmopen/XxT9TiaJ1ibf06TNRCMjQADS4opDHvQLguLZHpqkRlvuJYZicvJW4iaOalPsKIs0kpZ3F6864ZzibyObYiaucUQSrdp4pFTNDyIpxw/0';

$avatarResponse = $client->get($url);

$avatar = \Image::make($avatarResponse->getBody()->getContents());

$endTimestamp = microtime(true);

info($startTimestamp);
info($endTimestamp);
info($endTimestamp - $startTimestamp);

在這裡我先使用 GuzzleHttp 獲取頭像,再使用 Image::make($data) 建立頭像。

注意,要高潮了…… :sunglasses:

看看下面的日誌截圖,三次平均耗時在 0.07 秒左右,和前面的 16 秒相比,差了 200 多倍。
file

至於為什麼會出現這種現象,自己也沒搞清楚,但這無疑是一點比較有用且小眾的經驗。

相關文章