10 月 23 - 25 日,QCon 上海站即将召开,现在购票,享9折优惠 了解详情
写点什么

Facebook 移动端照片预览背后的技术

  • 2015-08-14
  • 本文字数:1578 字

    阅读完需:约 5 分钟

当在 Facebook 移动端上浏览某个人的用户资料或页面时,首先看到的往往是图片。这些图片是构成 Facebook 体验不可缺少的一部分,但有时候,图片的下载与展示非常慢,在低速或移动网络中尤其如此。而在像印度这样的发展中国家市场上,许多 Facebook 新用户主要是使用 2G 网络。近日,Facebook 工程师 Brian K Cabral Edward Kandrot 撰文描述了Facebook 解决这一问题的过程。

封面照片是屏幕上最显眼的部分,但它也是加载最慢的部分之一。这主要有两个原因:一是封面照片的大小常常达到100KB,而2G 连接的传输速度可能只有32KB/ 秒;二是应用程序需要发送两个网络请求才能显示封面照片。它首先向 GraphQL 服务器发送请求,获得照片 URL,然后发送第二个网络请求,使用该 URL 从 CDN 获取照片。第二个网络请求的延迟相当长,比第一个长许多。

为了解决上述问题,他们希望能够由原照片生成一张 200 字节大小的效果图,然后将其作为 GraphQL 响应的一部分在第一次请求应答中直接返回,这样可以省掉第二次请求,极大地缩短用户资料和页首的显示延迟。当然,他们最终还是要从 CDN 下载完整照片并进行展示,但这可以在后台进行。至此,问题变成如何将照片压缩成 200 字节。

他们希望照片的效果图有一种磨砂玻璃的效果。这既有趣,又能与原始照片保持一致。磨砂玻璃效果采用高斯滤波器比较容易实现,而且图片越模糊,分辨率就越低,图片的尺寸就越小。不过,为了提供良好的用户体验,分辨率也不能太低。通过多次尝试,他们得出,42x42 的图片可以达到他们想要的效果,而分辨率再高一些并不会带来更好的效果。但是,即使只显示图片的DC 分量,每个像素仍然需要3 个字节,那么42x42x3 就是5292 字节,远远超出200 字节的目标。

他们开始评估标准的压缩技术,试图找出一种最好的方法,将数据压缩至200 字节。遗憾的是,只是对图片进行熵编码(比如 zlib )的话,只能将图片压缩一半,仍然太大。他们还评估了其它若干非标准技术,但最终,他们决定试一下 JPEG 图像编码。遗憾的是,JPEG 头本身就有几百个字节的大小。不过,去掉 JPEG 头,编码的数据有效负荷接近 200 字节。

于是,他们开始探索,JPEG 图片是否有可能使用一个固定的头,那样就可以将其存储在客户端,而不需要传输。JPEG 头包含多个表。在 Q 值一定的情况下,量化表是不变的。通过试验,他们发现,Q20 生成的图片可以满足他们的要求。虽然他们的图片不是固定尺寸,但基本上都限制在 42x42 以下。他们还仔细查看了 JPEG 头中的其它内容,发现只有 Huffman 表会随着图片的不同发生变化。Q 值、图片数据及图片尺寸决定着 Huffman 表中的频率值,每一项变化都会导致不同的压缩比和有效负荷字节数。他们在一组图片上进行了试验,并最终找出了一个可以作为标准的 Huffman 表。

虽然他们处理了大量的图片,但总有一些该方案不适用的情况。为此,他们增加了一个版本号。如果发现任何极端情况,或者未来发现了更好的 Huffman 表,那么他们就可以更新相关图片的版本号,并将新表发送给客户端。最终的格式包含一个字节的版本号、一个字节的宽度、一个字节的高度和大约 200 字节的有效负荷。服务器只将这一格式作为 GraphQL 响应的一部分发送,然后由客户端将 JPEG 体附加到预定义的 JPEG 头上,生成一个普通的 JPEG 图片。经过标准的 JPEG 解码后,客户端可以运行预定的高斯模糊,并拉伸其尺寸以适应窗口大小。

最终,他们获得一种可以满足需求的格式。在网速缓慢的情况下,这帮助他们将用户资料和页面加载时间缩短了 30%。而在网速非常快的情况下,这可以确保用户立即看到封面照片预览,提升了整体体验。


感谢徐川对本文的审校。

给InfoQ 中文站投稿或者参与内容翻译工作,请邮件至 editors@cn.infoq.com 。也欢迎大家通过新浪微博( @InfoQ @丁晓昀),微信(微信号: InfoQChina )关注我们,并与我们的编辑和其他读者朋友交流(欢迎加入 InfoQ 读者交流群)。

2015-08-14 08:398987
用户头像

发布了 1008 篇内容, 共 431.0 次阅读, 收获喜欢 346 次。

关注

评论

发布
暂无评论
发现更多内容

【崖山论“见”】YashanDB Meetup 第2期|数据库“大心脏”融合存储引擎揭秘

YashanDB

Markdown基础语法教程

进基的小张

学习 markdown markdown语法 markdown编辑器 基础

【问题排查篇】一次业务问题对 ES 的 cardinality 原理探究 | 京东云技术团队

京东科技开发者

ES 京东云 企业号 5 月 PK 榜

图像识别数据集的重要性及其分类

数据堂

PS 2020 photoshop绿色版

源字节1号

C++多线程编程和同步机制:详解和实例演示

小万哥

c++ 程序员 后端 多线程 同步

云原生典型应用架构

穿过生命散发芬芳

云原生架构 三周年连更

开源项目LuckyDraw分享&介绍

进基的小张

小程序 开源 开发 GitHub、 项目上线

async/await详解

不叫猫先生

JavaScript async/await 三周年连更

这8种常见的防火墙,分别有哪些优缺点?

wljslmz

防火墙 三周年连更

2023-05-05:给定一个无向、连通的树 树中有 n 个标记为 0...n-1 的节点以及 n-1 条边 。 给定整数 n 和数组 edges , edges[i] = [ai, bi]表示树中的

福大大架构师每日一题

golang 算法 rust

木兰汇专访 | 网心科技联合创始人马婷:创业者的“长期主义”

网心科技

Zebec生态发展进入加速期,拿好ZBC坐等价值兑现

股市老人

Java实现坦克大战1.0

timerring

Java

Java多线程基础

timerring

Java

LLMs 记忆体全新升级:六大新功能全面出击,用户体验值拉满!

Zilliz

大模型时代 向量数据库 zillizcloud LLMs

【分布式技术专题】「分布式技术架构」手把手教你如何开发一个属于自己的限流器RateLimiter功能服务

码界西柚

分布式 限流器 三周年连更 动手实现 RateLimter

Zebec生态发展进入加速期,拿好ZBC坐等价值兑现

西柚子

服务网格(Service Mesh)是什么?

乌龟哥哥

三周年连更

Flink应用开发

阿泽🧸

flink 三周年连更

matlab实现通信原理

袁袁袁袁满

三周年连更

Kafka性能测试初探

FunTester

海泰方圆《数字政府密码应用与数据安全合规性建设指南》顺利通过评审

电子信息发烧客

Shell脚本的变量

芯动大师

Shell命令 三周年连更 shell变量

手把手教会你 | 网络编程

TiAmo

socket通信 服务器编程 单用户模式

1分钟学会、3分钟上手、5分钟应用,快速上手责任链框架详解 | 京东云技术团队

京东科技开发者

Netty 京东云 企业号 5 月 PK 榜

2 行代码开启 SAST,将代码漏洞定位到具体行数

极狐GitLab

DevOps DevSecOps SAST 应用安全测试 安全扫描

ChatGPT 何时替代码农?

酱紫的小白兔

码农 机器人 ChatGPT

《AGI时代的破局之道 | 社区征文》

后台技术汇

三周年征文

下载LORA模型

IT蜗壳-Tango

三周年连更

Facebook移动端照片预览背后的技术_Meta_谢丽_InfoQ精选文章