Python
170 篇视频分析
最近 AI 因为 ChatGPT 大热,正好找个由头玩一下,家里为了看娃装了个摄像头,一周拍的录像大概 20 多 G,可以拿来练练手。之前都是老婆人肉一个个看的,我这次先筛选出有动静的片段,后续老婆再看 最初的想法,是使用 haarcascades 分类器的,毕竟是老牌分类器,又是 opencv 自带的,公司用了一段时间也还行。但是 full_body 和 frontalface 都试过了,家里光线和环境比较复杂,误报很多。无奈换成了有动静才保留对应视频,这里参考了 利用 OpenCV 过滤监控 …
最近 AI 因为 ChatGPT 大热,正好找个由头玩一下,家里为了看娃装了个摄像头,一周拍的录像大概 20 多 G,可以拿来练练手。之前都是老婆人肉一个个看的,我这次先筛选出有动静的片段,后续老婆再看 最初的想法,是使用 haarcascades 分类器的,毕竟是老牌分类器,又是 opencv 自带的,公司用了一段时间也还行。但是 full_body 和 frontalface 都试过了,家里光线和环境比较复杂,误报很多。无奈换成了有动静才保留对应视频,这里参考了 利用 OpenCV 过滤监控 …
发布 pysproto
今天是个值得纪念的日子,我终于将适用于 Python 3 的 pysproto 成功上传到 pypi 了,顺便写一篇博客吐槽下 Python 的打包发布系统 依稀记得之前将 C 文件都放在 src 目录里,结果死活编译不过,于是都散装放在根目录了;然后 Pypi 要先发布测试包,再在网页操作一下,发布成正式包。setup.py 作为包的描述文件,long_description 字段还得用 reStructure Text 的格式写,不然就提交不过。pysproto 这个模块需要头文件,但是屡屡 …
今天是个值得纪念的日子,我终于将适用于 Python 3 的 pysproto 成功上传到 pypi 了,顺便写一篇博客吐槽下 Python 的打包发布系统 依稀记得之前将 C 文件都放在 src 目录里,结果死活编译不过,于是都散装放在根目录了;然后 Pypi 要先发布测试包,再在网页操作一下,发布成正式包。setup.py 作为包的描述文件,long_description 字段还得用 reStructure Text 的格式写,不然就提交不过。pysproto 这个模块需要头文件,但是屡屡 …
博客中英文间添加空格
因为新冠病毒肺炎疫情,春节在家待了 11 天了,百无聊赖之下,想着优化一下老博客的排版。准备在中英文间补上空格,显得更美观一点,结果一篇博客都没改完就觉得累死了。。准备写工具来搞 搜了一下有 现成的代码 ,但是依赖 Pelican。作者还提到可以用 MPT 优化,但是我看了一下 MPT 的介绍,是类似前缀树的东西,每次取一个字符分析的话,是不会取到一个串的,前缀树用不上,倒是可以用二叉树简化一下区间查找。于是读完了 GeeksForGeeks 的 interval tree 介绍 ,自己实现了二 …
因为新冠病毒肺炎疫情,春节在家待了 11 天了,百无聊赖之下,想着优化一下老博客的排版。准备在中英文间补上空格,显得更美观一点,结果一篇博客都没改完就觉得累死了。。准备写工具来搞 搜了一下有 现成的代码 ,但是依赖 Pelican。作者还提到可以用 MPT 优化,但是我看了一下 MPT 的介绍,是类似前缀树的东西,每次取一个字符分析的话,是不会取到一个串的,前缀树用不上,倒是可以用二叉树简化一下区间查找。于是读完了 GeeksForGeeks 的 interval tree 介绍 ,自己实现了二 …
git 与 redmine 联动
现在留给开发的提交权限越来越少了,qc 同学为了保证测试覆盖,让搞了个钩子,提交信息里必须写单号,没有 qc 单子的提交会弹钉钉警告,提错版本的也会被警告,心累。最近一周比较闲,决定用 Python 脚本做个类似的检查辅助一下 代码仓库 fix_issue 是用来关单的,redmine 的页面开着,一段时间后做完,手动标记完成时,如果中间有人改动过,就会将其他人的改动冲掉。。用脚本关就只会改状态了。同时,每个单子的完成状态都不一样,对于功能开发的单子,会比 bug 单多几个状态。。。 …
现在留给开发的提交权限越来越少了,qc 同学为了保证测试覆盖,让搞了个钩子,提交信息里必须写单号,没有 qc 单子的提交会弹钉钉警告,提错版本的也会被警告,心累。最近一周比较闲,决定用 Python 脚本做个类似的检查辅助一下 代码仓库 fix_issue 是用来关单的,redmine 的页面开着,一段时间后做完,手动标记完成时,如果中间有人改动过,就会将其他人的改动冲掉。。用脚本关就只会改状态了。同时,每个单子的完成状态都不一样,对于功能开发的单子,会比 bug 单多几个状态。。。 …
jemalloc 内存占用问题
最近,有部分越南的服务器内存不断上涨,怀疑是内存泄漏,因为框架提供的内存报告里,C 内存和 Lua 占用内存都不大,和 ps 里看的差好多。总内存在 12G 左右,C 和 Lua 的加起来约 4G,两者相差了 8G 经过一番排查,排除了混用 glibc malloc 和 jemalloc 的可能。于是 写了一个多线程的测试程序 ,由多个生产者 - 消费者线程对组成。生产者分配一个随机大小的内存(在 SIZE 范围内),然后 memset 将内存遍历一次,再将指针通过管道发给消费者。消费者拿到指针 …
最近,有部分越南的服务器内存不断上涨,怀疑是内存泄漏,因为框架提供的内存报告里,C 内存和 Lua 占用内存都不大,和 ps 里看的差好多。总内存在 12G 左右,C 和 Lua 的加起来约 4G,两者相差了 8G 经过一番排查,排除了混用 glibc malloc 和 jemalloc 的可能。于是 写了一个多线程的测试程序 ,由多个生产者 - 消费者线程对组成。生产者分配一个随机大小的内存(在 SIZE 范围内),然后 memset 将内存遍历一次,再将指针通过管道发给消费者。消费者拿到指针 …
罕见的 coredump 了
最近,项目在越南版删档测试的时候,发生了罕见的 coredump,简单记一点排查日志 目前的敏感词过滤是在 C 层做判定的,先后经过几个项目考验,模块算是比较稳定了。越南版有个需求,需要将敏感词里的空格去掉。比如敏感词是 abc,现在不能说 abc 了,但是玩家可以输入 a b c,所以需要过滤掉空格。有同事就对 C 层改了一下,判断 rune 是 32 的时候,就继续判断后续字符,出事的代码大致如下: lua_rawgeti(L, 1, j); uint32_t rune = …
最近,项目在越南版删档测试的时候,发生了罕见的 coredump,简单记一点排查日志 目前的敏感词过滤是在 C 层做判定的,先后经过几个项目考验,模块算是比较稳定了。越南版有个需求,需要将敏感词里的空格去掉。比如敏感词是 abc,现在不能说 abc 了,但是玩家可以输入 a b c,所以需要过滤掉空格。有同事就对 C 层改了一下,判断 rune 是 32 的时候,就继续判断后续字符,出事的代码大致如下: lua_rawgeti(L, 1, j); uint32_t rune = …
iPhone 惊爆史诗级漏洞?漏洞细节解析
最近 @axi0mX 提到 iOS 有一个不能修复的漏洞,命名 checkm8(读 checkmate),可以击穿 iPhone 4S 到 iPhone X 间的所有 iOS 设备。而且由于这个漏洞存在于只读的 bootrom 中,苹果应该没法通过系统更新来修复掉。他发布这个漏洞是为了让大家可以安全的在最新系统下越狱,这样系统更安全,开发者也有更大的空间。 好奇 看了一眼 GitHub 仓库 ,作者两天前提交了一份
最近 @axi0mX 提到 iOS 有一个不能修复的漏洞,命名 checkm8(读 checkmate),可以击穿 iPhone 4S 到 iPhone X 间的所有 iOS 设备。而且由于这个漏洞存在于只读的 bootrom 中,苹果应该没法通过系统更新来修复掉。他发布这个漏洞是为了让大家可以安全的在最新系统下越狱,这样系统更安全,开发者也有更大的空间。 好奇 看了一眼 GitHub 仓库 ,作者两天前提交了一份
线程数与游戏卡顿
在某天凌晨,欧美服出现了卡顿,但是服务器的 CPU 并不高,内部服务监控日志来看,是 clusteragent 的 mq overload 了,网卡 IO 从流量上来看,也没达到瓶颈。后来,对方 SA 说是参数配错了,8 核的机器配了 24 线程,改成 8 线程后重启,就不卡顿了。这里排查的时候用到了 tracetag,虽然有点麻烦,还是值得的。 后来,又再一次出现了同样的问题。反复调参后,发现 center 配 4 线程就有问题,配 6 线程就不会卡顿。子熏怀疑是 线程权重设置有问题 ,前面的 …
在某天凌晨,欧美服出现了卡顿,但是服务器的 CPU 并不高,内部服务监控日志来看,是 clusteragent 的 mq overload 了,网卡 IO 从流量上来看,也没达到瓶颈。后来,对方 SA 说是参数配错了,8 核的机器配了 24 线程,改成 8 线程后重启,就不卡顿了。这里排查的时候用到了 tracetag,虽然有点麻烦,还是值得的。 后来,又再一次出现了同样的问题。反复调参后,发现 center 配 4 线程就有问题,配 6 线程就不会卡顿。子熏怀疑是 线程权重设置有问题 ,前面的 …
技能问题引发内存泄漏
最近,在国服上的新职业技能,包含了一个弱点标记技能。玩家用技能打怪的时候,有一定概率给怪挂上弱点,下次攻击时用另一个技能攻击弱点,能爆出更大伤害。弱点的生命周期大约半分钟,过了以后弱点会消失,玩家退出场景后,弱点也会消失。 实现的时候,弱点命中情况记在了受害者身上,同时注册监听了一个玩家死亡事件,方便玩家死亡的时候,清理受害者身上记录的玩家命中弱点信息。但是实现的时候,漏掉了反注册监听事件,导致怪物虽然死亡,但是事件管理器上还一直引用着这个对象,引发内存泄漏。 万幸的是,对于场景服务,之前加上了 …
最近,在国服上的新职业技能,包含了一个弱点标记技能。玩家用技能打怪的时候,有一定概率给怪挂上弱点,下次攻击时用另一个技能攻击弱点,能爆出更大伤害。弱点的生命周期大约半分钟,过了以后弱点会消失,玩家退出场景后,弱点也会消失。 实现的时候,弱点命中情况记在了受害者身上,同时注册监听了一个玩家死亡事件,方便玩家死亡的时候,清理受害者身上记录的玩家命中弱点信息。但是实现的时候,漏掉了反注册监听事件,导致怪物虽然死亡,但是事件管理器上还一直引用着这个对象,引发内存泄漏。 万幸的是,对于场景服务,之前加上了 …
PullRequest 找原作者做 review
最近对代码库进行了一次全局替换,改了 150 个左右的文件,发了 PR 后需要找原作者确认一下,于是写了个工具做 git blame, 地址在这里 写完发现一个问题,如果只是新增一个函数,没有调用,是应该不用找原作者的 …… 但是,要识别出新增一个函数,没想象中容易,需要基于 ast 来做 diff,才能发现。也就是说,这个工具对于批量替换的功能,才比较好用,其他改动不太合适,蛋疼
最近对代码库进行了一次全局替换,改了 150 个左右的文件,发了 PR 后需要找原作者确认一下,于是写了个工具做 git blame, 地址在这里 写完发现一个问题,如果只是新增一个函数,没有调用,是应该不用找原作者的 …… 但是,要识别出新增一个函数,没想象中容易,需要基于 ast 来做 diff,才能发现。也就是说,这个工具对于批量替换的功能,才比较好用,其他改动不太合适,蛋疼
Nginx 超时设定
最近针对公司的 goscon 网关发了一个 PR,新增了握手阶段的超时判定。现在回顾一下 Nginx 的所有超时判定,看看目前还缺少哪些判定 **client_header_timeout (默认 60 秒)** **client_body_timeout (默认 60 秒)** **keepalive_timeout (默认 75 秒)** **lingering_timeout (默认 5 秒)** **<strong>resolver_timeout (默认 30 秒)** …
最近针对公司的 goscon 网关发了一个 PR,新增了握手阶段的超时判定。现在回顾一下 Nginx 的所有超时判定,看看目前还缺少哪些判定 **client_header_timeout (默认 60 秒)** **client_body_timeout (默认 60 秒)** **keepalive_timeout (默认 75 秒)** **lingering_timeout (默认 5 秒)** **<strong>resolver_timeout (默认 30 秒)** …
Rust 对协程的思考
最近和同事聊起来,觉得 lua 缺乏编译型语言的类型校验功能,还有变量拼写检查之类的,导致线上总是有低级错误出现。比如最近有一个是变量名拼写少了一个字母,导致某功能没开启;还有一个是变量传参时,之前测试多加了一个参数,测试完成后忘记删了,导致参数顺序不对。之前看过有个 TypeLua,没想到现在已经不怎么维护了,去搞了 Titan-lang,然而 Titan 也是 4 个月没动静了。。。 目前也没想到什么好的解决办法,于是顺带看看 Rust-lang,开阔一下思路。我最佩服 rust 这帮人的, …
最近和同事聊起来,觉得 lua 缺乏编译型语言的类型校验功能,还有变量拼写检查之类的,导致线上总是有低级错误出现。比如最近有一个是变量名拼写少了一个字母,导致某功能没开启;还有一个是变量传参时,之前测试多加了一个参数,测试完成后忘记删了,导致参数顺序不对。之前看过有个 TypeLua,没想到现在已经不怎么维护了,去搞了 Titan-lang,然而 Titan 也是 4 个月没动静了。。。 目前也没想到什么好的解决办法,于是顺带看看 Rust-lang,开阔一下思路。我最佩服 rust 这帮人的, …
Python 的定时执行
最近手把手教妹子写 Python,被一篇博客误导了,这里记录一下。 妹子需要的是一个定时闹钟,到点往钉钉群里推个消息。她一顿搜索猛如虎,参照着其他人的博客,搞了一个 while: target_time = mktime(time.strptime("2019-5-29 15:30:00", "%Y-%m-%d %H:%M:%S")) while True: now = time.time() if now > target_time: print(u" 到点 ") break 这种没啥技术含量 …
最近手把手教妹子写 Python,被一篇博客误导了,这里记录一下。 妹子需要的是一个定时闹钟,到点往钉钉群里推个消息。她一顿搜索猛如虎,参照着其他人的博客,搞了一个 while: target_time = mktime(time.strptime("2019-5-29 15:30:00", "%Y-%m-%d %H:%M:%S")) while True: now = time.time() if now > target_time: print(u" 到点 ") break 这种没啥技术含量 …
Mesh 内存分配器的 mmap 小技巧
最近看了 一篇内存分配器的论文 ,原理很简单,但是里面的数学论证还没看懂,这次先简单写一下原理和用到的 API。 内存分配器是用于封装操作系统提供的底层 API,给应用程序提供动态内存的。内存不断申请释放后,往往会形成内存碎片。当需要申请一段较大的内存时,当前剩余内存总量是够的,但是被当前申请的内存块隔断成一个个小隔间,内存分配器无法给出指定长度的内存。这时就只能向操作系统重新申请,或者对应用程序返回分配失败了。 ( 图片来自这里 ) 如上图所示,不断申请内存后,内存占用如 Figure 2 所 …
最近看了 一篇内存分配器的论文 ,原理很简单,但是里面的数学论证还没看懂,这次先简单写一下原理和用到的 API。 内存分配器是用于封装操作系统提供的底层 API,给应用程序提供动态内存的。内存不断申请释放后,往往会形成内存碎片。当需要申请一段较大的内存时,当前剩余内存总量是够的,但是被当前申请的内存块隔断成一个个小隔间,内存分配器无法给出指定长度的内存。这时就只能向操作系统重新申请,或者对应用程序返回分配失败了。 ( 图片来自这里 ) 如上图所示,不断申请内存后,内存占用如 Figure 2 所 …
尝鲜 svnup
最近有同事折腾了一下 svnup 的编译,终于可以在 Mac OS X 和 Linux 上面编译通过了, 仓库在这里:https://github.com/lvzixun/svnup/ 看 subversion 的代码,他是封装了一个 libsvn_client 的库来做实际逻辑的。update 的时候一个一个请求的发,是因为有可能需要处理冲突的情况,一个一个处理冲突,对于 frontend 来说比较简单吧 所以 svnup 其实相当于一个爬虫,根据版本号直接批量将文件下载下来,不管本地文件有没 …
最近有同事折腾了一下 svnup 的编译,终于可以在 Mac OS X 和 Linux 上面编译通过了, 仓库在这里:https://github.com/lvzixun/svnup/ 看 subversion 的代码,他是封装了一个 libsvn_client 的库来做实际逻辑的。update 的时候一个一个请求的发,是因为有可能需要处理冲突的情况,一个一个处理冲突,对于 frontend 来说比较简单吧 所以 svnup 其实相当于一个爬虫,根据版本号直接批量将文件下载下来,不管本地文件有没 …
HTTPPostmultipartform-data 支持
最近需要向平台发送录像文件,但是 Skynet 没有 multipart/form-data 的 Post 请求支持,写篇 blog 记录一下 所以只能有最原始的 httpc.request 方法了。请求头比较灵活,可以自己设置为 Content-type: multipart/form-data; 除了这个,还需要设置一个 boundary,用来分割需要同时上传多个 field 的情况。每个 field 长这样: …
最近需要向平台发送录像文件,但是 Skynet 没有 multipart/form-data 的 Post 请求支持,写篇 blog 记录一下 所以只能有最原始的 httpc.request 方法了。请求头比较灵活,可以自己设置为 Content-type: multipart/form-data; 除了这个,还需要设置一个 boundary,用来分割需要同时上传多个 field 的情况。每个 field 长这样: …
redis 的 LRU 算法(二)
前文再续,书接上一回 。上次讲到 redis 的 LRU 算法,文章实在精妙,最近可能有机会用到其中的技巧,顺便将下半部翻译出来,实现的时候参考下。 搏击俱乐部的第一法则:用裸眼观测你的算法 Redis2.8 的 LRU 实现已经上线了,在不同的负载环境下经过测试,用户没有抱怨 Redis 的清理机制。为了继续改进,我希望能观察到算法的性能,同时不会浪费大量 CPU,不增加 1 比特空间占用。 我设计了一个测试用例。导入指定数量的 key,然后顺序访问他们,好让他们的最近访问时间顺序递减。再添 …
前文再续,书接上一回 。上次讲到 redis 的 LRU 算法,文章实在精妙,最近可能有机会用到其中的技巧,顺便将下半部翻译出来,实现的时候参考下。 搏击俱乐部的第一法则:用裸眼观测你的算法 Redis2.8 的 LRU 实现已经上线了,在不同的负载环境下经过测试,用户没有抱怨 Redis 的清理机制。为了继续改进,我希望能观察到算法的性能,同时不会浪费大量 CPU,不增加 1 比特空间占用。 我设计了一个测试用例。导入指定数量的 key,然后顺序访问他们,好让他们的最近访问时间顺序递减。再添 …
Skynet 服务热点火焰图分析
最近花了一周时间对场景服务进行热点分析,利用 以前的火焰图工具 做了一点微小的贡献,分享下心得(仓库地址在 https://github.com/spin6lock/skynet_systemtap_set)。 Skynet 是一个轻量级的多线程在线游戏框架 。线程作为 worker,从服务的队列中抽出有消息的,然后处理上面的消息。服务间通过发消息来相互通信。目前服务主要是用 Lua 进行编写。 以前做的火焰图工具,没法单独看一个 skynet 服务的堆栈,只能看到整个进程的。要想针对单个服务做 …
最近花了一周时间对场景服务进行热点分析,利用 以前的火焰图工具 做了一点微小的贡献,分享下心得(仓库地址在 https://github.com/spin6lock/skynet_systemtap_set)。 Skynet 是一个轻量级的多线程在线游戏框架 。线程作为 worker,从服务的队列中抽出有消息的,然后处理上面的消息。服务间通过发消息来相互通信。目前服务主要是用 Lua 进行编写。 以前做的火焰图工具,没法单独看一个 skynet 服务的堆栈,只能看到整个进程的。要想针对单个服务做 …
内存爆灯
最近产品在韩国上线了,上线后的第一个周末,人数最多的一服内存爆了,被 OOM 杀掉宕机了,很郁闷 机器用的 4 核 16G,aws 的实例。周四开服后,每天零点左右的在线人数峰值,内存都超过了 80% 的告警线。但是运营方不希望停机,于是采取了定时通过 GM 指令调用 gc,15 分钟回收一次内存,希望撑过峰值。到了周六晚,白天加班回到家,有点松懈了,就没再盯着内存曲线看,结果一不留神就爆了。。。峰值从 78% 飙升到 91%,只用了 7 分钟,定时 gc 没赶上,就这样挂了 按之前内网的压测结 …
最近产品在韩国上线了,上线后的第一个周末,人数最多的一服内存爆了,被 OOM 杀掉宕机了,很郁闷 机器用的 4 核 16G,aws 的实例。周四开服后,每天零点左右的在线人数峰值,内存都超过了 80% 的告警线。但是运营方不希望停机,于是采取了定时通过 GM 指令调用 gc,15 分钟回收一次内存,希望撑过峰值。到了周六晚,白天加班回到家,有点松懈了,就没再盯着内存曲线看,结果一不留神就爆了。。。峰值从 78% 飙升到 91%,只用了 7 分钟,定时 gc 没赶上,就这样挂了 按之前内网的压测结 …
时区问题
最近,游戏要上国外运营了,搞完就算告一段落了放下种种不舍,搞好时区的问题,好好的送它一程吧 受时区影响的问题主要分两类,一类是运营活动,一类是特殊玩法的开启。每天定时刷新的本来就有考虑时区,略过不表 运营活动设计的时候已经考虑到时区,每个活动设计的时候,都需要填写活动开启的日期、时间及时区,这方面问题简化了很多。中间需要修改的,是偶尔有几个活动自作聪明,没有用库提供的日期计算函数,自己拿秒数来算。换上考虑时区的函数之后,就没有问题了。核心代码如下: local TD = TIMEZONE * …
最近,游戏要上国外运营了,搞完就算告一段落了放下种种不舍,搞好时区的问题,好好的送它一程吧 受时区影响的问题主要分两类,一类是运营活动,一类是特殊玩法的开启。每天定时刷新的本来就有考虑时区,略过不表 运营活动设计的时候已经考虑到时区,每个活动设计的时候,都需要填写活动开启的日期、时间及时区,这方面问题简化了很多。中间需要修改的,是偶尔有几个活动自作聪明,没有用库提供的日期计算函数,自己拿秒数来算。换上考虑时区的函数之后,就没有问题了。核心代码如下: local TD = TIMEZONE * …
与机器共生
最近写代码比较少,干脆分享一点八卦,博诸君一笑 :) 几年前,在 GitHub 上建了几个 golang 的项目,主要是练手用的,也没几个人关注。最近几天,忽然几个仓库同时收到 PR, 类似这样的 ,大意就是对仓库跑了下 gofmt,其他别的都没干,请合并修改。然后在 issue 里写明了项目的地址,原来还是用 golang 写爬虫做的。自动用 GitHub 的 API 爬取 golang 的仓库,clone 到本地,跑完 gofmt 后,看看有没有修改,有修改就提交 PR。 当时有点郁闷,仿佛 …
最近写代码比较少,干脆分享一点八卦,博诸君一笑 :) 几年前,在 GitHub 上建了几个 golang 的项目,主要是练手用的,也没几个人关注。最近几天,忽然几个仓库同时收到 PR, 类似这样的 ,大意就是对仓库跑了下 gofmt,其他别的都没干,请合并修改。然后在 issue 里写明了项目的地址,原来还是用 golang 写爬虫做的。自动用 GitHub 的 API 爬取 golang 的仓库,clone 到本地,跑完 gofmt 后,看看有没有修改,有修改就提交 PR。 当时有点郁闷,仿佛 …
bug 狩猎
最近需求少了,终于有时间修一下底层的 bug,做一点工具方便查 bug,写篇文章简单记录一下。 一是优化了一个玩法进程的启动速度。这个玩法需要用战力做匹配,玩家按战力分段放进不同的桶里,每个桶用 skiplist 组织。启动服务器的时候,会遍历所有玩家,放进对应的桶里,方便正式开放的时候进行搜索匹配。之前是遍历策划配置的战力分段表,高端玩家几乎要遍历完整个表才能进到桶里。现在改成了二分查找,匹配速度提高了好多 二是隔壁组做 mmo 的同事,问了下有没有现成的查内存泄漏的工具。他们加班的比较凶,周 …
最近需求少了,终于有时间修一下底层的 bug,做一点工具方便查 bug,写篇文章简单记录一下。 一是优化了一个玩法进程的启动速度。这个玩法需要用战力做匹配,玩家按战力分段放进不同的桶里,每个桶用 skiplist 组织。启动服务器的时候,会遍历所有玩家,放进对应的桶里,方便正式开放的时候进行搜索匹配。之前是遍历策划配置的战力分段表,高端玩家几乎要遍历完整个表才能进到桶里。现在改成了二分查找,匹配速度提高了好多 二是隔壁组做 mmo 的同事,问了下有没有现成的查内存泄漏的工具。他们加班的比较凶,周 …
LessonLearned
最近,中兴 ZTE 违反美国商务部禁令,向伊朗出售敏感技术,被美国下达长达 7 年的禁止令,教训十分深刻。以诚待人,信守承诺,才能在商业社会站稳脚跟。 还是说说最近自己上的一课吧。上了港台服以后,奇奇怪怪的问题比较多。其中之一是玩家被异常登录了。现象是玩家登录游戏,提示账号被异常登录。这种现象本来应该在玩家顶号操作时,被顶号的设备上出现的。不应该在正在登录的活跃客户端上显示 回顾现在的登录过程,玩家连上游戏后,首先会创建一个 session。登录完成后,会产生 user 挂在 session 上 …
最近,中兴 ZTE 违反美国商务部禁令,向伊朗出售敏感技术,被美国下达长达 7 年的禁止令,教训十分深刻。以诚待人,信守承诺,才能在商业社会站稳脚跟。 还是说说最近自己上的一课吧。上了港台服以后,奇奇怪怪的问题比较多。其中之一是玩家被异常登录了。现象是玩家登录游戏,提示账号被异常登录。这种现象本来应该在玩家顶号操作时,被顶号的设备上出现的。不应该在正在登录的活跃客户端上显示 回顾现在的登录过程,玩家连上游戏后,首先会创建一个 session。登录完成后,会产生 user 挂在 session 上 …
下划线引起的血案
最近公司搬迁,所有虚拟机都要重新部署,累死了。然后 Python 一堆依赖以前没管理好,直接装全局位置,也忘记导出一份版本号到新机器来安装。这是祸根 换到新机器后,Skynet 和 Golang 相关应用都跑起来了。但是 Python 写的内部应用有点问题,网站认证后,认证用户名 valid_username 一直传不到应用里。检查过内部 Oauth 的代码,以及 Nginx 的转发配置,都没有问题。最终通过重放请求定位到是 Gevent 丢掉了这个参数。同事帮忙翻了下 更新日志 ,发现因为安全 …
最近公司搬迁,所有虚拟机都要重新部署,累死了。然后 Python 一堆依赖以前没管理好,直接装全局位置,也忘记导出一份版本号到新机器来安装。这是祸根 换到新机器后,Skynet 和 Golang 相关应用都跑起来了。但是 Python 写的内部应用有点问题,网站认证后,认证用户名 valid_username 一直传不到应用里。检查过内部 Oauth 的代码,以及 Nginx 的转发配置,都没有问题。最终通过重放请求定位到是 Gevent 丢掉了这个参数。同事帮忙翻了下 更新日志 ,发现因为安全 …
Intel 的 CPU 漏洞:Spectre
最近觉得越来越忙,写博客都没精力了。一定是太沉迷农药和刷即刻了 17 年年底,18 年年初,Intel 被爆出了 Meltdown(熔断)和 Spectre(幽灵)漏洞。等 Spectre 攻击的 POC 出来以后, 去 github 围观了一下 ,真的非常精妙,好想贴上来分享一下。 void victim_function(size_t x) { if (x < array1_size) { temp &= array2[array1[x] * 512]; } } 主要代码就在 …
最近觉得越来越忙,写博客都没精力了。一定是太沉迷农药和刷即刻了 17 年年底,18 年年初,Intel 被爆出了 Meltdown(熔断)和 Spectre(幽灵)漏洞。等 Spectre 攻击的 POC 出来以后, 去 github 围观了一下 ,真的非常精妙,好想贴上来分享一下。 void victim_function(size_t x) { if (x < array1_size) { temp &= array2[array1[x] * 512]; } } 主要代码就在 …
git 和 redmine 同步
最近实现了 github 以及内部的 gitbucket 与 redmine 的同步。 redmine 是内部使用的一套工单系统,用于跟踪 bug 和需求,由于最近同时开发的版本比较多,在不同分支的提交容易漏掉。现在改为用 redmine 的工单跟踪需求和 bug 修复,提交的时候,只要在提交日志里写上单号,机器人就可以将提交信息同步到表单,可以方便的跟踪到提交有没有漏提交到指定分支。 实现上居然很简单,整个过程还是很愉悦的。gitbucket 方面比较简单,gitbucket 的仓库属主可以添 …
最近实现了 github 以及内部的 gitbucket 与 redmine 的同步。 redmine 是内部使用的一套工单系统,用于跟踪 bug 和需求,由于最近同时开发的版本比较多,在不同分支的提交容易漏掉。现在改为用 redmine 的工单跟踪需求和 bug 修复,提交的时候,只要在提交日志里写上单号,机器人就可以将提交信息同步到表单,可以方便的跟踪到提交有没有漏提交到指定分支。 实现上居然很简单,整个过程还是很愉悦的。gitbucket 方面比较简单,gitbucket 的仓库属主可以添 …
redis 的 LRU 算法(一)
最近加班比较累,完全不想写作了。。 刚看到 一篇有趣的文章 ,是 redis 的作者 antirez 对 redis 的 LRU 算法的回顾。LRU 算法是 Least Recently Used 的意思,将最近最少使用的资源丢掉。Redis 经常被用作 cache,如果能够将不常用的 key 移除,尽量保留常用的,那内存的利用率就相当高了。当然,LRU 也有弱点,考虑下面一种情况: ~~~~~A~~~~~A~~~~~A~~~~A~~~~~A~~~~~A~~| …
最近加班比较累,完全不想写作了。。 刚看到 一篇有趣的文章 ,是 redis 的作者 antirez 对 redis 的 LRU 算法的回顾。LRU 算法是 Least Recently Used 的意思,将最近最少使用的资源丢掉。Redis 经常被用作 cache,如果能够将不常用的 key 移除,尽量保留常用的,那内存的利用率就相当高了。当然,LRU 也有弱点,考虑下面一种情况: ~~~~~A~~~~~A~~~~~A~~~~A~~~~~A~~~~~A~~| …
skynet 的网络收发
最近,有位前同事在 skynet 仓库里提了个 有关网络性能的 issue,正好理一下 skynet 的流程。
最近,有位前同事在 skynet 仓库里提了个 有关网络性能的 issue,正好理一下 skynet 的流程。
skynet 的火焰图
之前搞过一下 systemtap(systemtap 折腾笔记 ),可惜很快琐事缠身,没有继续搞下去。最近偷空搞了一下,有点意思。 章大大的思路,是用 perl 生成 systemtap 脚本,从 /proc/$pid/maps 里面扫出 liblua.so 的地址。然后 hook 这个地址里,以 luaL_* 和 lua_* 开头的 lua 虚拟机 C 函数。hook 住的函数里,都会有个参数 L,这个 L 表示 lua 的虚拟机。接下来就是按 lua 的 C 代码撸一遍,看看怎么从 L 的内 …
之前搞过一下 systemtap(systemtap 折腾笔记 ),可惜很快琐事缠身,没有继续搞下去。最近偷空搞了一下,有点意思。 章大大的思路,是用 perl 生成 systemtap 脚本,从 /proc/$pid/maps 里面扫出 liblua.so 的地址。然后 hook 这个地址里,以 luaL_* 和 lua_* 开头的 lua 虚拟机 C 函数。hook 住的函数里,都会有个参数 L,这个 L 表示 lua 的虚拟机。接下来就是按 lua 的 C 代码撸一遍,看看怎么从 L 的内 …
伤感三月
带着我经历过两个项目的 boss 离职了,好遗憾。老同事过来我们组帮忙了,算是一个小小的惊喜。 最近看了《垃圾回收的算法与实现》,说实话,译者的水平比较有限,有几处明显的理解错误。不过,书里的插图还是很易懂的,看着伪代码和插图,勉强读了下来。读完会比较清醒的意识到,即使有 gc 帮助,还是有可能会有内存泄漏的。月中抽空压测了一下,的确发现了有泄漏。。 我们用的脚本语言是 Lua,Lua 采用的是标记清除算法,从根出发,搜索不可达对象并回收掉。如果有泄漏,一定是有资源被某个地方引用住了,没有释放。 …
带着我经历过两个项目的 boss 离职了,好遗憾。老同事过来我们组帮忙了,算是一个小小的惊喜。 最近看了《垃圾回收的算法与实现》,说实话,译者的水平比较有限,有几处明显的理解错误。不过,书里的插图还是很易懂的,看着伪代码和插图,勉强读了下来。读完会比较清醒的意识到,即使有 gc 帮助,还是有可能会有内存泄漏的。月中抽空压测了一下,的确发现了有泄漏。。 我们用的脚本语言是 Lua,Lua 采用的是标记清除算法,从根出发,搜索不可达对象并回收掉。如果有泄漏,一定是有资源被某个地方引用住了,没有释放。 …
加班月
本月都在埋头加班,没搞什么有趣的东西,就分享一篇 Cloudflare 捅的篓子吧 XD Google 有个叫 Project Zero 的安全团队,成员 Tavis Ormandy 某天做一个语料库项目,突然发现 Google 缓存数据里出现了完整的 https 请求。排查发现这些请求都来自于 Cloudflare。Cloudflare 是业界闻名的 CDN,通过 DNS 解释的原理工作,不需要修改页面的资源地址,而是将代理资源的域名,解释到靠近访客的 Cloudflare 服务器上,以此达到 …
本月都在埋头加班,没搞什么有趣的东西,就分享一篇 Cloudflare 捅的篓子吧 XD Google 有个叫 Project Zero 的安全团队,成员 Tavis Ormandy 某天做一个语料库项目,突然发现 Google 缓存数据里出现了完整的 https 请求。排查发现这些请求都来自于 Cloudflare。Cloudflare 是业界闻名的 CDN,通过 DNS 解释的原理工作,不需要修改页面的资源地址,而是将代理资源的域名,解释到靠近访客的 Cloudflare 服务器上,以此达到 …
theevolutionofLua 全文翻译
终于赶在春节前将论文全文翻译完,以后有时间将前面三章重新翻译一次,因为刚开始的时候没打算全文翻译的。。第一次每天花 25 分钟完成这么长的一篇翻译,证明滴水可以穿石,哈哈哈 中文地址:Lua 的演进 祝各位新春快乐,鸡年大吉,恭喜恭喜
终于赶在春节前将论文全文翻译完,以后有时间将前面三章重新翻译一次,因为刚开始的时候没打算全文翻译的。。第一次每天花 25 分钟完成这么长的一篇翻译,证明滴水可以穿石,哈哈哈 中文地址:Lua 的演进 祝各位新春快乐,鸡年大吉,恭喜恭喜
2016 年终总结
今年写了 14 篇博客,比去年的 18 篇要少,没有什么新技术,有点遗憾。倒是读了几篇好文章,比如 Linkedin 团队分享的 The Log,还有 The evolution of Lua。看了一下去年的 年终总结 ,发现目标基本都没完成。゚ヽ (゚Д`)ノ゚。 只有坚持博客这点算是完成了。关于 TCP/IP 协议,其实很想就 Google 家的 BBR 写一篇短文,等下试试。建站这点完全提不起动力,买了域名和 VPS 之后,就搭了个 Google 网页代理就算了。。 2016 是第一次感觉 …
今年写了 14 篇博客,比去年的 18 篇要少,没有什么新技术,有点遗憾。倒是读了几篇好文章,比如 Linkedin 团队分享的 The Log,还有 The evolution of Lua。看了一下去年的 年终总结 ,发现目标基本都没完成。゚ヽ (゚Д`)ノ゚。 只有坚持博客这点算是完成了。关于 TCP/IP 协议,其实很想就 Google 家的 BBR 写一篇短文,等下试试。建站这点完全提不起动力,买了域名和 VPS 之后,就搭了个 Google 网页代理就算了。。 2016 是第一次感觉 …
《一个 Go 程序系统线程暴涨的问题》结论
原文地址:https://zhuanlan.zhihu.com/p/22474724 作者的结论没写好,我来说两句。。
原文地址:https://zhuanlan.zhihu.com/p/22474724 作者的结论没写好,我来说两句。。
空中换心
最近一周在做一件非常刺激的事情,刺激到不想再干第二遍了 T_T。。。还有一个月就要内测的时候,换掉服务器架构,而且还要同时做需求,无异于对空中的飞机换引擎啊 8 月末的时候,老大开了个会,服务器架构要重构一下,将以前的逻辑分服改成物理分服。之前的架构里,开新服很简单,但因为是大服结构,任何一个逻辑服挂了,都会影响其他服的玩家,隔离性不够高。同时,做单服的服务时,处理逻辑需要考虑不同服的影响,添加了额外的心智负担,不容易做对。于是,架构决定改成这样: 每个 game 是一个进程,这样任意 game …
最近一周在做一件非常刺激的事情,刺激到不想再干第二遍了 T_T。。。还有一个月就要内测的时候,换掉服务器架构,而且还要同时做需求,无异于对空中的飞机换引擎啊 8 月末的时候,老大开了个会,服务器架构要重构一下,将以前的逻辑分服改成物理分服。之前的架构里,开新服很简单,但因为是大服结构,任何一个逻辑服挂了,都会影响其他服的玩家,隔离性不够高。同时,做单服的服务时,处理逻辑需要考虑不同服的影响,添加了额外的心智负担,不容易做对。于是,架构决定改成这样: 每个 game 是一个进程,这样任意 game …
阅读分享:游戏服务器的设计与面向日志的工作流
7 月的工作平淡无奇,除了 X 系统由借鉴 A 游戏改成借鉴 B 游戏,就没什么了,还是谈点别的吧。 最近看了 《游戏服务器端究竟解决了什么问题》,推荐给大家。作者关于烂框架的分析很有趣,框架定义角色时,不恰当的角色划分,会引起额外的复杂度,作者文章中后部分有分析。 作者对服务器消息流通的分析,相当见功力。游戏的服务器端,可以抽象的看成消息的生产者和消费者的集合。每一个生产者 / 消费者,就是一个服务。skynet 的优势,在于提供了服务这个封装,一组功能相对独立的逻辑,可以组合在一个服务内,通 …
7 月的工作平淡无奇,除了 X 系统由借鉴 A 游戏改成借鉴 B 游戏,就没什么了,还是谈点别的吧。 最近看了 《游戏服务器端究竟解决了什么问题》,推荐给大家。作者关于烂框架的分析很有趣,框架定义角色时,不恰当的角色划分,会引起额外的复杂度,作者文章中后部分有分析。 作者对服务器消息流通的分析,相当见功力。游戏的服务器端,可以抽象的看成消息的生产者和消费者的集合。每一个生产者 / 消费者,就是一个服务。skynet 的优势,在于提供了服务这个封装,一组功能相对独立的逻辑,可以组合在一个服务内,通 …
六月小结
六月的最后一天,解决了一个服务死循环的问题。吐槽下 skynet,既然已经可以检测到 endless loop,为什么不直接做个调试器去打出死循环在哪里?而且默认不自带超时功能,死了以后基本上服务统计的 gm 指令都挂了。要做超时的 call,还需要自己套个代理服务上去。 这个月将手头的系统都开发完了,开始进入修 bug 阶段。月中的时候接替同事,跟了一下玩法方面的代码,熟悉了玩法的代码结构。排行榜现在统一交到一个服务上去做了,这个服务会创建跟玩家一一对应的 role,然后每个 role 还能饰 …
六月的最后一天,解决了一个服务死循环的问题。吐槽下 skynet,既然已经可以检测到 endless loop,为什么不直接做个调试器去打出死循环在哪里?而且默认不自带超时功能,死了以后基本上服务统计的 gm 指令都挂了。要做超时的 call,还需要自己套个代理服务上去。 这个月将手头的系统都开发完了,开始进入修 bug 阶段。月中的时候接替同事,跟了一下玩法方面的代码,熟悉了玩法的代码结构。排行榜现在统一交到一个服务上去做了,这个服务会创建跟玩家一一对应的 role,然后每个 role 还能饰 …
忙忙忙
最近都在加班,没什么好写的。每周六天,没事也要过来,有点崩溃。 邮箱、聊天之类的都做成信道,尽量和数据抽离开,由具体系统处理对客户端的数据转换,但是 orm 那块不够灵活。如果不走 orm,担心数据格式不对,直接用字符串保存的话,又丢了格式,以后运营的时候不好查找数据。 玩法堆了几个,成长系统比较多,光英雄的就堆了 5、6 个了。战斗力计算没时间去理清,虽然都是简单的读表处理,但是各个系统之间有交互,不知道现在这套接口够不够灵活,会不会坑爹。另外,还有一些 buff 之类的,一直只有客户端维护, …
最近都在加班,没什么好写的。每周六天,没事也要过来,有点崩溃。 邮箱、聊天之类的都做成信道,尽量和数据抽离开,由具体系统处理对客户端的数据转换,但是 orm 那块不够灵活。如果不走 orm,担心数据格式不对,直接用字符串保存的话,又丢了格式,以后运营的时候不好查找数据。 玩法堆了几个,成长系统比较多,光英雄的就堆了 5、6 个了。战斗力计算没时间去理清,虽然都是简单的读表处理,但是各个系统之间有交互,不知道现在这套接口够不够灵活,会不会坑爹。另外,还有一些 buff 之类的,一直只有客户端维护, …
回炉重铸 - 设计模式的领悟
整个四月都在回炉重造之前的英雄成长系统,就因为决定换一个方向,累死。回头看看去年,没想到也是 4 月 30 号写的博客。。。 重造的过程里,同时在看《head first 设计模式》这本书。作者加了很多有趣的插图进去,以前是很讨厌这么做作的书,但是现在读来觉得没那么累,挺好的,可能是老了吧。。。里面提到的开放 - 封闭原则很有启发意义。以前写代码,写的很老实,不够偷懒,总是一字一句把策划的文案搬进去,抽象层次不够,搞的人很累。开放 - 封闭原则就教导,写代码应该对扩展开放,以后策划有新需求,只要 …
整个四月都在回炉重造之前的英雄成长系统,就因为决定换一个方向,累死。回头看看去年,没想到也是 4 月 30 号写的博客。。。 重造的过程里,同时在看《head first 设计模式》这本书。作者加了很多有趣的插图进去,以前是很讨厌这么做作的书,但是现在读来觉得没那么累,挺好的,可能是老了吧。。。里面提到的开放 - 封闭原则很有启发意义。以前写代码,写的很老实,不够偷懒,总是一字一句把策划的文案搬进去,抽象层次不够,搞的人很累。开放 - 封闭原则就教导,写代码应该对扩展开放,以后策划有新需求,只要 …
pythonsproto 支持 64 位有符号整数
小伙伴需要 64 位整数做物品的 id,之前 python sproto 的判断有问题,写篇日志记录一下。 之前有问题的代码是这样的: if (!PyInt_Check(data)) { PyErr_SetObject(SprotoError, PyString_FromFormat("type mismatch, tag:%s, expected int", tagname)); return -1; } long i = PyInt_AsLong(data); int vh = i >> …
小伙伴需要 64 位整数做物品的 id,之前 python sproto 的判断有问题,写篇日志记录一下。 之前有问题的代码是这样的: if (!PyInt_Check(data)) { PyErr_SetObject(SprotoError, PyString_FromFormat("type mismatch, tag:%s, expected int", tagname)); return -1; } long i = PyInt_AsLong(data); int vh = i >> …
pysprotobug 修复
最近,找隔壁组的同学测试了一下我的 pysproto,他们提了很多有益的建议,非常感谢。 在测试中,出现了一次诡异的 coredump。当数据变大的时候,就有很大的机率遇上 double free。在 sproto 和 python sproto 插件里插了一堆打印点后,发现 sproto 在解包的时候报错了。但是 unpack 的代码相当简单,下意识忽略过去了。找云大侠看了一下数据,发现的确有个长度数据错了。至于是在哪一层出错了,还是要再找找。接着我们尝试了直接用 lua 版的 sproto …
最近,找隔壁组的同学测试了一下我的 pysproto,他们提了很多有益的建议,非常感谢。 在测试中,出现了一次诡异的 coredump。当数据变大的时候,就有很大的机率遇上 double free。在 sproto 和 python sproto 插件里插了一堆打印点后,发现 sproto 在解包的时候报错了。但是 unpack 的代码相当简单,下意识忽略过去了。找云大侠看了一下数据,发现的确有个长度数据错了。至于是在哪一层出错了,还是要再找找。接着我们尝试了直接用 lua 版的 sproto …
最近设计的反思
最近完成了邮箱的功能。 邮箱的设计参考了 mmzb 的设计,基于一套 msgsrv 来实现。msgsrv 是一个消息中转的服务,这个服务是为了简化玩家之间消息传递的过程。比如邮箱要向一个离线玩家发信,为了避免对离线玩家的数据进行修改,会通过 msgsrv 发送到玩家对应的 msgbox 里。玩家上线后,会自动查询自己的 msgsrv,检索未读消息。当玩家上线时,会主动在 msgsrv 中发起订阅。每当有新的消息进入,msgsrv 会直接发送到玩家所在的 agent 上,实现实时通知。唯一例外的情 …
最近完成了邮箱的功能。 邮箱的设计参考了 mmzb 的设计,基于一套 msgsrv 来实现。msgsrv 是一个消息中转的服务,这个服务是为了简化玩家之间消息传递的过程。比如邮箱要向一个离线玩家发信,为了避免对离线玩家的数据进行修改,会通过 msgsrv 发送到玩家对应的 msgbox 里。玩家上线后,会自动查询自己的 msgsrv,检索未读消息。当玩家上线时,会主动在 msgsrv 中发起订阅。每当有新的消息进入,msgsrv 会直接发送到玩家所在的 agent 上,实现实时通知。唯一例外的情 …
服务器被发现存在未授权访问
今天下午,友商的同学突然发了个确认信息过来,让我们确认一下服务器的归属。然后就抛出了个大新闻:我司服务器存在问题,所有文件都可以任意访问。根据对方反映的信息,确认是之前玩票性质的一个项目:avalon 出了问题。https://github.com/ejoy/avalon/blob/master/lualib/staticfile.lua#L12-L17 这里没有做输入检查,就直接使用 io.open 了。 另外一个地方,是因为这个项目的玩票性质,所以 SA 同学随便找台空的服务器丢上去了,而且 …
今天下午,友商的同学突然发了个确认信息过来,让我们确认一下服务器的归属。然后就抛出了个大新闻:我司服务器存在问题,所有文件都可以任意访问。根据对方反映的信息,确认是之前玩票性质的一个项目:avalon 出了问题。https://github.com/ejoy/avalon/blob/master/lualib/staticfile.lua#L12-L17 这里没有做输入检查,就直接使用 io.open 了。 另外一个地方,是因为这个项目的玩票性质,所以 SA 同学随便找台空的服务器丢上去了,而且 …
RRDtool 简介
最近公司换了办公地址,新厂址的宽带质量不怎么样,于是用 RRDTool 布了一套网络质量监控的系统,来定位公司内部与机房的连接问题。RRDTool 是一套经典的工具,前身是 MRTG,因为其中的性能有所不足,绘图的灵活性不够,于是作者 Tobias Oetiker 又重新开发了一套 RRDTool。这套工具包含了日志记录和图表绘制两部分,可以满足各种指标监控的用途。 RRDTool 的 RR,指的是 Round-robin,
最近公司换了办公地址,新厂址的宽带质量不怎么样,于是用 RRDTool 布了一套网络质量监控的系统,来定位公司内部与机房的连接问题。RRDTool 是一套经典的工具,前身是 MRTG,因为其中的性能有所不足,绘图的灵活性不够,于是作者 Tobias Oetiker 又重新开发了一套 RRDTool。这套工具包含了日志记录和图表绘制两部分,可以满足各种指标监控的用途。 RRDTool 的 RR,指的是 Round-robin,
折腾域名的 dns
最近,购买域名的时候遇到了几个概念,刚开始不是很懂,最后都是直接找客服给我改好的,现在小结一下帮助理解。 DNS 域名管理是按后缀进行分组的,比如 .com 域名,作为最早的商用域名,有很高的推广价值。再比如各个国家的顶级域名,例如中国的 .cn,加拿大的 .ca,简单易记。我们购买的,是通常意义上,www 与顶级域名之间的部分,叫二级域名。 二级域名会挂在某个根域名下,各个根域名会分给各个承包商进行承包,各自销售。其中有个国际组织在掺和,叫 Internet Corporation for …
最近,购买域名的时候遇到了几个概念,刚开始不是很懂,最后都是直接找客服给我改好的,现在小结一下帮助理解。 DNS 域名管理是按后缀进行分组的,比如 .com 域名,作为最早的商用域名,有很高的推广价值。再比如各个国家的顶级域名,例如中国的 .cn,加拿大的 .ca,简单易记。我们购买的,是通常意义上,www 与顶级域名之间的部分,叫二级域名。 二级域名会挂在某个根域名下,各个根域名会分给各个承包商进行承包,各自销售。其中有个国际组织在掺和,叫 Internet Corporation for …
2015 年终总结
2015 年是我第一次感觉人生过得快的一年。这一年买房了,月供比较重,有种喘不过气的感觉。15 年的阅读量比 14 年少,主要是网络小说看的少了,人文类的阅读量上来了,比较耗费时间。另外,15 年计算机专业的书读的很少,那本《redis 设计与实现》还没看完,有点遗憾。15 年开始思考一些大问题,比如两性平等,科技进步带来的发展,比如文明发展为什么不均衡,主体与客体,人为什么会感觉愉快。 15 年的博客写了 18 篇,比 14 年的 15 篇多了一点点,基本维持在每月一篇到两篇的节奏,但是文章的 …
2015 年是我第一次感觉人生过得快的一年。这一年买房了,月供比较重,有种喘不过气的感觉。15 年的阅读量比 14 年少,主要是网络小说看的少了,人文类的阅读量上来了,比较耗费时间。另外,15 年计算机专业的书读的很少,那本《redis 设计与实现》还没看完,有点遗憾。15 年开始思考一些大问题,比如两性平等,科技进步带来的发展,比如文明发展为什么不均衡,主体与客体,人为什么会感觉愉快。 15 年的博客写了 18 篇,比 14 年的 15 篇多了一点点,基本维持在每月一篇到两篇的节奏,但是文章的 …
mmzb 游戏事故分析
最近一次线上更新,老项目挂了,遍地哀嚎,日活跃掉了好多,心痛。。。 这次维护时,SA 为了缩减硬件资源,做了一次数据库迁移。给到开发手上的 player db,只有一些索引数据,不带有任一玩家数据。玩家上线的时候,skynet 自动从 redis-persist 服务中拉取(redis-persist 是一个基于旁路监听的 redis 落地程序,相对独立,参见 之前的博文 )。这也是 RP 服务的第一次高强度使用。按之前的策略,每次玩家下线都会在 RP 服务中存档,三个月不上线的玩家,会自动从 …
最近一次线上更新,老项目挂了,遍地哀嚎,日活跃掉了好多,心痛。。。 这次维护时,SA 为了缩减硬件资源,做了一次数据库迁移。给到开发手上的 player db,只有一些索引数据,不带有任一玩家数据。玩家上线的时候,skynet 自动从 redis-persist 服务中拉取(redis-persist 是一个基于旁路监听的 redis 落地程序,相对独立,参见 之前的博文 )。这也是 RP 服务的第一次高强度使用。按之前的策略,每次玩家下线都会在 RP 服务中存档,三个月不上线的玩家,会自动从 …
为 sproto 手写了一个 pythonparser
这是 sproto 系列文章的第三篇,可以参考前面的《 为 sproto 添加 python 绑定 》、《 为 python-sproto 添加 map 支持 》。 .type { .field { name 0 : string buildin 1 : integer type 2 : integer tag 3 : integer array 4 : boolean key 5 : integer # If key exists, array must be true, and it's a …
这是 sproto 系列文章的第三篇,可以参考前面的《 为 sproto 添加 python 绑定 》、《 为 python-sproto 添加 map 支持 》。 .type { .field { name 0 : string buildin 1 : integer type 2 : integer tag 3 : integer array 4 : boolean key 5 : integer # If key exists, array must be true, and it's a …
Lua 小技巧
来公司以后,业务逻辑都用 lua 写。写了好长时间了,到最近才觉得有点掌握了 Lua 的灵活。最近用 Lua 写了个类似集合一样的东西,如果两次向集合里放入同一个元素,就会报错,方便检查配置。代码如下: -- keep data across rule local m = {} local where_defines = {} local getinfo = debug.getinfo name2id = setmetatable({}, { __index = m, __newindex = …
来公司以后,业务逻辑都用 lua 写。写了好长时间了,到最近才觉得有点掌握了 Lua 的灵活。最近用 Lua 写了个类似集合一样的东西,如果两次向集合里放入同一个元素,就会报错,方便检查配置。代码如下: -- keep data across rule local m = {} local where_defines = {} local getinfo = debug.getinfo name2id = setmetatable({}, { __index = m, __newindex = …
Techparty- 广州 10 月 31 日 Docker 专场沙龙后记
华为的童鞋技术能力很强,但是两位讲师的都没听进去。重点听了两个,一个是芒果 TV 的 Docker 之路,另一个是 Coding 的实践和思考。 芒果 TV 的主讲人是一直仰慕的 CMGS,从豆瓣出来后去了国企芒果台。因为内部阻力问题,无法实现 PaaS。转而实现了细粒度的调度。物理机 +Docker 为芒果台省了不少机器,而且性能还比 AWS 的要强。实践上,主要用到了 MacVLan,在二层网络上做网络调度。还有 Devicemapper,但是 dm 受镜像大小的影响比较大,超过 2G 大小 …
华为的童鞋技术能力很强,但是两位讲师的都没听进去。重点听了两个,一个是芒果 TV 的 Docker 之路,另一个是 Coding 的实践和思考。 芒果 TV 的主讲人是一直仰慕的 CMGS,从豆瓣出来后去了国企芒果台。因为内部阻力问题,无法实现 PaaS。转而实现了细粒度的调度。物理机 +Docker 为芒果台省了不少机器,而且性能还比 AWS 的要强。实践上,主要用到了 MacVLan,在二层网络上做网络调度。还有 Devicemapper,但是 dm 受镜像大小的影响比较大,超过 2G 大小 …
1password 密码库格式更新
由于国内网络安全做的太差,经常发生被脱裤的事件,比如最近的网易邮箱(via 乌云 ),所以只好用 1password 这类密码管理软件,实现一站一密。昨晚半夜冻醒了,刷推刷到了这个:1password-leaks-your-data,整个人吓醒了 =_=# 作者有点标题党,脱水版可以参见 reddit 的 这篇文章 ,大意是 1password 的旧密码库格式叫 agilechains,大体是 json 结构,里面只有密码是加密的,密码项的名字和 URL 并未加密。官方提到历史原因,早期计算能力 …
由于国内网络安全做的太差,经常发生被脱裤的事件,比如最近的网易邮箱(via 乌云 ),所以只好用 1password 这类密码管理软件,实现一站一密。昨晚半夜冻醒了,刷推刷到了这个:1password-leaks-your-data,整个人吓醒了 =_=# 作者有点标题党,脱水版可以参见 reddit 的 这篇文章 ,大意是 1password 的旧密码库格式叫 agilechains,大体是 json 结构,里面只有密码是加密的,密码项的名字和 URL 并未加密。官方提到历史原因,早期计算能力 …
SSL 加密与系统时间
最近,家里的神州老笔记本没电池了,要拆 C 面才能换主板电池,懒得动手,于是搞了个 Network Time 来做对时。主要是未搞对时之前,所有 https 的站点都用不了,老人家也抱怨炒股不行,崩溃了。。。这时候才知道,原来证书也是要验证时间的。 在 SSL 会话里,客户端需要验证服务器的身份,这是通过证书检查来完成的。证书验证中,会涉及跟时间相关的两点: 服务器的证书(及涉及到的其他证书)的有效验证时间需要包含当前时间。每个证书都有 notBefore(不早于)和 notAfter(不晚于) …
最近,家里的神州老笔记本没电池了,要拆 C 面才能换主板电池,懒得动手,于是搞了个 Network Time 来做对时。主要是未搞对时之前,所有 https 的站点都用不了,老人家也抱怨炒股不行,崩溃了。。。这时候才知道,原来证书也是要验证时间的。 在 SSL 会话里,客户端需要验证服务器的身份,这是通过证书检查来完成的。证书验证中,会涉及跟时间相关的两点: 服务器的证书(及涉及到的其他证书)的有效验证时间需要包含当前时间。每个证书都有 notBefore(不早于)和 notAfter(不晚于) …
python 和 nodejs 的 aes128 加密对比
之前的机器人是用 python 写的,有同事想改写成 nodejs 版,但是验证一直通不过,于是帮忙爬了一下文档。 #encoding:utf8 from Crypto.Cipher import AES import binascii key = 'abcdabcdabcdabcd' plaintext = 'Secret Message A' encobj = AES.new(key, AES.MODE_ECB) ciphertext = encobj.encrypt(plaintext) …
之前的机器人是用 python 写的,有同事想改写成 nodejs 版,但是验证一直通不过,于是帮忙爬了一下文档。 #encoding:utf8 from Crypto.Cipher import AES import binascii key = 'abcdabcdabcdabcd' plaintext = 'Secret Message A' encobj = AES.new(key, AES.MODE_ECB) ciphertext = encobj.encrypt(plaintext) …
9 月补记
9 月份本来打算搞一下 bt,可惜一直没时间完成种子下载的部分,暂此搁笔。 由于 XcodeGhost 肆虐,于是顺手搞了个 XcodeGhost 的服务器版:https://github.com/spin6lock/XcodeGhostServer,联系 SA 帮忙指向本机,结果公司里大家都更新的好快,只发现一位同学中招 :) 只是弹窗还有点问题,JSON 里面的字段都有了,不知道是不是 scheme 不对,所以 openUrl 的时候有问题,稍后再看看。 XcodeGhost 的三个域名 …
9 月份本来打算搞一下 bt,可惜一直没时间完成种子下载的部分,暂此搁笔。 由于 XcodeGhost 肆虐,于是顺手搞了个 XcodeGhost 的服务器版:https://github.com/spin6lock/XcodeGhostServer,联系 SA 帮忙指向本机,结果公司里大家都更新的好快,只发现一位同学中招 :) 只是弹窗还有点问题,JSON 里面的字段都有了,不知道是不是 scheme 不对,所以 openUrl 的时候有问题,稍后再看看。 XcodeGhost 的三个域名 …
对 bt 的一些想法
一直想做一个像 磁力助手 这样的网站,参考了 小虾的文章 。最近花了比较多的时间,自己实现了一遍,写写实验过程的体验。 术语: DHT 网络是为了 参考文章:
一直想做一个像 磁力助手 这样的网站,参考了 小虾的文章 。最近花了比较多的时间,自己实现了一遍,写写实验过程的体验。 术语: DHT 网络是为了 参考文章:
旧梦重温
这个月主要在搞两件事,其一是:https://github.com/spin6lock/pydnsproxy,其二是一个 bt 客户端,用来搜索磁力链接,下载种子的,还没搞好。 除了 bug 修复,就是给 pydnsproxy 添加了 http dns 的解析方式,这种方式的优势,可参考企鹅的 【鹅厂网事】全局精确流量调度新思路 -HttpDNS 服务详解 。简单来说,就是抛开原有的 dns 协议,直接提供一个 http 接口,给出域名,返回对应 ip。额外参数还包括请求 ip,可以根据请求 …
这个月主要在搞两件事,其一是:https://github.com/spin6lock/pydnsproxy,其二是一个 bt 客户端,用来搜索磁力链接,下载种子的,还没搞好。 除了 bug 修复,就是给 pydnsproxy 添加了 http dns 的解析方式,这种方式的优势,可参考企鹅的 【鹅厂网事】全局精确流量调度新思路 -HttpDNS 服务详解 。简单来说,就是抛开原有的 dns 协议,直接提供一个 http 接口,给出域名,返回对应 ip。额外参数还包括请求 ip,可以根据请求 …
树莓派改用中山大学软件源
**** 最近借了同事的第一代树莓派来玩,主要是想试试玩 SDR,之前听说可以上传一个月的航班广播(ADS-B 广播信息)就可以获得永久资格,随时查阅附近有什么航班飞行。后来发现 flightradar24.com 已经升级规则了,要持续上传数据。。。于是打算听听收音机算了,上手装了 raspbian,毕竟 debian 系统比较熟悉。国内网速着急,先换个源 ** 使用说明 ** 编辑 /etc/apt/sources.list 文件,参考如下命令: sudo vim …
**** 最近借了同事的第一代树莓派来玩,主要是想试试玩 SDR,之前听说可以上传一个月的航班广播(ADS-B 广播信息)就可以获得永久资格,随时查阅附近有什么航班飞行。后来发现 flightradar24.com 已经升级规则了,要持续上传数据。。。于是打算听听收音机算了,上手装了 raspbian,毕竟 debian 系统比较熟悉。国内网速着急,先换个源 ** 使用说明 ** 编辑 /etc/apt/sources.list 文件,参考如下命令: sudo vim …
翻译 lpeg 入门教程
原文地址:http://lua-users.org/wiki/LpegTutorial 简单匹配 LPeg 是一个用于文本匹配的有力表达方式,比 Lua 原生的字符串匹配和标准正则表达式更优异。但是,就像其他任何语言一样,你需要知道简单的词汇和如何组合他们。 最佳的学习方式,是通过交互式对话,熟悉基本的模式。首先,我们定义一些缩写: $ lua -llpeg Lua 5.1.4 Copyright (C) 1994-2008 Lua.org, PUC-Rio > match = …
原文地址:http://lua-users.org/wiki/LpegTutorial 简单匹配 LPeg 是一个用于文本匹配的有力表达方式,比 Lua 原生的字符串匹配和标准正则表达式更优异。但是,就像其他任何语言一样,你需要知道简单的词汇和如何组合他们。 最佳的学习方式,是通过交互式对话,熟悉基本的模式。首先,我们定义一些缩写: $ lua -llpeg Lua 5.1.4 Copyright (C) 1994-2008 Lua.org, PUC-Rio > match = …
为 python-sproto 添加 map 支持
上个月太忙了,做完这个修改还没写博客,现在补一下。。 之前使用 protobuf 做协议打包的时候,经常会有个痛点,没法用具体数据的值作为 key 来索引数据。比如现在客户端上传了造兵协议,协议大概长这样: { { troop_type = 101, amount = 1, }, { troop_tyoe = 102, amount = 2, }, } 可以看到,造兵协议是一个数组,数组里每个元素是一个结构,包含 troop_type(兵种类别)和 amount(数量)。每次收到的时候,都需要遍 …
上个月太忙了,做完这个修改还没写博客,现在补一下。。 之前使用 protobuf 做协议打包的时候,经常会有个痛点,没法用具体数据的值作为 key 来索引数据。比如现在客户端上传了造兵协议,协议大概长这样: { { troop_type = 101, amount = 1, }, { troop_tyoe = 102, amount = 2, }, } 可以看到,造兵协议是一个数组,数组里每个元素是一个结构,包含 troop_type(兵种类别)和 amount(数量)。每次收到的时候,都需要遍 …
玩家回档原因分析
在最近一次维护后,玩家发现有较大规模的数据回档,还有一小部分玩家无法登录。现在尝试还原一下现场。 当天维护的时候,SA 执行了一次数据库维护。维护是通过一个脚本完成的,而且执行过多次,理论上没有问题。而维护的过程中,开发组这边需要执行一个脚本,给一批玩家增加经验。这一切完成后,QC 简单复测了一下,就开服了。开服后发现,服务器出现大量报错,而且都是玩家数据出现问题。定位这个问题的时候,发现玩家的数据丢掉了导致无法登录,顿时吓尿了 =_=||| 论坛里也有玩家开始叫骂,定位了一下貌似是那批增加经验 …
在最近一次维护后,玩家发现有较大规模的数据回档,还有一小部分玩家无法登录。现在尝试还原一下现场。 当天维护的时候,SA 执行了一次数据库维护。维护是通过一个脚本完成的,而且执行过多次,理论上没有问题。而维护的过程中,开发组这边需要执行一个脚本,给一批玩家增加经验。这一切完成后,QC 简单复测了一下,就开服了。开服后发现,服务器出现大量报错,而且都是玩家数据出现问题。定位这个问题的时候,发现玩家的数据丢掉了导致无法登录,顿时吓尿了 =_=||| 论坛里也有玩家开始叫骂,定位了一下貌似是那批增加经验 …
为 sproto 添加 python 绑定
项目地址:https://github.com/spin6lock/python-sproto 第一次写 Python 的 C 扩展,留点笔记记录一下。主要的参考文档是:Extending Python with C/C++, 之前也看过 cython,但是用 Python 语法写 C 还是没学会,稍后再尝试用 cython 写一遍看看。 作为一个 C 扩展,是以 Module 的方式 import 进去代码里使用的,所以需要注册一下,把自己的接口告诉 Python 解释器。代码如下图: …
项目地址:https://github.com/spin6lock/python-sproto 第一次写 Python 的 C 扩展,留点笔记记录一下。主要的参考文档是:Extending Python with C/C++, 之前也看过 cython,但是用 Python 语法写 C 还是没学会,稍后再尝试用 cython 写一遍看看。 作为一个 C 扩展,是以 Module 的方式 import 进去代码里使用的,所以需要注册一下,把自己的接口告诉 Python 解释器。代码如下图: …
如何快速编写 Vim 语法高亮文件
这里有一份 中文的入门文档 ,但是太长了,不想读,所以有本文 最快的办法,就是找一个语法相近的语法高亮文件,稍微改一下 自己从头写的话,首先搞定关键字: syntax case match " 是否区分大小写 syntax keyword 你的关键字类别名字 x 关键字 1 关键字 2 syntax keyword 同样填 x 的话,不会覆盖,只追加 关键字 3 关键字 4 关键字搞不定的,一般用正则匹配: syntax match 类别名 / 正则表达式 / 正则有个麻烦是不能部分匹配,比如我 …
这里有一份 中文的入门文档 ,但是太长了,不想读,所以有本文 最快的办法,就是找一个语法相近的语法高亮文件,稍微改一下 自己从头写的话,首先搞定关键字: syntax case match " 是否区分大小写 syntax keyword 你的关键字类别名字 x 关键字 1 关键字 2 syntax keyword 同样填 x 的话,不会覆盖,只追加 关键字 3 关键字 4 关键字搞不定的,一般用正则匹配: syntax match 类别名 / 正则表达式 / 正则有个麻烦是不能部分匹配,比如我 …
windows 调试器尝鲜
曾几何时,我也下载过看雪论坛精华看的津津有味。可惜一直没有动手去调试,学到的 x86 汇编指令也忘得差不多了。最近将老机器的 T4200 CPU 换成了更省电,温度更低的 P8800,为了支援新的 VT 虚拟化,特地将 Dell 1545 的 BIOS 从 A8 升级到 A14。顺带发现 SLIC 已经自动升级到 2.0 了。但是升级以后,win7 开始菜单的睡眠功能就无法使用了,于是萌生了降级刷 BIOS 的想法。 下好了 1545A13 的 BIOS,运行后发现出现了一个 warning 信 …
曾几何时,我也下载过看雪论坛精华看的津津有味。可惜一直没有动手去调试,学到的 x86 汇编指令也忘得差不多了。最近将老机器的 T4200 CPU 换成了更省电,温度更低的 P8800,为了支援新的 VT 虚拟化,特地将 Dell 1545 的 BIOS 从 A8 升级到 A14。顺带发现 SLIC 已经自动升级到 2.0 了。但是升级以后,win7 开始菜单的睡眠功能就无法使用了,于是萌生了降级刷 BIOS 的想法。 下好了 1545A13 的 BIOS,运行后发现出现了一个 warning 信 …
休斯顿,我们遇到了一个问题
最近和前端同学聊得比较多,聊着聊着发现前端回报了一个诡异的错误,服务器端发给客户端的 JSON 错了,解不开。前端同学 bs 了一下服务器用的 JSON 库,居然连编码都会出错。我检查了所用的库,前后端的确用的不是同一个 json.lua,于是跑了一次简单的压测。当然,没有发现问题。过了两天,又遇到同一个问题了,这次我留心了一下错误的详细内容: coco/game.lua:86: coco/lib/json.lua:525: coco/lib/json.lua:240: expected …
最近和前端同学聊得比较多,聊着聊着发现前端回报了一个诡异的错误,服务器端发给客户端的 JSON 错了,解不开。前端同学 bs 了一下服务器用的 JSON 库,居然连编码都会出错。我检查了所用的库,前后端的确用的不是同一个 json.lua,于是跑了一次简单的压测。当然,没有发现问题。过了两天,又遇到同一个问题了,这次我留心了一下错误的详细内容: coco/game.lua:86: coco/lib/json.lua:525: coco/lib/json.lua:240: expected …
糟糕的十一月
十一月感觉就是写邮件系统和两个策划要的活动而已。。。 一直觉得邮件系统十分简单,但是实现的时候却不是一回事。实现速度比预期的慢,一方面是边写边参考了礼包系统的结构,另一方面是抽象错误。就因为邮件放在礼包的位置,然后邮件看起来只是比礼包多一两个字段,所以就参考了礼包系统。这个错误实在太严重。表现层的相似性居然影响到后端的实现!!! 上周的 code review 里,被喷了两个多小时。焦点主要是两个地方,一是对内部来说,其他子系统用邮件的时候不友好;二是协议来说,冗余太多,浪费带宽,协议之间也没有 …
十一月感觉就是写邮件系统和两个策划要的活动而已。。。 一直觉得邮件系统十分简单,但是实现的时候却不是一回事。实现速度比预期的慢,一方面是边写边参考了礼包系统的结构,另一方面是抽象错误。就因为邮件放在礼包的位置,然后邮件看起来只是比礼包多一两个字段,所以就参考了礼包系统。这个错误实在太严重。表现层的相似性居然影响到后端的实现!!! 上周的 code review 里,被喷了两个多小时。焦点主要是两个地方,一是对内部来说,其他子系统用邮件的时候不友好;二是协议来说,冗余太多,浪费带宽,协议之间也没有 …
skynet 的协程
之前对 skynet 的印象,主要是来自于我对 golang 的理解,对 gevent 开发的经验,以及云风的 blog。对于底层的代码,并没有仔细去阅读过。最近在实现业务系统的时候,发现有同事在同一个函数里做了一个互斥的判断,才发现对 skynet 的理解有误。 以前,用 python 的 gevent 框架实现游戏服务器的时候,会针对每个玩家建立 3-5 个 greenlet(协程),用于处理玩家身上的定时器事件,以及 IO 操作。然后还有少数几个协程处理全局的定时器事件。当然,战斗是放在独 …
之前对 skynet 的印象,主要是来自于我对 golang 的理解,对 gevent 开发的经验,以及云风的 blog。对于底层的代码,并没有仔细去阅读过。最近在实现业务系统的时候,发现有同事在同一个函数里做了一个互斥的判断,才发现对 skynet 的理解有误。 以前,用 python 的 gevent 框架实现游戏服务器的时候,会针对每个玩家建立 3-5 个 greenlet(协程),用于处理玩家身上的定时器事件,以及 IO 操作。然后还有少数几个协程处理全局的定时器事件。当然,战斗是放在独 …
redis-persist 上线
九月份惨不忍睹,因为代码质量不够高,直接被 Boss 喷成了筛子。被反复教育说要高质量的代码,要可维护、高性能 幸而,最后一周终于在紧张的加班中,灰度上线 redis-land-go 了,项目也改名为 redis-persist,github 在此 。 之前实现的,是 redis 到 leveldb,以及 skynet 从 leveldb 中读取数据的接口。最后一周添加的,是 SA 同事可能会用到的功能。主要是: dump restore_one restore_all sync …
九月份惨不忍睹,因为代码质量不够高,直接被 Boss 喷成了筛子。被反复教育说要高质量的代码,要可维护、高性能 幸而,最后一周终于在紧张的加班中,灰度上线 redis-land-go 了,项目也改名为 redis-persist,github 在此 。 之前实现的,是 redis 到 leveldb,以及 skynet 从 leveldb 中读取数据的接口。最后一周添加的,是 SA 同事可能会用到的功能。主要是: dump restore_one restore_all sync …
忙里偷闲的八月
八月依然有些很狗血的策划案要做,以至于花了两周时间,周五做出来后,连策划自己都觉得配置超多超复杂。。。 这个月比较过瘾的,是下决心做了 dns 的实验。当时为了防止 DNS 污染,曾经用 Python 写过一个 DNS 代理,通过 TCP 管道传输解析包,避免墙的干扰,地址在 google code。项目原本是通过丢弃最先返回的 udp 包来实现的,后来改为了 TCP 查询。不过,当时硬着头皮读的 RFC1035,只读懂了 TCP 的部分,只要将接收到的包体加上长度作为包头,就可以直接丢到 …
八月依然有些很狗血的策划案要做,以至于花了两周时间,周五做出来后,连策划自己都觉得配置超多超复杂。。。 这个月比较过瘾的,是下决心做了 dns 的实验。当时为了防止 DNS 污染,曾经用 Python 写过一个 DNS 代理,通过 TCP 管道传输解析包,避免墙的干扰,地址在 google code。项目原本是通过丢弃最先返回的 udp 包来实现的,后来改为了 TCP 查询。不过,当时硬着头皮读的 RFC1035,只读懂了 TCP 的部分,只要将接收到的包体加上长度作为包头,就可以直接丢到 …
并行的边界
七月份忙的狗一样,还一度要 12 点赶回公司修 bug,真累。。。 入职以来的这两个月,一直在业务层摸索,苦于没有文档,rpc 协议、单件服务的启动、为热更新去准备的环境变量等等,都要一一在摸索中问出来。幸而,终于走过了这一段。这也促使我开始思考,skynet、gevent、golang 之间,各自的优点和缺点是什么。 先从 skynet 说起,最直观的感受是,skynet 在 lua/c 里几乎完全复制了 python 的标准库。上至打包用的 serialize、json 库,下至打印字典 …
七月份忙的狗一样,还一度要 12 点赶回公司修 bug,真累。。。 入职以来的这两个月,一直在业务层摸索,苦于没有文档,rpc 协议、单件服务的启动、为热更新去准备的环境变量等等,都要一一在摸索中问出来。幸而,终于走过了这一段。这也促使我开始思考,skynet、gevent、golang 之间,各自的优点和缺点是什么。 先从 skynet 说起,最直观的感受是,skynet 在 lua/c 里几乎完全复制了 python 的标准库。上至打包用的 serialize、json 库,下至打印字典 …
初来乍到
来到新公司后,终于有机会用 git 作为版本控制的工具。通过 github 私有仓库进行 Pull Request 和 code review,的确十分方便。使用的时候发现自己关于分支的知识不够用了,出现过一次提交 Pull Request 后被 merge,然后自己本地又 merge 了,导致 git pull 时版本冲突的问题。另外,客户端不希望出现 merge,所有对共享配置的修改,都需要用 rebase 方式合并,又犯了一次错误 最近提交的代码里,主要是用 python 写的一个日志分析 …
来到新公司后,终于有机会用 git 作为版本控制的工具。通过 github 私有仓库进行 Pull Request 和 code review,的确十分方便。使用的时候发现自己关于分支的知识不够用了,出现过一次提交 Pull Request 后被 merge,然后自己本地又 merge 了,导致 git pull 时版本冲突的问题。另外,客户端不希望出现 merge,所有对共享配置的修改,都需要用 rebase 方式合并,又犯了一次错误 最近提交的代码里,主要是用 python 写的一个日志分析 …
进程 daemon 化
最近跳槽,转去简悦了,新公司的技术氛围很好,我要更加努力 ~ 有些问题不写博客的时候,以为自己是懂的,但是实际讨论的时候,发现有一些细节还是没有搞清楚,这次试试讲进程怎样 daemon 化。 首先上代码,这次的代码来自于 stackoverflow:http://stackoverflow.com/questions/17954432/creating-a-daemon-in-linux 1 /* 2 * daemonize.c 3 * This example daemonizes a …
最近跳槽,转去简悦了,新公司的技术氛围很好,我要更加努力 ~ 有些问题不写博客的时候,以为自己是懂的,但是实际讨论的时候,发现有一些细节还是没有搞清楚,这次试试讲进程怎样 daemon 化。 首先上代码,这次的代码来自于 stackoverflow:http://stackoverflow.com/questions/17954432/creating-a-daemon-in-linux 1 /* 2 * daemonize.c 3 * This example daemonizes a …
引用计数 gc 机制使用不当导致内存泄漏
上一篇文章找同事 review 了一下,收到的反馈是铺垫太长了,我尽量直入正题,哈哈 最近 dbd 压测时发现内存泄漏,其实这个问题去年已经暴露了,参见这篇 博客【压测周】。当时排查不够仔细,在此检讨下。关于 dbd 的内存问题,还有 这篇博客 讨论线程安全,以及 这篇博客 讨论临时变量的处理。当时还存了一个尾巴,因为用到关联数组进行脏数据管理,这部分数据是怎么释放的一直没搞明白。今天算是搞明白了,这个内存泄漏的 bug 也源于此。 基于引用计数的 gc 机制,应该是在引用计数为 0 的时候释放 …
上一篇文章找同事 review 了一下,收到的反馈是铺垫太长了,我尽量直入正题,哈哈 最近 dbd 压测时发现内存泄漏,其实这个问题去年已经暴露了,参见这篇 博客【压测周】。当时排查不够仔细,在此检讨下。关于 dbd 的内存问题,还有 这篇博客 讨论线程安全,以及 这篇博客 讨论临时变量的处理。当时还存了一个尾巴,因为用到关联数组进行脏数据管理,这部分数据是怎么释放的一直没搞明白。今天算是搞明白了,这个内存泄漏的 bug 也源于此。 基于引用计数的 gc 机制,应该是在引用计数为 0 的时候释放 …
嵌入式课程设计 -- 第一天
今天花了一个早上去配置开发环境,晕死。。。 主要问题是找到一个合适的 2410 实验箱。电脑方面虽然普遍带毒,好歹还是能跑起来。但实验箱方面就比较麻烦。一个是线缆的配合,包括串行线,串行线方面有两种,一种是斜纹,一种是直纹的,它们分别是交叉线和非交叉线。另一个比较重要的线缆是 JTAG 线,我们见的 JTAG 线比较少,所以刚开始的时候拿了另一个实验箱的线。 然后是熟悉了一下 vivi 的操作,首先是尝试把一个 helloworld 的文件通过 JTAG 线烧进去,这个理论上机器正常都可以输出结 …
今天花了一个早上去配置开发环境,晕死。。。 主要问题是找到一个合适的 2410 实验箱。电脑方面虽然普遍带毒,好歹还是能跑起来。但实验箱方面就比较麻烦。一个是线缆的配合,包括串行线,串行线方面有两种,一种是斜纹,一种是直纹的,它们分别是交叉线和非交叉线。另一个比较重要的线缆是 JTAG 线,我们见的 JTAG 线比较少,所以刚开始的时候拿了另一个实验箱的线。 然后是熟悉了一下 vivi 的操作,首先是尝试把一个 helloworld 的文件通过 JTAG 线烧进去,这个理论上机器正常都可以输出结 …
脚本引擎栈指针误操作引起内存泄露
最近,为了确定目标部署机器的配置,我们对服务器进行了玩家登录的压力测试。在 E7500 cpu,3G 内存的开发机上,同一时间登录人数不能超过 20 人。以 0.01 秒间隔登录,测试人数 5000 人,登录时一个核心在 30%-60% 之间波动,另一个核心比较空闲。稳定后,CPU 平均在 5% 一下(玩家只是登录后保持心跳),峰值内存在 2.3G 以内。但比较诡异的是,当玩家全部断开后,服务器的内存还是没有降下来。我觉得,可能是发生内存泄露了。 发现这个问题后,我排查了底层对玩家 user …
最近,为了确定目标部署机器的配置,我们对服务器进行了玩家登录的压力测试。在 E7500 cpu,3G 内存的开发机上,同一时间登录人数不能超过 20 人。以 0.01 秒间隔登录,测试人数 5000 人,登录时一个核心在 30%-60% 之间波动,另一个核心比较空闲。稳定后,CPU 平均在 5% 一下(玩家只是登录后保持心跳),峰值内存在 2.3G 以内。但比较诡异的是,当玩家全部断开后,服务器的内存还是没有降下来。我觉得,可能是发生内存泄露了。 发现这个问题后,我排查了底层对玩家 user …
译 libev 和 libevent 的设计差异
本文译自 what’s the difference between libev and libevent? 作者是 libev 作者 [ 问 ] 两个库都是为异步 io 调度而设计,在 Linux 上都是使用 epoll 机制,在 FreeBSD 上则都是 kqueue,还有诸如此类的很多相通之处。 除了这些表面上的差别外,其实这两者根本的区别在哪里呢?比如架构上,或者设计哲学上。 [ 答 ] 就设计哲学来说,libev 的诞生,是为了修复 libevent 设计上的一些错误决策。例如,全局变 …
本文译自 what’s the difference between libev and libevent? 作者是 libev 作者 [ 问 ] 两个库都是为异步 io 调度而设计,在 Linux 上都是使用 epoll 机制,在 FreeBSD 上则都是 kqueue,还有诸如此类的很多相通之处。 除了这些表面上的差别外,其实这两者根本的区别在哪里呢?比如架构上,或者设计哲学上。 [ 答 ] 就设计哲学来说,libev 的诞生,是为了修复 libevent 设计上的一些错误决策。例如,全局变 …
libevent 库 1.4 升级到 2.0 时无法 flush 的解决办法
libevent 的接口兼容性做的还算不错,基本上替换一下就转到新版本了。但是,强制 flush 数据的时候出了问题。目前的应用场景是,遇到顶号登录这种情形,先用 bufferevent_write 向客户端发送错误信息,然后再断开 socket。用的 flush 是这样的: void try_flush(bufferevent *bev) { int size = evbuffer_get_length(bufferevent_get_output(bev)); if (size > 0) { …
libevent 的接口兼容性做的还算不错,基本上替换一下就转到新版本了。但是,强制 flush 数据的时候出了问题。目前的应用场景是,遇到顶号登录这种情形,先用 bufferevent_write 向客户端发送错误信息,然后再断开 socket。用的 flush 是这样的: void try_flush(bufferevent *bev) { int size = evbuffer_get_length(bufferevent_get_output(bev)); if (size > 0) { …
游戏协议加密及身份验证
时间如白驹过隙,一眨眼就过去了,本打算在 2 月份发这篇的,结果一直误以为 2 月有 31 日 这一块之前一直感兴趣,终于在 2 月份争取到机会去做这一块的工作。前辈给我留下了一个鉴权的框架: 客户端连接服务器 服务器将随机数发给客户端 客户端用客户端私钥加密,发回到服务器 服务器端用客户端公钥解开密文,比对解开的随机数是否与原来的一致 如果一致,则客户端发送随机数到服务器,服务器用服务器端私钥加密,将密文发送到客户端;同时,产生新的随机数,用于稍后对会话进行 rc4 加密,并将这个随机数以客户 …
时间如白驹过隙,一眨眼就过去了,本打算在 2 月份发这篇的,结果一直误以为 2 月有 31 日 这一块之前一直感兴趣,终于在 2 月份争取到机会去做这一块的工作。前辈给我留下了一个鉴权的框架: 客户端连接服务器 服务器将随机数发给客户端 客户端用客户端私钥加密,发回到服务器 服务器端用客户端公钥解开密文,比对解开的随机数是否与原来的一致 如果一致,则客户端发送随机数到服务器,服务器用服务器端私钥加密,将密文发送到客户端;同时,产生新的随机数,用于稍后对会话进行 rc4 加密,并将这个随机数以客户 …
初探 groupcache
groupcache 是用于 dl.google.com 的一个 memcached 的替代品,相对于 memcached,提供更小的功能集和更高的效率,以第三方库的形式提供服务。 groupcache 的常见部署可参考下图: 不同于 memcached,groupcache 面向的是静态的缓存系统,比如 google 家的下载站,用来缓存对应的文件区块。一经 set 操作,key 对应的 value 就不再变化。使用的时候,需要自定义缓存缺失时使用的 set 操作。当发生 miss 的时候,首 …
groupcache 是用于 dl.google.com 的一个 memcached 的替代品,相对于 memcached,提供更小的功能集和更高的效率,以第三方库的形式提供服务。 groupcache 的常见部署可参考下图: 不同于 memcached,groupcache 面向的是静态的缓存系统,比如 google 家的下载站,用来缓存对应的文件区块。一经 set 操作,key 对应的 value 就不再变化。使用的时候,需要自定义缓存缺失时使用的 set 操作。当发生 miss 的时候,首 …
systemtap 折腾笔记
在这货上花费了不少时间,都是受了 @agentzh 大神的蛊惑 :) 他写的 nginx-systemtap-toolkit 监测的数据很有价值,对于系统优化实在是利器。 最早折腾 systemtap,是在 Ubuntu 12.04 上搞的,内核版本是 3.8.0-29-generic,流程参考 官方教程 。因为 12.04 版本比较新,所以不需要重新编译内核了。然后添加带调试信息的内核,以及相关的 Linux 头文件。整个过程还算顺利,就是公司网速比较慢。下载完成后,用 ubuntu 官方仓库 …
在这货上花费了不少时间,都是受了 @agentzh 大神的蛊惑 :) 他写的 nginx-systemtap-toolkit 监测的数据很有价值,对于系统优化实在是利器。 最早折腾 systemtap,是在 Ubuntu 12.04 上搞的,内核版本是 3.8.0-29-generic,流程参考 官方教程 。因为 12.04 版本比较新,所以不需要重新编译内核了。然后添加带调试信息的内核,以及相关的 Linux 头文件。整个过程还算顺利,就是公司网速比较慢。下载完成后,用 ubuntu 官方仓库 …
Mongodb 在 NUMA 机器上的优化
10gen 在 mongodb 的部署指南上,提到了在 NUMA 机器上,mongodb 可能会出现问题,参见:http://docs.mongodb.org/manual/administration/production-notes/#production-numa 里面引用了一篇博客,主要讲 MySQL 的 swap insanity,而 mongodb 也会遇到类似的问题,博客地址 …
10gen 在 mongodb 的部署指南上,提到了在 NUMA 机器上,mongodb 可能会出现问题,参见:http://docs.mongodb.org/manual/administration/production-notes/#production-numa 里面引用了一篇博客,主要讲 MySQL 的 swap insanity,而 mongodb 也会遇到类似的问题,博客地址 …
转设置 Android 手机以使用 ARMStreamline 进行性能分析(一)
Streamline 5.7 版。Streamline 是 ARM Development Studio 5 的一个组成模块。因此,可通过下载 ARM DS-5 专业版、基础版或免费的 DS-5 公众版(针对 Android 系统)来获得它。 目标 ARM 设备,HTC Sensation 4G - [Qualcomm Snapdragon …
Streamline 5.7 版。Streamline 是 ARM Development Studio 5 的一个组成模块。因此,可通过下载 ARM DS-5 专业版、基础版或免费的 DS-5 公众版(针对 Android 系统)来获得它。 目标 ARM 设备,HTC Sensation 4G - [Qualcomm Snapdragon …
转设置 Android 手机以使用 ARMStreamline 进行性能分析(二)
General Setup( 常规设置 ),确保启用了 Profiling Support ( 分析支持 ) 选项。 Kernel Hacking( 内核开发 ),在子菜单中,导航至 Tracers 子菜单,然后按下 Enter。确保启用 Trace 进程上下文开关选项。 Kernel Features( 内核功能 ),确保启用 High Resolution Timer Support ( 高分辨率定时器支持 )。如果正在使用对称多处理器 (SMP) 设备,则启用 Use local …
General Setup( 常规设置 ),确保启用了 Profiling Support ( 分析支持 ) 选项。 Kernel Hacking( 内核开发 ),在子菜单中,导航至 Tracers 子菜单,然后按下 Enter。确保启用 Trace 进程上下文开关选项。 Kernel Features( 内核功能 ),确保启用 High Resolution Timer Support ( 高分辨率定时器支持 )。如果正在使用对称多处理器 (SMP) 设备,则启用 Use local …
FreeBSD 打开 DTrace 支持
主要翻译自:https://wiki.freebsd.org/DTrace FreeBSD 跟 Linux 发行版一个比较大的差异,就是提倡源码构建。因此这里提到比较多的编译开关设置。自 2012 年 5 月后,DTrace 支持默认是打开的,因此以下步骤不再需要了。留意 uname -a 输出的日期即可。 添加内核编译选项,打开 DTrace 支持 打开调试符号 makeoptions DEBUG="-g" # build kernel with gdb(1) debug symbols 对于 …
主要翻译自:https://wiki.freebsd.org/DTrace FreeBSD 跟 Linux 发行版一个比较大的差异,就是提倡源码构建。因此这里提到比较多的编译开关设置。自 2012 年 5 月后,DTrace 支持默认是打开的,因此以下步骤不再需要了。留意 uname -a 输出的日期即可。 添加内核编译选项,打开 DTrace 支持 打开调试符号 makeoptions DEBUG="-g" # build kernel with gdb(1) debug symbols 对于 …
压测周
本周主要工作是解决 dbd 的多线程 bug,可是失败了。 为了重现这个多线程的 bug,准备模拟多用户登录的情景,当多个用户需要保存数据的时候,就会跑到多线程序列化数据的部分,应该可以重现这个 bug。于是,从周一到周三,花了三天时间,用 python+gevent 写了一个模拟客户端,实现了客户端连接服务器和登录的流程。其实这个测试工具,在上一个项目里已经写了一点了,基本数据类型的解包比如整型,字符串解包已经有了。但是,我翻看代码才发现,当时没有写打包协议的实现写的过程比较流畅,用了 …
本周主要工作是解决 dbd 的多线程 bug,可是失败了。 为了重现这个多线程的 bug,准备模拟多用户登录的情景,当多个用户需要保存数据的时候,就会跑到多线程序列化数据的部分,应该可以重现这个 bug。于是,从周一到周三,花了三天时间,用 python+gevent 写了一个模拟客户端,实现了客户端连接服务器和登录的流程。其实这个测试工具,在上一个项目里已经写了一点了,基本数据类型的解包比如整型,字符串解包已经有了。但是,我翻看代码才发现,当时没有写打包协议的实现写的过程比较流畅,用了 …
类型系统线程安全
最近情绪有点失控,跟很欣赏的同事吵架了,真难过。有些话,可能真的只有吵架才会说出口,只好安慰自己,这未尝不是一次难得的交流。究其原因,就是一段代码由我开发,他接手维护,然后交给我继续跟进;最近频繁报 bug,他觉得在替我擦屁股,收拾代码,我也觉得我在替他擦屁股,大家心里有气,但是谁也没有说出口。多点面对面交流,多点讨论,工作压力小一点,可能就可以避免了。 最近修复的 dbd 的 bug,一个是字符串管理上面的, 上一篇博文 已经提到了 mapping_to_bson 的,这周还发现了 …
最近情绪有点失控,跟很欣赏的同事吵架了,真难过。有些话,可能真的只有吵架才会说出口,只好安慰自己,这未尝不是一次难得的交流。究其原因,就是一段代码由我开发,他接手维护,然后交给我继续跟进;最近频繁报 bug,他觉得在替我擦屁股,收拾代码,我也觉得我在替他擦屁股,大家心里有气,但是谁也没有说出口。多点面对面交流,多点讨论,工作压力小一点,可能就可以避免了。 最近修复的 dbd 的 bug,一个是字符串管理上面的, 上一篇博文 已经提到了 mapping_to_bson 的,这周还发现了 …
dbd 到 mongo 的序列化问题及稳定性
最近工作压力有点大,情绪偶然会失控,要好好反省一下自己。 上周本来打算写 CSP 相关的东西,但是目前做得还不够多,积累的经验不足,就放弃了。中间找到很好的参考资料,一并放在这里。一篇是比较短的论文,可以观其大略:http://www.cs.ucf.edu/courses/cop4020/sum2009/CSP-hoare.pdf,另一个链接是 hoare 写的关于进程演算的书 …
最近工作压力有点大,情绪偶然会失控,要好好反省一下自己。 上周本来打算写 CSP 相关的东西,但是目前做得还不够多,积累的经验不足,就放弃了。中间找到很好的参考资料,一并放在这里。一篇是比较短的论文,可以观其大略:http://www.cs.ucf.edu/courses/cop4020/sum2009/CSP-hoare.pdf,另一个链接是 hoare 写的关于进程演算的书 …
进程演算中的事件概念
最近将军团模块的 bug 修的差不多了,可以准备下一步的分布式改造了。只是每次想起这工程量,就有够头大的了。 在修改军团的时候,除了不断增补单元测试,就是思考分布式的交互。不同进程间的交互,一个 rpc 协议就是一个消息,消息间是有严格的先后顺序的,
最近将军团模块的 bug 修的差不多了,可以准备下一步的分布式改造了。只是每次想起这工程量,就有够头大的了。 在修改军团的时候,除了不断增补单元测试,就是思考分布式的交互。不同进程间的交互,一个 rpc 协议就是一个消息,消息间是有严格的先后顺序的,
青春请你归来,再伴我一会
加班到 12 点,走出公司的时候,发现大街上伴我同行的,只有一大帮小姐了,so sad 持续加班获得的效率红利已经渐渐消失,前面留下的技术债越来越成为前进的障碍。发版本的前一晚,提交频率非常高,经常有人抱怨更新后进不去游戏。客户端没有人搞单元测试,偏偏脚本又无法通过静态编译消灭一部分低级错误。于是,就变成了《唐伯虎点秋香》那一幕: 本周主要做的是公会的公告板系统。一般公会的聊天都是纯文本,只要记得记录就好,但是 coc 的公会还有同意和拒绝这种操作,以及捐兵,而且这两项还是实时推送。推送消息的时 …
加班到 12 点,走出公司的时候,发现大街上伴我同行的,只有一大帮小姐了,so sad 持续加班获得的效率红利已经渐渐消失,前面留下的技术债越来越成为前进的障碍。发版本的前一晚,提交频率非常高,经常有人抱怨更新后进不去游戏。客户端没有人搞单元测试,偏偏脚本又无法通过静态编译消灭一部分低级错误。于是,就变成了《唐伯虎点秋香》那一幕: 本周主要做的是公会的公告板系统。一般公会的聊天都是纯文本,只要记得记录就好,但是 coc 的公会还有同意和拒绝这种操作,以及捐兵,而且这两项还是实时推送。推送消息的时 …
再堕噩梦,斩龙之旅
本周继续做公会功能,有点乏味。 这次主要是基于上周完成的框架,进行具体功能的协议对接。原本以为对接会很简单,毕竟之前的功能模块都已经写过单元测试了,虽然覆盖率不高,好歹还是能跑通 happy path 的。实际用的时候,才发现上周设计的 api 粒度太细了。隐约记得第一次做公会,也是犯了这个错误,api 之间是十分正交,每一个完成的功能也很简单,方便测试。但是,用的时候需要调用多个 api,因此需要处理多种错误情况,而没有 goto 语句,又导致需要将同一段错误处理代码多次复制粘贴。 另一个比 …
本周继续做公会功能,有点乏味。 这次主要是基于上周完成的框架,进行具体功能的协议对接。原本以为对接会很简单,毕竟之前的功能模块都已经写过单元测试了,虽然覆盖率不高,好歹还是能跑通 happy path 的。实际用的时候,才发现上周设计的 api 粒度太细了。隐约记得第一次做公会,也是犯了这个错误,api 之间是十分正交,每一个完成的功能也很简单,方便测试。但是,用的时候需要调用多个 api,因此需要处理多种错误情况,而没有 goto 语句,又导致需要将同一段错误处理代码多次复制粘贴。 另一个比 …
抄作业的一周
本周主要处理军团的抄袭工作。。。 第二次做类似公会模块的东东了,分功能的时候还算轻车熟路,只是几个管理器之间概念层次不同,组装的时候还真费神。这一块的东西,技术上倒谈不上有什么难度,但是比较繁琐,就怕某个功能点没做好,以后填坑就痛苦了。这次配合着单元测试来搞,每个功能组件都有单元测试配套,然后自己写了一点文档,说明这个模块的组成,各个功能需要实现的目标,希望以后修改会比较方便。 本质上,公会是双向映射的结构,需要公会能查询到会员,还能根据会员属性排序。而会员不仅要能索引到公会,还需要能得到自己的 …
本周主要处理军团的抄袭工作。。。 第二次做类似公会模块的东东了,分功能的时候还算轻车熟路,只是几个管理器之间概念层次不同,组装的时候还真费神。这一块的东西,技术上倒谈不上有什么难度,但是比较繁琐,就怕某个功能点没做好,以后填坑就痛苦了。这次配合着单元测试来搞,每个功能组件都有单元测试配套,然后自己写了一点文档,说明这个模块的组成,各个功能需要实现的目标,希望以后修改会比较方便。 本质上,公会是双向映射的结构,需要公会能查询到会员,还能根据会员属性排序。而会员不仅要能索引到公会,还需要能得到自己的 …
supervisor 很赞!
最近,公司进行了新的架构设计,原来一个区服一组进程,变成了对外只有一台服,后面 N 组多进程进行服务的模式。于是,管理进程就变成了一个头痛的问题。原来是在写代码的目录里放置各种脚本解决的,关闭脚本,开启脚本,重启脚本,更新脚本,还有一打用来看各种日志的脚本。这些脚本还是严重目录相关的,要执行某些命令,只能 cd 到指定目录执行(或者用硬连接 + 设置脚本所在目录为当前目录解决?whatever)。遇到实际部署的时候,还需要 ssh 到指定机器上,运行指定脚本,有时候还担心服务器起不来,需要人肉 …
最近,公司进行了新的架构设计,原来一个区服一组进程,变成了对外只有一台服,后面 N 组多进程进行服务的模式。于是,管理进程就变成了一个头痛的问题。原来是在写代码的目录里放置各种脚本解决的,关闭脚本,开启脚本,重启脚本,更新脚本,还有一打用来看各种日志的脚本。这些脚本还是严重目录相关的,要执行某些命令,只能 cd 到指定目录执行(或者用硬连接 + 设置脚本所在目录为当前目录解决?whatever)。遇到实际部署的时候,还需要 ssh 到指定机器上,运行指定脚本,有时候还担心服务器起不来,需要人肉 …
添加 mongodb 支持
最近花了些时间,将引擎的存储换成了 mongodb。 私下,我觉得现有的存储机制极为落后。现在写数据的操作交由单独的进程完成,该进程兼当数据缓冲与持续化数据的责任。此次引擎的更换,只是简单的利用 mongo 的官方 c 驱动,将数据打到 mongo 里面,代替写文件的做法而已。该进程的数据缓冲角色,还是没有变化。mongodb 的优势在于对内存的高效利用,增加一层作为中转,就会失去这个速度上的优势。 往引擎里添加 mongo,比较头大的是跟引擎脚本的类型系统打交道。比较了一下 BSON 支持的数 …
最近花了些时间,将引擎的存储换成了 mongodb。 私下,我觉得现有的存储机制极为落后。现在写数据的操作交由单独的进程完成,该进程兼当数据缓冲与持续化数据的责任。此次引擎的更换,只是简单的利用 mongo 的官方 c 驱动,将数据打到 mongo 里面,代替写文件的做法而已。该进程的数据缓冲角色,还是没有变化。mongodb 的优势在于对内存的高效利用,增加一层作为中转,就会失去这个速度上的优势。 往引擎里添加 mongo,比较头大的是跟引擎脚本的类型系统打交道。比较了一下 BSON 支持的数 …
TheimplementationofLua5.0 阅读笔记(二)
6 线程和协程 读完这篇文章我才意识到 python 的协程到底缺了什么,这个就是 coroutine 和 semi-coroutine 的区别了。区别就是,semi-coroutine 只能返回(yield)到调用者所在位置,不能将控制权交到任意其他协程上去。具有这个特征的,都是 semi-coroutine。 Lua 实现协程的时候,充分利用了其 C 栈和 Lua 栈。进行协程调用的时候,解释器会在 C 栈上会进行一次递归调用,然后协程自身的栈在新建立的 Lua 栈里消长。当一个协程结束的时 …
6 线程和协程 读完这篇文章我才意识到 python 的协程到底缺了什么,这个就是 coroutine 和 semi-coroutine 的区别了。区别就是,semi-coroutine 只能返回(yield)到调用者所在位置,不能将控制权交到任意其他协程上去。具有这个特征的,都是 semi-coroutine。 Lua 实现协程的时候,充分利用了其 C 栈和 Lua 栈。进行协程调用的时候,解释器会在 C 栈上会进行一次递归调用,然后协程自身的栈在新建立的 Lua 栈里消长。当一个协程结束的时 …
TheImplementationofLua5.0 阅读笔记(一)
没想到 Lua 的作者理论水平这么高,这篇文章读的我顿生高屋建瓴之感。云风分享了一篇中译:http://www.codingnow.com/2000/download/The%20Implementation%20of%20Lua5.0.pdf 全篇的主题有 4 个:1. 基于寄存器的虚拟机;2. 用于将 table 作为数组使用的新算法;3. 闭包的实现;4. 以及协程。第二点我关注不多,会写的比较简略。 1 简介 简介主要就是说,我们搞 Lua 嘛,就是一个实验室出来的产品,没想到今天在工业 …
没想到 Lua 的作者理论水平这么高,这篇文章读的我顿生高屋建瓴之感。云风分享了一篇中译:http://www.codingnow.com/2000/download/The%20Implementation%20of%20Lua5.0.pdf 全篇的主题有 4 个:1. 基于寄存器的虚拟机;2. 用于将 table 作为数组使用的新算法;3. 闭包的实现;4. 以及协程。第二点我关注不多,会写的比较简略。 1 简介 简介主要就是说,我们搞 Lua 嘛,就是一个实验室出来的产品,没想到今天在工业 …
移动安卓端网络库开发
最近在协助客户端做网络通讯和登录流程,增进了对 Lua 的了解,捣鼓 Libevent 的静态库编译,掌握了部分 Android NDK 的开发技巧。真机调试遇到一个比较大的问题,由于资源较大,打包出来的 apk 有 100M大小,每次因为一个语法错误或者路径大小写问题,导致重新写 apk,都有种吐血的感觉。因此,想搞个热更新的框架和联机远程调试的 Lua 调试器。 另外,由于项目预期只有短短 3 个月的开发时间,时间管理方面遇到比较大的问题。客户端的主程又死抱着 C++ 的那套对象思想,跟其他 …
最近在协助客户端做网络通讯和登录流程,增进了对 Lua 的了解,捣鼓 Libevent 的静态库编译,掌握了部分 Android NDK 的开发技巧。真机调试遇到一个比较大的问题,由于资源较大,打包出来的 apk 有 100M大小,每次因为一个语法错误或者路径大小写问题,导致重新写 apk,都有种吐血的感觉。因此,想搞个热更新的框架和联机远程调试的 Lua 调试器。 另外,由于项目预期只有短短 3 个月的开发时间,时间管理方面遇到比较大的问题。客户端的主程又死抱着 C++ 的那套对象思想,跟其他 …
从 lua 调用 C 函数
最近在进入 Lua 编程的状态,一度令我困惑的是,Lua 提供的功能少的可怜,跟自备电池的 python 相比,可说是简陋了。连 table 的打印,都需要自己实现,也因此有了一打的第三方方案。后来我想明白了,以 Lua 和 C 如此紧密的关系,只需要建立 Lua 的 binding,那么丰富而性能强大的 C 库资源完全可以为 Lua 所用,这样就不愁功能缺失了。 关于 C 调用 Lua,前段时间已经写过一篇短文了:《多语言协作与二进制交互》,现在补上从 Lua 调用 C 的这一篇。先上一段 …
最近在进入 Lua 编程的状态,一度令我困惑的是,Lua 提供的功能少的可怜,跟自备电池的 python 相比,可说是简陋了。连 table 的打印,都需要自己实现,也因此有了一打的第三方方案。后来我想明白了,以 Lua 和 C 如此紧密的关系,只需要建立 Lua 的 binding,那么丰富而性能强大的 C 库资源完全可以为 Lua 所用,这样就不愁功能缺失了。 关于 C 调用 Lua,前段时间已经写过一篇短文了:《多语言协作与二进制交互》,现在补上从 Lua 调用 C 的这一篇。先上一段 …
新的开始
原项目没有上线的机会了,停止开发,伤心了好久。目前转到手机开发上去了,使用开源的 cocos-2dx 引擎,貌似坑比较多啊
原项目没有上线的机会了,停止开发,伤心了好久。目前转到手机开发上去了,使用开源的 cocos-2dx 引擎,貌似坑比较多啊
外服部署时遇到的问题
吐槽一下,公司的权限给的很死,部署的时候麻烦事比较多,趁手的工具需要自己手动编译,无法利用 port 安装。 昨天遇到一个外服部署的问题,表现为外服不能登陆,用部署工具重新发布代码后,仍然如此。于是联系运维的同学进行处理,运维的同学帮助排障时发现引擎启动报错,提示 rc/simul_efun must be loadable,认为是代码的问题。回去检查代码后,没有发现问题,而且这个文件已经很长时间没有更改了,怀疑是编译的问题。后来,手动连接外服,将验证服务器跑起来了,但是游戏服依然提示同样的错误 …
吐槽一下,公司的权限给的很死,部署的时候麻烦事比较多,趁手的工具需要自己手动编译,无法利用 port 安装。 昨天遇到一个外服部署的问题,表现为外服不能登陆,用部署工具重新发布代码后,仍然如此。于是联系运维的同学进行处理,运维的同学帮助排障时发现引擎启动报错,提示 rc/simul_efun must be loadable,认为是代码的问题。回去检查代码后,没有发现问题,而且这个文件已经很长时间没有更改了,怀疑是编译的问题。后来,手动连接外服,将验证服务器跑起来了,但是游戏服依然提示同样的错误 …
迅捷 FASTFWR171-3G 实战 OpenWRT
FAST 是 TP-LINK 的一个子品牌,所推出的 FWR171-3G 与 TP-LINK wr703n 的硬件采用相同规格,而前者要便宜 20 块,区别只在品牌、外观与软件界面。于是果断入手,然后尝试 OpenWRT。 上手后第一件事,就是通过官方界面进行线路测试。目前的网络连接是,通过 RJ45 接口接入光猫进行 PPPOE 拨号,然后利用 wifi 信号完成无线路由功能。遗憾的是,通过官方界面进行拨号连接时提示密码错误,无法联通。于是,去找到了 wr703n 的固件刷上,文件是 …
FAST 是 TP-LINK 的一个子品牌,所推出的 FWR171-3G 与 TP-LINK wr703n 的硬件采用相同规格,而前者要便宜 20 块,区别只在品牌、外观与软件界面。于是果断入手,然后尝试 OpenWRT。 上手后第一件事,就是通过官方界面进行线路测试。目前的网络连接是,通过 RJ45 接口接入光猫进行 PPPOE 拨号,然后利用 wifi 信号完成无线路由功能。遗憾的是,通过官方界面进行拨号连接时提示密码错误,无法联通。于是,去找到了 wr703n 的固件刷上,文件是 …
游戏服务器设计的思考
gevent 并发模型:缺点:多玩家交互的时候需要使用锁,bug 比较隐蔽。进行耗时较长的查询时有可能某些资源已经过期,也需要使用锁保护。 Mudos Like: 优点:游戏逻辑进程同一时间只处理一个玩家的一个请求 缺点:与玩家交互比较密集的时候需要用到异步回调,需要从磁盘读数据的时候要异步回调,搞得写函数很恶心。而且回调函数里需要把前面的检查再做一次,跟 gevent 的并发模型比较没有了优势。 展望 erlang: 将游戏的功能按服务的方式提供,不提供服务时就关闭进程,进程间用消息机制解耦合 …
gevent 并发模型:缺点:多玩家交互的时候需要使用锁,bug 比较隐蔽。进行耗时较长的查询时有可能某些资源已经过期,也需要使用锁保护。 Mudos Like: 优点:游戏逻辑进程同一时间只处理一个玩家的一个请求 缺点:与玩家交互比较密集的时候需要用到异步回调,需要从磁盘读数据的时候要异步回调,搞得写函数很恶心。而且回调函数里需要把前面的检查再做一次,跟 gevent 的并发模型比较没有了优势。 展望 erlang: 将游戏的功能按服务的方式提供,不提供服务时就关闭进程,进程间用消息机制解耦合 …
多语言协作与二进制交互
最近刚刚完成了服务器端 rpc 协议的 python 封装,理论上说,后续的开发可以以 python 继续进行了。只是代码热更新还没好,项目进度又吃紧,暂时先放下了。利用 rpc 协议连接不同进程,各个进程就可以自由选择语言去开发,不局限于 C、LPC 了。让项目能够充分利用各个语言的优势,在不同的场景下选择特长语言进行开发,这图景不错。 而客户端所用的 Lua 脚本,则是以另一种方式实现了多语言协作开发。通过精巧的 Lua API,C 层可以将一些灵活多变的逻辑操作转交给上层的 Lua 逻辑去 …
最近刚刚完成了服务器端 rpc 协议的 python 封装,理论上说,后续的开发可以以 python 继续进行了。只是代码热更新还没好,项目进度又吃紧,暂时先放下了。利用 rpc 协议连接不同进程,各个进程就可以自由选择语言去开发,不局限于 C、LPC 了。让项目能够充分利用各个语言的优势,在不同的场景下选择特长语言进行开发,这图景不错。 而客户端所用的 Lua 脚本,则是以另一种方式实现了多语言协作开发。通过精巧的 Lua API,C 层可以将一些灵活多变的逻辑操作转交给上层的 Lua 逻辑去 …
从一段代码里看 FreeBSD 与 Linux 内存分配的不同
唉,拖延症无以复加了。 最近,公司移植服务器端游戏引擎到 Linux 上的时候,遇上了段错误。问题代码大略如下: char *arr = malloc(len); ... if (IsInvalid(arr[0])){ arr++; } ... free(arr); 很明显,对操作系统分配的内存块进行了指针操作后,再扔回到 free 函数进行释放,是会导致异常行为的。但是,该引擎的代码已经有较长的历史了,为什么在 FreeBSD 上没有遇到问题呢? 这主要是因为 FreeBSD 与 Linux …
唉,拖延症无以复加了。 最近,公司移植服务器端游戏引擎到 Linux 上的时候,遇上了段错误。问题代码大略如下: char *arr = malloc(len); ... if (IsInvalid(arr[0])){ arr++; } ... free(arr); 很明显,对操作系统分配的内存块进行了指针操作后,再扔回到 free 函数进行释放,是会导致异常行为的。但是,该引擎的代码已经有较长的历史了,为什么在 FreeBSD 上没有遇到问题呢? 这主要是因为 FreeBSD 与 Linux …
存储器性能测试
Xeon E5620 E7500 In virtual machine, E7500 最近做了个存储器性能测试,结果如上图。z 轴表示速度,单位是 MB/s, x 轴和 y 轴一个表示步长,即两次访问数据之间的距离;另一个是读写的数据总量,单位是字节。源代码可以通过 http://csapp.cs.cmu.edu/public/1e/public/mountain.tar 获取。 这个测试是 CSAPP 书里用来说明存储器山的一个实验。关于这个测试,有两个基本的概念:时间局部性与空间局部性。 …
Xeon E5620 E7500 In virtual machine, E7500 最近做了个存储器性能测试,结果如上图。z 轴表示速度,单位是 MB/s, x 轴和 y 轴一个表示步长,即两次访问数据之间的距离;另一个是读写的数据总量,单位是字节。源代码可以通过 http://csapp.cs.cmu.edu/public/1e/public/mountain.tar 获取。 这个测试是 CSAPP 书里用来说明存储器山的一个实验。关于这个测试,有两个基本的概念:时间局部性与空间局部性。 …
欢送 2012
新年快乐!2012 年就要过去了,本月看代码为主,少动手了,分享两篇文章给大家: 第一篇是 varnish 作者 Poul henning 写的,题为 Notes from the Architect,作者的观点可以总结为三点: 相信虚拟存储系统,不要手动进行内存分页管理,而是依赖虚存系统做这件事。不要和虚存系统作对。 减少内存的访问次数,最小化多核心之间对于 cache 的争夺。 合理调度线程,按最近工作时间来安排,尽可能保证 cache 已处于热身状态。 另一篇是 LuaJit 的作者 …
新年快乐!2012 年就要过去了,本月看代码为主,少动手了,分享两篇文章给大家: 第一篇是 varnish 作者 Poul henning 写的,题为 Notes from the Architect,作者的观点可以总结为三点: 相信虚拟存储系统,不要手动进行内存分页管理,而是依赖虚存系统做这件事。不要和虚存系统作对。 减少内存的访问次数,最小化多核心之间对于 cache 的争夺。 合理调度线程,按最近工作时间来安排,尽可能保证 cache 已处于热身状态。 另一篇是 LuaJit 的作者 …
tig 支持中文搜索
tig 是一个基于 ncurses 库的 git log、status 的浏览器,看 log 的时候非常方便,可以非常简单的查看每次 log 的 diff,同时方便的切换到其他视角例如 diff、blame、tree 等等。但是,tig 有一个问题,不支持搜索中文。 检查了相关的 issue 以后,确认了链接时使用 -lncursesw,支持中文这种宽字符的显示,实际应用中也可以显示,但就是没办法搜索中文。于是,我向作者报告了这个 …
tig 是一个基于 ncurses 库的 git log、status 的浏览器,看 log 的时候非常方便,可以非常简单的查看每次 log 的 diff,同时方便的切换到其他视角例如 diff、blame、tree 等等。但是,tig 有一个问题,不支持搜索中文。 检查了相关的 issue 以后,确认了链接时使用 -lncursesw,支持中文这种宽字符的显示,实际应用中也可以显示,但就是没办法搜索中文。于是,我向作者报告了这个 …
LPC 及 MudOS 简介 ( 一 )
天下盛境这个项目让我萌生退意了,拖延了一个多月,没想到公司居然先解散了。接着是面试,入职新公司,回头看来,还是感慨人算不如天算阿。 新公司也是游戏行业的,初看了下项目的架构,与以前的有较大差别,是一套脱胎于 MudOS 的异步 IO、多进程的游戏架构。于是最近在研究 Mudos 的相关知识。刚刚入门,挑了最简单的 Lil Mudlib 进行学习,Mudos 的版本为 v22.2b14,既能够成功跑起来接受玩家的链接,又不会有复杂的功能阻碍理解,正好动手边改边学。 LPC 是一门专门为 Mudos …
天下盛境这个项目让我萌生退意了,拖延了一个多月,没想到公司居然先解散了。接着是面试,入职新公司,回头看来,还是感慨人算不如天算阿。 新公司也是游戏行业的,初看了下项目的架构,与以前的有较大差别,是一套脱胎于 MudOS 的异步 IO、多进程的游戏架构。于是最近在研究 Mudos 的相关知识。刚刚入门,挑了最简单的 Lil Mudlib 进行学习,Mudos 的版本为 v22.2b14,既能够成功跑起来接受玩家的链接,又不会有复杂的功能阻碍理解,正好动手边改边学。 LPC 是一门专门为 Mudos …
大面积断线原因分析
昨天,在台服上运行的服务器爆发了大面积断线。从时间点上看,跟一个副本活动高度重合,因此,今天早上就紧急屏蔽了该活动模块。 拿到 log 进行分析,看到的异常大部分是从战斗副本返回主城时发生的。副本活动产生的异常倒是没有看到,而且这个副本在国内也经历过几个运营商实际运营的测试,出现问题的机会应该比较少。 从战斗副本返回主城的过程经过一次调整,原有的流程是副本退出时保存到 mysql,再在主城里从数据库恢复过来。现有的流程,是先把所需数据打包,然后通过 tcp 发送到主城,由主城进行解包并恢复到角色 …
昨天,在台服上运行的服务器爆发了大面积断线。从时间点上看,跟一个副本活动高度重合,因此,今天早上就紧急屏蔽了该活动模块。 拿到 log 进行分析,看到的异常大部分是从战斗副本返回主城时发生的。副本活动产生的异常倒是没有看到,而且这个副本在国内也经历过几个运营商实际运营的测试,出现问题的机会应该比较少。 从战斗副本返回主城的过程经过一次调整,原有的流程是副本退出时保存到 mysql,再在主城里从数据库恢复过来。现有的流程,是先把所需数据打包,然后通过 tcp 发送到主城,由主城进行解包并恢复到角色 …
断线与资源释放
断线先不释放资源,待刚刚收到的请求完成后,再统一回收资源 开发框架应该提供一套通用的日志监控接口和资源分配接口,以确定资源的消耗情况,确定性能热点。
断线先不释放资源,待刚刚收到的请求完成后,再统一回收资源 开发框架应该提供一套通用的日志监控接口和资源分配接口,以确定资源的消耗情况,确定性能热点。
RPC 的思考
基于 google protobuf 的 rpc 框架介绍系列文章 目前,基于消息包的消息收发 步骤:确定前端需要的相关信息 定义交互步骤 编写相应的 proto 文件 编译,分别生成前后端代码 层次太低。对前后端交互的思考,是在函数调用的层面上的,但是实际上做的,却是将函数调用手动转为数据包。针对具体传递的消息编写消息包的 proto,本无可厚非。但是,每次都要编写内容为空的 Request 包让我很蛋疼。究其原因,是每次都需要重写 Request/Response 语义的东东。 语义:基于函 …
基于 google protobuf 的 rpc 框架介绍系列文章 目前,基于消息包的消息收发 步骤:确定前端需要的相关信息 定义交互步骤 编写相应的 proto 文件 编译,分别生成前后端代码 层次太低。对前后端交互的思考,是在函数调用的层面上的,但是实际上做的,却是将函数调用手动转为数据包。针对具体传递的消息编写消息包的 proto,本无可厚非。但是,每次都要编写内容为空的 Request 包让我很蛋疼。究其原因,是每次都需要重写 Request/Response 语义的东东。 语义:基于函 …
【翻译】HowwemakeGitHubfast( 我们如何让 github 更快 )
译者注:我是一名开源爱好者,十分喜爱 github,github 也是一个乐于分享的站点。这篇文章介绍了 github 为应对更高访问量而搭建的架构,虽然已经是 09 年的文章,仍有一定的参考价值,因此翻译此文分享给大家 [ 我们如何让 github 变得更快 ](https://github.com/blog/530-how-we-made-github-fast) mojombo October 20, 2009 Translations: Беларускі, Deutsch, …
译者注:我是一名开源爱好者,十分喜爱 github,github 也是一个乐于分享的站点。这篇文章介绍了 github 为应对更高访问量而搭建的架构,虽然已经是 09 年的文章,仍有一定的参考价值,因此翻译此文分享给大家 [ 我们如何让 github 变得更快 ](https://github.com/blog/530-how-we-made-github-fast) mojombo October 20, 2009 Translations: Беларускі, Deutsch, …
tricks: 如何把 sqlalchemy 的数据转化为 json 格式
sqlalchemy 最恶心的对象,就是通过 execute 得到的结果,那是 rowproxy 列表。为了优化,rowproxy 使用了 slot,使其失去了动态性,而又经常要转换成 json 格式,于是可以这样: d=dict(rowproxy.items()) json.dumps(d)
sqlalchemy 最恶心的对象,就是通过 execute 得到的结果,那是 rowproxy 列表。为了优化,rowproxy 使用了 slot,使其失去了动态性,而又经常要转换成 json 格式,于是可以这样: d=dict(rowproxy.items()) json.dumps(d)
项目总结
入职一年有余了。 收获 第一次参加实战项目,也是第一次参加多人协作的项目,感觉很新鲜。回头看,学校应该多开展这样的训练。多人协作跟个人开发最大的不同,是需要大量阅读他人的项目代码,在实现功能的时候,也需要不断的进行妥协。要阅读一个新项目的代码,从最初的版本 checkout 进行阅读往往是比较好的选择,可以比较清晰的看到项目的架构思想,把握模块开发的惯用法。另外,首先阅读核心工具库帮助很大,一是能够很清晰看到老大的功力(笑),二是对于阅读他人的新模块,尽快投入开发,能够有较大帮助。 在学校学习 …
入职一年有余了。 收获 第一次参加实战项目,也是第一次参加多人协作的项目,感觉很新鲜。回头看,学校应该多开展这样的训练。多人协作跟个人开发最大的不同,是需要大量阅读他人的项目代码,在实现功能的时候,也需要不断的进行妥协。要阅读一个新项目的代码,从最初的版本 checkout 进行阅读往往是比较好的选择,可以比较清晰的看到项目的架构思想,把握模块开发的惯用法。另外,首先阅读核心工具库帮助很大,一是能够很清晰看到老大的功力(笑),二是对于阅读他人的新模块,尽快投入开发,能够有较大帮助。 在学校学习 …
智能去除选定区域
这篇文章缘起于这篇博客:http://xiaoxia.org/2011/12/03/shocked-by-gimp-filter-smart-remove-selection/ 看完以后着实震惊了,这下要去掉照片里的东西实在太简单了。在群里吼了一声以后,美术表示 Photoshop CS5 很淡定。于是我找来了 Photoshop CS5 (PS CS5) 教程 看看,大约 9 分钟的时候,CS5 潇洒地 P 掉了背景中的一个人,神奇了! 这项工作原来是要靠人手完成的,自己选取一块相近的纹理,通 …
这篇文章缘起于这篇博客:http://xiaoxia.org/2011/12/03/shocked-by-gimp-filter-smart-remove-selection/ 看完以后着实震惊了,这下要去掉照片里的东西实在太简单了。在群里吼了一声以后,美术表示 Photoshop CS5 很淡定。于是我找来了 Photoshop CS5 (PS CS5) 教程 看看,大约 9 分钟的时候,CS5 潇洒地 P 掉了背景中的一个人,神奇了! 这项工作原来是要靠人手完成的,自己选取一块相近的纹理,通 …
分享三个好用的装饰器
1 def log_wrapper(func):2 @functools.wraps(func)3 def log_func_name(self, *args, **kws):4 logger.debug(" 调用函数 [%s]", func.func_name)5 logger.debug(" 参数为 :%s, %s", [arg.__unicode__() for arg in args], kws)6 result = func(self, *args, **kws)7 …
1 def log_wrapper(func):2 @functools.wraps(func)3 def log_func_name(self, *args, **kws):4 logger.debug(" 调用函数 [%s]", func.func_name)5 logger.debug(" 参数为 :%s, %s", [arg.__unicode__() for arg in args], kws)6 result = func(self, *args, **kws)7 …
根据 pythonprotobuf 自动生成 protobuf 包收发接口
利用 protobuf 进行串行化和反串行化处理,封装出来的 rpc 服务很好用。但是有个缺点,就是测试时,一些很简单的接口都要重新实现一次,程序体内就一些简单的赋值语句。写了个代码生成器,用来生成 protobuf 对应的请求函数和回应函数,请求函数根据 req 的内容,生成赋值函数体;回应函数只是负责把服务器返回的包进行打印。 先用 .proto 文件生成 protobuf 的 xxx_pb2.py 文件,将其放入 protobuf 目录 #!/usr/bin/env python# -*- …
利用 protobuf 进行串行化和反串行化处理,封装出来的 rpc 服务很好用。但是有个缺点,就是测试时,一些很简单的接口都要重新实现一次,程序体内就一些简单的赋值语句。写了个代码生成器,用来生成 protobuf 对应的请求函数和回应函数,请求函数根据 req 的内容,生成赋值函数体;回应函数只是负责把服务器返回的包进行打印。 先用 .proto 文件生成 protobuf 的 xxx_pb2.py 文件,将其放入 protobuf 目录 #!/usr/bin/env python# -*- …
台电 k6 你立功了
等了一年,还是停留在 v2.11 的固件上,英文就一渣排版。只能自己动手了 写了个英文排版的,两种排版方式,一是按 最小破损度 进行排版,最小破损度追求的是文章排版的整齐性,也就是行尾空格数目尽可能相等。这样外观上就会比较平整,当然,行尾的空格可以移到行内,使得每行刚好满足给定宽度。另一种是按 最小行数 进行排版。这种排版相当直观,就是把原文一个词一个词地放入一行中,当不能再放入时,就进行换行。 源码: #!/usr/bin/env python#encoding=utf8# 最小破损度排版 …
等了一年,还是停留在 v2.11 的固件上,英文就一渣排版。只能自己动手了 写了个英文排版的,两种排版方式,一是按 最小破损度 进行排版,最小破损度追求的是文章排版的整齐性,也就是行尾空格数目尽可能相等。这样外观上就会比较平整,当然,行尾的空格可以移到行内,使得每行刚好满足给定宽度。另一种是按 最小行数 进行排版。这种排版相当直观,就是把原文一个词一个词地放入一行中,当不能再放入时,就进行换行。 源码: #!/usr/bin/env python#encoding=utf8# 最小破损度排版 …
python 实现的简单的 epub2txt
等了 1 年,还是没等到台电 k6 的固件更新,好失望。 由于 k6 不支持 epub 的目录跳转、内嵌字体,且每次阅读均需要重新解压 epub,既浪费电又浪费时间,因此干脆转成 txt 算了。 先用 zipfile 进行解压 然后用 HTMLParser 进行正文提取 最后输出同名 txt 代码在 http://code.google.com/p/yaepub2txt 上托管,google code 上的另外一个 epub2txt 似乎也是国内的兄弟写的,是基于 html2txt 的库和 …
等了 1 年,还是没等到台电 k6 的固件更新,好失望。 由于 k6 不支持 epub 的目录跳转、内嵌字体,且每次阅读均需要重新解压 epub,既浪费电又浪费时间,因此干脆转成 txt 算了。 先用 zipfile 进行解压 然后用 HTMLParser 进行正文提取 最后输出同名 txt 代码在 http://code.google.com/p/yaepub2txt 上托管,google code 上的另外一个 epub2txt 似乎也是国内的兄弟写的,是基于 html2txt 的库和 …
vim 定制配色方案
个人一直比较喜欢内置的 desert 配色,无奈安装了 pyflakes 之后语法错误的地方老是看不清楚,纠结了很久。在 muzuiget 的指点下,有所进展。可以参考他写的 《Vim 终端配色转换工具》。但是转换色彩之后,还是无法转到自定义的颜色方案。 我使用的终端是 ubuntu 自带的 gnome-terminal, 既然不是古董级产品,不应该有色彩支援上的问题。为了验证这一点,我参考了 arch 维基的 这一篇 ,还有 这一篇 。一语惊醒梦中人,原来 vim 需要开启 256 色方案才可 …
个人一直比较喜欢内置的 desert 配色,无奈安装了 pyflakes 之后语法错误的地方老是看不清楚,纠结了很久。在 muzuiget 的指点下,有所进展。可以参考他写的 《Vim 终端配色转换工具》。但是转换色彩之后,还是无法转到自定义的颜色方案。 我使用的终端是 ubuntu 自带的 gnome-terminal, 既然不是古董级产品,不应该有色彩支援上的问题。为了验证这一点,我参考了 arch 维基的 这一篇 ,还有 这一篇 。一语惊醒梦中人,原来 vim 需要开启 256 色方案才可 …
ubuntu 下访问 E72
由于家里的电脑没有蓝牙,每次传送文件都十分麻烦,像我这种懒人又不甘心去找数据线,只能够在 wifi 上打主意了。 E72 采用的是 s60v3 版 FP2 的系统,虽然是 sb 系统,不过比较实用。要完成这次跨系统文件传输的任务,还需要一个 好工具:SymSMB 4.0。 它可以模拟 win 的共享模式,方便其他系统进行访问。我使用的是 dospy 论坛汉化的版本, 参考过 这篇教程 。大致的流程是:在 SymSMB 的控制面板里,找到帐号,新建一个用户,建议设置密码(免得酿成 一个男人不会修电 …
由于家里的电脑没有蓝牙,每次传送文件都十分麻烦,像我这种懒人又不甘心去找数据线,只能够在 wifi 上打主意了。 E72 采用的是 s60v3 版 FP2 的系统,虽然是 sb 系统,不过比较实用。要完成这次跨系统文件传输的任务,还需要一个 好工具:SymSMB 4.0。 它可以模拟 win 的共享模式,方便其他系统进行访问。我使用的是 dospy 论坛汉化的版本, 参考过 这篇教程 。大致的流程是:在 SymSMB 的控制面板里,找到帐号,新建一个用户,建议设置密码(免得酿成 一个男人不会修电 …
python 实现的最近最少使用算法
LFU(Least Frequently Used,最少使用 ) 是一种缓存管理算法,其过期策略为替换出缓存中最少使用项。若各项使用次数相等,则参考 LRU(Least Recently Used,最近最少使用 ) 进行替换。 实现过程中,一直希望绕开链表去实现。尝试过用优先队列,但是优先队列对于优先级的调整处理很复杂,而当替换某些缓存项时,优先队列里保存的索引值又会过期,暂时未想到解决方法。一个比较拙劣的实现是使用 sort() 对使用次数进行排序,Python 内置的 sort 相当独特,是 …
LFU(Least Frequently Used,最少使用 ) 是一种缓存管理算法,其过期策略为替换出缓存中最少使用项。若各项使用次数相等,则参考 LRU(Least Recently Used,最近最少使用 ) 进行替换。 实现过程中,一直希望绕开链表去实现。尝试过用优先队列,但是优先队列对于优先级的调整处理很复杂,而当替换某些缓存项时,优先队列里保存的索引值又会过期,暂时未想到解决方法。一个比较拙劣的实现是使用 sort() 对使用次数进行排序,Python 内置的 sort 相当独特,是 …
新浪微博显示原创图片
鉴于我跟室友都比较渴求这个功能,尤其是观察美女时用,特别写了这个 userscript: http://userscripts.org/scripts/show/105670
鉴于我跟室友都比较渴求这个功能,尤其是观察美女时用,特别写了这个 userscript: http://userscripts.org/scripts/show/105670
GreaseMonkey 渐进
此段代码是从 document 中取出所有标签为 div 的节点,放入 zPara 数组中,然后通过 for 循环统一改变其背景色和前景色。
此段代码是从 document 中取出所有标签为 div 的节点,放入 zPara 数组中,然后通过 for 循环统一改变其背景色和前景色。
如何组织文件
最近想入手个 1T 的移动硬盘,但是想到如何组织文件,就觉得十分头痛。 自我总结下文件组织的经历: Windows windows 天然的不稳定性,每每让我胆战心惊,很可能忽然在周末跪低,然后父亲大人就把 C 盘格式化了。因此,历史经验表明,C 盘是不能放资料的。惯常的组织方法是: C 盘 只安装系统 D 盘 安装软件,放我的文档和收藏夹 E 盘 安装游戏或作为备份盘 F 盘 BT 下载 如此组织,一是方便系统重装的时候,常用软件和日常数据能够得到妥善保存;二是避免 BT 下载之类带来频繁磁盘整 …
最近想入手个 1T 的移动硬盘,但是想到如何组织文件,就觉得十分头痛。 自我总结下文件组织的经历: Windows windows 天然的不稳定性,每每让我胆战心惊,很可能忽然在周末跪低,然后父亲大人就把 C 盘格式化了。因此,历史经验表明,C 盘是不能放资料的。惯常的组织方法是: C 盘 只安装系统 D 盘 安装软件,放我的文档和收藏夹 E 盘 安装游戏或作为备份盘 F 盘 BT 下载 如此组织,一是方便系统重装的时候,常用软件和日常数据能够得到妥善保存;二是避免 BT 下载之类带来频繁磁盘整 …
在 cygwin 上安装 gevent
由于公司点餐要用 QQ,只能寄身于 WinXP 下做开发。但是 win 下各种不能折腾很不爽,幸而有 Cygwin 然而,使用 easy_install 居然安装不了 Cygwin,弹出一大堆 core.c 的错误,一直没搞懂。只好与 win 的丑陋的命令行相伴,还设置了 PATH 指向 cygwin 的 bin,为的就是能顺利 ls。 遍寻不获后,今天看到这篇日志 http://d.hatena.ne.jp/ymotongpoo/20110108/1294494273,终于醒悟过来了。。。我没 …
由于公司点餐要用 QQ,只能寄身于 WinXP 下做开发。但是 win 下各种不能折腾很不爽,幸而有 Cygwin 然而,使用 easy_install 居然安装不了 Cygwin,弹出一大堆 core.c 的错误,一直没搞懂。只好与 win 的丑陋的命令行相伴,还设置了 PATH 指向 cygwin 的 bin,为的就是能顺利 ls。 遍寻不获后,今天看到这篇日志 http://d.hatena.ne.jp/ymotongpoo/20110108/1294494273,终于醒悟过来了。。。我没 …
使用 python 对 txt 格式的小说进行处理
vim 的确是神器,可惜 sed 与 vim 不完全通用。这篇文章受《 用 vim 对 txt 格式的小说重新排版》的启发,在此致谢! 经常下载 txt 的电子书,格式却不合心意,只好自己再处理。首要的就是处理段内换行。 原来的打算是定制一个 vim 模式,到时候处理小说时进入该模式,再使用各种快捷键。以此避免 txt 快捷键对日常编程的干扰。后来发现,vim 不像 emacs,可以定制自己的模式。(可能可以定制专用的 vimrc 解决,未经尝试) 于是转向脚本寻求解决办法。sed 与 awk …
vim 的确是神器,可惜 sed 与 vim 不完全通用。这篇文章受《 用 vim 对 txt 格式的小说重新排版》的启发,在此致谢! 经常下载 txt 的电子书,格式却不合心意,只好自己再处理。首要的就是处理段内换行。 原来的打算是定制一个 vim 模式,到时候处理小说时进入该模式,再使用各种快捷键。以此避免 txt 快捷键对日常编程的干扰。后来发现,vim 不像 emacs,可以定制自己的模式。(可能可以定制专用的 vimrc 解决,未经尝试) 于是转向脚本寻求解决办法。sed 与 awk …
RLE 游程长度编码
昨天看心情好,就花了两个小时写了个 RLE 的 demo,可是 p7zip 帮我删了。。。晚上再写,用 gcc rle.c -o rle.c 脑抽啊我 今天不死心,再写了一个!【RLE 压缩 】 RLE 是基于这样一种思路:如果整个文件由 A 构成,那么我们只需要用 A 次数去表示该文件就可以了。 为了表示序列开始,需要一个标识符,我选择了 0xff。这样,每个序列就表示为 0xff 字符 次数。 当单个字符出现次数少于 3 的时候,压缩就得不偿失,因此对小于 3 个字符的不处理而直接输出。 详 …
昨天看心情好,就花了两个小时写了个 RLE 的 demo,可是 p7zip 帮我删了。。。晚上再写,用 gcc rle.c -o rle.c 脑抽啊我 今天不死心,再写了一个!【RLE 压缩 】 RLE 是基于这样一种思路:如果整个文件由 A 构成,那么我们只需要用 A 次数去表示该文件就可以了。 为了表示序列开始,需要一个标识符,我选择了 0xff。这样,每个序列就表示为 0xff 字符 次数。 当单个字符出现次数少于 3 的时候,压缩就得不偿失,因此对小于 3 个字符的不处理而直接输出。 详 …
SICP 与函数式编程
马马虎虎地看完了第四章跟第五章,终于可以为 SICP 这本书画上一个句号。 似乎 GCD 跟 fibonacci 这两个程序在每门语言里都会被实现一遍。这应该是涉及到递归的定义吧,对于函数式编程来说,递归是深刻而基础的,循环可以没有,递归不可或缺。特别是 fibonacci 的双递归,一方面考验了编程使用者的技巧,另一方面考验了这门编程语言的实现。(参见 维基百科 ) 其中印象比较深刻的,是将函数作为参数和返回值。而且在 scheme 的语法中,显得非常自然。C 中也有函数指针,相对地就显得复杂 …
马马虎虎地看完了第四章跟第五章,终于可以为 SICP 这本书画上一个句号。 似乎 GCD 跟 fibonacci 这两个程序在每门语言里都会被实现一遍。这应该是涉及到递归的定义吧,对于函数式编程来说,递归是深刻而基础的,循环可以没有,递归不可或缺。特别是 fibonacci 的双递归,一方面考验了编程使用者的技巧,另一方面考验了这门编程语言的实现。(参见 维基百科 ) 其中印象比较深刻的,是将函数作为参数和返回值。而且在 scheme 的语法中,显得非常自然。C 中也有函数指针,相对地就显得复杂 …
视频数据编解码技术
我真的很难专心持续做一件事情呢,最近因为课程需要写了篇文章应付,博诸君一笑 ** 视频编码与文件格式的常见误区 ** 常见的视频编码 MPEG2 MPEG-2 是 MPEG 工作组于 1994 年发布的视频和音频压缩国际标准。MPEG-2 通常用来为广播信号提供视频和音频编码,包括卫星电视、有线电视等。MPEG-2 经过少量修改后,也成为 DVD 产品的核心技术。MPEG-2 的系统描述部分(第 1 部分)定义了传输流,它用来一套在非可靠介质上传输数字视频信号和音频信号的机制,主要用在广播电视领 …
我真的很难专心持续做一件事情呢,最近因为课程需要写了篇文章应付,博诸君一笑 ** 视频编码与文件格式的常见误区 ** 常见的视频编码 MPEG2 MPEG-2 是 MPEG 工作组于 1994 年发布的视频和音频压缩国际标准。MPEG-2 通常用来为广播信号提供视频和音频编码,包括卫星电视、有线电视等。MPEG-2 经过少量修改后,也成为 DVD 产品的核心技术。MPEG-2 的系统描述部分(第 1 部分)定义了传输流,它用来一套在非可靠介质上传输数字视频信号和音频信号的机制,主要用在广播电视领 …
C 程序设计语言答案 chapter3
第三章答案 主要围绕 itoa 做文章,加深对整数类型的理解和字符串数组的操作。 第三章貌似是一个转折点,前面的练习更加像一些玩具,后面的会更有挑战性。
第三章答案 主要围绕 itoa 做文章,加深对整数类型的理解和字符串数组的操作。 第三章貌似是一个转折点,前面的练习更加像一些玩具,后面的会更有挑战性。
C 程序设计语言答案 chapter2
时不时练习一下还是蛮过瘾的,不过后面的习题应该会挺有难度吧,期待 ing 第二章答案
时不时练习一下还是蛮过瘾的,不过后面的习题应该会挺有难度吧,期待 ing 第二章答案
C 程序设计语言答案 chapter1
最近面试屡屡受挫,搞得颇为狼狈。断断续续地看完了 K&R 的 C Bible,刚把第一章的习题完成了。不得不说,这本薄薄的小书习题很有质量。对于指针的运用很有启发,给了我很多的灵感。看完很想说:原来 C 语言还可以这样用! 习题都是自己做的,若有错漏,还请不吝赐教。 ch1
最近面试屡屡受挫,搞得颇为狼狈。断断续续地看完了 K&R 的 C Bible,刚把第一章的习题完成了。不得不说,这本薄薄的小书习题很有质量。对于指针的运用很有启发,给了我很多的灵感。看完很想说:原来 C 语言还可以这样用! 习题都是自己做的,若有错漏,还请不吝赐教。 ch1
ubuntu 下 svn 上传到 googlecode
在 Google code 上也混迹了一段时间,提交 patch 和 issue 都试过了,可惜一直没找到哥们给个 commitor 当当。今天特地去挖了个坑,试试 owner 的滋味。 在 source 下的 checkout 里,可以很清晰地看到需要填写的命令。可是 ubuntu 的 svn 有点诡异,以 ownership checkout 一个 project,居然也不需要输入密码,搞了我很长时间。 更纠结的还在后头,svn add 添加完文件,svn commit 进行提交,发现首先要 …
在 Google code 上也混迹了一段时间,提交 patch 和 issue 都试过了,可惜一直没找到哥们给个 commitor 当当。今天特地去挖了个坑,试试 owner 的滋味。 在 source 下的 checkout 里,可以很清晰地看到需要填写的命令。可是 ubuntu 的 svn 有点诡异,以 ownership checkout 一个 project,居然也不需要输入密码,搞了我很长时间。 更纠结的还在后头,svn add 添加完文件,svn commit 进行提交,发现首先要 …
操作系统逻辑地址与物理地址的转换
逻辑地址 / 页面大小 = 页号 逻辑地址 mod 页面大小 = 页内偏移 通过页号查找页表得到对应的物理区块 物理地址 = 物理区块 x 页大小 + 页内偏移 页号也可以通过位映射的方法实现,例如页表只有 4 项,则只需逻辑地址的前两位就可以确定页号。 参考: http://goo.gl/iGYn
逻辑地址 / 页面大小 = 页号 逻辑地址 mod 页面大小 = 页内偏移 通过页号查找页表得到对应的物理区块 物理地址 = 物理区块 x 页大小 + 页内偏移 页号也可以通过位映射的方法实现,例如页表只有 4 项,则只需逻辑地址的前两位就可以确定页号。 参考: http://goo.gl/iGYn
入手台电 K6
最近入手了电纸书,折腾了好久,感觉有点浪费时间阿,这时间和钱拿去买书读书该多好 期间遇到一个问题,6 寸屏幕的电纸书看 pdf 相当痛苦,幸好新固件有 pdf 重排。但换行依然不知所谓不明就里不能人道于是需要自己处理下,网上流行一个 wps 处理法 ,大意就是将 txt 文本粘贴进 wps 的 6 寸模板里,然后另存为 pdf。这样可以设置自己喜爱的字体,的确是不错的选择。此外还有通过虚拟打印机打印成 pdf 的。 txt 源不是那么容易找的,万一找回来的已经是 pdf,怎么办呢?可以通过 …
最近入手了电纸书,折腾了好久,感觉有点浪费时间阿,这时间和钱拿去买书读书该多好 期间遇到一个问题,6 寸屏幕的电纸书看 pdf 相当痛苦,幸好新固件有 pdf 重排。但换行依然不知所谓不明就里不能人道于是需要自己处理下,网上流行一个 wps 处理法 ,大意就是将 txt 文本粘贴进 wps 的 6 寸模板里,然后另存为 pdf。这样可以设置自己喜爱的字体,的确是不错的选择。此外还有通过虚拟打印机打印成 pdf 的。 txt 源不是那么容易找的,万一找回来的已经是 pdf,怎么办呢?可以通过 …
archlinux 安装 quick-init 导致根目录可读的修复
不得不说,Arch Linux 真的非常快!搭积木式的构建方式可以给我一种掌控感。后来听说 quick-init 可以 4 秒启动,禁不住去试试,结果。。。失败了,只好卸载之,结果根文件系统变成只读,无法上网。。。 经过一轮 google,锁定在 /etc/inittab 和 /etc/rc.conf 文件上,首先把这两个文件恢复原样。/etc 中可以看到 inittab.pacsave 或 inittab.original 的备份文件,恢复即可。 若重启依然无法解决,通常是因为把 …
不得不说,Arch Linux 真的非常快!搭积木式的构建方式可以给我一种掌控感。后来听说 quick-init 可以 4 秒启动,禁不住去试试,结果。。。失败了,只好卸载之,结果根文件系统变成只读,无法上网。。。 经过一轮 google,锁定在 /etc/inittab 和 /etc/rc.conf 文件上,首先把这两个文件恢复原样。/etc 中可以看到 inittab.pacsave 或 inittab.original 的备份文件,恢复即可。 若重启依然无法解决,通常是因为把 …
virtualbox 安装 gentoo
一直想尝试一下 fvwm,又不想搞坏现在的 ubuntu,顺便就搞个 gentoo 玩玩。 基本的安装顺序照官方的 guidebook 就可以了,但配置内核的时候要注意如下选项: Processor type and features ---> [*] Tickless System (Dynamic Ticks) [ ] High Resolution Timer Support [ ] Symmetric multi-processing support Subarchitecture …
一直想尝试一下 fvwm,又不想搞坏现在的 ubuntu,顺便就搞个 gentoo 玩玩。 基本的安装顺序照官方的 guidebook 就可以了,但配置内核的时候要注意如下选项: Processor type and features ---> [*] Tickless System (Dynamic Ticks) [ ] High Resolution Timer Support [ ] Symmetric multi-processing support Subarchitecture …
Ubuntu 下利用 expect 脚本自动登录 ssh 作代理
这类文章网上已经有很多了,实在不想再重复,可惜一直没有一个双击就连上 ssh 的,要不写个 GUI?putty 很搞,还是弹出一个命令行出来填用户名密码,那我干脆直接在 terminal 搞定啦。 #!/usr/bin/expect -f #auto ssh login set timeout 20 spawn ssh login_name@host_name expect *password: send 123456\r interact 网上流传的大多都是上面一段代码,问题就在最后一句上面: …
这类文章网上已经有很多了,实在不想再重复,可惜一直没有一个双击就连上 ssh 的,要不写个 GUI?putty 很搞,还是弹出一个命令行出来填用户名密码,那我干脆直接在 terminal 搞定啦。 #!/usr/bin/expect -f #auto ssh login set timeout 20 spawn ssh login_name@host_name expect *password: send 123456\r interact 网上流传的大多都是上面一段代码,问题就在最后一句上面: …
着迷 twittering
似乎最近迷上了翻过伟大的长城这项体育活动,而且还是为翻墙而翻墙那一种。。。 继 twip 之后,又迷上了 gtap 这个 twitter api proxy。这个代理架设在 gae 上,用的还是我熟悉的 python 语言,非常亲切。当然,那坨 Django 的代码也不是我暂时能够捣鼓出来的,hack 的时候用了点拙劣的手法。 twitter 这种思维碎片,我总喜欢将其归为短信一类,因此手机发推才比较接近我的习惯。鉴于非智能机 hack 的难度较高,没有 vpn 和 ssh 可用,只好用 gae …
似乎最近迷上了翻过伟大的长城这项体育活动,而且还是为翻墙而翻墙那一种。。。 继 twip 之后,又迷上了 gtap 这个 twitter api proxy。这个代理架设在 gae 上,用的还是我熟悉的 python 语言,非常亲切。当然,那坨 Django 的代码也不是我暂时能够捣鼓出来的,hack 的时候用了点拙劣的手法。 twitter 这种思维碎片,我总喜欢将其归为短信一类,因此手机发推才比较接近我的习惯。鉴于非智能机 hack 的难度较高,没有 vpn 和 ssh 可用,只好用 gae …
python-twitter 与第三方 api 协作
上回讲到搭建了 twip 作为 twitter api proxy,那当然要好好地利用一下。正好最近做了一个 twitter 的机器人,每次都要翻代理上推实在麻烦,另外一个问题是 twitter 对 http basic authorization 的限制逐渐收紧,现在的 api 限制为 60 per hour,稍后会再次缩减到 45,而 oauth 则相反,准备在 150/h 的基础上逐渐推到 1500/h(via)。因此,利用 twip 的 oauth 特性进行中转会是相当不错的选择。 这个 …
上回讲到搭建了 twip 作为 twitter api proxy,那当然要好好地利用一下。正好最近做了一个 twitter 的机器人,每次都要翻代理上推实在麻烦,另外一个问题是 twitter 对 http basic authorization 的限制逐渐收紧,现在的 api 限制为 60 per hour,稍后会再次缩减到 45,而 oauth 则相反,准备在 150/h 的基础上逐渐推到 1500/h(via)。因此,利用 twip 的 oauth 特性进行中转会是相当不错的选择。 这个 …
Oauth 与 twip 杂感
今天帮忙搭建 twip 了,主要参考了 http://yht.in/archives/90 这篇文章。 twip 的主要原理,就是通过一台在墙外而国内又可以访问的独立主机作为跳板,国内用户首先连接到该独立主机上,然后再通过主机与 twitter 交换数据。为了提高安全性,twitter 今年 6 月份停止了 http basic authorize,取而代之的是 Oauth 的认证。用户的登录过程由 twitter 完成,最后 twitter 将用户的认证结果和授权告诉应用。得益于 …
今天帮忙搭建 twip 了,主要参考了 http://yht.in/archives/90 这篇文章。 twip 的主要原理,就是通过一台在墙外而国内又可以访问的独立主机作为跳板,国内用户首先连接到该独立主机上,然后再通过主机与 twitter 交换数据。为了提高安全性,twitter 今年 6 月份停止了 http basic authorize,取而代之的是 Oauth 的认证。用户的登录过程由 twitter 完成,最后 twitter 将用户的认证结果和授权告诉应用。得益于 …
sshtunnel 翻过伟大的长城
项目进入到一个稳定期,就等词库的扩张了。我打算在 twitter 上架设一个 twitter 机器人,搞搞新意思。看了下 twitter api 的文档,发现 python 的 twitter 库还真不少,看中的有两款:python-twitter 和 tweepy, 稍微看了看,python-twitter 首页就有示例了,就你吧。 以迅雷不及掩耳盗铃之势装好了 simlejson 和 oauth 的依赖,就可以开始工作了。本地测试通过~~由于众所周知的原因,不能直接访问到 twitter,似 …
项目进入到一个稳定期,就等词库的扩张了。我打算在 twitter 上架设一个 twitter 机器人,搞搞新意思。看了下 twitter api 的文档,发现 python 的 twitter 库还真不少,看中的有两款:python-twitter 和 tweepy, 稍微看了看,python-twitter 首页就有示例了,就你吧。 以迅雷不及掩耳盗铃之势装好了 simlejson 和 oauth 的依赖,就可以开始工作了。本地测试通过~~由于众所周知的原因,不能直接访问到 twitter,似 …
python 中文编码笔记
最近碰了很多钉子。。。 不得不说,python2.6 相较于之前发布的版本,就编码方面来说,有明显的进步。本机使用的是 python2.6,同样的代码根本没有遇到问题。到了服务器上部署时,一台服务器的 python2.5 和另一台服务器的 python2.4,都折磨得我苦不堪言。 先厘清几个概念:python 内置的字符类型是 unicode,当需要进行编码转换时,都要先转成 unicode,然后再转换成目标编码。而 str 类型是二进制类型,例如 声明变量 uniStr=u’ 的 …
最近碰了很多钉子。。。 不得不说,python2.6 相较于之前发布的版本,就编码方面来说,有明显的进步。本机使用的是 python2.6,同样的代码根本没有遇到问题。到了服务器上部署时,一台服务器的 python2.5 和另一台服务器的 python2.4,都折磨得我苦不堪言。 先厘清几个概念:python 内置的字符类型是 unicode,当需要进行编码转换时,都要先转成 unicode,然后再转换成目标编码。而 str 类型是二进制类型,例如 声明变量 uniStr=u’ 的 …
分布式有感
最近有点疲于奔命的感觉,孤军作战不是好事阿。 以前学分布式计算原理与应用,一直对老师和教材有不满。教材虽然写的中规中矩,可是对 java 的偏向性无疑是一个败笔。书中的 Java 代码起个 helloworld 的作用还可以,真要用起来总觉得生涩无比,整天就在流里面转来转去。实验方面,socket 的相关代码没有 c 的清晰,要不是 string 类封装了一些应手的函数,真不知道有什么优点。RMI 看上去很美好,只是这种美好是建立在实验的基础上的。要真的应用起来,单单异常处理就会要命,网络的不确 …
最近有点疲于奔命的感觉,孤军作战不是好事阿。 以前学分布式计算原理与应用,一直对老师和教材有不满。教材虽然写的中规中矩,可是对 java 的偏向性无疑是一个败笔。书中的 Java 代码起个 helloworld 的作用还可以,真要用起来总觉得生涩无比,整天就在流里面转来转去。实验方面,socket 的相关代码没有 c 的清晰,要不是 string 类封装了一些应手的函数,真不知道有什么优点。RMI 看上去很美好,只是这种美好是建立在实验的基础上的。要真的应用起来,单单异常处理就会要命,网络的不确 …
CrossSiteRequestForgeries 跨站伪请求
今天看 Django 的 tutorial,里面提到了这样一种跨站攻击: 假设有客户 Bob 在浏览论坛页面(Bob 真可怜~~~),Alice 发布了一个很热的帖子,里面有 而在这个场景里,论坛和银行都是 Bob 所信任的,这就是 csrf 的可怕之处 。Django 推荐凡是影响服务器端数据的动作,均使用 post,另外还引入了 csrf_token 预防事故。
今天看 Django 的 tutorial,里面提到了这样一种跨站攻击: 假设有客户 Bob 在浏览论坛页面(Bob 真可怜~~~),Alice 发布了一个很热的帖子,里面有 而在这个场景里,论坛和银行都是 Bob 所信任的,这就是 csrf 的可怕之处 。Django 推荐凡是影响服务器端数据的动作,均使用 post,另外还引入了 csrf_token 预防事故。
web.py+gae= 我的第一个留言板【一】
最近体验了一把 web.py 开发的便捷。 建议在看 web.py 的 cookbook 之前,对 http 协议的 get 方法和 post 方法先了解一下,html 最好也要有基本的知识。 web.py 的工作流程,一般是从 URL 映射开始,然后把请求分派给不同的处理类处理,处理类比较像一个粘合层,负责从数据层拿数据,以及告诉 render 如何形成最后的页面效果。同时,它也负责控制整个交互的过程。数据层封装了数据库相关的操作,有了它,可以很方便的更换不同的数据库。当然,在具体的字段属性上 …
最近体验了一把 web.py 开发的便捷。 建议在看 web.py 的 cookbook 之前,对 http 协议的 get 方法和 post 方法先了解一下,html 最好也要有基本的知识。 web.py 的工作流程,一般是从 URL 映射开始,然后把请求分派给不同的处理类处理,处理类比较像一个粘合层,负责从数据层拿数据,以及告诉 render 如何形成最后的页面效果。同时,它也负责控制整个交互的过程。数据层封装了数据库相关的操作,有了它,可以很方便的更换不同的数据库。当然,在具体的字段属性上 …
web.py+gae= 我的第一个留言板【二】
下面接着说说 google application engine 和 webpy 配套的问题。在我完成留言板的时候,这方面的资料还是很少,中文资料更少,希望 webpy 社区能够壮大啊。 gae 据说很有 Django 的风格,也是内置 Django 的,而 web.py 则需要自备。因此,在应用目录中应该放入 web.py 解压后得到的 web 目录。否则会导致 Import error: no module named web 详细的发布过程,可以参考 chinaunix 的这篇文章 …
下面接着说说 google application engine 和 webpy 配套的问题。在我完成留言板的时候,这方面的资料还是很少,中文资料更少,希望 webpy 社区能够壮大啊。 gae 据说很有 Django 的风格,也是内置 Django 的,而 web.py 则需要自备。因此,在应用目录中应该放入 web.py 解压后得到的 web 目录。否则会导致 Import error: no module named web 详细的发布过程,可以参考 chinaunix 的这篇文章 …
Datagramsocketwithconnection-orientedinJava
数据报通常采用 udp 协议进行传输,UDP 相较于 TCP 协议能够节省带宽,相应的获得较高速度,但不能保证包的安全抵达和顺序不变。 Java 关于 datagram 提供有 connect 方法,该方法绑定了远端的 IP 地址和端口号,即该 socket 以后只能向绑定目标主机发送数据或接受数据。 当目标地址不可达,且收到了该地址不可达的 ICMP 包时,会抛出 PortUnreachableException 异常,但不能保证一定抛出该异常。 ** 该方法也不能保证包的顺序和安全抵达 …
数据报通常采用 udp 协议进行传输,UDP 相较于 TCP 协议能够节省带宽,相应的获得较高速度,但不能保证包的安全抵达和顺序不变。 Java 关于 datagram 提供有 connect 方法,该方法绑定了远端的 IP 地址和端口号,即该 socket 以后只能向绑定目标主机发送数据或接受数据。 当目标地址不可达,且收到了该地址不可达的 ICMP 包时,会抛出 PortUnreachableException 异常,但不能保证一定抛出该异常。 ** 该方法也不能保证包的顺序和安全抵达 …
thetruthaboutsessions 择译
cookie get parameter cookie+fingerprint generated by user agent
cookie get parameter cookie+fingerprint generated by user agent
web.py0.3 版本 tutorial 示例
我承认我看中文了。。。中文安装指南导向的是 web.py 0.2 版本的 tutorial 翻译,版本有点旧,且 0.3 与 0.2 的 tutorial 不兼容。 首先是下载压缩包,然后解压,最后 sudo ./setup.py (我用的是 ubuntu ) 示例代码如下,主要是 run 方法的方式有点不同。 好简洁的一个 web app,感觉比 java servelet 的一大堆概念要清晰多了。
我承认我看中文了。。。中文安装指南导向的是 web.py 0.2 版本的 tutorial 翻译,版本有点旧,且 0.3 与 0.2 的 tutorial 不兼容。 首先是下载压缩包,然后解压,最后 sudo ./setup.py (我用的是 ubuntu ) 示例代码如下,主要是 run 方法的方式有点不同。 好简洁的一个 web app,感觉比 java servelet 的一大堆概念要清晰多了。
apache-tomcat-6.0.26 的 cgi 配置过程
这东西折磨我太久了,写篇笔记。 Apache 的目录很好认,我下的是 zip 绿色版,解压开就看见 running 这个说明文件了,建议大家读读。 conf 目录是放置配置文件的,bin 则是可执行文件的位置,只需双击 startup.bat,即可启动 Apache。 要运行 cgi,主要是改两个文件,一个是 web.xml,一个是 context.xml。 context.xml 主要是改这么一行: 直接在 context 后加上 privileged 就可以了,用于放行可执行文件。 …
这东西折磨我太久了,写篇笔记。 Apache 的目录很好认,我下的是 zip 绿色版,解压开就看见 running 这个说明文件了,建议大家读读。 conf 目录是放置配置文件的,bin 则是可执行文件的位置,只需双击 startup.bat,即可启动 Apache。 要运行 cgi,主要是改两个文件,一个是 web.xml,一个是 context.xml。 context.xml 主要是改这么一行: 直接在 context 后加上 privileged 就可以了,用于放行可执行文件。 …
MatlabCell 功能
最近完成模式分类的作业,需要大量使用 matlab, 期间发现了一个问题,是 matlab 代码的复用程度。 在面向过程编程里, 基本的复用单位是函数,程序的复杂度籍此下放到函数的接口上。设计好函数间的接口,基本上就成功了一半。在面向对象编程里, 基本的复用单位是对象,对象使得数据具有了一定程度的自维护。而在 matlab 里, 我很长时间都没有找到方向,因为我搞不清楚复用的单位是什么。 matlab 中,基本的单位是矩阵,针对矩阵系统有一大堆的函数供你调用。但是,想自己写程序还是有一定的麻烦 …
最近完成模式分类的作业,需要大量使用 matlab, 期间发现了一个问题,是 matlab 代码的复用程度。 在面向过程编程里, 基本的复用单位是函数,程序的复杂度籍此下放到函数的接口上。设计好函数间的接口,基本上就成功了一半。在面向对象编程里, 基本的复用单位是对象,对象使得数据具有了一定程度的自维护。而在 matlab 里, 我很长时间都没有找到方向,因为我搞不清楚复用的单位是什么。 matlab 中,基本的单位是矩阵,针对矩阵系统有一大堆的函数供你调用。但是,想自己写程序还是有一定的麻烦 …
浅论函数式语言的环境,兼谈闭包
函数式语言与命令式语言的一个根本不同,就是下面这个两个数交换的例子居然是正确的: a=1 b=2 a,b=b,a print a ,b 输出 2 1 究其原因,是环境造成的。什么是环境呢?通俗点讲,你可以将环境看成是一个栈,栈单元的内容就是各个变量的值。可见,上述 a 和 b 赋值时的环境均是 a=1,b=2。再看一个 lisp 的例子: 设环境 r 为 r=( (X.(A B)) (Y.(C D))) 则 r((EXPR (X Y) (CONS X Y)) (CDR Y) (CAR X)) …
函数式语言与命令式语言的一个根本不同,就是下面这个两个数交换的例子居然是正确的: a=1 b=2 a,b=b,a print a ,b 输出 2 1 究其原因,是环境造成的。什么是环境呢?通俗点讲,你可以将环境看成是一个栈,栈单元的内容就是各个变量的值。可见,上述 a 和 b 赋值时的环境均是 a=1,b=2。再看一个 lisp 的例子: 设环境 r 为 r=( (X.(A B)) (Y.(C D))) 则 r((EXPR (X Y) (CONS X Y)) (CDR Y) (CAR X)) …
最近要跟函数式语言干一仗!
本来打算先征服 ML(meta language)的,结果可耻地失败了,并且归结为译者水平太低。 然后拿了本《Lisp 语言》回来看,语言很平实,的确比较适合我,可惜作者马希文教授已经作古了,天妒英才啊。 但是看完表之后还是卡住了,思维的转变的确不是一朝一夕的事。不过马教授比 ML 作者出色的地方,是开卷即讲述 s 表达式的概念,教你分清原子与 s 表达式。然后介绍简写法,流畅地引入了表的概念。而且表的描述非常生动(没有右支是非 nil 原子结束的 s 表达式),接下来的 …
本来打算先征服 ML(meta language)的,结果可耻地失败了,并且归结为译者水平太低。 然后拿了本《Lisp 语言》回来看,语言很平实,的确比较适合我,可惜作者马希文教授已经作古了,天妒英才啊。 但是看完表之后还是卡住了,思维的转变的确不是一朝一夕的事。不过马教授比 ML 作者出色的地方,是开卷即讲述 s 表达式的概念,教你分清原子与 s 表达式。然后介绍简写法,流畅地引入了表的概念。而且表的描述非常生动(没有右支是非 nil 原子结束的 s 表达式),接下来的 …
RBF、K-NN 与 Decisiontree
要做一个 classifier,的确不易。面对需要训练的 classifier,是否 training error 越少越好呢?显然不是,因为虽然 training error 降低了,但 test error 不见得就会降低,实际表现为一个拐点。如下图: 为了平衡 error 的权重,我们引入了额外的函数 lambda*,训练效果由 error 和 lambda* 共同评价。下面讨论一下 lambda 的取值: (存疑) 因此,我们采取多个函数综合评估的方式进行,即 RBF(radial …
要做一个 classifier,的确不易。面对需要训练的 classifier,是否 training error 越少越好呢?显然不是,因为虽然 training error 降低了,但 test error 不见得就会降低,实际表现为一个拐点。如下图: 为了平衡 error 的权重,我们引入了额外的函数 lambda*,训练效果由 error 和 lambda* 共同评价。下面讨论一下 lambda 的取值: (存疑) 因此,我们采取多个函数综合评估的方式进行,即 RBF(radial …
java 路径设置
这个问题简直是痛中之痛,为什么如此现代,标榜人性化的 java 居然会让我等在环境变量的设置上反复煎熬?! 在 path 变量中 (没有则新建),添加 新建 CLASSPATH 变量 , 添加 文件名保存为 Hello.java,当前目录进入命令行,输入命令: javac Hello.java java Hello 今天花了差不多一个小时,正常编译通过,就是因为敲了 “java Hello.class”,所以一直报错 could not find main class program will …
这个问题简直是痛中之痛,为什么如此现代,标榜人性化的 java 居然会让我等在环境变量的设置上反复煎熬?! 在 path 变量中 (没有则新建),添加 新建 CLASSPATH 变量 , 添加 文件名保存为 Hello.java,当前目录进入命令行,输入命令: javac Hello.java java Hello 今天花了差不多一个小时,正常编译通过,就是因为敲了 “java Hello.class”,所以一直报错 could not find main class program will …
最长公共子序列 --- 从动态规划说起
我比较不长记性,你要我马上写一个动态规划给你是比较有难度的。在我眼里,动态规划就是一个优化程序的手段,适合于有大量重复子计算问题的时候用,原理就跟缓冲有点像,把需要重复计算的东西都放进内存里,需要的时候通过索引之类的东西直接查询,节省重新计算的时间。 下面来看一幅图: 假设要从 A 到 H,在这个带权图中求最短路径。那么有: min(H)=min(min(F)+FH,min(G)+GH) min(F)=min(min(D)+DF,min(E)+EF) …
我比较不长记性,你要我马上写一个动态规划给你是比较有难度的。在我眼里,动态规划就是一个优化程序的手段,适合于有大量重复子计算问题的时候用,原理就跟缓冲有点像,把需要重复计算的东西都放进内存里,需要的时候通过索引之类的东西直接查询,节省重新计算的时间。 下面来看一幅图: 假设要从 A 到 H,在这个带权图中求最短路径。那么有: min(H)=min(min(F)+FH,min(G)+GH) min(F)=min(min(D)+DF,min(E)+EF) …
JavaScript 中的闭包
一看到闭包这个词,我就会想起线性代数中的封闭空间,也就是说,这个空间中的所有向量,无论经过何种运算,最终结果还是会落在该空间中。那么 JavaScript 中会不会也是类似的概念呢? 我们来看一个定义: 所谓闭包,指的是一个拥有许多变量和绑定了这些变量的环境的表达式(通常是一个函数),因而这些变量也是该表达式的一部分。 这说明了,JavaScript 中的闭包是包含了上下文的函数,也就是说,这个函数的作用基础,是它所处的环境,这是不能超越的,跟线性代数是不是有一点似曾相识的感觉呢? 换个角度看, …
一看到闭包这个词,我就会想起线性代数中的封闭空间,也就是说,这个空间中的所有向量,无论经过何种运算,最终结果还是会落在该空间中。那么 JavaScript 中会不会也是类似的概念呢? 我们来看一个定义: 所谓闭包,指的是一个拥有许多变量和绑定了这些变量的环境的表达式(通常是一个函数),因而这些变量也是该表达式的一部分。 这说明了,JavaScript 中的闭包是包含了上下文的函数,也就是说,这个函数的作用基础,是它所处的环境,这是不能超越的,跟线性代数是不是有一点似曾相识的感觉呢? 换个角度看, …
StandardML 语言(一)
在 Windows 平台下推荐使用 Moscow ML 解释器,主要是安装比较方便,其他有 Standard ML of New Jersey, 安装后需要设置环境变量(即 bin 目录所在位置)。 要引用系统模块,请使用 load “module”, 例如: -load “Math”; -Math 4.0; 函数名后需要空一格。 从 C/C++ 语言转来的同学,请多多练习 andalso 与 orelse,另外,条件表达式 if E then E1 else E2 else 部分必须存在(即 …
在 Windows 平台下推荐使用 Moscow ML 解释器,主要是安装比较方便,其他有 Standard ML of New Jersey, 安装后需要设置环境变量(即 bin 目录所在位置)。 要引用系统模块,请使用 load “module”, 例如: -load “Math”; -Math 4.0; 函数名后需要空一格。 从 C/C++ 语言转来的同学,请多多练习 andalso 与 orelse,另外,条件表达式 if E then E1 else E2 else 部分必须存在(即 …
初探 Git
今天闷着头看了半天 git,终于明白了 git 的基本工作原理。想提高你对 git 的认识,请移玉步到 http://progit.org/book/zh,中文翻译很不错,感谢先行的兄弟们! 以前项目组进行版本管理的时候,采用的是 tortoiseSVN,正如某君所说,SVN 并非一无是处,但是总有又痛又痒的感觉。学习 SVN,我有了和其他人进行版本协作的经验,不过发生合并冲突的机会还是比较少的(一般每个人负责一个单元),常用的操作就是 checkout 然后 coding。不得不说,由于和服务 …
今天闷着头看了半天 git,终于明白了 git 的基本工作原理。想提高你对 git 的认识,请移玉步到 http://progit.org/book/zh,中文翻译很不错,感谢先行的兄弟们! 以前项目组进行版本管理的时候,采用的是 tortoiseSVN,正如某君所说,SVN 并非一无是处,但是总有又痛又痒的感觉。学习 SVN,我有了和其他人进行版本协作的经验,不过发生合并冲突的机会还是比较少的(一般每个人负责一个单元),常用的操作就是 checkout 然后 coding。不得不说,由于和服务 …
银行家算法(Thebanker'salgorithm)
已被进程占用 1. 进程资源需求最大值 1. 系统可用资源 1. 有 A、B 两进程,当前可用资源无法满足任一进程的需要,但 A 在运行时暂时释放了所占用的资源,使得 B 得以结束,从而释放更多资源,使得 A 顺利结束。1. 有 A、B、C 三个进程,当前资源可以满足 A 的运行需要,因此此时 A 并没有陷入死锁。
已被进程占用 1. 进程资源需求最大值 1. 系统可用资源 1. 有 A、B 两进程,当前可用资源无法满足任一进程的需要,但 A 在运行时暂时释放了所占用的资源,使得 B 得以结束,从而释放更多资源,使得 A 顺利结束。1. 有 A、B、C 三个进程,当前资源可以满足 A 的运行需要,因此此时 A 并没有陷入死锁。