Browsed by
分类:English

好烂啊有点差凑合看看还不错很精彩 (No Ratings Yet)
Loading...
48 views
左耳朵耗子给出的学习指南

左耳朵耗子给出的学习指南

你是否觉得自己从学校毕业的时候只做过小玩具一样的程序?走入职场后哪怕没有什么经验也可以把以下这些课外练习走一遍(朋友的抱怨:学校课程总是从理论出发,作业项目都看不出有什么实际作用,不如从工作中的需求出发)

建议:

· 不要乱买书,不要乱追新技术新名词,基础的东西经过很长时间积累而且还会在未来至少10年通用。

· 回顾一下历史,看看历史上时间线上技术的发展,你才能明白明天会是什么样。

· 一定要动手,例子不管多么简单,建议至少自己手敲一遍看看是否理解了里头的细枝末节。

· 一定要学会思考,思考为什么要这样,而不是那样。还要举一反三地思考。

注:你也许会很奇怪为什么下面的东西很偏Unix/Linux,这是因为我觉得Windows下的编程可能会在未来很没有前途,原因如下:

· 现在的用户界面几乎被两个东西主宰了,1)Web,2)移动设备iOS或Android。Windows的图形界面不吃香了。

· 越来越多的企业在用成本低性能高的Linux和各种开源技术来构架其系统,Windows的成本太高了。

· 微软的东西变得太快了,很不持久,他们完全是在玩弄程序员。详情参见《Windows编程革命史

所以,我个人认为以后的趋势是前端是Web+移动,后端是Linux+开源。开发这边基本上没Windows什么事。

启蒙入门

1、 学习一门脚本语言,例如Python/Ruby

可以让你摆脱对底层语言的恐惧感,脚本语言可以让你很快开发出能用得上的小程序。实践项目:

· 处理文本文件,或者csv (关键词 python csv, python open, python sys) 读一个本地文件,逐行处理(例如 word count,或者处理log)

· 遍历本地文件系统 (sys, os, path),例如写一个程序统计一个目录下所有文件大小并按各种条件排序并保存结果

· 跟数据库打交道 (python sqlite),写一个小脚本统计数据库里条目数量

· 学会用各种print之类简单粗暴的方式进行调试

· 学会用Google (phrase, domain, use reader to follow tech blogs)

为什么要学脚本语言,因为他们实在是太方便了,很多时候我们需要写点小工具或是脚本来帮我们解决问题,你就会发现正规的编程语言太难用了。

2、 用熟一种程序员的编辑器(不是IDE) 和一些基本工具

· Vim / Emacs / Notepad++,学会如何配置代码补全,外观,外部命令等。

· Source Insight (或 ctag)

使用这些东西不是为了Cool,而是这些编辑器在查看、修改代码/配置文章/日志会更快更有效率。

3、 熟悉Unix/Linux Shell和常见的命令行

· 如果你用windows,至少学会用虚拟机里的linux, vmware player是免费的,装个Ubuntu吧

· 一定要少用少用图形界面。

· 学会使用man来查看帮助

· 文件系统结构和基本操作 ls/chmod/chown/rm/find/ln/cat/mount/mkdir/tar/gzip …

· 学会使用一些文本操作命令 sed/awk/grep/tail/less/more …

· 学会使用一些管理命令 ps/top/lsof/netstat/kill/tcpdump/iptables/dd…

· 了解/etc目录下的各种配置文章,学会查看/var/log下的系统日志,以及/proc下的系统运行信息

· 了解正则表达式,使用正则表达式来查找文件。

对于程序员来说Unix/Linux比Windows简单多了。(参看我四年前CSDN的博文《其实Unix很简单》)学会使用Unix/Linux你会发现图形界面在某些时候实在是太难用了,相当地相当地降低工作效率。

4、 学习Web基础(HTML/CSS/JS) + 服务器端技术 (LAMP)

未来必然是Web的世界,学习WEB基础的最佳网站是W3School

· 学习HTML基本语法

· 学习CSS如何选中HTML元素并应用一些基本样式(关键词:box model)

· 学会用  Firefox + Firebug 或 chrome 查看你觉得很炫的网页结构,并动态修改。

· 学习使用 Javascript操纵HTML元件。理解DOM和动态网页(http://oreilly.com/catalog/9780596527402) 网上有免费的章节,足够用了。或参看 DOM 。

· 学会用  Firefox + Firebug 或 chrome 调试 Javascript代码(设置断点,查看变量,性能,控制台等)

· 在一台机器上配置Apache或 Nginx

· 学习PHP,让后台PHP和前台HTML进行数据交互,对服务器相应浏览器请求形成初步认识。实现一个表单提交和反显的功能。

· 把PHP连接本地或者远程数据库 MySQL(MySQL 和 SQL现学现用够了)

· 跟完一个名校的网络编程课程(例如:http://www.stanford.edu/~ouster/cgi-bin/cs142-fall10/index.php ) 不要觉得需要多于一学期时间,大学生是全职一学期选3-5门课,你业余时间一定可以跟上

· 学习一个 javascript库(例如jQuery 或 ExtJS)+  Ajax (异步读入一个服务器端图片或者

· 做个小网数据库内容)+JSON数据格式。

· HTTP: The Definitive Guide 读完前4章你就明白你每天上网用浏览器的时候发生的事情了(proxy, gateway, browsers)

· 站(例如:一个小的留言板,支持用户登录,Cookie/Session,增、删、改、查,上传图片附件,分页显示)

· 买个域名,租个空间,做个自己的网站。

进阶加深

1、 C语言和操作系统调用

· 重新学C语言,理解指针和内存模型,用C语言实现一下各种经典的算法和数据结构。推荐《计算机程序设计艺术》、《算法导论》和《编程珠玑》。

· 学习(麻省理工免费课程)计算机科学和编程导论

· 学习(麻省理工免费课程)C语言内存管理

· 学习Unix/Linux系统调用(Unix高级环境编程),,了解系统层面的东西。

o 用这些系统知识操作一下文件系统,用户(实现一个可以拷贝目录树的小程序)

o 用fork/wait/waitpid写一个多进程的程序,用pthread写一个多线程带同步或互斥的程序。多进程多进程购票的程序。

o 用signal/kill/raise/alarm/pause/sigprocmask实现一个多进程间的信号量通信的程序。

o 学会使用gcc和gdb来编程和调试程序(参看我的《用gdb调试程序》)

o 学会使用makefile来编译程序。(参看我的《跟我一起写makefile》)

o IPC和Socket的东西可以放到高级中来实践。

· 学习Windows SDK编程(Windows 程序设计 MFC程序设计

o 写一个窗口,了解WinMain/WinProcedure,以及Windows的消息机制。

o 写一些程序来操作Windows SDK中的资源文件或是各种图形控件,以及作图的编程。

o 学习如何使用MSDN查看相关的SDK函数,各种WM_消息以及一些例程。

o 这本书中有很多例程,在实践中请不要照抄,试着自己写一个自己的例程。

o 不用太多于精通这些东西,因为GUI正在被Web取代,主要是了解一下Windows 图形界面的编程。@virushuo 说:“ 我觉得GUI确实不那么热门了,但充分理解GUI工作原理是很重要的。包括移动设备开发,如果没有基础知识仍然很吃力。或者说移动设备开发必须理解GUI工作,或者在win那边学,或者在mac/iOS上学”。

2、学习 Java

·  Java 的学习主要是看经典的Core  Java 《 Java 核心技术编程》和《 Java编程思想》(有两卷,我仅链了第一卷,足够了,因为 Java的图形界面了解就可以了)

· 学习JDK,学会查阅 Java API Doc http://download.oracle.com/ javase/6/docs/api/

· 了解一下 Java这种虚拟机语言和C和Python语言在编译和执行上的差别。从C、 Java、Python思考一下“跨平台”这种技术。

· 学会使用IDE Eclipse,使用Eclipse 编译,调试和开发 Java程序。

· 建一个Tomcat的网站,尝试一下JSP/Servlet/JDBC/MySQL的Web开发。把前面所说的那个PHP的小项目试着用JSP和Servlet实现一下。

3、Web的安全与架构

· 学习HTML5,网上有很多很多教程,以前酷壳也介绍过很多,我在这里就不罗列了。

· 学习Web开发的安全问题(参考新浪微博被攻击的这个事,以及Ruby的这篇文章

· 学习HTTP Server的rewrite机制,Nginx的反向代理机制,fast-cgi(如:PHP-FPM

· 学习Web的静态页面缓存技术。

· 学习Web的异步工作流处理,数据Cache,数据分区,负载均衡,水平扩展的构架。

实践任务:

o 使用HTML5的canvas 制作一些Web动画。

o 尝试在前面开发过的那个Web应用中进行SQL注入,JS注入,以及XSS攻击。

o 把前面开发过的那个Web应用改成构造在Nginx + PHP-FPM + 静态页面缓存的网站

4、学习关系型数据库

· 你可以安装MSSQLServer或MySQL来学习数据库。

· 学习教科书里数据库设计的那几个范式,1NF,2NF,3NF,……

· 学习数据库的存过,触发器,视图,建索引,游标等。

· 学习SQL语句,明白表连接的各种概念(参看《SQL  Join的图示》)

· 学习如何优化数据库查询(参看《MySQL的优化》)

· 实践任务:设计一个论坛的数据库,至少满足3NF,使用SQL语句查询本周,本月的最新文章,评论最多的文章,最活跃用户。

5、一些开发工具

· 学会使用SVN或Git来管理程序版本。

· 学会使用JUnit来对 Java进行单元测试。

· 学习C语言和 Java语言的coding standard 或 coding guideline。(我N年前写过一篇关C语言非常简单的文章——《编程修养》,这样的东西你可以上网查一下,一大堆)。

· 推荐阅读《代码大全》《重构》《代码整洁之道

高级深入

1、C++ /  Java 和面向对象

我个人以为学好C++, Java也就是举手之劳。但是C++的学习曲线相当的陡。不过,我觉得C++是最需要学好的语言了。参看两篇趣文“C++学习信心图” 和“21天学好C++

· 学习(麻省理工免费课程)C++面向对象编程

· 读我的 “如何学好C++”中所推荐的那些书至少两遍以上(如果你对C++的理解能够深入到像我所写的《C++虚函数表解析》或是《C++对象内存存局)()》,或是《C/C++返回内部静态成员的陷阱》那就非常不错了)

· 然后反思为什么C++要干成这样, Java则不是?你一定要学会对比C++和 Java的不同。比如, Java中的初始化,垃圾回收,接口,异常,虚函数,等等。

实践任务:

o 用C++实现一个BigInt,支持128位的整形的加减乘除的操作。

o 用C++封装一个数据结构的容量,比如hash table。

o 用C++封装并实现一个智能指针(一定要使用模板)。

· 《设计模式》必需一读,两遍以上,思考一下,这23个模式的应用场景。主要是两点:1)钟爱组合而不是继承,2)钟爱接口而不是实现。(也推荐《深入浅出设计模式》)

实践任务:

o 使用工厂模式实现一个内存池。

o 使用策略模式制做一个类其可以把文本文件进行左对齐,右对齐和中对齐。

o 使用命令模式实现一个命令行计算器,并支持undo和redo。

o 使用修饰模式实现一个酒店的房间价格订价策略——旺季,服务,VIP、旅行团、等影响价格的因素。

· 学习STL的用法和其设计概念  – 容器,算法,迭代器,函数子。如果可能,请读一下其源码。

· 实践任务:尝试使用面向对象、STL,设计模式、和WindowsSDK图形编程的各种技能

o 做一个贪吃蛇或是俄罗斯方块的游戏。支持不同的级别和难度。

o 做一个文件浏览器,可以浏览目录下的文件,并可以对不同的文件有不同的操作,文本文件可以打开编辑,执行文件则执行之,mp3或avi文件可以播放,图片文件可以展示图片。

· 学习C++的一些类库的设计,如: MFC(看看候捷老师的《深入浅出MFC》) ,Boost, ACE,  CPPUnit,STL (STL可能会太难了,但是如果你能了解其中的设计模式和设计那就太好了,如果你能深入到我写的《STL string类的写时拷贝技术》那就非常不错了,ACE需要很强在的系统知识,参见后面的“加强对系统的了解”)

·  Java是真正的面向对象的语言, Java的设计模式多得不能再多,也是用来学习面向对象的设计模式的最佳语言了(参看 Java中的设计模式)。

· 推荐阅读《Effective  Java》 and 《 Java解惑》

· 学习 Java的框架, Java的框架也是多,如Spring, Hibernate,Struts 等等,主要是学习 Java的设计,如IoC等。

·  Java的技术也是烂多,重点学习J2EE架构以及JMS, RMI, 等消息传递和远程调用的技术。

· 学习使用 Java做Web Service (官方教程在这里

· 实践任务:尝试在Spring或Hibernate框架下构建一个有网络的Web Service的远程调用程序,并可以在两个Service中通过JMS传递消息。

C++和 Java都不是能在短时间内能学好的,C++玩是的深, Java玩的是广,我建议两者选一个。我个人的学习经历是:

· 深究C++(我深究C/C++了十来年了)

· 学习 Java的各种设计模式。

2、加强系统了解

重要阅读下面的几本书:

· 《Unix编程艺术》了解Unix系统领域中的设计和开发哲学、思想文化体系、原则与经验。你一定会有一种醍醐灌顶的感觉。

· 《Unix网络编程卷1,套接字》这是一本看完你就明白网络编程的书。重要注意TCP、UDP,以及多路复用的系统调用select/poll/epoll的差别。

· 《TCP/IP详解 卷1:协议》- 这是一本看完后你就可以当网络黑客的书。了解以太网的的运作原理,了解TCP/IP的协议,运作原理以及如何TCP的调优。

实践任务:

o 理解什么是阻塞(同步IO),非阻塞(异步IO),多路复用(select, poll, epoll)的IO技术。

o 写一个网络聊天程序,有聊天服务器和多个聊天客户端(服务端用UDP对部分或所有的的聊天客户端进Multicast或Broadcast)。

o 写一个简易的HTTP服务器。

· 《Unix网络编程卷2,进程间通信》信号量,管道,共享内存,消息等各种IPC…… 这些技术好像有点老掉牙了,不过还是值得了解。

实践任务:

o 主要实践各种IPC进程序通信的方法。

o 尝试写一个管道程序,父子进程通过管道交换数据。

o 尝试写一个共享内存的程序,两个进程通过共享内存交换一个C的结构体数组。

· 学习《Windows核心编程》一书。把CreateProcess,Windows线程、线程调度、线程同步(Event,  信号量,互斥量)、异步I/O,内存管理,DLL,这几大块搞精通。

· 实践任务:使用CreateProcess启动一个记事本或IE,并监控该程序的运行。把前面写过的那个简易的HTTP服务用线程池实现一下。写一个DLL的钩子程序监控指定窗口的关闭事件,或是记录某个窗口的按键。

· 有了多线程、多进程通信,TCP/IP,套接字,C++和设计模式的基本,你可以研究一下ACE了。使用ACE重写上述的聊天程序和HTTP服务器(带线程池)

· 实践任务:通过以上的所有知识,尝试

o 写一个服务端给客户端传大文件,要求把100M的带宽用到80%以上。(注意,磁盘I/O和网络I/O可能会很有问题,想一想怎么解决,另外,请注意网络传输最大单元MTU)

o 了解BT下载的工作原理,用多进程的方式模拟BT下载的原理。

3、系统架构

· 负载均衡。HASH式的,纯动态式的。(可以到Google学术里搜一些关于负载均衡的文章读读)

· 多层分布式系统 – 客户端服务结点层、计算结点层、数据cache层,数据层。J2EE是经典的多层结构。

· CDN系统– 就近访问,内容边缘化。

· P2P式系统,研究一下BT和电驴的算法。比如:DHT算法

· 服务器备份,双机备份系统(Live-Standby和Live-Live系统),两台机器如何通过心跳监测对方?集群主结点备份。

· 虚拟化技术,使用这个技术,可以把操作系统当应用程序一下切换或重新配置和部署。

· 学习Thrift,二进制的高性能的通讯中间件,支持数据(对象)序列化和多种类型的RPC服务。

· 学习Hadoop。Hadoop框架中最核心的设计就是:MapReduce和HDFS。MapReduce的思想是由Google的一篇论文所提及而被广为流传的,简单的一句话解释MapReduce就是“任务的分解与结果的汇总”。HDFS是Hadoop分布式文件系统(Hadoop Distributed File System)的缩写,为分布式计算存储提供了底层支持。

了解NoSQL数据库(有人说可能是一个过渡炒作的技术),不过因为超大规模以及高并发的纯动态型网站日渐成为主流,而SNS类网站在数据存取过程中有着实时性等刚性需求,这使得目前NoSQL数据库慢慢成了人们所关注的焦点,并大有成为取代关系型数据库而成为未来主流数据存储模式的趋势。当前NoSQL数据库很多,大部分都是开源的,其中比较知名的有:MemcacheDB、Redis、

好烂啊有点差凑合看看还不错很精彩 (No Ratings Yet)
Loading...
332 views
Java日期格式化

Java日期格式化

Java日期格式化

 

import java.text.ParseException;

import java.text.SimpleDateFormat;

import java.util.Date;

import java.util.Locale;

public class CX {

public static void main(String[] args) throws ParseException {

SimpleDateFormat sdf;

Date date; String s, s2 ;

// Jul 20, 2016 2:05:09 pm

String ds = “Jul 20, 2016 2:05:09 pm”;

date = new Date();

sdf = new SimpleDateFormat(“MMMMM dd,yyyy hh:mm:ss a”, Locale.ENGLISH );

s = sdf.format(date);

System.out.println(s);

date = sdf.parse(s);

System.out.println(“date = ” + date);

date = sdf.parse(ds);

System.out.println(“date2 = ” + date);

sdf = new SimpleDateFormat(“MMM dd,yyyy hh:mm:ss aa”, Locale.ENGLISH);

s = sdf.format(date); System.out.println(s);

date = sdf.parse(s);

System.out.println(“date = ” + date);

date = sdf.parse(ds);

System.out.println(“date2 = ” + date); }
}

输出:

June 22,2017 03:33:48 PM

date = Thu Jun 22 15:33:48 CST 2017

date2 = Wed Jul 20 14:05:09 CST 2016

Jul 20,2016 02:05:09 PM

date = Wed Jul 20 14:05:09 CST 2016

date2 = Wed Jul 20 14:05:09 CST 2016

好烂啊有点差凑合看看还不错很精彩 (No Ratings Yet)
Loading...
345 views
Update in WordPress 4.8

Update in WordPress 4.8

An Update with You in Mind

WordPress 4.8 adds some great new features. Gear up for a more intuitive WordPress!

Though some updates seem minor, they’ve been built by hundreds of contributors with you in mind. Get ready for new features you’ll welcome like an old friend: link improvements, three new media widgets covering images, audio, and video, an updated text widget that supports visual editing, and an upgraded news section in your dashboard which brings in nearby and upcoming WordPress events.

 

Exciting Widget Updates

Image Widget

Adding an image to a widget is now a simple task that is achievable for any WordPress user without needing to know code. Simply insert your image right within the widget settings. Try adding something like a headshot or a photo of your latest weekend adventure — and see it appear automatically.

Video Widget

A welcome video is a great way to humanize the branding of your website. You can now add any video from the Media Library to a sidebar on your site with the new Video widget. Use this to showcase a welcome video to introduce visitors to your site or promote your latest and greatest content.

Audio Widget

Are you a podcaster, musician, or avid blogger? Adding a widget with your audio file has never been easier. Upload your audio file to the Media Library, go to the widget settings, select your file, and you’re ready for listeners. This would be a easy way to add a more personal welcome message, too!

Rich Text Widget

This feature deserves a parade down the center of town! Rich-text editing capabilities are now native for Text widgets. Add a widget anywhere and format away. Create lists, add emphasis, and quickly and easily insert links. Have fun with your newfound formatting powers, and watch what you can accomplish in a short amount of time.

好烂啊有点差凑合看看还不错很精彩 (No Ratings Yet)
Loading...
341 views
WordPress Backups « WordPress Codex

WordPress Backups « WordPress Codex

WordPress Backups

Note: Want to skip the hard stuff? Skip to Automated Solutions such asWordPress Plugins for backups.

Your WordPress database contains every post, every comment and every link you have on your blog. If your database gets erased or corrupted, you stand to lose everything you have written. There are many reasons why this could happen and not all are things you can control. With a proper backup of your WordPress database and files, you can quickly restore things back to normal.

Instructions to back up your WordPress site include:

  1. WordPress Site and your WordPress Database
  2. Automatic WordPress backup options

In addition, support is provided online at the WordPress Support Forum to help you through the process.

Site backups are essential because problems inevitably occur and you need to be in a position to take action when disaster strikes. Spending a few minutes to make an easy, convenient backup of your database will allow you to spend even more time being creative and productive with your website.

来源: WordPress Backups « WordPress Codex

好烂啊有点差凑合看看还不错很精彩 (No Ratings Yet)
Loading...
304 views
Making Photos Smaller Without Quality Loss – by Yelp

Making Photos Smaller Without Quality Loss – by Yelp

Making Photos Smaller Without Quality Loss

Yelp has over 100 million user-generated photos ranging from pictures of dinners or haircuts, to one of our newest features, #yelfies. These images account for a majority of the bandwidth for users of the app and website, and represent a significant cost to store and transfer. In our quest to give our users the best experience, we worked hard to optimize our photos and were able to achieve a 30% average size reduction. This saves our users time and bandwidth and reduces our cost to serve those images. Oh, and we did it all without reducing the quality of these images!

Background

Yelp has been storing user-uploaded photos for over 12 years. We save lossless formats (PNG, GIF) as PNGs and all other formats as JPEG. We use Python and Pillow for saving images, and start our story of photo uploads with a snippet like this:

With this as a starting point, we began to investigate potential optimizations on file size that we could apply without a loss in quality.

Optimizations

First, we had to decide whether to handle this ourselves or let a CDN provider magically change our photos. With the priority we place on high quality content, it made sense to evaluate options and make potential size vs quality tradeoffs ourselves. We moved ahead with research on the current state of photo file size reduction – what changes could be made and how much size / quality reduction was associated with each. With this research completed, we decided to work on three primary categories. The rest of this post explains what we did and how much benefit we realized from each optimization.

  1. Changes in Pillow
    • Optimize flag
    • Progressive JPEG
  2. Changes to application photo logic
    • Large PNG detection
    • Dynamic JPEG quality
  3. Changes to JPEG encoder
    • Mozjpeg (trellis quantization, custom quantization matrix)

Changes in Pillow

Optimize Flag

This is one of the easiest changes we made: enabling the setting in Pillow responsible for additional file size savings at the cost of CPU time (optimize=True). Due to the nature of the tradeoff being made, this does not impact image quality at all.

For JPEG, this flag instructs the encoder to find the optimal Huffman coding by making an additional pass over each image scan. Each first pass, instead of writing to file, calculates the occurrence statistics of each value, required information to compute the ideal coding. PNG internally uses zlib, so the optimize flag in that case effectively instructs the encoder to use gzip -9 instead of gzip -6.

This is an easy change to make but it turns out that it is not a silver bullet, reducing file size by just a few percent.

Progressive JPEG

When saving an image as a JPEG, there are a few different types you can choose from:

  • Baseline JPEG images load from top to bottom.
  • Progressive JPEG images load from more blurry to less blurry. The progressive option can easily be enabled in Pillow (progressive=True). As a result, there is a perceived performance increase (that is, it’s easier to notice when an image is partially absent than it is to tell it’s not fully sharp).

Additionally, the way progressive files are packed generally results in a small reduction to file size. As more fully explained by the Wikipedia article, JPEG format uses a zigzag pattern over the 8×8 blocks of pixels to do entropy coding. When the values of those blocks of pixels are unpacked and laid out in order, you generally have non-zero numbers first and then sequences of 0s, with that pattern repeating and interleaved for each 8×8 block in the image. With progressive encoding, the order of the unwound pixel blocks changes. The higher value numbers for each block come first in the file, (which gives the earliest scans of a progressive image its distinct blockiness), and the longer spans of small numbers, including more 0s, that add the finer details are towards the end. This reordering of the image data doesn’t change the image itself, but does increase the number of 0s that might be in a row (which can be more easily compressed).

Comparison with a delicious user-contributed image of a donut (click for larger):

(left) A mock of how a baseline JPEG renders.

(left) A mock of how a baseline JPEG renders.

(right) A mock of how a progressive JPEG renders.

(right) A mock of how a progressive JPEG renders.

Changes to Application Photo Logic

Large PNG Detection

Yelp targets two image formats for serving user-generated content – JPEG and PNG. JPEG is a great format for photos but generally struggles with high-contrast design content (like logos). By contrast, PNG is fully-lossless, so great for graphics but too large for photos where small distortions are not visible. In the cases where users upload PNGs that are actually photographs, we can save a lot of space if we identify these files and save them as JPEG instead. Some common sources of PNG photos on Yelp are screenshots taken by mobile devices and apps that modify photos to add effects or borders.

(left) A typical composited PNG upload with logo and border. (right) A typical PNG upload from a screenshot.

(left) A typical composited PNG upload with logo and border. (right) A typical PNG upload from a screenshot.

We wanted to reduce the number of these unnecessary PNGs, but it was important to avoid overreaching and changing format or degrading quality of logos, graphics, etc. How can we tell if something is a photo? From the pixels?

Using an experimental sample of 2,500 images, we found that a combination of file size and unique pixels worked well to detect photos. We generate a candidate thumbnail image at our largest resolution and see if the output PNG file is larger than 300KiB. If it is, we’ll also check the image contents to see if there are over 2^16 unique colors (Yelp converts RGBA image uploads to RGB, but if we didn’t, we would check that too).

In the experimental dataset, these hand-tuned thresholds to define “bigness” captured 88% of the possible file size savings (i.e. our expected file size savings if we were to convert all of the images) without any false-positives of graphics being converted.

Dynamic JPEG Quality

The first and most well-known way to reduce the size of JPEG files is a setting called quality. Many applications capable of saving to the JPEG format specify quality as a number.

Quality is somewhat of an abstraction. In fact, there are separate qualities for each of the color channels of a JPEG image. Quality levels 0 – 100 map to different quantization tables for the color channels, determining how much data is lost (usually high frequency). Quantization in the signal domain is the one step in the JPEG encoding process that loses information.

The simplest way to reduce file size is to reduce the quality of the image, introducing more noise. Not every image loses the same amount of information at a given quality level though.

We can dynamically choose a quality setting which is optimized for each image, finding an ideal balance between quality and size. There are two ways to do this:

  • Bottom-up: These are algorithms that generate tuned quantization tables by processing the image at the 8×8 pixel block level. They calculate both how much theoretical quality was lost and how that lost data either amplifies or cancels out to be more or less visible to the human eye.
  • Top-down: These are algorithms that compare an entire image against an original version of itself and detect how much information was lost. By iteratively generating candidate images with different quality settings, we can choose the one that meets a minimum evaluated level by whichever evaluation algorithm we choose.

We evaluated a bottom-up algorithm, which in our experience did not yield suitable results at the higher end of the quality range we wanted to use (though it seems like it may still have potential in the mid-range of image qualities, where an encoder can begin to be more adventurous with the bytes it discards). Many of the scholarly papers on this strategy were published in the early 90s when computing power was at a premium and took shortcuts that option B addresses, such as not evaluating interactions across blocks.

So we took the second approach: use a bisection algorithm to generate candidate images at different quality levels, and evaluate each candidate image’s drop in quality by calculating its structural similarity metric (SSIM) using pyssim, until that value is at a configurable but static threshold. This enables us to selectively lower the average file size (and average quality) only for images which were above a perceivable decrease to begin with.

In the below chart, we plot the SSIM values of 2500 images regenerated via 3 different quality approaches.

  1. The original images made by the current approach at quality = 85 are plotted as the blue line.
  2. An alternative approach to lowering file size, changing quality = 80, is plotted as the red line.
  3. And finally, the approach we ended up using, dynamic quality, SSIM 80-85, in orange, chooses a quality for the image in the range 80 to 85 (inclusive) based on meeting or exceeding an SSIM ratio: a pre-computed static value that made the transition occur somewhere in the middle of the images range. This lets us lower the average file size without lowering the quality of our worst-quality images.

SSIMs of 2500 images with 3 different quality strategies.

SSIMs of 2500 images with 3 different quality strategies.

SSIM?

There are quite a few image quality algorithms that try to mimic the human vision system. We’ve evaluated many of these and think that SSIM, while older, is most suitable for this iterative optimization based on a few characteristics:

  1. Sensitive to JPEG quantization error
  2. Fast, simple algorithm
  3. Can be computed on PIL native image objects without converting images to PNG and passing them to CLI applications (see #2)

Example Code for Dynamic Quality:

There are a few other blog posts about this technique, here is one by Colt Mcanlis. And as we go to press, Etsy has published one here! High five, faster internet!

Changes to JPEG Encoder

Mozjpeg

Mozjpeg is an open-source fork of libjpeg-turbo, which trades execution time for file size. This approach meshes well with the offline batch approach to regenerating images. With the investment of about 3-5x more time than libjpeg-turbo, a few more expensive algorithms make images smaller!

One of mozjpeg’s differentiators is the use of an alternative quantization table. As mentioned above, quality is an abstraction of the quantization tables used for each color channel. All signs point to the default JPEG quantization tables as being pretty easy to beat. In the words of the JPEG spec:

These tables are provided as examples only and are not necessarily suitable for any particular application.

So naturally, it shouldn’t surprise you to learn that these tables are the default used by most encoder implementations… 🤔🤔🤔

Mozjpeg has gone through the trouble of benchmarking alternative tables for us, and uses the best performing general-purpose alternative for images it creates.

Mozjpeg + Pillow

Most Linux distributions have libjpeg installed by default. So using mozjpeg under Pillow doesn’t work by default, but configuring it isn’t terribly difficult either. When you build mozjpeg, use the --with-jpeg8 flag and make sure it can be linked by Pillow will find it. If you’re using Docker, you might have a Dockerfile like:

That’s it! Build it and you’ll be able to use Pillow backed by mozjpeg within your normal images workflow.

Impact

How much did each of those improvements matter for us? We started this research by randomly sampling 2,500 of Yelp’s business photos to put through our processing pipeline and measure the impact on file size.

  1. Changes to Pillow settings were responsible for about 4.5% of the savings
  2. Large PNG detection was responsible for about 6.2% of the savings
  3. Dynamic Quality was responsible for about 4.5% of the savings
  4. Switching to the mozjpeg encoder was responsible for about 13.8% of the savings

This adds up to an average image file size reduction of around 30%, which we applied to our largest and most common image resolutions, making the website faster for users and saving terabytes a day in data transfer. As measured at the CDN:

Average filesize over time, as measured from the CDN (combined with non-image static content).

Average filesize over time, as measured from the CDN (combined with non-image static content).

What we didn’t do

This section is intended to introduce a few other common improvements that you might be able to make, that either weren’t relevant to Yelp due to defaults chosen by our tooling, or tradeoffs we chose not to make.

Subsampling

Subsampling is a major factor in determining both quality and file size for web images. Longer descriptions of subsampling can be found online, but suffice it to say for this blog post that we were already subsampling at 4:1:1 (which is Pillow’s default when nothing else is specified) so we weren’t able to realize any further savings here.

Lossy PNG encoding

After learning what we did about PNGs, choosing to preserve some of them as PNG but with a lossy encoder like pngmini could have made sense, but we chose to resave them as JPEG instead. This is an alternate option with reasonable results, 72-85% file size savings over unmodified PNGs according to the author.

Dynamic content types

Support for more modern content types like WebP or JPEG2k is certainly on our radar. Even once that hypothetical project ships, there will be a long-tail of users requesting these now-optimized JPEG/PNG images which will continue to make this effort well worth it.

SVG

We use SVG in many places on our website, like the static assets created by our designers that go into our styleguide. While this format and optimization tools like svgo are useful to reduce website page weight, it isn’t related to what we did here.

Vendor Magic

There are too many providers to list that offer image delivery / resizing / cropping / transcoding as a service. Including open-source thumbor. Maybe this is the easiest way to support responsive images, dynamic content types and remain on the cutting edge for us in the future. For now our solution remains self-contained.

Further Reading

Two books listed here absolutely stand on their own outside the context of the post, and are highly recommended as further reading on the subject.

来源: Making Photos Smaller Without Quality Loss

好烂啊有点差凑合看看还不错很精彩 (No Ratings Yet)
Loading...
72 views
Netty : what’s it

Netty : what’s it

Netty is an asynchronous event-driven network application framework
for rapid development of maintainable high performance protocol servers & clients.

 

Netty is a NIO client server framework which enables quick and easy development of network applications such as protocol servers and clients. It greatly simplifies and streamlines network programming such as TCP and UDP socket server.

‘Quick and easy’ doesn’t mean that a resulting application will suffer from a maintainability or a performance issue. Netty has been designed carefully with the experiences earned from the implementation of a lot of protocols such as FTP, SMTP, HTTP, and various binary and text-based legacy protocols. As a result, Netty has succeeded to find a way to achieve ease of development, performance, stability, and flexibility without a compromise.

Features

Design

  • Unified API for various transport types – blocking and non-blocking socket
  • Based on a flexible and extensible event model which allows clear separation of concerns
  • Highly customizable thread model – single thread, one or more thread pools such as SEDA
  • True connectionless datagram socket support (since 3.1)

Ease of use

  • Well-documented Javadoc, user guide and examples
  • No additional dependencies, JDK 5 (Netty 3.x) or 6 (Netty 4.x) is enough
    • Note: Some components such as HTTP/2 might have more requirements. Please refer to the Requirements page for more information.

Performance

  • Better throughput, lower latency
  • Less resource consumption
  • Minimized unnecessary memory copy

Security

  • Complete SSL/TLS and StartTLS support

Community

  • Release early, release often
  • The author has been writing similar frameworks since 2003 and he still finds your feed back precious!

来源: Netty: Home

好烂啊有点差凑合看看还不错很精彩 (No Ratings Yet)
Loading...
65 views
Congrats, you are now part of the InfoQ community

Congrats, you are now part of the InfoQ community

Thank you for confirming your email.

You will now be receiving our amazing content to help you navigate trends in the industry, every Tuesday.
In the meantime, here is a sample of our most recent newsletter: http://www.infoq.com/newsletter_sample.html

Please add the send address to your address book, contacts or safe list.

If you did not register or feel that this subscription is an error, you may unsubscribe by clicking on this link: http://www.infoq.com/newsletter/unsubscribe.action?si=MTAxMzM5MDk2NzM2

May the force be with you,

InfoQ team

好烂啊有点差凑合看看还不错很精彩 (No Ratings Yet)
Loading...
274 views
Is Java “pass-by-reference” or “pass-by-value”?

Is Java “pass-by-reference” or “pass-by-value”?

结果让人有些意外,到底是 引用传递 还是 值传递?

public class DogTest {

public static void main( String[] args ) {
Dog aDog = new Dog(“Max”);
// we pass the object to foo
foo(aDog);
// aDog variable is still pointing to the “Max” dog when foo(…) returns
if (aDog.getName().equals(“Max”)) { System.out.println(“11=”+aDog);} // true, java passes by value
if (aDog.getName().equals(“Fifi”)) { System.out.println(“22=”+aDog);} // false
}

public static void foo(Dog d) {
d.getName().equals(“Max”); // true
// change d inside of foo() to point to a new Dog instance “Fifi”
d = new Dog(“Fifi”);
if (d.getName().equals(“Fifi”)) { System.out.println(“33=”+d); } // true
}
}

class Dog {
String name;
public Dog(String s ){
name =s ;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}

@Override
public String toString() {
// TODO Auto-generated method stub
return String.format(” Dog[name=%s]”, name);
}
}

来源: methods – Is Java “pass-by-reference” or “pass-by-value”? – Stack Overflow

好烂啊有点差凑合看看还不错很精彩 (No Ratings Yet)
Loading...
292 views
好烂啊有点差凑合看看还不错很精彩 (No Ratings Yet)
Loading...
308 views
比尔·盖茨在哈佛大学毕业典礼上的演讲

比尔·盖茨在哈佛大学毕业典礼上的演讲

 

( (Cambridge, MA – Thursday, June 7, 2007) Harvard University’s 356th Commencement included Senior Class Chapel Service and Morning Exercises in Tercentenary Theatre. Bill Gates was the speaker at Afternoon Exercises Staff Photo by Rose Lincoln/Harvard News Office )

 

President Bok, former President Rudenstine, incoming President Faust, members of the Harvard Corporation and the Board of Overseers, members of the faculty, parents, and especially, the graduates:

尊敬的Bok校长,Rudenstine前校长,即将上任的Faust校长,哈佛集团的各位成员,监管理事会的各位理事,各位老师,各位家长,各位同学:

I’ve been waiting more than 30 years to say this: “Dad, I always told you I’d come back and get my degree.”

有一句话我等了三十年,现在终于可以说了:”老爸,我总是跟你说,我会回来拿到我的学位的!”

I want to thank Harvard for this timely honor. I’ll be changing my job next year … and it will be nice to finally have a college degree on my resume.

我要感谢哈佛大学在这个时候给我这个荣誉。明年,我就要换工作了(注:指从微软公司退休)……我终于可以在简历上写我有一个大学学位,这真是不错啊。

I applaud the graduates today for taking a much more direct route to your degrees. For my part, I’m just happy that the Crimson has called me “Harvard’s most successful dropout.” I guess that makes me valedictorian of my own special class … I did the best of everyone who failed.

我为今天在座的各位同学感到高兴,你们拿到学位可比我简单多了。哈佛的校报称我是”哈佛大学历史上最成功的辍学生”。我想这大概使我有资格代表我这一类学生发言……在所有的失败者里,我做得最好。

But I also want to be recognized as the guy who got Steve Ballmer to drop out of business school. I’m a bad influence. That’s why I was invited to speak at your graduation. If I had spoken at your orientation, fewer of you might be here today.

但是,我还要提醒大家,我使得Steve Ballmer(注:微软总经理)也从哈佛商学院退学了。因此,我是个有着恶劣影响力的人。这就是为什么我被邀请来在你们的毕业典礼上演讲。如果我在你们入学欢迎仪式上演讲,那么能够坚持到今天在这里毕业的人也许会少得多吧。

Harvard was just a phenomenal experience for me. Academic life was fascinating. I used to sit in on lots of classes I hadn’t even signed up for. And dorm life was terrific. I lived up at Radcliffe, in Currier House. There were always lots of people in my dorm room late at night discussing things, because everyone knew I didn’t worry about getting up in the morning. That’s how I came to be the leader of the anti-social group. We clung to each other as a way of validating our rejection of all those social people.

对我来说,哈佛的求学经历是一段非凡的经历。校园生活很有趣,我常去旁听我没选修的课。哈佛的课外生活也很棒,我在Radcliffe过着逍遥自在的日子。每天我的寝室里总有很多人一直待到半夜,讨论着各种事情。因为每个人都知道我从不考虑第二天早起。这使得我变成了校园里那些不安分学生的头头,我们互相粘在一起,做出一种拒绝所有正常学生的姿态。

Radcliffe was a great place to live. There were more women up there, and most of the guys were science-math types. That combination offered me the best odds, if you know what I mean. This is where I learned the sad lesson that improving your odds doesn’t guarantee success.

Radcliffe是个过日子的好地方。那里的女生比男生多,而且大多数男生都是理工科的。这种状况为我创造了最好的机会,如果你们明白我的意思。可惜的是,我正是在这里学到了人生中悲伤的一课:机会大,并不等于你就会成功。

One of my biggest memories of Harvard came in January 1975, when I made a call from Currier House to a company in Albuquerque that had begun making the world’s first personal computers. I offered to sell them software.

我在哈佛最难忘的回忆之一,发生在1975年1月。那时,我从宿舍楼里给位于Albuquerque的一家公司打了一个电话,那家公司已经在着手制造世界上第一台个人电脑。我提出想向他们出售软件。

I worried that they would realize I was just a student in a dorm and hang up on me. Instead they said: “We’re not quite ready, come see us in a month,” which was a good thing, because we hadn’t written the software yet. From that moment, I worked day and night on this little extra credit project that marked the end of my college education and the beginning of a remarkable journey with Microsoft.

我很担心,他们会发觉我是一个住在宿舍的学生,从而挂断电话。但是他们却说:”我们还没准备好,一个月后你再来找我们吧。”这是个好消息,因为那时软件还根本没有写出来呢。就是从那个时候起,我日以继夜地在这个小小的课外项目上工作,这导致了我学生生活的结束,以及通往微软公司的不平凡的旅程的开始。

What I remember above all about Harvard was being in the midst of so much energy and intelligence. It could be exhilarating, intimidating, sometimes even discouraging, but always challenging. It was an amazing privilege – and though I left early, I was transformed by my years at Harvard, the friendships I made, and the ideas I worked on.

不管怎样,我对哈佛的回忆主要都与充沛的精力和智力活动有关。哈佛的生活令人愉快,也令人感到有压力,有时甚至会感到泄气,但永远充满了挑战性。生活在哈佛是一种吸引人的特殊待遇……虽然我离开得比较早,但是我在这里的经历、在这里结识的朋友、在这里发展起来的一些想法,永远地改变了我。

But taking a serious look back … I do have one big regret.

但是,如果现在严肃地回忆起来,我确实有一个真正的遗憾。

I left Harvard with no real awareness of the awful inequities in the world – the appalling disparities of health, and wealth, and opportunity that condemn millions of people to lives of despair.

我离开哈佛的时候,根本没有意识到这个世界是多么的不平等。人类在健康、财富和机遇上的不平等大得可怕,它们使得无数的人们被迫生活在绝望之中。

I learned a lot here at Harvard about new ideas in economics and politics. I got great exposure to the advances being made in the sciences.

我在哈佛学到了很多经济学和政治学的新思想。我也了解了很多科学上的新进展。

But humanity’s greatest advances are not in its discoveries – but in how those discoveries are applied to reduce inequity. Whether through democracy, strong public education, quality health care, or broad economic opportunity – reducing inequity is the highest human achievement.

但是,人类最大的进步并不来自于这些发现,而是来自于那些有助于减少人类不平等的发现。不管通过何种手段—-民主制度、健全的公共教育体系、高质量的医疗保健、还是广泛的经济机会—-减少不平等始终是人类最大的成就。

I left campus knowing little about the millions of young people cheated out of educational opportunities here in this country. And I knew nothing about the millions of people living in unspeakable poverty and disease in developing countries.

我离开校园的时候,根本不知道在这个国家里,有几百万的年轻人无法获得接受教育的机会。我也不知道,发展中国家里有无数的人们生活在无法形容的贫穷和疾病之中。

It took me decades to find out.

我花了几十年才明白了这些事情。

You graduates came to Harvard at a different time. You know more about the world’s inequities than the classes that came before. In your years here, I hope you’ve had a chance to think about how – in this age of accelerating technology – we can finally take on these inequities, and we can solve them.

在座的各位同学,你们是在与我不同的时代来到哈佛的。你们比以前的学生,更多地了解世界是怎样的不平等。在你们的哈佛求学过程中,我希望你们已经思考过一个问题,那就是在这个新技术加速发展的时代,我们怎样最终应对这种不平等,以及我们怎样来解决这个问题。

Imagine, just for the sake of discussion, that you had a few hours a week and a few dollars a month to donate to a cause – and you wanted to spend that time and money where it would have the greatest impact in saving and improving lives. Where would you spend it?

为了讨论的方便,请想象一下,假如你每个星期可以捐献一些时间、每个月可以捐献一些钱—-你希望这些时间和金钱,可以用到对拯救生命和改善人类生活有最大作用的地方。你会选择什么地方?

For Melinda and for me, the challenge is the same: how can we do the most good for the greatest number with the resources we have.

对Melinda(注:盖茨的妻子)和我来说,这也是我们面临的问题:我们如何能将我们拥有的资源发挥出最大的作用。

During our discussions on this question, Melinda and I read an article about the millions of children who were dying every year in poor countries from diseases that we had long ago made harmless in this country. Measles, malaria, pneumonia, hepatitis B, yellow fever. One disease I had never even heard of, rotavirus, was killing half a million kids each year – none of them in the United States.

在讨论过程中,Melinda和我读到了一篇文章,里面说在那些贫穷的国家,每年有数百万的儿童死于那些在美国早已不成问题的疾病。麻疹、疟疾、肺炎、乙型肝炎、黄热病、还有一种以前我从未听说过的轮状病毒,这些疾病每年导致50万儿童死亡,但是在美国一例死亡病例也没有。

We were shocked. We had just assumed that if millions of children were dying and they could be saved, the world would make it a priority to discover and deliver the medicines to save them. But it did not. For under a dollar, there were interventions that could save lives that just weren’t being delivered.

我们被震惊了。我们想,如果几百万儿童正在死亡线上挣扎,而且他们是可以被挽救的,那么世界理应将用药物拯救他们作为头等大事。但是事实并非如此。那些价格还不到一美元的救命的药剂,并没有送到他们的手中。

If you believe that every life has equal value, it’s revolting to learn that some lives are seen as worth saving and others are not. We said to ourselves: “This can’t be true. But if it is true, it deserves to be the priority of our giving.”

如果你相信每个生命都是平等的,那么当你发现某些生命被挽救了,而另一些生命被放弃了,你会感到无法接受。我们对自己说:”事情不可能如此。如果这是真的,那么它理应是我们努力的头等大事。”

So we began our work in the same way anyone here would begin it. We asked: “How could the world let these children die?”

所以,我们用任何人都会想到的方式开始工作。我们问:”这个世界怎么可以眼睁睁看着这些孩子死去?”

The answer is simple, and harsh. The market did not reward saving the lives of these children, and governments did not subsidize it. So the children died because their mothers and their fathers had no power in the market and no voice in the system.

答案很简单,也很令人难堪。在市场经济中,拯救儿童是一项没有利润的工作,政府也不会提供补助。这些儿童之所以会死亡,是因为他们的父母在经济上没有实力,在政治上没有能力发出声音。

But you and I have both.

但是,你们和我在经济上有实力,在政治上能够发出声音。

We can make market forces work better for the poor if we can develop a more creative capitalism – if we can stretch the reach of market forces so that more people can make a profit, or at least make a living, serving people who are suffering from the worst inequities. We also can press governments around the world to spend taxpayer money in ways that better reflect the values of the people who pay the taxes.

我们可以让市场更好地为穷人服务,如果我们能够设计出一种更有创新性的资本主义制度—-如果我们可以改变市场,让更多的人可以获得利润,或者至少可以维持生活—-那么,这就可以帮到那些正在极端不平等的状况中受苦的人们。我们还可以向全世界的政府施压,要求他们将纳税人的钱,花到更符合纳税人价值观的地方。

If we can find approaches that meet the needs of the poor in ways that generate profits for business and votes for politicians, we will have found a sustainable way to reduce inequity in the world. This task is open-ended. It can never be finished. But a conscious effort to answer this challenge will change the world.

如果我们能够找到这样一种方法,既可以帮到穷人,又可以为商人带来利润,为政治家带来选票,那么我们就找到了一种减少世界性不平等的可持续的发展道路。这个任务是无限的。它不可能被完全完成,但是任何自觉地解决这个问题的尝试,都将会改变这个世界。

I am optimistic that we can do this, but I talk to skeptics who claim there is no hope. They say: “Inequity has been with us since the beginning, and will be with us till the end – because people just … don’t … care.” I completely disagree.

在这个问题上,我是乐观的。但是,我也遇到过那些感到绝望的怀疑主义者。他们说:”不平等从人类诞生的第一天就存在,到人类灭亡的最后一天也将存在。—-因为人类对这个问题根本不在乎。”我完全不能同意这种观点。

I believe we have more caring than we know what to do with.

我相信,问题不是我们不在乎,而是我们不知道怎么做。

All of us here in this Yard, at one time or another, have seen human tragedies that broke our hearts, and yet we did nothing – not because we didn’t care, but because we didn’t know what to do. If we had known how to help, we would have acted.

此刻在这个院子里的所有人,生命中总有这样或那样的时刻,目睹人类的悲剧,感到万分伤心。但是我们什么也没做,并非我们无动于衷,而是因为我们不知道做什么和怎么做。如果我们知道如何做是有效的,那么我们就会采取行动。

The barrier to change is not too little caring; it is too much complexity.

改变世界的阻碍,并非人类的冷漠,而是世界实在太复杂。

To turn caring into action, we need to see a problem, see a solution, and see the impact. But complexity blocks all three steps.

为了将关心转变为行动,我们需要找到问题,发现解决办法的方法,评估后果。但是世界的复杂性使得所有这些步骤都难于做到。

Even with the advent of the Internet and 24-hour news, it is still a complex enterprise to get people to truly see the problems. When an airplane crashes, officials immediately call a press conference. They promise to investigate, determine the cause, and prevent similar crashes in the future.

即使有了互联网和24小时直播的新闻台,让人们真正发现问题所在,仍然十分困难。当一架飞机坠毁了,官员们会立刻召开新闻发布会,他们承诺进行调查、找到原因、防止将来再次发生类似事故。

But if the officials were brutally honest, they would say: “Of all the people in the world who died today from preventable causes, one half of one percent of them were on this plane. We’re determined to do everything possible to solve the problem that took the lives of the one half of one percent.”

但是如果那些官员敢说真话,他们就会说:”在今天这一天,全世界所有可以避免的死亡之中,只有0.5%的死者来自于这次空难。我们决心尽一切努力,调查这个0.5%的死亡原因。”

The bigger problem is not the plane crash, but the millions of preventable deaths.

显然,更重要的问题不是这次空难,而是其他几百万可以预防的死亡事件。

We don’t read much about these deaths. The media covers what’s new – and millions of people dying is nothing new. So it stays in the background, where it’s easier to ignore. But even when we do see it or read about it, it’s difficult to keep our eyes on the problem. It’s hard to look at suffering if the situation is so complex that we don’t know how to help. And so we look away.

我们并没有很多机会了解那些死亡事件。媒体总是报告新闻,几百万人将要死去并非新闻。如果没有人报道,那么这些事件就很容易被忽视。另一方面,即使我们确实目睹了事件本身或者看到了相关报道,我们也很难持续关注这些事件。看着他人受苦是令人痛苦的,何况问题又如此复杂,我们根本不知道如何去帮助他人。所以我们会将脸转过去。

If we can really see a problem, which is the first step, we come to the second step: cutting through the complexity to find a solution.

就算我们真正发现了问题所在,也不过是迈出了第一步,接着还有第二步:那就是从复杂的事件中找到解决办法。

Finding solutions is essential if we want to make the most of our caring. If we have clear and proven answers anytime an organization or individual asks “How can I help?,” then we can get action – and we can make sure that none of the caring in the world is wasted. But complexity makes it hard to mark a path of action for everyone who cares — and that makes it hard for their caring to matter.

如果我们要让关心落到实处,我们就必须找到解决办法。如果我们有一个清晰的和可靠的答案,那么当任何组织和个人发出疑问”如何我能提供帮助”的时候,我们就能采取行动。我们就能够保证不浪费一丁点全世界人类对他人的关心。但是,世界的复杂性使得很难找到对全世界每一个有爱心的人都有效的行动方法,因此人类对他人的关心往往很难产生实际效果。

Cutting through complexity to find a solution runs through four predictable stages: determine a goal, find the highest-leverage approach, discover the ideal technology for that approach, and in the meantime, make the smartest application of the technology that you already have — whether it’s something sophisticated, like a drug, or something simpler, like a bednet.

从这个复杂的世界中找到解决办法,可以分为四个步骤:确定目标,找到最高效的方法,发现适用于这个方法的新技术,同时最聪明地利用现有的技术,不管它是复杂的药物,还是最简单的蚊帐。

The AIDS epidemic offers an example. The broad goal, of course, is to end the disease. The highest-leverage approach is prevention. The ideal technology would be a vaccine that gives lifetime immunity with a single dose. So governments, drug companies, and foundations fund vaccine research. But their work is likely to take more than a decade, so in the meantime, we have to work with what we have in hand – and the best prevention approach we have now is getting people to avoid risky behavior.

艾滋病就是一个例子。总的目标,毫无疑问是消灭这种疾病。最高效的方法是预防。最理想的技术是发明一种疫苗,只要注射一次,就可以终生免疫。所以,政府、制药公司、基金会应该资助疫苗研究。但是,这样研究工作很可能十年之内都无法完成。因此,与此同时,我们必须使用现有的技术,目前最有效的预防方法就是设法让人们避免那些危险的行为。

Pursuing that goal starts the four-step cycle again. This is the pattern. The crucial thing is to never stop thinking and working – and never do what we did with malaria and tuberculosis in the 20th century – which is to surrender to complexity and quit.

要实现这个新的目标,又可以采用新的四步循环。这是一种模式。关键的东西是永远不要停止思考和行动。我们千万不能再犯上个世纪在疟疾和肺结核上犯过的错误,那时我们因为它们太复杂,而放弃了采取行动。

The final step – after seeing the problem and finding an approach – is to measure the impact of your work and share your successes and failures so that others learn from your efforts.

在发现问题和找到解决方法之后,就是最后一步—-评估工作结果,将你的成功经验或者失败经验传播出去,这样其他人就可以从你的努力中有所收获。

You have to have the statistics, of course. You have to be able to show that a program is vaccinating millions more children. You have to be able to show a decline in the number of children dying from these diseases. This is essential not just to improve the program, but also to help draw more investment from business and government.

当然,你必须有一些统计数字。你必须让他人知道,你的项目为几百万儿童新接种了疫苗。你也必须让他人知道,儿童死亡人数下降了多少。这些都是很关键的,不仅有利于改善项目效果,也有利于从商界和政府得到更多的帮助。

But if you want to inspire people to participate, you have to show more than numbers; you have to convey the human impact of the work – so people can feel what saving a life means to the families affected.

但是,这些还不够,如果你想激励其他人参加你的项目,你就必须拿出更多的统计数字;你必须展示你的项目的人性因素,这样其他人就会感到拯救一个生命,对那些处在困境中的家庭到底意味着什么。

I remember going to Davos some years back and sitting on a global health panel that was discussing ways to save millions of lives. Millions! Think of the thrill of saving just one person’s life – then multiply that by millions. … Yet this was the most boring panel I’ve ever been on – ever. So boring even I couldn’t bear it.

几年前,我去瑞士达沃斯旁听一个全球健康问题论坛,会议的内容有关于如何拯救几百万条生命。天哪,是几百万!想一想吧,拯救一个人的生命已经让人何等激动,现在你要把这种激动再乘上几百万倍……但是,不幸的是,这是我参加过的最最乏味的论坛,乏味到我无法强迫自己听下去。

What made that experience especially striking was that I had just come from an event where we were introducing version 13 of some piece of software, and we had people jumping and shouting with excitement. I love getting people excited about software – but why can’t we generate even more excitement for saving lives?

那次经历之所以让我难忘,是因为之前我们刚刚发布了一个软件的第13个版本,我们让观众激动得跳了起来,喊出了声。我喜欢人们因为软件而感到激动,那么我们为什么不能够让人们因为能够拯救生命而感到更加激动呢?

You can’t get people excited unless you can help them see and feel the impact. And how you do that – is a complex question.

除非你能够让人们看到或者感受到行动的影响力,否则你无法让人们激动。如何做到这一点,并不是一件简单的事。

Still, I’m optimistic. Yes, inequity has been with us forever, but the new tools we have to cut through complexity have not been with us forever. They are new – they can help us make the most of our caring – and that’s why the future can be different from the past.

同前面一样,在这个问题上,我依然是乐观的。不错,人类的不平等有史以来一直存在,但是那些能够化繁为简的新工具,却是最近才出现的。这些新工具可以帮助我们,将人类的同情心发挥最大的作用,这就是为什么将来同过去是不一样的。

The defining and ongoing innovations of this age – biotechnology, the computer, the Internet – give us a chance we’ve never had before to end extreme poverty and end death from preventable disease.

这个时代无时无刻不在涌现出新的革新—-生物技术,计算机,互联网—-它们给了我们一个从未有过的机会,去终结那些极端的贫穷和非恶性疾病的死亡。

Sixty years ago, George Marshall came to this commencement and announced a plan to assist the nations of post-war Europe. He said: “I think one difficulty is that the problem is one of such enormous complexity that the very mass of facts presented to the public by press and radio make it exceedingly difficult for the man in the street to reach a clear appraisement of the situation. It is virtually impossible at this distance to grasp at all the real significance of the situation.”

六十年前,乔治·马歇尔也是在这个地方的毕业典礼上,宣布了一个计划,帮助那些欧洲国家的战后建设。他说:”我认为,困难的一点是这个问题太复杂,报纸和电台向公众源源不断地提供各种事实,使得大街上的普通人极端难于清晰地判断形势。事实上,经过层层传播,想要真正地把握形势,是根本不可能的。”

Thirty years after Marshall made his address, as my class graduated without me, technology was emerging that would make the world smaller, more open, more visible, less distant.

马歇尔发表这个演讲之后的三十年,我那一届学生毕业,当然我不在其中。那时,新技术刚刚开始萌芽,它们将使得这个世界变得更小、更开放、更容易看到、距离更近。

The emergence of low-cost personal computers gave rise to a powerful network that has transformed opportunities for learning and communicating.

低成本的个人电脑的出现,使得一个强大的互联网有机会诞生,它为学习和交流提供了巨大的机会。

The magical thing about this network is not just that it collapses distance and makes everyone your neighbor. It also dramatically increases the number of brilliant minds we can have working together on the same problem – and that scales up the rate of innovation to a staggering degree.

网络的神奇之处,不仅仅是它缩短了物理距离,使得天涯若比邻。它还极大地增加了怀有共同想法的人们聚集在一起的机会,我们可以为了解决同一个问题,一起共同工作。这就大大加快了革新的进程,发展速度简直快得让人震惊。

At the same time, for every person in the world who has access to this technology, five people don’t. That means many creative minds are left out of this discussion — smart people with practical intelligence and relevant experience who don’t have the technology to hone their talents or contribute their ideas to the world.

与此同时,世界上有条件上网的人,只是全部人口的六分之一。这意味着,还有许多具有创造性的人们,没有加入到我们的讨论中来。那些有着实际的操作经验和相关经历的聪明人,却没有技术来帮助他们,将他们的天赋或者想法与全世界分享。

We need as many people as possible to have access to this technology, because these advances are triggering a revolution in what human beings can do for one another. They are making it possible not just for national governments, but for universities, corporations, smaller organizations, and even individuals to see problems, see approaches, and measure the impact of their efforts to address the hunger, poverty, and desperation George Marshall spoke of 60 years ago.

我们需要尽可能地让更多的人有机会使用新技术,因为这些新技术正在引发一场革命,人类将因此可以互相帮助。新技术正在创造一种可能,不仅是政府,还包括大学、公司、小机构、甚至个人,能够发现问题所在、能够找到解决办法、能够评估他们努力的效果,去改变那些马歇尔六十年前就说到过的问题—-饥饿、贫穷和绝望。

Members of the Harvard Family: Here in the Yard is one of the great collections of intellectual talent in the world.

哈佛是一个大家庭。这个院子里在场的人们,是全世界最有智力的人类群体之一。

What for?

我们可以做些什么?

There is no question that the faculty, the alumni, the students, and the benefactors of Harvard have used their power to improve the lives of people here and around the world. But can we do more? Can Harvard dedicate its intellect to improving the lives of people who will never even hear its name?

毫无疑问,哈佛的老师、校友、学生和资助者,已经用他们的能力改善了全世界各地人们的生活。但是,我们还能够再做什么呢?有没有可能,哈佛的人们可以将他们的智慧,用来帮助那些甚至从来没有听到过”哈佛”这个名字的人?

Let me make a request of the deans and the professors – the intellectual leaders here at Harvard: As you hire new faculty, award tenure, review curriculum, and determine degree requirements, please ask yourselves:

请允许我向各位院长和教授,提出一个请求—-你们是哈佛的智力领袖,当你们雇用新的老师、授予终身教职、评估课程、决定学位颁发标准的时候,请问你们自己如下的问题:

Should our best minds be dedicated to solving our biggest problems?

我们最优秀的人才是否在致力于解决我们最大的问题?

Should Harvard encourage its faculty to take on the world’s worst inequities? Should Harvard students learn about the depth of global poverty … the prevalence of world hunger … the scarcity of clean water …the girls kept out of school … the children who die from diseases we can cure?

哈佛是否鼓励她的老师去研究解决世界上最严重的不平等?哈佛的学生是否从全球那些极端的贫穷中学到了什么……世界性的饥荒……清洁的水资源的缺乏……无法上学的女童……死于非恶性疾病的儿童……哈佛的学生有没有从中学到东西?

Should the world’s most privileged people learn about the lives of the world’s least privileged?

那些世界上过着最优越生活的人们,有没有从那些最困难的人们身上学到东西?

These are not rhetorical questions – you will answer with your policies.

这些问题并非语言上的修辞。你必须用自己的行动来回答它们。

My mother, who was filled with pride the day I was admitted here – never stopped pressing me to do more for others. A few days before my wedding, she hosted a bridal event, at which she read aloud a letter about marriage that she had written to Melinda. My mother was very ill with cancer at the time, but she saw one more opportunity to deliver her message, and at the close of the letter she said: “From those to whom much is given, much is expected.”

我的母亲在我被哈佛大学录取的那一天,曾经感到非常骄傲。她从没有停止督促我,去为他人做更多的事情。在我结婚的前几天,她主持了一个新娘进我家的仪式。在这个仪式上,她高声朗读了一封关于婚姻的信,这是她写给Melinda的。那时,我的母亲已经因为癌症病入膏肓,但是她还是认为这是又一个传播她的信念的机会。在那封信的结尾,她写道:”你的能力越大,人们对你的期望也就越大。”

When you consider what those of us here in this Yard have been given – in talent, privilege, and opportunity – there is almost no limit to what the world has a right to expect from us.

想一想吧,我们在这个院子里的这些人,被给予过什么—-天赋、特权、机遇—-那么可以这样说,全世界的人们几乎有无限的权力,期待我们做出贡献。

In line with the promise of this age, I want to exhort each of the graduates here to take on an issue – a complex problem, a deep inequity, and become a specialist on it. If you make it the focus of your career, that would be phenomenal. But you don’t have to do that to make an impact. For a few hours every week, you can use the growing power of the Internet to get informed, find others with the same interests, see the barriers, and find ways to cut through them.

同这个时代的期望一样,我也要向今天各位毕业的同学提出一个忠告:你们要选择一个问题,一个复杂的问题,一个有关于人类深刻的不平等的问题,然后你们要变成这个问题的专家。如果你们能够使得这个问题成为你们职业的核心,那么你们就会非常杰出。但是,你们不必一定要去做那些大事。每个星期只用几个小时,你就可以通过互联网得到信息,找到志同道合的朋友,发现困难所在,找到解决它们的途径。

Don’t let complexity stop you. Be activists. Take on the big inequities. It will be one of the great experiences of your lives.

不要让这个世界的复杂性阻碍你前进。要成为一个行动主义者。将解决人类的不平等视为己任。它将成为你生命中最重要的经历之一。

You graduates are coming of age in an amazing time. As you leave Harvard, you have technology that members of my class never had. You have awareness of global inequity, which we did not have. And with that awareness, you likely also have an informed conscience that will torment you if you abandon these people whose lives you could change with very little effort. You have more than we had; you must start sooner, and carry on longer.

在座的各位毕业的同学,你们所处的时代是一个神奇的时代。当你们离开哈佛的时候,你们拥有的技术,是我们那一届学生所没有的。你们已经了解到了世界上的不平等,我们那时还不知道这些。有了这样的了解之后,要是你再弃那些你可以帮助的人们于不顾,就将受到良心的谴责,只需一点小小的努力,你就可以改变那些人们的生活。你们比我们拥有更大的能力;你们必须尽早开始,尽可能长时期坚持下去。

Knowing what you know, how could you not?

知道了你们所知道的一切,你们怎么可能不采取行动呢?

And I hope you will come back here to Harvard 30 years from now and reflect on what you have done with your talent and your energy. I hope you will judge yourselves not on your professional accomplishments alone, but also on how well you have addressed the world’s deepest inequities … on how well you treated people a world away who have nothing in common with you but their humanity.

我希望,30年后你们还会再回到哈佛,想起你们用自己的天赋和能力所做出的一切。我希望,在那个时候,你们用来评价自己的标准,不仅仅是你们的专业成就,而包括你们为改变这个世界深刻的不平等所做出的努力,以及你们如何善待那些远隔千山万水、与你们毫不涉及的人们,你们与他们唯一的共同点就是同为人类。

Good luck.

最后,祝各位同学好运。

(完)

下载PDF格式全文(zip文件,208K)

 

 

 

 

 

 

 

 

 

跳至工具栏