Project Icon

ucall

超高性能的JSON远程过程调用库

UCall是一个基于JSON-RPC的远程过程调用库,性能显著优于FastAPI和gRPC。该库支持原生类型及numpy数组、PIL图像等自定义类型,适用于实际应用开发和多模态AI部署。UCall通过io_uring实现高效IO,并采用SIMD加速解析,即使在免费层服务器上也能实现卓越性能。此外,UCall还提供了简洁的Python接口和命令行工具,大大简化了远程调用过程。

UCall

JSON远程过程调用库
速度比FastAPI快100倍


Discord     LinkedIn     Twitter     博客     GitHub


现代大多数网络通信要么建立在缓慢且模糊的REST API之上,要么建立在不必要复杂的gRPC之上。 例如,FastAPI看起来非常易于使用。 我们的目标是达到同样甚至更简单的使用体验。

FastAPIUCall
pip install fastapi uvicorn
pip install ucall
from fastapi import FastAPI
import uvicorn

server = FastAPI()

@server.get('/sum')
def sum(a: int, b: int):
    return a + b

uvicorn.run(...)    
from ucall.posix import Server
# 在Linux 5.19+上使用 from ucall.uring import Server

server = Server()

@server
def sum(a: int, b: int):
    return a + b

server.run()    

在最新的8核CPU上处理一个简单的FastAPI调用需要超过一毫秒的时间。 在这段时间内,光可以通过光纤传输300公里,到达邻近的城市或国家。 那么UCall与FastAPI和gRPC相比如何呢?

设置🔁服务器单客户端延迟32客户端吞吐量
Fast API over REST🐍1'203 μs3'184 rps
Fast API over WebSocket🐍86 μs11'356 rps ¹
gRPC ²🐍164 μs9'849 rps
UCall with POSIXC62 μs79'000 rps
UCall with io_uring🐍40 μs210'000 rps
UCall with io_uringC22 μs231'000 rps
表格说明

所有基准测试都在AWS的通用实例上进行,使用Ubuntu 22.10 AMI。 这是第一个带有Linux内核5.19的主要AMI,为网络操作提供了更广泛的io_uring支持。 这些具体数字是在配备Graviton 3芯片的c7g.metal高性能实例上获得的。

  • 🔁列标记在后续请求中是否重用TCP/IP连接。
  • "服务器"列定义了服务器实现所使用的编程语言。
  • "延迟"列报告了发送请求到接收响应之间的时间。μ代表微秒,μs随后表示微秒。
  • "吞吐量"列报告了当从同一台机器上运行的多个客户端进程查询同一服务器应用程序时,每秒处理的请求数。

¹ FastAPI无法使用WebSockets处理并发请求。

² 我们尝试用gRPC生成C++后端,但其数字令人怀疑地并没有更好。还有一个异步gRPC选项未尝试。

这怎么可能?!

一个只有几千行代码的小项目如何能与两个最知名的网络库竞争? UCall站在巨人的肩膀上

  • 使用io_uring实现无中断IO。

    • 5.1+版本支持io_uring_prep_read_fixed
    • 5.19+版本支持io_uring_prep_accept_direct
    • 5.19+版本支持io_uring_register_files_sparse
    • 5.19+版本可选支持IORING_SETUP_COOP_TASKRUN
    • 6.0+版本可选支持IORING_SETUP_SINGLE_ISSUER
  • 使用SIMD加速的解析器和手动内存控制。

    • 使用[simdjson][simdjson]解析JSON,速度比gRPC解包ProtoBuf更快。
    • 使用[Turbo-Base64][base64]从Base64格式解码二进制值。
    • 使用[picohttpparser][picohttpparser]导航HTTP头。

你已经看到了往返延迟...,每秒请求吞吐量...,想看看带宽吗? 自己试试吧!

@server
def echo(data: bytes):
    return data

比FastAPI功能更强大

FastAPI支持原生类型,而UCall支持numpy.ndarrayPIL.Image和其他自定义类型。 这在构建实际应用或想要部署多模态AI时非常有用,就像我们使用UForm所做的那样。

from ucall.rich_posix import Server
import ufrom

server = Server()
model = uform.get_model('unum-cloud/uform-vl-multilingual')

@server
def vectorize(description: str, photo: PIL.Image.Image) -> numpy.ndarray:
    image = model.preprocess_image(photo)
    tokens = model.preprocess_text(description)
    joint_embedding = model.encode_multimodal(image=image, text=tokens)

    return joint_embedding.cpu().detach().numpy()

我们还有自己的可选Client类,可以帮助处理这些自定义类型。

from ucall.client import Client

client = Client()
# 显式JSON-RPC调用:
response = client({
    'method': 'vectorize',
    'params': {
        'description': description,
        'image': image,
    },
    'jsonrpc': '2.0',
    'id': 100,
})
# 或者使用语法糖:
response = client.vectorize(description=description, image=image) 

类似cURL的命令行界面

除了Python Client,我们还提供了一个易于使用的命令行界面,可通过pip install ucall安装。 它允许你调用远程服务器、上传文件,并直接支持图像和NumPy数组。 将前面的例子转换为Bash脚本,在同一台机器上调用服务器:

ucall vectorize description='产品描述' -i image=./本地/路径.png

调用远程服务器:

ucall vectorize description='产品描述' -i image=./本地/路径.png --uri 0.0.0.0 -p 8545

打印文档,使用ucall -h

用法: ucall [-h] [--uri URI] [--port PORT] [-f [FILE ...]] [-i [IMAGE ...]] [--positional [POSITIONAL ...]] method [kwargs ...]

UCall客户端命令行界面

位置参数:
  method                方法名
  kwargs                方法参数
选项:
  -h, --help            显示此帮助信息并退出
  --uri URI             服务器 URI
  --port PORT           服务器端口
  -f [FILE ...], --file [FILE ...]
                        方法位置参数
  -i [IMAGE ...], --image [IMAGE ...]
                        方法位置参数
  --positional [POSITIONAL ...]
                        方法位置参数

您也可以显式注释类型,以区分整数、浮点数和字符串,避免歧义。

ucall auth id=256 ucall auth id:int=256 ucall auth id:str=256


免费层吞吐量

我们将带宽测量留给爱好者,但会分享一些更多数字。
一般逻辑是,您无法从免费层机器中挤出高性能。
目前 AWS 提供以下选项:老式 Intel 和新的 Graviton 2 芯片上的 `t2.micro` 和 `t4g.small`。
这个库非常快,只需要 1 个核心就能运行,所以您甚至可以在小型免费层服务器上运行快速服务器!

| 设置                    |   🔁   | 服务器  | 客户端  | `t2.micro` | `t4g.small` |
| :---------------------- | :---: | :----: | :-----: | ---------: | ----------: |
| Fast API over REST      |   ❌   |   🐍    |    1    |    328 rps |     424 rps |
| Fast API over WebSocket |   ✅   |   🐍    |    1    |  1'504 rps |   3'051 rps |
| gRPC                    |   ✅   |   🐍    |    1    |  1'169 rps |   1'974 rps |
|                         |       |        |         |            |             |
| UCall with POSIX        |   ❌   |   C    |    1    |  1'082 rps |   2'438 rps |
| UCall with io_uring     |   ✅   |   C    |    1    |          - |   5'864 rps |
| UCall with POSIX        |   ❌   |   C    |   32    |  3'399 rps |  39'877 rps |
| UCall with io_uring     |   ✅   |   C    |   32    |          - |  88'455 rps |

在这种情况下,每个服务器都被同一可用区内的 1 个或 32 个其他实例的请求轰炸。
如果您想重现这些基准测试,请查看 GitHub 上的 [`sum` 示例][sum-examples]。

快速开始

对于 Python:

```sh
pip install ucall

对于 CMake 项目:

include(FetchContent)
FetchContent_Declare(
    ucall
    GIT_REPOSITORY https://github.com/unum-cloud/ucall
    GIT_SHALLOW TRUE
)
FetchContent_MakeAvailable(ucall)
include_directories(${ucall_SOURCE_DIR}/include)

C 的使用示例比 Python 更冗长。 我们希望使它尽可能轻量级,并允许可选参数而不进行动态分配和命名查找。 因此,与 Python 层不同,我们期望用户使用 ucall_param_named_i64() 及其兄弟函数手动从调用上下文中提取参数。

#include <cstdio.h>
#include <ucall/ucall.h>

static void sum(ucall_call_t call, ucall_callback_tag_t) {
    int64_t a{}, b{};
    char printed_sum[256]{};
    bool got_a = ucall_param_named_i64(call, "a", 0, &a);
    bool got_b = ucall_param_named_i64(call, "b", 0, &b);
    if (!got_a || !got_b)
        return ucall_call_reply_error_invalid_params(call);

    int len = snprintf(printed_sum, 256, "%ll", a + b);
    ucall_call_reply_content(call, printed_sum, len);
}

int main(int argc, char** argv) {

    ucall_server_t server{};
    ucall_config_t config{};

    ucall_init(&config, &server);
    ucall_add_procedure(server, "sum", &sum, NULL);
    ucall_take_calls(server, 0);
    ucall_free(server);
    return 0;
}

路线图

  • 批量请求
  • 通过原始 TCP 套接字的 JSON-RPC
  • 通过带 HTTP 的 TCP 的 JSON-RPC
  • 并发会话
  • NumPy array 和 Pillow 序列化
  • HTTPS 支持
  • 适用于 ML 的批处理端点
  • 零 ETL 中继调用
  • 与 [UKV][ukv] 集成
  • 用于 Web 界面的 WebSockets
  • Linux 上基于 AF_XDP 和 UDP 的替代品

想影响路线图并请求功能吗?加入 Discord 上的讨论。

为什么选择 JSON-RPC?

  • 传输独立:UDP、TCP,您想用什么就用什么。
  • 应用层是可选的:使用 HTTP 与否由您决定。
  • 与 REST API 不同,只有一种传递参数的方式。
项目侧边栏1项目侧边栏2
推荐项目
Project Cover

豆包MarsCode

豆包 MarsCode 是一款革命性的编程助手,通过AI技术提供代码补全、单测生成、代码解释和智能问答等功能,支持100+编程语言,与主流编辑器无缝集成,显著提升开发效率和代码质量。

Project Cover

AI写歌

Suno AI是一个革命性的AI音乐创作平台,能在短短30秒内帮助用户创作出一首完整的歌曲。无论是寻找创作灵感还是需要快速制作音乐,Suno AI都是音乐爱好者和专业人士的理想选择。

Project Cover

有言AI

有言平台提供一站式AIGC视频创作解决方案,通过智能技术简化视频制作流程。无论是企业宣传还是个人分享,有言都能帮助用户快速、轻松地制作出专业级别的视频内容。

Project Cover

Kimi

Kimi AI助手提供多语言对话支持,能够阅读和理解用户上传的文件内容,解析网页信息,并结合搜索结果为用户提供详尽的答案。无论是日常咨询还是专业问题,Kimi都能以友好、专业的方式提供帮助。

Project Cover

阿里绘蛙

绘蛙是阿里巴巴集团推出的革命性AI电商营销平台。利用尖端人工智能技术,为商家提供一键生成商品图和营销文案的服务,显著提升内容创作效率和营销效果。适用于淘宝、天猫等电商平台,让商品第一时间被种草。

Project Cover

吐司

探索Tensor.Art平台的独特AI模型,免费访问各种图像生成与AI训练工具,从Stable Diffusion等基础模型开始,轻松实现创新图像生成。体验前沿的AI技术,推动个人和企业的创新发展。

Project Cover

SubCat字幕猫

SubCat字幕猫APP是一款创新的视频播放器,它将改变您观看视频的方式!SubCat结合了先进的人工智能技术,为您提供即时视频字幕翻译,无论是本地视频还是网络流媒体,让您轻松享受各种语言的内容。

Project Cover

美间AI

美间AI创意设计平台,利用前沿AI技术,为设计师和营销人员提供一站式设计解决方案。从智能海报到3D效果图,再到文案生成,美间让创意设计更简单、更高效。

Project Cover

AIWritePaper论文写作

AIWritePaper论文写作是一站式AI论文写作辅助工具,简化了选题、文献检索至论文撰写的整个过程。通过简单设定,平台可快速生成高质量论文大纲和全文,配合图表、参考文献等一应俱全,同时提供开题报告和答辩PPT等增值服务,保障数据安全,有效提升写作效率和论文质量。

投诉举报邮箱: service@vectorlightyear.com
@2024 懂AI·鲁ICP备2024100362号-6·鲁公网安备37021002001498号