Spark aggregate 例子

// 先上个最简单的例子看下

scala> val l = List(1,2,3,4,5,6,7,8,9,10)
l: List[Int] = List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)

// aggregate (默认值) ( seqOp, comOp )

scala> l.aggregate(0)((x, y) => x + y, (x, y) => x + y)
res7: Int = 55

// 一般的介绍全都是 x, y 看的可难受了。。看了一会资料之后我感觉还是换个名字看着舒服些:

l.aggregate(0)((res, next) => res + next, (chunkA, chunkB) => chunkA + chunkB)
res9: Int = 55

// seqOp 中参数 res 是上一次计算的结果,默认值是在第一阶的函数中传的 0, next 是遍历的下一个元素
// comOp 中参数 chunA, chunkB 则是 scala 并发计算时不同线程算出来的结果,所以不同的 chunk 直接相加即可
// 理解了这个之后就很简单了

// 求平均值
scala> val tmp = l.aggregate(0, 0)((res, next) => (res._1 + next, res._2 + 1), (chunkA, chunkB) => (chunkA._1 + chunkB._1, chunkA._2 + chunkB._2))
res10: (Int, Int) = (55,10)

scala> val avg = tmp._1 / tmp._2.toDouble
avg: Double = 5.5

Mac 安装 scala & spark

# 确保已安装 java 7+

# spark 需要 scala 2.11.x (目前最新 2.12.x)
wget https://downloads.lightbend.com/scala/2.11.11/scala-2.11.11.tgz
tar zxvf scala-2.11.11.tgz
cd scala-2.11.11

# 配置环境变量
# export PATH="$PATH:`pwd`/bin"

# 检查安装是否成功
scala -version

# 本地模式设置 ip (for spark)
sudo hostname -s 127.0.0.1

# 安装 spark
wget https://d3kbcqa49mib13.cloudfront.net/spark-2.1.1-bin-hadoop2.7.tgz
tar zxvf spark-2.1.1-bin-hadoop2.7.tgz
cd spark-2.1.1-bin-hadoop2.7

# 启动 spark
./bin/spark-shell
# 没有报错即成功

然后就可以 hello world 了

Node.js 8.0.0 async pattern benchmark

Node.js 的 8.0 版本终于发布了,等了两天没人测评,于是决定抛砖引玉。
首先需要说明的是,由于不方便拿业务代码测试来评测,所以本次基准测试(benchmark)毫无新意的沿用了 bluebird 的基准测试。测试比较的的内容是多个异步模式(async pattern)之间的性能对比。

目前 Node.js 业内比较异步模式性能比较靠谱的方式是基于 Gorki Kosev’s 的 《Analysis of generators and other async patterns in node》 的 benchmark。该 benchmark 模拟会模拟同时混合大量同步与异步操作的处理场景。具体指标是处理这些操作消耗的时间(ms)以及内存(MB)。

直接上一个 Node.js v8.0.0 的测试报告:

results for 10000 parallel executions, 1 ms per I/O op

file                                       time(ms)  memory(MB)
callbacks-baseline.js                           328       24.11
callbacks-suguru03-neo-async-waterfall.js       409       35.66
promises-bluebird-generator.js                  703       40.76
promises-bluebird.js                            781       51.74
promises-then-promise.js                        922       67.02
promises-cujojs-when.js                         963       65.11
promises-lvivski-davy.js                       1071       96.27
promises-tildeio-rsvp.js                       1159       87.05
callbacks-caolan-async-waterfall.js            1345      102.79
promises-dfilatov-vow.js                       1504      131.96
promises-calvinmetcalf-lie.js                  1870      164.99
promises-ecmascript6-native.js                 2167      167.91
promises-obvious-kew.js                        2269      225.37
generators-tj-co.js                            2273      119.98
observables-pozadi-kefir.js                    3170      188.55
promises-medikoo-deferred.js                   3202      114.25
observables-Reactive-Extensions-RxJS.js        4622      238.07
streamline-generators.js                       6096      128.54
promises-kriskowal-q.js                       12051      391.93
observables-caolan-highland.js                12269      534.94
streamline-callbacks.js                       62359      198.94
observables-baconjs-bacon.js.js                 OOM         OOM

Platform info:
Linux 2.6.32-042stab117.14 x64
Node.JS 7.7.4
V8 5.5.372.42
Intel(R) Xeon(R) CPU           L5640  @ 2.27GHz × 2

其中的测试项中, 比较常见的详情分别是:

执行速度最快的还是原生的 callback

在内存占用方面可以看到 native 的 promise 较之前的版本有明显的下降,已经达到 async 模块的水平了。

完整执行数据 (ms)

pattern 6-1 6-2 7-1 7-2 8-1 8-2
callbacks-baseline.js 335 348 345 328 357 370
callbacks-suguru03-neo-async-waterfall.js 426 433 428 409 462 428
promises-bluebird.js 829 892 750 781 779 770
promises-bluebird-generator.js 838 973 707 703 782 789
promises-cujojs-when.js 916 961 978 963 977 965
promises-then-promise.js 827 913 940 922 987 1102
promises-lvivski-davy.js 1014 1149 1035 1071 1131 1142
promises-tildeio-rsvp.js 1085 1124 1189 1159 1186 1142
promises-ecmascript6-native.js 2530 2540 2286 2167 1216 1350
callbacks-caolan-async-waterfall.js 1317 1312 1427 1345 1433 1430
generators-tj-co.js 2753 2642 2267 2273 1616 1671
promises-dfilatov-vow.js 1382 1496 1665 1504 1688 1770
promises-calvinmetcalf-lie.js 1650 1795 1784 1870 2031 2177
promises-obvious-kew.js 2326 2421 2173 2269 2610 2667
promises-medikoo-deferred.js 4231 4416 3477 3202 3227 3048
observables-pozadi-kefir.js 60466 64587 3177 3170 3442 3161
streamline-generators.js 5533 6048 6682 6096 3013 3228
streamline-callbacks.js 8340 8784 79046 62359 4360 4339
observables-Reactive-Extensions-RxJS.js 4488 4947 4514 4622 5614 5578
observables-caolan-highland.js 152903 164368 12903 12269 17796 17243
promises-kriskowal-q.js 14618 15963 13198 12051 21159 19219
observables-baconjs-bacon.js.js 37014 33282 45257

完整内存数据 (MB)

pattern 6-1 6-2 7-1 7-2 8-1 8-2
callbacks-baseline.js 30 30 24 24 31 31
callbacks-suguru03-neo-async-waterfall.js 43 43 35 35 39 39
promises-bluebird-generator.js 39 40 40 40 41 43
promises-bluebird.js 49 49 50 51 49 48
promises-cujojs-when.js 59 60 65 65 61 60
promises-then-promise.js 59 59 68 67 73 74
generators-tj-co.js 131 131 119 119 74 75
promises-tildeio-rsvp.js 89 89 88 87 80 82
promises-lvivski-davy.js 91 90 97 96 103 102
streamline-generators.js 179 179 129 128 102 102
promises-ecmascript6-native.js 187 187 163 167 95 104
callbacks-caolan-async-waterfall.js 101 101 102 102 108 108
streamline-callbacks.js 163 251 199 198 127 126
promises-dfilatov-vow.js 130 147 132 131 153 159
promises-calvinmetcalf-lie.js 152 135 164 164 147 166
promises-medikoo-deferred.js 190 190 114 114 183 183
observables-pozadi-kefir.js 146 152 188 188 202 202
promises-obvious-kew.js 217 216 79 225 228 232
observables-Reactive-Extensions-RxJS.js 229 230 236 238 243 244
promises-kriskowal-q.js 837 848 370 391 387 388
observables-caolan-highland.js 485 492 517 534 585 559
observables-baconjs-bacon.js.js 826 833 582

小结

  • neo 版的 async 依旧是最快的异步解决方案。
  • 依赖 native 版本的实现(promise/co 等)都有一定程度的性能、内存提升(不过提升的不是很多)。
  • native 的 promise 在提升之后性能已与 async 模块相当,并且 bluebird 的实现与 native 版本差距进一步缩小,bluebird 已经没有成倍的优势。

PS:目前该 benchmark 尚未加入 async/await (笔者已经提了 issue,在考虑要不要自己撸),加入之后会更新本文。

http://echarts.min.js

Mac Sublime 的 Switch Project 不能输入

这个坑爹 BUG, 起因是启用了搜狗输入法的 [中文英文间加入空格], 于是搜狗拦截输入, 使得在 Sublime 的部分地方出现了不能输入的情况.

引申一下, Sublime 对跨平台的输入源处理的不是很好, 之前也出现过按住回车不能一直换行, 按住不动只会插入一个换行, 那时切换搜狗输入法就好了.

Mac docker-machine: Error with pre-create check: “exit status 126”

126 是没有安装 VirtualBox 的报错. 如果你想安装是可以通过如下命令安装:

if ! type "brew" > /dev/null; then
  ruby -e "$(curl -fsSL https://raw.github.com/Homebrew/homebrew/go/install)";
fi
brew tap phinze/homebrew-cask && brew install brew-cask;
brew cask install vagrant;
brew cask install virtualbox;

不过需要了解的是 Docker for Mac 默认是没有使用 VirtualBox 而是使用了 HyperKit, 所以是不用建立 VirtualBox 来做 service. 如果你需要改什么配置可以直接通过 docker for Mac 的 Docker -> Preferences 去改.

ubuntu vps 安装 docker 失败 Cannot connect to the Docker daemon at unix:///var/run/docker.sock.

详情见兴致冲冲的安装:

wget -qO- https://get.docker.com/ | sh

然后

docker info

输出:

Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?

通过 service docker restart 尝试没有变化, 查看 docker 的日志 tail -5f /var/log/upstart/docker.log 发现

time="2017-04-23T01:13:59.857654612-04:00" level=fatal msg="Your Linux kernel version 2.6.32-042stab116.2 is not supported for running docker. Please upgrade your kernel to 3.10.0 or newer."

所以问题是, 当前 linux 的 kernel 2.6 版本太低, 需要升级到 3.10 以上. 坑爹的 vps 自带模板[捂脸] 然后基于 OpenZV 6 的 vps 默认内核是 2.6, docker 需要基于 3.x 的内核, 只有 OpenZV 7 的 vps 才支持 (基于 3.x 内核).

Node.js 的 require.resolve 简介

简单的说, 在 Node.js 中使用 fs 读取文件的时候, 经常碰到要拼一个文件的绝对路径的问题 (fs 处理相对路径均以进程执行目录为准). 之前一直的方法都是, 使用 path 模块以及 __dirname 变量 :

fs.readFileSync(path.join(__dirname, './assets/some-file.txt'));

使用 require.resolve 可以简化这一过程:

fs.readFileSync(require.resolve('./assets/some-file.txt'));

此外, require.resolve 还会在拼接好路径之后检查该路径是否存在, 如果 resolve 的目标路径不存在, 就会抛出 Cannot find module './some-file.txt' 的异常. 省略了一道检查文件是否存在的工序 (fs.exists).

这个报错并不会加重你的检查负担, 毕竟使用 fs 去操作文件时, 如果发现文件不存在也会抛出异常. 反之, 通过 require.resovle 可以在提前在文件中作为常量定义, 那么在应用启动时就可以抛异常, 而不是等到具体操作文件的时候才抛异常.