结合实例理解流式输出的几种实现方法

0 Comment

如果有用过 ChatGPT 等大语言模型,可能就会发现在聊天对话中,AI 的输出文本是一批批“蹦出来”的,这就是所谓的流式输出。在浏览器上,是怎么实现这种效果呢?

本篇文章会介绍 4 种常见方法来实现流式输出效果,每种方法都会结合实际例子来演示。在业务中选择哪种方法,取决于具体的需求和场景。

  1. 客户端轮询:客户端定时(如每几秒)发送请求到后端服务,获取新的数据。
  2. 分块传输:HTTP/1.1 支持,服务器一次可以只发送部分响应内容,客户端接收到部分数据后就可以开始处理。
  3. Server-Sent Events:服务器向浏览器推送信息,浏览器创建一个到服务器的单向连接,服务器通过这个连接可以发送多个消息。
  4. Web Socket:建立一个持久的、全双工的连接,允许服务器和客户端之间进行实时、双向的通信。

阅读全文

结合实例深入理解 C++ 对象的内存布局

0 Comment

在前面 Bazel 依赖缺失导致的 C++ 进程 coredump 问题分析 这篇文章,因为二进制使用了不同版本的 proto 对象,对象的内存布局不一致导致读、写成员的内存地址错乱,进而导致进程 crash 掉。但是当时并没有展开细聊下面的问题:

  1. 对象在内存中是怎么布局的?
  2. 成员方法是如何拿到成员变量的地址?

这些其实涉及 C++ 的对象模型,《深度探索 C++对象模型:Inside the C++ Object Model》这本书全面聊了这个问题,非常值得一读。不过这本书读起来并不容易,有的内容读过后如果没有加以实践,也很难完全理解。本篇文章试着从实际的例子出发,帮助大家对 C++ 类成员变量和函数在内存布局有个直观的理解,后面再读这本书也会容易理解些。

阅读全文

C++ 函数可变参实现方法的演进

0 Comment

可变参数函数是接受可变数量参数的函数,在不少场景下,可变参数函数是非常有用的。比如想打印日志时,可以接受任意数量的参数,然后将这些参数拼接输出到控制台,如下:

1
2
3
4
{
// ...;
LogInfo(user, cost, action, result);
}

在C++中,可变参数函数的实现方法也是不断演进的,从最初C风格的可变参数列表,到 C++11 的变参模板,再到 C++17 引入的折叠表达式,见证了 C++ 语言的逐步发展和完善。接下来本文会介绍这三种方式的实现细节以及优缺点。

阅读全文