从TdEngine20行代码引发的风波,看10倍程序员与普通程序员的差距

      上周笔者的一篇博客这位创造Github冠军项目的老男人,堪称10倍程序员本尊对于TdEngine的建立过程及其创始人陶建辉老师进行了介绍,并对于TdEngine团队在github上开源的一段consumer-productor经典实现的代码进行了解读,出乎我意料的是在此文被各种转载的过程中,陶老师传奇的创业故事好像并没有代码本身引起的讨论大。在这里心疼这位IT老兵1秒钟。

从TdEngine20行代码引发的风波,看10倍程序员与普通程序员的差距_第1张图片

          一个#引发的血案  

    当然这场风波首先是我的锅,由于最近Python中毒,而且导致C的代码也用#注释被各位程序员大大们无情吐槽了。

从TdEngine20行代码引发的风波,看10倍程序员与普通程序员的差距_第2张图片

 

从TdEngine20行代码引发的风波,看10倍程序员与普通程序员的差距_第3张图片

     这里我先给各位读者们道个歉,真是好久不搞C了水平下降,望各位原谅。     

   TdEngine的consumer-productor代码到底是不是最优方案

      在之前的文章中我也曾经介绍过,陶老师这位10倍程序员对于代码是有一定洁癖的,能10行实现的功能绝对不写11行,近年来的陶老师主要作品:信客户端只有18K大小,胎心算法的实现只用了600行代码,而TDengine这样一个数据库项目竟然只需要1.5M安装包就能搞定,堪称是惜代码如金。

     不过这个追求高效最优的Flag却也使我文章《这位创造Github冠军项目的老男人,堪称10倍程序员本尊》中解读的consumer-productor代码,引发了大量的讨论。其中影响力比较大的观点如下:

从TdEngine20行代码引发的风波,看10倍程序员与普通程序员的差距_第4张图片

      这其中争议的焦点在于TdEngine用了1个互斥体( mutex)和2个信号量(semaphore)来保证线程的调用安全,而很多人第一感觉是用2个信号量太多了,1个应该能够了,所以就没自己动手实现直接开怼。不过真REVIEW他们所谓的示例代码,问题就显而易见了。

从TdEngine20行代码引发的风波,看10倍程序员与普通程序员的差距_第5张图片

 上述代码在写消息时(实现push函数)为了节省信号量直接使用了sleep函数,而这其中的问题有两个。

1.效率变低,使用sleep等10ms看似开销不大,但是对于TdEngine这种高性能要求的场景这种处理是明显不合适的。

2.sleep并不保证线程安全,如果恰好几个进程同时完成sleep,则有可能在队列已满的情况下继续写消息,造成消息丢失。

        consumer-productor的工作机制

为了更好的说明问题,我用PPT做了个动画来说明消息队列的工作机制:

从TdEngine20行代码引发的风波,看10倍程序员与普通程序员的差距_第6张图片

 原谅笔者并不是个PPTER,上图并不美观,不过以队列深度为1的队列为例consumer-productor的基本工作机制其实就如上图:

·1.初始状态队列为空,读线程被读信号量阻塞,写线程可以被放行。

2.消息由写线程push进队列后,写线程被写信号量阻塞,读信号量被post,读进程可以被放行。

3.消息由读进程读出后,读信号量再被次阻塞,写信号量被post,写进程可以被放行。再次回到初始状态。

     所以看到没,在consumer-productor的实现中并没有把2个信号量压缩为1个的方案,虽然这有点反直觉,不过对于代码良好的嗅觉应该就是普通程序员和10倍程序员的最大区别。

     那么咱们说了这么多TdEnguine的consumer-productor(https://github.com/taosdata/TDengine/blob/master/src/util/src/tsched.c)到底有没有瑕疵呢?经我反复的review找出下面的一个问题:也就是参数param由void *转为SSchedQueue *后应该做类型判断才好。如果读者们还能发现优化空间也欢迎留言,预计陶老师还是会亲自回答。

从TdEngine20行代码引发的风波,看10倍程序员与普通程序员的差距_第7张图片

你可能感兴趣的:(TdEngine,物联网,陶建辉,时序数据库,10倍程序员,10倍程序员)