Shell和Sql都是日常工作中经常使用的工具,发现LeetCode还有一些ShellSql问题,由于项目中写Shell和Sql不是很多,练习的时候有些题目还稍微遇到了一点困难,记录如下。

Shell

192. Word Frequency

难度:Medium
题目大意:

  • 写一个bash脚本计算word.txt文件中每个单词出现的频率
  • 只存在小写字母单词表,单词只使用一个或是多个空格分割
  • 输出频率时候按照降序排列,由于保证单词的频率相互不重复,不用考虑再使用字典序做二次排序

示例输入:

1
2
the day is sunny the the
the sunny is is

示例输出:

1
2
3
4
the 4
is 3
sunny 2
day 1

使用sort/uniq计算频率

1
cat words.txt | tr -s ' ' '\n' | sort | uniq -c | sort -r | awk '{ print $2, $1  }'
  • tr -s : 将空格替换为换行,其中-s --squeeze-repeats指明将连续的空格视为一个空格
  • sort : 按照字典序排序,为统计频率做准备,因为uniq只能统计连续出现的单词
  • uniq -c : 将排序后单词序列中连续出现的重复单词去重,-c将重复次数输出
  • sort -r : 按照频率降序排列结果
  • awk : 将输出结果的第一栏和第二栏调换输出

仅仅使用awk和sort

awk功能非常强大。

1
awk '{for(i=1;i<=NF;i++) a[$i]++} END {for(k in a) print k,a[k]}' words.txt | sort -k2 -nr

  • awk的对于每一行生效的指令中,对于每一行的每一栏的单词,将他们统计到map中
  • awk最后指令,将单词与频率输出
  • sort -k2 -nr : 使用第二栏的数据,进行降序排序

194. Transpose File

难度:Medium
题目大意:

  • 写一个bash脚本转置file.txt给出单词的矩阵
  • 单词只使用一个空格分割

示例输入:

1
2
3
name age
alice 21
ryan 30

示例输出:

1
2
name alice ryan
age 21 30

awk

还是继续awk大法好,awk其实类似于一个文件处理的编程框架。
awk和sed使用好,比直接写shell和使用各种命令进行管道叠加要效率高并且可读性高。

1
2
3
4
5
6
7
8
9
10
11
12
13
awk '{
row=NR;
col=NF;
for(i=1;i<=NF;i++) a[NR, i]=$i;
}
END {
for(i=1;i<=col;i++) {
printf("%s", a[1, i]);
for(j=2;j<=row;j++)
printf(" %s", a[j, i]);
print "";
}
}' file.txt

直接将单词矩阵存下来,然后转置输出。

Sql

176. Second Highest Salary

难度:Easy
题目大意:

  • Employee表中选出第二高的薪水记录
  • 如果不存在第二高的记录,返回null
1
2
3
4
5
6
7
+----+--------+
| Id | Salary |
+----+--------+

| 1 | 100 |
| 2 | 200 |
| 3 | 300 |
+----+--------+

1
2
3
select ifnull(
(select distinct Salary from Employee order by Salary desc limit 1,1)
, null) as SecondHighestSalary

使用ifnull函数进行记录是否为空的判断。

178. Rank Scores

难度:Medium
题目大意:

  • 用Sql来为分数分级,对于相同的分数,分为同一级,下一级和前一级别连续编号。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
+----+-------+
| Id | Score |
+----+-------+

| 1 | 3.50 |
| 2 | 3.65 |
| 3 | 4.00 |
| 4 | 3.85 |
| 5 | 4.00 |
| 6 | 3.65 |
+----+-------+


输出:
+-------+------+

| Score | Rank |
+-------+------+

| 4.00 | 1 |
| 4.00 | 1 |
| 3.85 | 2 |
| 3.65 | 3 |
| 3.65 | 3 |
| 3.50 | 4 |
+-------+------+

1
2
3
4
5
6
select Score,
( @rank := @rank + ( @prev <> (@prev := Score) ) ) as Rank
from
(
select Score from Scores order by Score desc
) A, (select @rank := 0, @prev := -1) Init

参考他人解法,使用零时表中的两个变量,分别记录分级编号和上一个分数,方便判断是否分数相同。

180. Consecutive Numbers

难度:Medium
题目大意:

  • 用Sql选出连续出现三次即以上的数字
1
2
3
4
5
6
7
8
9
10
11
+----+-----+
| Id | Num |
+----+-----+
| 1 | 1 |
| 2 | 1 |
| 3 | 1 |
| 4 | 2 |
| 5 | 1 |
| 6 | 2 |
| 7 | 2 |
+----+-----+
1
2
3
4
select distinct Num as ConsecutiveNums from (
select Id, Num, ( @rank := if(@prev = (@prev := NUM), @rank+1, 1) ) as Rank
from Logs, (select @rank := 1, @prev := -1) Init
) as temp where Rank = 3;

参考178的思路,将每条记录按照是否连续进行编号,再把所有有三次连续出现的不重复数字选出。

184. Department Highest Salary

难度:Medium
题目大意:

  • 挑选出每个部门最高薪水的记录
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

Employee:
+----+-------+--------+--------------+

| Id | Name | Salary | DepartmentId |
+----+-------+--------+--------------+

| 1 | Joe | 70000 | 1 |
| 2 | Henry | 80000 | 2 |
| 3 | Sam | 60000 | 2 |
| 4 | Max | 90000 | 1 |
| 5 | Janet | 69000 | 1 |
| 6 | Randy | 85000 | 1 |
+----+-------+--------+--------------+


Department:
+----+----------+

| Id | Name |
+----+----------+

| 1 | IT |
| 2 | Sales |
+----+----------+


输出:
+------------+----------+--------+

| Department | Employee | Salary |
+------------+----------+--------+

| IT | Max | 90000 |
| Sales | Henry | 80000 |
+------------+----------+--------+

解法1:900ms

1
2
3
select d.name as Department, e.Name as Employee, Salary
from Employee e inner join Department d on e.DepartmentId = d.Id
where Salary = (select max(Salary) from Employee where DepartmentId = d.Id)

比较暴力,有个Employee记录都有一个冗余的子查询。

解法2:600ms

1
2
3
4
5
6
7
8
select t3.Name as Department, t2.Name as Employee, t1.Salary as Salary
from
(
select max(Salary) as Salary, DepartmentId
from Employee
group by DepartmentId
) t1, Employee t2, Department t3
where t1.Salary = t2.Salary and t1.DepartmentId = t2.DepartmentId and t1.DepartmentId = t3.Id

先把每个部门的最高薪水一起聚合算出,再全连接表并筛选出部门和薪水都匹配的员工记录。

185. Department Top Three Salaries

难度:Hard
题目大意:

  • 在上一题基础上,挑选出每个部门前三高薪水的记录
  • 如果少于三条记录,则只显示存在的记录
1
2
3
4
5
6
7
8
9
select t1.Name as Department, t2.Name as Employee, t2.Salary as Salary
from(
select Name, ifnull((
select distinct Salary from Employee e
where e.DepartmentId = d.Id
order by Salary desc limit 2,1)
, 0) as Salary, Id as DepartmentId from Department d
) t1, Employee t2
where t1.Salary <= t2.Salary and t1.DepartmentId = t2.DepartmentId

和上一题思路类似,先选出第三高的薪水,再全连接筛选。

联网是一切的开始。学校的校园网建设还是比较完善的。从费用上来说每个月20G免费流量,就算用超价格也还是比较合理的;管理界面有查看流量报表、查看在线终端和登陆日志的功能,甚至能自动下线一些可能是蹭网的设备,考虑得很周到,用招行手机网银充值页很方便;宿舍每个床位都有网口,可以通过Web认证登陆,图书馆等公共场所还有免费的热点覆盖,速度也还不错。

所以为什么我要想方设法节省流量的开支呢?

  • 开支:在一周内我就把20G免费流量几乎用光,在9月的第一天用掉了1.5G流量,按照这个趋势下去,每个月开支。。。
  • 良好的习惯:从我爸身上学到的精算流量、和运营商斗智斗勇的良好习惯,必须想方设法节省流量开支。
  • 本科期间的陋习:本科期间使用了一些方法节省自己的流量开支,现在需要增加这个开支就心里痒痒的。
  • 更好的学习与生活环境:如果上网需要担心开支问题,势必会影响获取网络上各种优质资源的积极性。
  • 其他:顺带解决在宿舍无法使用路由器访问IPv6网络的困惑。

于是在同学和学长的提醒下,并大概分析了我的流量都花到了什么地方后,我终于意识到了IPv6免流量的优势,并想着如何最大程度发挥IPv6的优势。

通过路由器也能获取到IPv6地址

宿舍的一个网口需要同时接入手机、电脑等设备,就得使用一个无线路由器了。由于之前我一直偏好将路由器设置为router模式,所以在路由器的内部网路中,我的设备都没有IPv6地址。上PT下载时,还必须将网线直插到电脑上,非常麻烦。之前我一直认为这是路由器不支持IPv6的表现,但稍微考虑后发现如果路由器只是作为AP,充当一个无线交换机的角色后,电脑手机是可以直接从校园网自动获取到独立的IPv6地址的,虽然这样稍微有点不安全,因为我习惯用路由器做一个保护,防止其他用户可以直接访问到我电脑的端口。
使用的路由器是mini型的低端路由器,切换成为AP模式后就无登陆密码保护了,这时候需要手动调整电脑IP到路由器使用的子网段,再访问路由器管理界面设置密码。

1
$ sudo ifconfig wlan0 192.168.1.100 netmask 255.255.255.0

我的流量都去哪儿了?

虽然并没有详细的统计结果,但我主要耗费的流量在于

  • 看Youtube每日订阅的视频,耗费了大量的流量,并且由于在VPS上开了冗余发包(用于低质量网路环境加速),可能实际流量是视频流量的2-3倍。
  • 其他外网网站访问流量,刷推、查看RSS订阅、搜索和Google办公套件等。
  • 更新电脑和手机软件,耗费不多,但也是比较大的一部分开销。
  • 偶尔看国内视频,耗费不多。
  • PT下载电影,已经使用IPv6了。
  • 国内的网站访问流量。

由于使用私人梯子,并且看Youtube等外网流量都是走梯子的,所以如果我和VPS之间的流量转换为IPv6,就应该能节省一大笔流量了。并且从这个思路看,也可以找国内的IPv6代理中转来节省在国内的流量。

配置影梭监听IPv6地址

使用的搬瓦工VPS申请IPv6地址非常容易,在控制面板 > Admin functions > IPv6 Addresses 内添加地址即可,几分钟生效。
由于IPv6地址目前几乎是使用不完的,可以申请到一个子网的全部地址,不过目前使用其中一个就行了。

add_ipv6

然后启动两个影梭服务器实例,分别监听IPv4和IPv6地址:

1
2
3
4
5
6
"server":"0.0.0.0" # IPv4 地址
"server":"::" # IPv6 地址

# 启动服务器
/usr/bin/ss-server -c /etc/shadowsocks/config.json -a root -u -f /var/run/shadowsocks/shadowsocks.pid
/usr/bin/ss-server -c /etc/shadowsocks/config6.json -a root -u -f /var/run/shadowsocks/shadowsocks6.pid

最后在电脑上启动两个客户端,分别连接两个服务器,并监听两个本地端口,这样方便在本机没有IPv6地址的时候进行切换。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# local hosts
x.x.x.x yqf.me
y:y:y:y:y:y:y:y yqfv6.me

# v4
"server": "yqf.me",
"local_port": 11000,

# v6
"server": "yqfv6.me",
"local_port": 11001,

# 启动客户端
ss-local --fast-open -c /path/to/config.json &
ss-local --fast-open -c /path/to/config6.json &

至此所有外网的流量就走IPv6了。

电脑软件更新

  • 通过命令行指定使用IPv6。

    1
    sudo apt-get -o Acquire::ForceIPv6=true install pkg
  • 通过更换校园网内部的源来节省这一部分流量,看到校园内还有AOSP的镜像,表示万一有这方面需求可以节省很多流量了。

通过Chrome查看DNS缓存记录

可以通过chrome://net-internals/#dns查看一下有哪些网站已经支持了IPv6,youku没有支持。

迷你主机

缘由

外公家的电脑已经十分老旧,还是奔腾双核,1G内存,100G机械硬盘的配置。每次我去外公家帮忙处理电脑使用上的疑问时,都被这台老古董卡到不行,慢慢地我发现外公使用电脑的频率也下降了,便承诺实习工资给外公更新一个更好的主机。

前两天突然想起这个承诺,也就没有顾上和我爸进行更加深入的讨论,准备直接一手包办了这件事情。

选择

外公的需求很简单,上网:看股票、新闻、邮票信息,偶尔电影;游戏:在线的象棋、围棋等;照片浏览:儿女拷来的照片可以自行浏览;节假日的娱乐:可能会被家里亲戚用来上网娱乐。

本来我预想我接下来一定要自行完整地配置一台主机,不过由于此处不是自用,并且之前看到网上有不少对mini主机的讨论,也看到了一些测评博文,便想这次还是偷懒一下了。

询问店家节前还发不发货,结果赶上最后一天发货,便没有多想,¥1610下单了标准的一个版本。

  • CPU:Intel i5 4258U,2C4T,默频2.4Ghz,睿频2.9Ghz,锐炬5100核显。比我笔记本的3317U要好,估计是直接性能过剩了
  • 内存:镁光 4G DDR3 1866Mhz
  • 硬盘:东芝 128G SSD M.2接口

开箱与简单评测

下单后就没有去管这件事情,顺丰包邮,两天就到了,由于直接是套餐,系统也已经装好,基本上是开箱即用。

尺寸

尺寸很小,和JD卡的对比。分量倒不算很轻,是全铝机箱,由于是无风扇被动散热,十分静音,跑分时能听到电流声音。

内部

虽然不需要升级配置了,还是拆开了底部,发现升级余地还是很大的,可以继续加内存,M.2硬盘和sata硬盘。

外部接口十分丰富:

  • 两个HDMI接口,店家还附赠了HDMI-VGA转接线和HDMI延长线
  • 内置的300M无线网卡
  • 两个以太网口
  • 背部四个USB2.0口,前部四个USB3.0口
  • 音频输入输出口和红外接收器(也偷懒没尝试)

早上到货开箱后,发现是Win7 旗舰版,开箱即用,便进行了系统备份和简单的跑分:

跑分

只知道应该要比我笔记本性能好,而我现在的小本使用状态良好,完全没有升级的欲望。

上门服务

所以下午就开心地直接提去外公家上门服务了,带了我妈买的羽绒服给外婆,mini主机给外公,两位老人都十分开心。

首先是进行老主机的数据备份,需要拷贝10G的老照片出来,由于硬盘是3.5英寸的而我没有USB盒来直接读,只好以后再进行照片的拷贝。

然后安装了手写板的驱动、棋牌游戏等,并和外公一起试用成功。

最后简单地了解了外公的其他需求,如看股票和看邮票,添加了游览器的相关网站的收藏。

外公虽然八十多高龄,但还是非常认真地学习电脑的使用,经常在线棋牌游戏和浏览新闻,这里真是需要赞一个,更换了更快的电脑后,对于新技术新知识的获取应该体验更佳了。

其他

  • 机械键盘:雷柏V500,绝对的入门款,准备写够100篇博客再奖励自己一个中端键盘。
  • 一代小米手环:每天争取一万步,日积月累养成锻炼的习惯。
  • 小米路由器mini:放家中,插上USB移动硬盘后可以远程下载,结合小米盒子便打造出一个粗糙的家庭NAS,分享和串流影片十分方便。
  • 各种USB 3.0硬盘盒:把各种硬盘换盒后,终于获得了新生。

持续半年的实习告一段落,企业实习不仅仅是我们学习技术、锻炼能力的绝佳机会,更是从另一个角度深入理解整个行业的绝佳机会,我也非常珍惜这半年的实习机会。现将一些实习报告中一些片段摘出。

企业背景以及企业文化

我成为Intel实习生经过

我在2014年6月至11月期间参加了第七届Intel杯全国大学生软件创新大赛,并带领团队获得一等奖。2015年4月份开始,大家都开始投实习面试的时候,我通过Intel教育微博,获取到了Intel中国招聘实习生的消息,当时抱着试试看的心理投了简历。
三轮电话面试询问基础的计算机基础知识后,我来到Intel亚太研发中心on site面试,被带到三楼的会议室,在两个小时和四位同事交谈并白板编程后,我也大概知晓这只团队的主要兴趣是在Intel平台上,前沿的Web技术的优化。大致分为三个方向:Web RTC、Javascript虚拟机和Chromium渲染、内存和功耗的优化及应用,对这三个方向我都有一定的兴趣。小组的兴趣广泛,也在积极在Web技术与Intel平台的整合上寻求新的方向。
Intel效率很高,第二天便通知可以来Intel做实习生。由于之前学院并没有学长去上海Intel实习的经历分享,我便想打开这一局面,寻求去一家大家不那么熟悉的公司进行实习,也方便日后的相互分享。随后得知将在SSG/STO/WTO下进行实习,对开源浏览器Chromium在Intel平台上进行性能和能耗优化。我准备与七月开始进行半年的实习,随后和Manager建立了邮件联系。

Intel的历史

在来Intel之前,我对Intel产品线和历史了解很少,仅限于我们家购入的第一台电脑是奔腾4,那大概是Intel增长最快的一个时候,还有我的笔记本是Core i5,当时也完全没去研究其制程架构、主频三缓等,以为都是一样的。在平常浏览业界新闻时,看到近年Intel出了很多人机交互和物联网的新探索,认为技术实力酷炫并实际推向了市场。

Intel是全球最大的半导体芯片制造商,它成立于1968年,具有44年产品创新和市场领导的历史。1971年,Intel推出了全球第一个微处理器。微处理器所带来的计算机和互联网革命,改变了整个世界。Intel公司在随着个人电脑普及,Intel公司成为世界上最大设计和生产半导体的科技巨擘。为全球日益发展的计算机工业提供建筑模块,包括微处理器、芯片组、板卡、系统及软件等。这些产品为标准计算机架构的组成部分。业界利用这些产品为最终用户设计制造出先进的计算机。Intel公司致力于在客户机、服务器、网络通讯、互联网解决方案和互联网服务方面为日益兴起的全球互联网经济提供建筑模块。

Intel公司的构成

从我实习这几个月的浅显的观察来看,Intel至少由以下五个核心方面构成:芯片设计,软件服务,生产制造,市场营销和人力资源,风险投资。

芯片设计

Intel的产品线覆盖了信息产业中高利润的一部分,服务于数据中心、个人电脑、移动设备和物联网可穿戴设备的CPU,其中目前家喻户晓的酷睿处理器,服务器上使用的至强处理器,移动平台上的凌动处理器和物联网中的Intel伽利略/爱迪生开发板,小如指甲的Curie SOC。其中一些已经不单纯是CPU了。Intel之前退出内存领域后,又积极进行固态硬盘的研发,目前是数据中心的首选和高端固态硬盘的代表,并且也在积极进行新存储技术的研发。这里引用新闻,Intel将在2016推出一种新存储器技术,这在公司内部也引发了讨论:

Intel去年最重大的科技成果不是推出14nm工艺的Skylake处理器,而是3D XPoint存储芯片,性能是当前水平的1000倍,但它可不是NAND非易失性闪存这么简单,实际上能带来一次电脑革命,因为它还可以作为DIMM插槽的内存使用。Intel准备在2016年开始推出基于3D XPoint技术的存储产品,现在曝光的就是容量高达6TB的DIMM插槽产品,很快电脑内存就能跑步进入TB时代了。

听到上述新闻,似乎计算机的发展轨道将发生变化,很多我们之前认为的架构、优化方法都将被打破。Intel的持续发展的确非常需要这样的前沿技术壁垒。

Intel还研发配套的芯片组,母板样例和以太、无线网卡。也做一些高端的PC周边产品。Intel近年也加大了多种形态PC的研发,Intel NUC、Compute Stick、2 in 1设备都显示了其活力,一些软硬件结合的解决方案如Real Sense实感技术提供了更好的人机交互。值得一提的是由于占据CPU设计,硬件上的很多标准也是由Intel进行主导和推动的。

软件服务

我目前实习所在的Intel亚太研发中心便是主要进行软件服务开发的。Intel的很大一部分软件投入在开源社区中,如Linux、Hadoop、OpenStack等,其IOT部门似乎开源社区的一大贡献团队,受到广泛的赞誉。参与软件标准的制定,如Html5。也积极进行推行自己的解决方案,如ICC编译器、V-Tune等方便开发者进行性能调优。我目前的实习部门便是努力在Intel平台上进行开源浏览器Chromium的性能优化。

生产制造

Intel是少数拥有中央处理器芯片制造工艺的厂商,工艺水平常年领先同行半代到一代,自行设计自行生产,目前Intel依旧不断推动着摩尔定律,生产更加高性能能耗低的芯片。

市场营销和人力资源

Intel是一家跨国公司,拥有很多的雇员,并自行售卖芯片给OEM厂商和消费者。这些部门和其他后勤部门为Intel的发展、繁荣起到了一定影响。

风险投资

Intel组建了Intel Capital来管理所有的风险投资,最近Intel收购和投资动作频频,投资Yuneec无人机,德国无人机 Ascending Technologies,量子计算机,170亿美元收购Altera等等。所以我们可以发现Intel也在增强自己的资源整合优势,占领未来的热门技术壁垒。

Intel公司目前的SWOT(优势/劣势/机遇/挑战)

在2015年底,manager用SWOT总结我们全组工作。这里我也尝试总结目前Intel的SWOT。

优势

Intel是少数几家还有fab的芯片设计厂商了,其制造工艺的技术壁垒让它的产品非常具有竞争力,其商业策略也倾向于追求高利润的市场,只做利润最高的核心芯片制造,专攻新技术形成壁垒。其目前强大的资源整合能力,不论是其他厂商和消费者,能提供非常好的客户体验,占领着行业上游,是规则的制定者。并且依旧在收购和投资新技术,涉及面广阔。

劣势

PC市场近年一直萎缩,Intel之前最主要的利润来源增长乏力,并且在PC和DC市场上,Intel占有绝对优势,AMD乏力,导致竞争匮乏,市场缺乏了活力。过于依赖这两个市场会导致很大的问题。

在现在一片红海的移动领域,Intel份额很小,受到了ARM商业模式和高通、三星、苹果等厂商修改版ARM芯片的联合冲击,芯片可选种类和性能能耗没有太多竞争力,并且生态也难以建立起来,比如很多优化只针对ARM平台。移动领域中,不仅仅是卖CPU,还在售卖通信方案、媒体处理甚至指纹识别、成像优化都被集成进来,这方面Intel的产品看起来就不如其他厂商的丰满,而且由于节奏太慢(还按照自己做桌面CPU的脚步),不得不说是在被吊打。这目前是Intel难以打开的一个局面。

在显卡盛行的时代,虽然Intel核心显卡已经能胜任大多数人的日常需求,但现在逆势增长的游戏本领域,高端显卡的利润可能已经高于CPU,并且高端显卡目前也通过GPGPU、CUBA等技术抢占CPU的地盘。对于通过显卡等进行的加速计算,Intel显卡性能不够,软件支持也不足,没有很好的解决方案。不知道收购了Altera的Intel能否带来一些给予FPGA的新的解决方案,为特定场景高度优化的SOC可能会方便应用到无人机、可穿戴等领域。

挑战

最大的挑战除了商业模式,竞争对手,生态等,还有Intel能否改变自己,变得快起来,变得新奇酷炫,变得技术壁垒丰厚。不仅仅守着之前的成就,而积极利用自身资源开拓新的战线,如以前放弃内存,现在又用新技术做出内存速度的非易失性存储,这便是一个挺好的例子。

机遇

目前游戏本、DC的市场增长逆势,可以成为一大增长点。4G时代到来,高通霸主地位可能被撼动,Intel在移动芯片上也在不断努力,从一些大客户如苹果、小米等入手,或许能打开局面。移动操作系统不再单一,Windows和Chrome OS目前也能较好支持移动设备,这带来了x86平台在移动平台上的机遇。
在IOT方向,Intel的产品得到好评,并且已经投资了多家公司,智能连接万物是Intel的一个机会。Intel的新技术的发出,也将推动行业发展,并带来丰厚的收益。Intel的软件团队虽然支持客户很好,但还需要做很多Inside out的努力,提升Intel在软件行业的知名度。

其他

  • New Employee Orientation:一个两天的活动,进行Intel历史、企业文化的介绍和团建小游戏。
  • Site Update Meeting:由中国区的总经理主持,分析公司和Site的运行状态,现场QA。

实习环节中的问题和具体解决方案

分享Golang使用经验

每周的Code Study上,小组总会预先安排一个话题和主讲人。我主讲Golang,向团队成员介绍我是怎么开始用Golang的,介绍了一个简单的Hello World程序,紧接着从Golang现在发展得怎样、Golang的特性、官方工具链与他们的目的等方便大致介绍了Golang的入门使用,最后结合我自己写的几个程序跑分,来验证为什么我最终选择Golang作为我代理服务器实现的主要语言。

Golang有不少优点,它是编译,静态类型语言。有垃圾回收机制、丰富的标准库、好用的工具链,并在语言层面支持并发、内嵌C支持、向前兼容。这让它效率高,方便部署,拥有类似动态语言的特性,网络库等方便web开发,方便统一开发规范,让并发程序非常好写,并且语言底层注重性能和重用,方便升级最新的语言版本。

非常高兴和团队分享了我是如何选择我代理服务器的主语言的历程,并获得了他们的肯定。当时我在获取他们的开发需求后,便提出了这个语言,Intel的员工非常开放,并不对语言技术提出限制,而是非常鼓励我先进行一下探索,并拿出数据说话,这让我非常佩服Intel这种重视数据和实时,积极听取大家意见的观念。

分享行业热点:React

在本周的News Update上,我提供了React & React Native的foil供大家学习。主要介绍了这个Facebook出的野心勃勃的前端框架,React Native 把重点放在所有开发人员关心的平台的开发效率上—开发者只需学习一种语言就能轻易为任何平台高效地编写代码。Facebook 在多个应用程序产品中使用了React Native,并将继续为 React Native 投资。

我接下来从Component,Virtual DOM和Unidirectional Data Flow三个重点介绍了react的核心思想,并把它和HTML5应用,Intel的Crosswalk、Phone Gap/Cordova等技术进行了比较。

会议中我们从浏览器开发者的角度和应用使用者的角度来分析了各个框架的优劣,并承认了React所具有的一点优势,我们也探讨了从Intel的优势:芯片角度来DOM的渲染进行优化,并产生了一些有意义的讨论。

会后Manager让我们有时间可以进行新技术的尝试,我后期尝试了React Native技术,来构建原生的Android应用,虽然并没有开发真实的应用,不过开发体验很顺畅,推荐在小型实验性项目中进行进一步的探索。

这是我第一次进行组内的News Update分享,内容都是组内成员精心挑选出的业界新闻或是技术分享,之前听到过一些Intel的新技术和黑科技宣传,或者是竞争对手的设备更新消息,mentor非常鼓励我进行这次分享,并认为我将几个Intel的工具拿出来对比很好,提醒Intel员工注意到了最新的业界动向和资讯。

SWPC软件峰会

一年一度的英特尔亚太研发中心软件峰会到来,我们一直在开发的工具由于进展不错,被Manager鼓励进行主题演讲,并可以共享给其他团队的人进行测试使用。不过这个测试使用由于项目的部署稍显复杂,便使用了虚拟机搭建环境,会后准备直接分发虚拟机镜像便可以让其他人使用了。
由我来封装一个搭建好环境的虚拟机,并协助mentor准备主题演讲的Foil,这里我将我新框架的思路和mentor进行了详细的讨论,在他的foil上我填写了更多的细节,并由我俩一起修改。Manager也参与到foil的制作和修改过程中,他在邮件中详细指明了自己的修改意见,和我们一起迭代修改foil。

会议前一天,宣传的邮件便发向了几个其他小组,下午开始的主题演讲来得人并不是很多,但我们还是精心完成了整个宣传过程,并给出两份拷贝。我们小组的十多位同时也都到场捧场,我们也借此机会详细解释了我们工具的使用和一个很好的优化故事。
我们也去参加了一些其他小组的主题演讲,在他们booth旁边,查看他们作品的使用情况,并与他们交流,整个活动像是一个内部的交流大会,平时垂直分割的各个team终于有机会面对面地交流相互的工作,增加了解,激发合作和创新。

自己的工作能参与在整个site的软件峰会中,非常高兴,整个准备过程不到一周,安排合理,最终的演讲十分顺利,我的软件演示也没有出现纰漏。企业内部增进不同team的相互交流,激发新的增长,让内部的想法让更多人知道,这对于Intel的持续创新是十分重要的。

其他

  • 主持自己项目的Design Review和Code Review
  • 性能优化,从profile数据入手,最后用数据说话
  • 锻炼Root Cause Bug的能力
  • 跟随mentor进行客户支持

自己的体会

技术体会

注重数据,注重优化

在和mentor、manager交流时,我曾经几次想直接说我的一个看法,他们都告诫我,不要着急下这么一个结论,需要拿出数据进行分析做出判断。在邮件中,我们都会附带有我们得出结论的数据,这样才能让其他的同事信服。数据在Intel是十分重要的,这也是一种很严谨的工程态度。某些重要的决策不是拍拍大脑就可以做出的,做出预测、实验、收集数据、分析、再验证才能做出结论。

Intel的工程师非常注重性能和优化,当然我们也注重需求和复杂度,如果只是一个很少使用的小脚本,不断追求高性能稍显无意义。对于程序的性能问题,我们会使用Intel或是其他的程序运行时分析工具,分析热点代码、关键路径等,再对这些20%的瓶颈代码进行有目的的优化,这样才能做到省时省力、事半功倍。

分解步骤,动态规划

经常我们在讨论项目接下来的安排时,总是感觉一团乱麻,而这时候manager会在白板前,大致画出我们的计划,然后按照难易程度、优先级,划分成为几个小的子任务,有的任务非常关键,有的可以并行,有点也许可有可无只是锦上添花。然后我们相互谈到,划分阶段和每个人的具体任务分配,这样一套简单的流程下来,任务、时间节点、负责人都十分清楚,随后我们更新网上的SharePoint并互发邮件进行确认,这样安排就很有效率地完成了。

项目进行中,如果需要改动计划也比较简单。毕竟分阶段,如果完成到后面的阶段时,就已经是超出预期了,这样整个任务的风险管理很好,不会失控,通常还能超出预期,达到很好的效果和激励作用。

管理体会

主持一个有效的代码审查会议

我在给manager邮件说明我已经完成原型,可以进行一次代码审查了,但manager指出如果我们想进行一次优质的代码审查的话,还需要预先准备一下,因为我现在在做的工作已经不是一个单人的小项目了,而需要组内更加紧密地交流。需要先更新我项目的Wiki,并且等待反馈,因为组内同学需要一定的时间来部署、上手和验证我的原型,而此时我可以继续我后续的设计。

我还需要描述我设计中的概念和想法,这样我们才能进行代码审查的会议;在我们团队的公共的Wiki页面上创建一个我的项目主页,这样才能方便大家在会议前都尝试一下,提出更加具有针对性的意见。

从Manger的回信来看,我还需要在怎样表述我的思路,文档化我的设计上多下工夫,因为这并不是我一人的项目,在我完成初期的探索后,将我的设计很好的转化为team共有的knowledge也是非常重要的,通过design review,code study和wiki等进行一系列活动。

代码规范和在线代码审查

在之前的项目中,我对代码规范没有过多要求自己,虽然会进行重构,只是为了自己更容易理解,或是为了代码复用,对代码的美观、注释和其他行为规范都很缺乏,导致代码易读性很差,很难直接与其他人分享、开源,后来进行以库或组件、框架的形式发布,虽然美其名曰“封装好,提供接口”,但的确没法掩盖这个规范差的事实。

在这次实习中,我们的代码均使用Git管理,并结合内部的gerrit代码审查工具进行在线的评审。我之前在项目中曾经尝试和同学一起使用GitHub共同开发,但最终效果不好。于是我便抓住此次机会规范自己的代码和评审流程,享受和同事一同开发带来的乐趣。

第一次代码提交后,我在终端拿到一个在线Code Review网址,便急急忙忙邀请manager和mentor进行在线评审,评论可以在代码上直接看到,非常直观。总体上我代码注释不够,并且有些冗余的空格和tab建,导致在线查看难看。后来了解到需要去除这些冗余的代码空格,并使用4空格替换tab。我不是一个很喜欢折腾这些细节的人,便想找一个工具来帮助我在提交代码前自动进行代码的格式化,去除上述的瑕疵,这样符合要求,又省时省力。

很快我就找到了一些工具,并写了一个bash脚本来自动化这一流程,manager对此表示欣赏。

我代码的注释不够,我也在后续的提交中补了注释,但还是缺少一个统一的规范,虽然便于阅读的时候理解,但很难从代码注释中提炼开发文档出来,这个是我以后再开发大型项目时候需要注意的。

代码审查流程,我们push到一个review分支后,网上由对应的网页能查看,添加reviewer,随后可以在线批注,然后我不断提交patch修改,满意后reviewer LGTM(Looks good to me)然后才能merge。

个人评定

年终需要进行每个人的评定,由个人撰写自评并自评等级,再和manager一对一进行sync,最后由manager进行提交。Intel的待遇和个人的等级和每年评定挂钩,新人如果评为超出预期的话,个人等级和待遇都将得到巨大的提升,而老员工则更多注重等级的提升和年终奖、股票所带来的附加收益。评定可以和manager开诚布公地讨论,追求实事求是,我也看到有些非常努力和出色的员工最终获得了待遇和评定的多重奖赏。

其他体会

团队交流与建设

团队的组内交流机会不少,每周两次例会,敏捷会议追踪热点事情,状态汇报每周的进度、安排和问题。每周通常还有一次Code Study,按照预先指定的顺序,小组成员分别挑选和自己工作最相关的技术问题准备一个小时的交流会。比如我就和组内成员分享了我为什么要在我的项目中使用Golang和Golang的入门。会后还有评分机制,每年好评多的同事还能获得manager准备的小礼物。

正式员工还会有家属见面会,并且整个site还会主持公益项目,可跟随团队一起去献爱心。吃饭聚会喝喝咖啡也是少不了的,同事获得奖励,有同事要离开我们都会好好聚一下,席上大家交流气氛热烈,并会进行一些保龄球、台球等娱乐活动,增进团队感情。

每两个月的大组聚会,大组的所有成员会聚集在饭店或是大厅中,便享受饮品,便听各个组的状态汇报,听新员工介绍自己,并为本季度表现好的员工加油鼓劲。

给予实习生的氛围与态度

Intel给予实习生非常轻松的工作环境,不加班,周末也少有同事来公司加班,没有特别大的压力,大概是轻松的环境下人才更具有创造力。Intel笔记本处理器目前在走低功耗的路线,默认频率较低,小于2Ghz,不过其睿频功能允许处理器自动升频到3Ghz以上,只要其散热等参数允许,睿频功能其实也像是Intel的这种时间安排策略,激发员工的积极性,如果有责任在身并且条件允许,员工是乐于自我奉献的。

在实习内容的日程安排上,并没有出现“这件事的截止日期在某日,必须做到”这样的硬指标,而是我们一起商议时间表,发现不能如期的话及时反馈调整。整个时间安排由manager把控进度,如果你提前完成了计划,那很好,便可以商议一些之前安排以外的工作。

Intel实习生的胸牌和正式员工没有区别,所以在公司内部是一样对待的。你可以参与公司的各种活动,在项目中与其他同事友好平等的交流。并不会因为你是实习生就会降低对你的要求,或是阻碍你去获取资源,进行项目挑战。几次讨论项目,我们都迅速地找一个会议室,对着白板一边讲解自己的看法,一边涂涂写写,项目讨论得很快,很多异议会很快消除,比线上讨论高效多了。

MSR (Monthly Summary Report)等

每一个季度会有整个Site的Sync会议,每两个月大组会进行茶话会,而每月会进行月报。先由每个员工进行向小组内汇报,小组长总结完毕层层上报。我们可以看到自己父组织和其兄弟组织的汇总月报,这对我们了解其他组的进展,了解公司动向,谋求交流合作创新有很大帮助。

实习反馈

  1. 按照实习生的能力进行分配
    我对我整体的实习安排比较满意,但还是遗憾于没有时间深入,通常对于实习生比较安全的做法是让他们做已经很明确的周边任务(初级),做一些创新性的项目和工具(中级),不过失败的话影响不大,做一些比较明确但很重要的任务(中高级),做非常重要又极具挑战性的任务(高级)。

  2. 可以布置一些重要的任务
    对于我来说,如果能做一个比较重要的任务,将更具有参与感,比如Facebook刚入职的员工是可以去做修改首页bug的这种任务的。对于招聘实习生的管理者来说,可以收集一些相对较为简单,但代码能投入实际使用,比如提交给upstream的这种任务,交给实习生做,应该能极大提升实习生的存在感。

  3. 可以多考虑实习生的需求
    每个实习生都有些不同,相比于只是想着“我们要拉一个实习生进来完成某项项目“,不如看看小组和实习生共有的需求,然后有针对性的调整,以激发出实习生最大的能力。有助于实习生以后发展的项目,比如开源等,也是相当于提升实习待遇的。

上次参加黑客马拉松之前有一个想法,就是希望能为两个人异地同看一个在线视频提供更好的体验:进度同步,弹幕,实时涂鸦等等。还有更多的实时语言功能就其实直接使用现成的微信就好。这样看来,视频进度同步和播放/暂停和拖动进度条的指令同步是核心功能。

当初想的通信技术方案是搭建一个私有服务器,两个浏览器通过一个Bookmarklet注入脚本,Websocket通信,并由中间的私人服务器中转进行。视频控制准备强制将flash视频转为Html5播放,方便控制,不过拖着一直没去实现。

最近看到一个推荐Chrome插件的知乎回答,答主使用Chrome扩展注入脚本,使用Peer.js,底层是WebRTC通信。去中心服务器直接通信,的确方便很多,并且已经支持多个视频站,插件也已经在Chrome Web Store上架,并Github开源,试用后立即Star了。

不过应该还有很多功能可以加,查看代码后觉得可扩展性也很好,不过在那之前,我想也许应该支持更多的视频站、让视频同步的体验更好才是纯粹的。

Flash的视频控制

之前固执地认为Flash视频是不可与Javascript交互的,2014年HackShanghai的时候,我们需要控制优酷视频的播放,后来由颢神找到了获取视频地址的方法,便转Html5的方式播放。不过那次由于想给用户提供一个更好的体验,很多UI都重写了,视频更加一体地融合在网页中,而这是Flash播放器做不到的。在看coplay源码的时候发现某些视频站已经发布了可以直接使用的API,如优酷的PlayerPause(false);info = PlayerInfo();等,可以直接方便地控制,更多的视频站由于自身需要,也加上了对javascript的API,通常我们query到DOM中的flash节点后,可以调用一个方法,比如土豆的player.notify('play'),更多是类似player.pauseQiyiVideo()这样。

Flash节点没有办法遍历这些在Flash中对外暴露的方法,那是怎么获得这些API的呢,可能官网上有文档,懒得去找了,跟随网页上Javascript的蛛丝马迹也许也能猜到。

尝试添加芒果台的适配器

于是我便开始猜测芒果台的API,在众多Javascript中(看到不少typo)找到了和Flash节点的调用,比如c('hunantv-player-1').getActionLogInfo(),不过只是一些视频信息。

我又开始尝试跟踪console中的播放和暂停的log,不过log是从Flash中打出的,或者是eval获得的,无法追踪源头。最终发现了一点Javascript中供Flash调用的回调函数,也没用什么用。我便觉得可能芒果台没有提供对外的API了。

看来硬猜是效率很低的。

通过反编译获知Flash视频控制的API

回想起之前Flash被Adobe降低优先级的新闻,提到Flash是ActionScript语言编写的,并交由FlashPlayer执行,之前并没有Flash的编程经验,但感觉应该很类似Java和JVM,便搜索到了一个免费的SWF decompiler,于是兴致勃勃地试了一下。

ffdec

反编译以后几乎是源码,ActionScript也基本上能读懂。查询Adobe文档后定位到ExternalInterface.addCallback()是注册对外的接口,而ExternalInterface.call()是Flash调用外部的Javascript函数,全文搜索反编译的结果很快就能定位到API了。

不过芒果台没有提供Seek,也就是设置视频进度的API,尝试Hack无果,最后还是放弃了。好在Bilibili和Acfun的API比较全,于是我便简单地加上了Bilibili的适配器。

应该来说一个好工具让我们效率倍增,尤其是Hack和性能调优的时候,比如Chrome的Javascript Profiler,Timeline和Trace就很好用,Web调优必备。