<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>博客 on Laputa</title>
    <link>https://chenjianyong.com/zh/blog/</link>
    <description>Recent content in 博客 on Laputa</description>
    <generator>Hugo</generator>
    <language>zh-CN</language>
    <lastBuildDate>Thu, 15 Dec 2022 00:00:00 +0000</lastBuildDate>
    <atom:link href="https://chenjianyong.com/zh/blog/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>Seastar: sharded service(2)</title>
      <link>https://chenjianyong.com/zh/blog/2022/seastar-sharded-service2/</link>
      <pubDate>Thu, 15 Dec 2022 00:00:00 +0000</pubDate>
      <guid>https://chenjianyong.com/zh/blog/2022/seastar-sharded-service2/</guid>
      <description>&lt;h2 id=&#34;preface&#34;&gt;Preface&lt;/h2&gt;&#xA;&lt;p&gt;&lt;a href=&#34;blog/2022/seastar-sharded-service1/&#34;&gt;第一篇&lt;/a&gt;里面介绍了一下 &lt;code&gt;seastar::sharded&lt;/code&gt; 的基本概念和用法, 一般情况下我们用这些就足够了, 但是 Seastar 还为其他一些特殊的使用场景提供了支持, 当程序功能越来越复杂, 碰到这些场景的概率肯定会更大, 所以从完备的层面考虑, 还是得介绍一些他们; 其实也并不困难, Seastar 是秉持实用主义的, 也就是说在里面的组件一定是有现实中的使用场景的, 用到他们只是时间的问题(了解了这些组件之后可以在 &lt;a href=&#34;https://github.com/redpanda-data/redpanda&#34;&gt;redpanda&lt;/a&gt; 和 &lt;a href=&#34;https://github.com/scylladb/scylladb&#34;&gt;scylladb&lt;/a&gt; 的 codebase 里搜索一下具体的使用场景)&lt;/p&gt;</description>
    </item>
    <item>
      <title>Seastar: sharded service(1)</title>
      <link>https://chenjianyong.com/zh/blog/2022/seastar-sharded-service1/</link>
      <pubDate>Thu, 01 Dec 2022 00:00:00 +0000</pubDate>
      <guid>https://chenjianyong.com/zh/blog/2022/seastar-sharded-service1/</guid>
      <description>&lt;h2 id=&#34;preface&#34;&gt;Preface&lt;/h2&gt;&#xA;&lt;p&gt;Seastar 是一个多线程异步库, 基于它的 App 通常都有在多个 shard(也称 logic core) 上对称部署服务的诉求; 为此我们需要在多个 shard 上创建服务的实例, 并且让这些实例执行某些操作; 这些涉及到 shard 之间的通信, Seastar 提倡使用显式的消息传递(message passing)而不是传统多线程编程常用的共享内存&amp;amp;加锁的方式进行通信, 为此提供了 &lt;code&gt;smp&lt;/code&gt; 工具; 所以我们其实可以这样写:&lt;/p&gt;</description>
    </item>
    <item>
      <title>Seastar: network stack</title>
      <link>https://chenjianyong.com/zh/blog/2022/seastar-network-stack/</link>
      <pubDate>Sun, 13 Nov 2022 00:00:00 +0000</pubDate>
      <guid>https://chenjianyong.com/zh/blog/2022/seastar-network-stack/</guid>
      <description>&lt;h1 id=&#34;seastar-network-stack&#34;&gt;Seastar: network stack&lt;/h1&gt;&#xA;&lt;h2 id=&#34;preface&#34;&gt;Preface&lt;/h2&gt;&#xA;&lt;p&gt;Seastar 中提供了两种协议栈:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;native stack&lt;/li&gt;&#xA;&lt;li&gt;posix stack&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;其中 native stack 是 seastar 自己实现的一套协议栈, 一般是和 DPDK 配合使用; 而 posix stack 则是传统的内核协议栈; 由于我并不了解 DPDK, 暂时也没有学习/使用的需要, 所以目前还是先关注 posix stack 的实现(只关注 TCP, unix socket/UDP/SCTP 暂时不管), 以及 seastar 是如何抽象 network stack 这个概念从而统一 native stack 和 posix stack 二者的.&lt;/p&gt;</description>
    </item>
    <item>
      <title>一个符号导致的问题</title>
      <link>https://chenjianyong.com/zh/blog/2022/%E4%B8%80%E4%B8%AA%E7%AC%A6%E5%8F%B7%E5%AF%BC%E8%87%B4%E7%9A%84%E9%97%AE%E9%A2%98/</link>
      <pubDate>Sun, 07 Aug 2022 00:00:00 +0000</pubDate>
      <guid>https://chenjianyong.com/zh/blog/2022/%E4%B8%80%E4%B8%AA%E7%AC%A6%E5%8F%B7%E5%AF%BC%E8%87%B4%E7%9A%84%E9%97%AE%E9%A2%98/</guid>
      <description>&lt;h2 id=&#34;preface&#34;&gt;Preface&lt;/h2&gt;&#xA;&lt;p&gt;最近在优化 Seastar 中 httpd 的一些逻辑，完事之后跑一跑单测想确认下对现有逻辑的确无影响，但是一跑发现有一个 chunk 相关的测试挂了——但是我明明还没有改动到这块，只是改了一下 keepalive 的判定逻辑。&lt;/p&gt;</description>
    </item>
    <item>
      <title>Seastar: temporary buffer</title>
      <link>https://chenjianyong.com/zh/blog/2022/seastar-temporary-buffer/</link>
      <pubDate>Sat, 16 Jul 2022 00:00:00 +0000</pubDate>
      <guid>https://chenjianyong.com/zh/blog/2022/seastar-temporary-buffer/</guid>
      <description>&lt;h2 id=&#34;preface&#34;&gt;Preface&lt;/h2&gt;&#xA;&lt;p&gt;&lt;code&gt;temporary_buffer&lt;/code&gt; 是 Seastar 提供的一种自我管理(self-managed)字节缓冲区，它类似于 &lt;code&gt;std::string&lt;/code&gt; 或者 &lt;code&gt;std::unique_ptr&amp;lt;char[]&amp;gt;&lt;/code&gt;，但是提供了一些更加灵活的内存管理机制，比如它可以独占底层的缓冲区，也可以和其他 &lt;code&gt;temporary_buffer&lt;/code&gt; 共享底层缓冲区、甚至只共享其他 &lt;code&gt;temporay_buffer&lt;/code&gt; 底层缓冲区的一部分&amp;hellip;，因为这些功能，这个数据结构在 Seastar 以及 Scylla/RedPanda 等基于 Seastar 的项目中使用得非常广泛&lt;/p&gt;</description>
    </item>
    <item>
      <title>Seastar: 用户线程</title>
      <link>https://chenjianyong.com/zh/blog/2022/seastar-%E7%94%A8%E6%88%B7%E7%BA%BF%E7%A8%8B/</link>
      <pubDate>Sun, 22 May 2022 00:00:00 +0000</pubDate>
      <guid>https://chenjianyong.com/zh/blog/2022/seastar-%E7%94%A8%E6%88%B7%E7%BA%BF%E7%A8%8B/</guid>
      <description>&lt;h2 id=&#34;preface&#34;&gt;Preface&lt;/h2&gt;&#xA;&lt;p&gt;通常我们在 seastar 中写代码是不能阻塞的，如果我们希望在一段异步代码之后执行完毕之后开始执行另外一个逻辑，那么我们就需要通过 continuation 的方式将其串联起来，比如：&lt;/p&gt;</description>
    </item>
    <item>
      <title>ucontext and coroutine</title>
      <link>https://chenjianyong.com/zh/blog/2022/ucontext-and-coroutine/</link>
      <pubDate>Sun, 08 May 2022 00:00:00 +0000</pubDate>
      <guid>https://chenjianyong.com/zh/blog/2022/ucontext-and-coroutine/</guid>
      <description>&lt;h2 id=&#34;preface&#34;&gt;Preface&lt;/h2&gt;&#xA;&lt;p&gt;最近在看 &lt;a href=&#34;http://docs.seastar.io/master/tutorial.html#seastarthread&#34;&gt;&lt;code&gt;seastar::thread&lt;/code&gt;&lt;/a&gt; 的实现，暂且不说它的巧妙(实际上目前还没有完全看懂，但是 Seastar 出品，必属精品)，我首先注意到了 &lt;em&gt;ucontext&lt;/em&gt;，这是 &lt;code&gt;seastar::thread&lt;/code&gt; 中能够等待一个 unavailable future 的关键，之前没有接触过这套 API，网上搜索了一下相关资料才了解到它居然可以用来实现协程，顿时有了兴趣。&lt;/p&gt;</description>
    </item>
    <item>
      <title>Seastar: semaphore</title>
      <link>https://chenjianyong.com/zh/blog/2022/seastar-semaphore/</link>
      <pubDate>Wed, 04 May 2022 00:00:00 +0000</pubDate>
      <guid>https://chenjianyong.com/zh/blog/2022/seastar-semaphore/</guid>
      <description>&lt;h2 id=&#34;preface&#34;&gt;Preface&lt;/h2&gt;&#xA;&lt;p&gt;最近在实现 &lt;a href=&#34;https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API&#34;&gt;fetch 接口&lt;/a&gt;时, 需要对单个 JS 脚本的单次执行过程中可以发起的 fetch 操作数进行限制(和 CloudFlare Workers &lt;a href=&#34;https://developers.cloudflare.com/workers/platform/limits/#simultaneous-open-connections&#34;&gt;类似&lt;/a&gt;):&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;总量限制：超过了则后续的 fetch 操作都将直接失败&lt;/li&gt;&#xA;&lt;li&gt;并发限制：超过了则后续的 fetch 请求将会被延迟(postpone)执行，直到有其他执行着的 fetch 请求结束&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;第一点很简单, 用一个计数器即可解决; 关键在于第二个, 要将超出了并发限制的 fetch 操作阻塞住, 直到有其他 fetch 操作结束(即返回的 promise 被 resolve)再唤醒它们执行.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Seastar: 系统调用线程</title>
      <link>https://chenjianyong.com/zh/blog/2022/seastar-%E7%B3%BB%E7%BB%9F%E8%B0%83%E7%94%A8%E7%BA%BF%E7%A8%8B/</link>
      <pubDate>Mon, 18 Apr 2022 00:00:00 +0000</pubDate>
      <guid>https://chenjianyong.com/zh/blog/2022/seastar-%E7%B3%BB%E7%BB%9F%E8%B0%83%E7%94%A8%E7%BA%BF%E7%A8%8B/</guid>
      <description>&lt;h2 id=&#34;preface&#34;&gt;Preface&lt;/h2&gt;&#xA;&lt;p&gt;在 Seastar 中，文件相关的操作并不直接由 reactor 线程(工作线程)执行，而是被 offload 到一个专门的线程中去执行，为此 Seastar 在 &lt;code&gt;reactor&lt;/code&gt; 中提供了诸多文件操作相关的方法；比如重命名一个文件就可以使用 &lt;code&gt;rename_file&lt;/code&gt; 方法：&lt;/p&gt;</description>
    </item>
    <item>
      <title>Seastar：核间通信</title>
      <link>https://chenjianyong.com/zh/blog/2022/seastar%E6%A0%B8%E9%97%B4%E9%80%9A%E4%BF%A1/</link>
      <pubDate>Sat, 02 Apr 2022 00:00:00 +0000</pubDate>
      <guid>https://chenjianyong.com/zh/blog/2022/seastar%E6%A0%B8%E9%97%B4%E9%80%9A%E4%BF%A1/</guid>
      <description>&lt;h2 id=&#34;preface&#34;&gt;Preface&lt;/h2&gt;&#xA;&lt;p&gt;虽然 Seastar 号称 share-nothing&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;，但是现代服务器开发中仍免不了需要核间通信；Seastar 为此在 &lt;code&gt;smp&lt;/code&gt; 类中提供了 &lt;code&gt;submit_to&lt;/code&gt; 方法用于向其他线程的 reactor 提交任务并执行：&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;&#xA;&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;&#xA;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td class=&#34;lntd&#34;&gt;&#xA;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-c++&#34; data-lang=&#34;c++&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;static&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;futurize_t&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;std&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;::&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;invoke_result_t&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Func&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;submit_to&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;unsigned&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;t&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Func&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;func&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;noexcept&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;p&gt;比如下面的代码：&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;&#xA;&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;&#xA;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;6&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td class=&#34;lntd&#34;&gt;&#xA;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-c++&#34; data-lang=&#34;c++&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;ss&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;::&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;future&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;&amp;gt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;std&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;::&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;cout&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;run on shard-&amp;#34;&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ss&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;::&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;this_shard_id&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;std&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;::&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;endl&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ss&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;::&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;smp&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;::&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;submit_to&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[]()&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;std&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;::&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;cout&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;run on shard-&amp;#34;&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ss&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;::&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;this_shard_id&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;std&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;::&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;endl&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;});&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;p&gt;首先在当前 shard 打印其 id，然后往 id 为 1 的 shard 提交一个异步任务，该异步任务也只是简单地打印出所在 shard 的 id&lt;/p&gt;</description>
    </item>
    <item>
      <title>Seastar: loop utility</title>
      <link>https://chenjianyong.com/zh/blog/2022/seastar-loop-utility/</link>
      <pubDate>Sat, 26 Mar 2022 00:00:00 +0000</pubDate>
      <guid>https://chenjianyong.com/zh/blog/2022/seastar-loop-utility/</guid>
      <description>&lt;h2 id=&#34;preface&#34;&gt;Preface&lt;/h2&gt;&#xA;&lt;p&gt;循环是绝大多数编程语言中必不可少的控制结构，比如 C++ 对数组中的元素求和：&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;&#xA;&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;&#xA;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;6&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;7&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td class=&#34;lntd&#34;&gt;&#xA;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-c++&#34; data-lang=&#34;c++&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;sum&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;std&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;::&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;vector&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ints&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;res&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;size_t&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;i&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;i&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ints&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;size&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;();&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;++&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;res&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ints&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;];&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;res&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;p&gt;然而在 Seastar 中，写循环却不是一件容易的事情——当然不是上面这种不涉及到任何的异步操作的循环，而是指循环重复执行一个异步操作。比如我们想实现这样一个 &lt;code&gt;search&lt;/code&gt; 函数：它依次从 Google、Bing 和 Baidu 搜索，有一个成功则将其内容输出至标准输出并停止搜索；或许我们可以马上写出下面这样一段代码：&lt;/p&gt;</description>
    </item>
    <item>
      <title>Seastar: FPC(2)</title>
      <link>https://chenjianyong.com/zh/blog/2022/seastar-fpc2/</link>
      <pubDate>Wed, 09 Mar 2022 00:00:00 +0000</pubDate>
      <guid>https://chenjianyong.com/zh/blog/2022/seastar-fpc2/</guid>
      <description>&lt;h2 id=&#34;preface&#34;&gt;Preface&lt;/h2&gt;&#xA;&lt;p&gt;这里不打算完整地解释 Seastar 中 future&amp;amp;promise 的实现，里面旁枝末节实在太多，比如：&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;API 的兼容性处理&lt;/li&gt;&#xA;&lt;li&gt;针对不同平台的优化&lt;/li&gt;&#xA;&lt;li&gt;针对 Debug 编译的特殊处理&lt;/li&gt;&#xA;&lt;li&gt;各种 Modern C++ 特性的使用&lt;/li&gt;&#xA;&lt;li&gt;针对 GCC/Clang 做的各种编译优化&lt;/li&gt;&#xA;&lt;li&gt;&amp;hellip;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;所以还是希望抓住其中的一些重难点以及做的一些优化进行分析。&lt;/p&gt;</description>
    </item>
    <item>
      <title>Seastar: FPC(1)</title>
      <link>https://chenjianyong.com/zh/blog/2022/seastar-fpc1/</link>
      <pubDate>Sun, 06 Mar 2022 00:00:00 +0000</pubDate>
      <guid>https://chenjianyong.com/zh/blog/2022/seastar-fpc1/</guid>
      <description>&lt;h2 id=&#34;preface&#34;&gt;Preface&lt;/h2&gt;&#xA;&lt;p&gt;主要讲的是 future&amp;amp;promise 一些基本概念以及设计原理，但是因为 Seastar 中的实现&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;非常复杂(毕竟是工业级产品，且经过了 LLVM 大牛的大量优化，多了许多与核心实现其实并没有关系的逻辑)，所以我并不打算直接硬上(其实之前尝试过好几次，但是看完了之后还是迷迷糊糊一知半解，所以打算换一种方法)，而是打算借助 CppCon 2015 上的一个 presentation&lt;sup id=&#34;fnref:2&#34;&gt;&lt;a href=&#34;#fn:2&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;2&lt;/a&gt;&lt;/sup&gt; 来介绍它的基本原理和简易实现；BTW，这个 presentation 的确讲的非常好，力荐！&lt;/p&gt;</description>
    </item>
    <item>
      <title>Boost: 侵入式容器</title>
      <link>https://chenjianyong.com/zh/blog/2022/boost-%E4%BE%B5%E5%85%A5%E5%BC%8F%E5%AE%B9%E5%99%A8/</link>
      <pubDate>Sat, 05 Mar 2022 00:00:00 +0000</pubDate>
      <guid>https://chenjianyong.com/zh/blog/2022/boost-%E4%BE%B5%E5%85%A5%E5%BC%8F%E5%AE%B9%E5%99%A8/</guid>
      <description>&lt;h2 id=&#34;preface&#34;&gt;Preface&lt;/h2&gt;&#xA;&lt;p&gt;最近在为 Lua/JS 子请求实现 HTTP 连接池，池子的大小是固定的，但是创建的连接数是由跑在我们 web server 之上的用户代码(Lua/JS)决定的，所以在空间不够时必然需要淘汰旧的连接。很容易想到 LRU 淘汰算法，通常我们使用哈希表+双向链表实现&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;：哈希表用于存储数据，并且支持 $\mathcal{O}(1)$ 查找；而双向链表用于维护元素的访问时序，并且可以$\mathcal{O}(1)$ 删除。&lt;/p&gt;</description>
    </item>
    <item>
      <title>V8: 模板(1)</title>
      <link>https://chenjianyong.com/zh/blog/2022/v8-%E6%A8%A1%E6%9D%BF1/</link>
      <pubDate>Thu, 17 Feb 2022 00:00:00 +0000</pubDate>
      <guid>https://chenjianyong.com/zh/blog/2022/v8-%E6%A8%A1%E6%9D%BF1/</guid>
      <description>&lt;h2 id=&#34;preface&#34;&gt;Preface&lt;/h2&gt;&#xA;&lt;p&gt;当我们在 web server 中做 v8 扩展开发时，我们在做些什么？&lt;/p&gt;&#xA;&lt;p&gt;可以和 OpenResty 中的 Lua 类比，其中很大一部分工作是将 web server 的原生(native)能力暴露在 JS 中供用户使用。在 Lua 中写 C/C++ API 我们只需要遵守它所要求的函数签名以及参数传递机制写函数并将其注入全局环境就足够了，比如：&lt;/p&gt;</description>
    </item>
    <item>
      <title>Lua: read-only table</title>
      <link>https://chenjianyong.com/zh/blog/2022/lua-read-only-table/</link>
      <pubDate>Sat, 29 Jan 2022 00:00:00 +0000</pubDate>
      <guid>https://chenjianyong.com/zh/blog/2022/lua-read-only-table/</guid>
      <description>&lt;h2 id=&#34;preface&#34;&gt;Preface&lt;/h2&gt;&#xA;&lt;p&gt;Lua 中的 API 都是以 Lua table 的方式存储并提供给用户使用，拿 OpenResty 中的 &lt;code&gt;ngx.say&lt;/code&gt; API 为例：其中 &lt;code&gt;ngx&lt;/code&gt; 是全局环境(也是一个 Lua table)中一个名为 &lt;code&gt;ngx&lt;/code&gt; 的 key 对应的 value(一个 table)，而 &lt;code&gt;say&lt;/code&gt;，则是 &lt;code&gt;ngx&lt;/code&gt; 这个 table 中一个名为 &lt;code&gt;say&lt;/code&gt; 的 key 对应的 value(一个 C function)；而 Lua 标准库也是如此。&lt;/p&gt;</description>
    </item>
    <item>
      <title>Lua: buffer system</title>
      <link>https://chenjianyong.com/zh/blog/2021/lua-buffer-system/</link>
      <pubDate>Sun, 14 Nov 2021 00:00:00 +0000</pubDate>
      <guid>https://chenjianyong.com/zh/blog/2021/lua-buffer-system/</guid>
      <description>&lt;h2 id=&#34;preface&#34;&gt;Preface&lt;/h2&gt;&#xA;&lt;p&gt;最近在实现一套和 OpenResty 中的 &lt;code&gt;ngx.re.*&lt;/code&gt; 类似的 API，其中 &lt;code&gt;gsub/sub&lt;/code&gt; 这俩用到了 &lt;code&gt;luaL_Buffer&lt;/code&gt;；在数据量比较小的情况下它工作的很好，可是一旦数据量上去了，程序就开始抛出异常，不过 OpenResty 却可以正常工作，着实困扰了我一阵；查阅资料发现网上说 &lt;code&gt;luaL_Buffer&lt;/code&gt; 的确比较坑，怀疑是不是我用的方式不太对；最终通过看内部实现发现了问题所在，写这篇 blog 记录下&lt;/p&gt;</description>
    </item>
    <item>
      <title>程序员修炼之道: 务实的哲学</title>
      <link>https://chenjianyong.com/zh/blog/2020/%E7%A8%8B%E5%BA%8F%E5%91%98%E4%BF%AE%E7%82%BC%E4%B9%8B%E9%81%93-%E5%8A%A1%E5%AE%9E%E7%9A%84%E5%93%B2%E5%AD%A6/</link>
      <pubDate>Sat, 19 Sep 2020 00:00:00 +0000</pubDate>
      <guid>https://chenjianyong.com/zh/blog/2020/%E7%A8%8B%E5%BA%8F%E5%91%98%E4%BF%AE%E7%82%BC%E4%B9%8B%E9%81%93-%E5%8A%A1%E5%AE%9E%E7%9A%84%E5%93%B2%E5%AD%A6/</guid>
      <description>&lt;h2 id=&#34;preface&#34;&gt;Preface&lt;/h2&gt;&#xA;&lt;p&gt;自接触编程以来，我看过的绝大部分书都是关于某项特定技术的，比如 &lt;a href=&#34;https://book.douban.com/subject/25708312/&#34;&gt;C++ Primer&lt;/a&gt;、&lt;a href=&#34;https://book.douban.com/subject/26745255/&#34;&gt;深入理解 Nginx&lt;/a&gt; 以及 OS、网络等计算机专业课相关的。诚然，这些都是必备的，但是正式工作后，越来越感觉如何成长是一个至关重要的议题，而正好《程序员修炼之道》第二版发布了，所以打算看看这本书，而实际上书的确很棒，仅第一章里面就有许多地方我深有同感，不过许多地方我想的并不全面，也缺乏归纳总结这些思想的能力；还是先摘抄一些我喜欢的段落。&lt;/p&gt;</description>
    </item>
  </channel>
</rss>
