1. Algorithm 每周一道算法题
本周算法题是:Z 字形变化
本题比较有趣的点是首先题目要理解,其次可以考虑使用 flag 以及 row 来规避一些边界条件的处理,还是比较有思维难度的
2. Review 阅读一篇英文文章
本周继续阅读 The C10K problem
- ACE, a heavyweight C++ I/O framework, contains object-oriented implementations of some of these I/O strategies and many other useful things. In particular, his Reactor is an OO way of doing nonblocking I/O, and Proactor is an OO way of doing asynchronous I/O.
ACE,一个重量级的 C++ I/O 框架,包含了一些面向对象的 I/O 策略的实现以及许多其他有用的功能。特别是它的 Reactor 是一种面向对象的非阻塞 I/O,并且 Proactor 是一种面向对象的异步 I/O。
- ASIO is an C++ I/O framework which is becoming part of the Boost library. It's like ACE updated for the STL era.
ASIO 是一个 C++ I/O 框架,该框架是 Boost 库的一部分。它可以看作是针对 STL 时代更新的 ACE。
- libevent is a lightweight C I/O framework by Niels Provos. It supports kqueue and select, and soon will support poll and epoll. It's level-triggered only, I think, which has both good and bad sides. Niels has a nice graph of time to handle one event as a function of the number of connections. It shows kqueue and sys_epoll as clear winners.
libevent 是一个由 Niels Provos 编写的轻量级的 c I/O 框架。它支持 kqueue 和 select,并且不久将会支持 poll 和 epoll。我认为它只支持水平触发,这既有好处也有缺点。Niels 有一张关于处理单个事件的时间图表,该图以连接数量为函数。图标显示 kqueue 和 sys_epoll 是明显的胜者。
- My own attempts at lightweight frameworks (sadly, not kept up to date):
我自己关于轻量级框架做的一些努力(很可惜,没有持续下去):
- Poller is a lightweight C++ I/O framework that implements a level-triggered readiness API using whatever underlying readiness API you want (poll, select, /dev/poll, kqueue, or sigio). It's useful for benchmarks that compare the performance of the various APIs. This document links to Poller subclasses below to illustrate how each of the readiness APIs can be used.
poller 是一个轻量级的 C++ I/O 框架,该框架实现了水平级别触发的 API,该 API 底层可以使用任何你想用的 API(poll、select、epoll、kequeue 等)。它在基准测试中相较于其他 API 是有优势的,这篇文章链接到 Poller 的子类,来说明这个 API 的每个方法是怎样使用的。
- rn is a lightweight C I/O framework that was my second try after Poller. It's lgpl (so it's easier to use in commercial apps) and C (so it's easier to use in non-C++ apps). It was used in some commercial products.
rn 是一个轻量级的 c I/O 框架,是我继 poller 后的第二次尝试。它是 lgpl 许可的(因此在商业 app 中试用非常方便),并且是用 c 编写的(因此在非 c++ 的 app 中试用是很简单的),它被用于一些商业产品中。
- Matt Welsh wrote a paper in April 2000 about how to balance the use of worker thread and event-driven techniques when building scalable servers. The paper describes part of his Sandstorm I/O framework.
Matt Welsh 在 2000 年 4 月份写了一篇论文,该论文主要是关于如何平衡工作线程和事件驱动技术,当创建一个可扩展的服务时。这篇论文描述了他的 Sandstorm I/O 框架的一部分。
- Cory Nelson's Scale! library - an async socket, file, and pipe I/O library for Windows
Cory Nelson's Scale! library 是针对 windows 的一个异步的 socket、file、以及 pipe I/O 库
I/O Strategies
Designers of networking software have many options. Here are a few:
网络软件的设计者有很多选择,比如以下这些:
- Whether and how to issue multiple I/O calls from a single thread
如何在单个线程中发出多个 I/O 调用,以及是否应该这样做
- Don't; use blocking/synchronous calls throughout, and possibly use multiple threads or processes to achieve concurrency
不要使用同步阻塞的调用,并且尽可能试用多线程或进程实现并发
- Use nonblocking calls (e.g. write() on a socket set to O_NONBLOCK) to start I/O, and readiness notification (e.g. poll() or /dev/poll) to know when it's OK to start the next I/O on that channel. Generally only usable with network I/O, not disk I/O.
使用非阻塞调用(比如将套接字设置为 O_NONBLOCK 后再调用 write())启动 I/O 操作,并使用就绪通知(比如 poll)来了解何时可以开启下一个 I/O 操作。通常只适用于网络 I/O,而不是磁盘 I/O。
- Use asynchronous calls (e.g. aio_write()) to start I/O, and completion notification (e.g. signals or completion ports) to know when the I/O finishes. Good for both network and disk I/O.
使用异步调用(比如 aio_write())开启 I/O,并且实现通知来了解什么时候 I/O 操作结束。这对网络和磁盘 I/O 来说都是适用的。
- How to control the code servicing each client
如何控制为每个客户端提供的代码
- one process for each client (classic Unix approach, used since 1980 or so)
每个客户端一个进程(经典的 Unix 方式,自大约 1980 年开始使用)
- one OS-level thread handles many clients; each client is controlled by:
一个操作系统级线程处理多个 client,每个 client 被以下部分控制:
- a user-level thread (e.g. GNU state threads, classic Java with green threads)
用户级别线程(比如 GUN 状态的线程,经典的 Java green 线程)
- a state machine (a bit esoteric, but popular in some circles; my favorite)
状态机(有点神秘,但在某些领域很受欢迎;这也是我最喜爱的方式)
- a continuation (a bit esoteric, but popular in some circles)
continuation,协程(有点神秘,但在某些领域很受欢迎)
- one OS-level thread for each client (e.g. classic Java with native threads)
一个 client 一个操作系统级线程(比如经典的 Java 本地线程)
- one OS-level thread for each active client (e.g. Tomcat with apache front end; NT completion ports; thread pools)
每个活跃的 client 一个操作系统系统级线程(比如使用 Apache 前端的 Tomcat;线程池等)
- Whether to use standard O/S services, or put some code into the kernel (e.g. in a custom driver, kernel module, or VxD)
是否使用标准的系统服务,还是将一部分代码放入内核(比如自定义的 driver,内核模块或 VxD)
The following five combinations seem to be popular:
以下五种组合似乎是比较受欢迎的
一个线程处理多个客户端,并且使用非阻塞 I/O 以及水平级别触发的通知
一个线程处理多个客户端,并且使用非阻塞 I/O 以及可读通知
一个服务线程处理多个 cleint,并且使用异步 I/O
-
serve one client with each server thread, and use blocking I/O 一个服务线程处理一个 cleint,并使用阻塞 I/O
将服务器代码嵌入内核
3. Techniques/Tips 分享一个小技巧
最近在尝试对所学的知识画脑图加深记忆,经过一段时间的尝试,发现该方法比较好,每天对学习的知识画脑图进行整理,晚上对脑图进行回顾,并且一份脑图包含两张图,一张是非常简略的脑图,一张是有细节的脑图,这样在回顾时先看简略脑图,然后回忆补充,遇到忘记的部分再看详细版脑图,效果还不错
4. Share 分享一个观点
本周在进行年终述职,所谓述职,可以理解为总结,在进行述职的过程中,发现了一些平时被自己遗忘的东西:
- 积累过少
- 输出过少
- 主动性不足
积累过少问题是由于今年工作方向换了三次,每个方向都没能深入学习、了解,导致对系统每个方向细节了解不够,好处是对系统整体有了了解,在新的一年内,需要对系统各方向、各领域深入了解,站在全局的角度思考系统存在的问题以及未来演进的方向
输出过少主要是今年学的东西其实蛮多的,书看了8 本,极客时间学了 6 门课程,但是没能及时对学习的东西进行归纳总结,导致很多知识快速的被遗忘,跟别人聊起来能想起大概,但一深入,就懵了,针对该问题,后续改进的方法是对所学的知识,及时进行归纳总结,首先形成思维导图或者文档,其次正确能在公司小组内部进行分享,因为只有当你能将别人讲懂,才表示你对这个知识是真正掌握了
主动性不足,主要体现在对于系统的关注不够,系统埋了很多点,设置了很多告警,但我基本从未关注过这些告警,并且对于系统存在的问题思考不足,主要工作是执行而非设计,这是一个缺陷,要转变身份,主动关注系统各种问题,提出系统优化方案,从执行者向设计者转变,不然永远都是小卒,成不了大将