当前位置: 首页 > news >正文

测试DuckDB LuaJit插件通过ffi调用c语言动态库性能

关键步骤有2步。
1.用c编译器(gcc/tcc等)编译动态库

tcc -shared -fPIC -o libsudoku_c.so sudoku_solve.c

2.在DuckDB中把动态库中的函数注册为luajit udf

SELECT * FROM luajit_module(mode := 'compile', sql_name := 'sudoku_c', source := ' return function(p) local ffi = require("ffi") ffi.cdef[[ int sudoku_solve(const char *p, char *out); ]] local lib = ffi.load("/mnt/c/d/libsudoku_c.so") local buf = ffi.new("char[82]") local rc = lib.sudoku_solve(p, buf) if rc ~= 1 then return NULL end return ffi.string(buf) end ');

然后用luajit_s等函数调用udf。

在Windows中调用不成功。

Microsoft Windows [版本 10.0.26200.8655] (c) Microsoft Corporation。保留所有权利。 C:\Users\lt>cd\d C:\d>duckdb155 DuckDB v1.5.5 (Variegata) Enter ".help" for usage hints. memory D load luajit; memory D C:\d>tcc\tcc -shared -fPIC -o libsudoku_c.so sudoku_solve.c C:\d>duckdb155 DuckDB v1.5.5 (Variegata) Enter ".help" for usage hints. memory D load luajit; memory D SELECT * FROM luajit_module(mode := 'compile', sql_name := 'sudoku_c', source := ' return function(p) local ffi = require("ffi") ffi.cdef[[ int sudoku_solve(const char *p, char *out); ]] local lib = ffi.load("/d/libsudoku_c.so") local buf = ffi.new("char[82]") local rc = lib.sudoku_solve(p, buf) if rc ~= 1 then return NULL end return ffi.string(buf) end '); ┌─────────┬─────────┬─────────┬─────────┬─────────┬──────────┐ │ ok │ mode │ phase │ message │ detail │ sql_name │ │ boolean │ varchar │ varchar │ varchar │ varchar │ varchar │ ├─────────┼─────────┼─────────┼─────────┼─────────┼──────────┤ │ true │ compile │ compile │ OK │ │ sudoku_c │ └─────────┴─────────┴─────────┴─────────┴─────────┴──────────┘ memory D SELECT luajit_s('sudoku_c', '000001002000020030004500600007600050080090006100005800001004000070900003400030020'); ┌───────────────────────────────────────────────────────────────────────────────────────────────────────────┐ │ luajit_s('sudoku_c', '000001002000020030004500600007600050080090006100005800001004000070900003400030020') │ │ varchar │ ├───────────────────────────────────────────────────────────────────────────────────────────────────────────┤ │ NULL │ └───────────────────────────────────────────────────────────────────────────────────────────────────────────┘

在WSL Linux中调用成功。首先用apt install 安装Tcc。

C:\d>wsl root@DESKTOP-59T6U68:/mnt/c/d# tcc Command 'tcc' not found, but can be installed with: apt install tcc root@DESKTOP-59T6U68:/mnt/c/d# apt install tcc Reading package lists... Done Building dependency tree... Done Reading state information... Done The following NEW packages will be installed: tcc 0 upgraded, 1 newly installed, 0 to remove and 48 not upgraded. Need to get 278 kB of archives. After this operation, 824 kB of additional disk space will be used. Get:1 http://archive.ubuntu.com/ubuntu jammy/universe amd64 tcc amd64 0.9.27+git20200814.62c30a4a-1 [278 kB] Fetched 278 kB in 1s (205 kB/s) Selecting previously unselected package tcc. (Reading database ... 84088 files and directories currently installed.) Preparing to unpack .../tcc_0.9.27+git20200814.62c30a4a-1_amd64.deb ... Unpacking tcc (0.9.27+git20200814.62c30a4a-1) ... Setting up tcc (0.9.27+git20200814.62c30a4a-1) ... Processing triggers for install-info (6.8-4build1) ... Processing triggers for man-db (2.10.2-1) ... root@DESKTOP-59T6U68:/mnt/c/d# tcc -shared -fPIC -o libsudoku_c2.so sudoku_solve.c root@DESKTOP-59T6U68:/mnt/c/d# ./duckdb155 DuckDB v1.5.5 (Variegata) Enter ".help" for usage hints. memory D .timer on memory D load luajit; Run Time (s): real 0.015 user 0.004387 sys 0.000000 memory D SELECT * FROM luajit_module(mode := 'compile', sql_name := 'sudoku_c', source := ' return function(p) local ffi = require("ffi") ffi.cdef[[ int sudoku_solve(const char *p, char *out); ]] local lib = ffi.load("/mnt/c/d/libsudoku_c2.so") local buf = ffi.new("char[82]") local rc = lib.sudoku_solve(p, buf) if rc ~= 1 then return NULL end return ffi.string(buf) end '); ┌─────────┬─────────┬─────────┬─────────┬─────────┬──────────┐ │ ok │ mode │ phase │ message │ detail │ sql_name │ │ boolean │ varchar │ varchar │ varchar │ varchar │ varchar │ ├─────────┼─────────┼─────────┼─────────┼─────────┼──────────┤ │ true │ compile │ compile │ OK │ │ sudoku_c │ └─────────┴─────────┴─────────┴─────────┴─────────┴──────────┘ Run Time (s): real 0.008 user 0.002350 sys 0.000048 memory D SELECT max(luajit_s('sudoku_c', column0)) from (from read_csv('sudoku17.txt',header=0) limit 100); ┌───────────────────────────────────────────────────────────────────────────────────┐ │ max(luajit_s('sudoku_c', column0)) │ │ varchar │ ├───────────────────────────────────────────────────────────────────────────────────┤ │ 978654213645231798213879654796518432521347986384926175437182569159463827862795341 │ └───────────────────────────────────────────────────────────────────────────────────┘ Run Time (s): real 0.950 user 0.900484 sys 0.008561 memory D root@DESKTOP-59T6U68:/mnt/c/d# tcc -shared -fPIC -o libsudoku_c3.so dlxdll.c root@DESKTOP-59T6U68:/mnt/c/d# exit exit memory D SELECT * FROM luajit_module(mode := 'compile', sql_name := 'sudoku_c', source := ' return function(p) local ffi = require("ffi") ffi.cdef[[ int sudoku_solve(const char *p, char *out); ]] local lib = ffi.load("/mnt/c/d/libsudoku_c3.so") local buf = ffi.new("char[82]") local rc = lib.sudoku_solve(p, buf) if rc ~= 1 then return NULL end return ffi.string(buf) end '); ┌─────────┬─────────┬─────────┬─────────┬─────────┬──────────┐ │ ok │ mode │ phase │ message │ detail │ sql_name │ │ boolean │ varchar │ varchar │ varchar │ varchar │ varchar │ ├─────────┼─────────┼─────────┼─────────┼─────────┼──────────┤ │ true │ compile │ compile │ OK │ │ sudoku_c │ └─────────┴─────────┴─────────┴─────────┴─────────┴──────────┘ Run Time (s): real 0.019 user 0.019758 sys 0.000000 memory D SELECT max(luajit_s('sudoku_c', column0)) from (from read_csv('sudoku17.txt',header=0) limit 100); ┌───────────────────────────────────────────────────────────────────────────────────┐ │ max(luajit_s('sudoku_c', column0)) │ │ varchar │ ├───────────────────────────────────────────────────────────────────────────────────┤ │ 978654213645231798213879654796518432521347986384926175437182569159463827862795341 │ └───────────────────────────────────────────────────────────────────────────────────┘ Run Time (s): real 0.075 user 0.031685 sys 0.026326 memory D memory D SELECT max(luajit_s('sudoku_c', column0)) from (from read_csv('sudoku17.txt',header=0) limit 1000); ┌───────────────────────────────────────────────────────────────────────────────────┐ │ max(luajit_s('sudoku_c', column0)) │ │ varchar │ ├───────────────────────────────────────────────────────────────────────────────────┤ │ 987563214124987653356412987671398542295174836843256179439825761562731498718649325 │ └───────────────────────────────────────────────────────────────────────────────────┘ Run Time (s): real 0.114 user 0.066773 sys 0.012692 memory D SELECT max(luajit_s('sudoku_c', column0)) from (from read_csv('sudoku17.txt',header=0) limit 10000); ┌───────────────────────────────────────────────────────────────────────────────────┐ │ max(luajit_s('sudoku_c', column0)) │ │ varchar │ ├───────────────────────────────────────────────────────────────────────────────────┤ │ 987652431164739582253481796375824619842916357619375824728163945431597268596248173 │ └───────────────────────────────────────────────────────────────────────────────────┘ Run Time (s): real 0.483 user 0.466168 sys 0.003213

分别使用两种算法的数独求解程序,跳舞链的速度比MRV启发式—dfs快得多。

又尝试mold的作者编写的chibicc编译器。先从源码编译二进制可执行文件。

C:\Users\lt>wsl root@DESKTOP-59T6U68:/mnt/c/Users/lt# docker start gcc gcc root@DESKTOP-59T6U68:/mnt/c/Users/lt# docker exec -it gcc bash root@6ae32a5ffcde:/# cd /par root@6ae32a5ffcde:/par# cd chibicc-main root@6ae32a5ffcde:/par/chibicc-main# make cc -std=c11 -g -fno-common -Wall -Wno-switch -c -o codegen.o codegen.c cc -std=c11 -g -fno-common -Wall -Wno-switch -c -o hashmap.o hashmap.c cc -std=c11 -g -fno-common -Wall -Wno-switch -c -o main.o main.c cc -std=c11 -g -fno-common -Wall -Wno-switch -c -o parse.o parse.c cc -std=c11 -g -fno-common -Wall -Wno-switch -c -o preprocess.o preprocess.c cc -std=c11 -g -fno-common -Wall -Wno-switch -c -o strings.o strings.c cc -std=c11 -g -fno-common -Wall -Wno-switch -c -o tokenize.o tokenize.c cc -std=c11 -g -fno-common -Wall -Wno-switch -c -o type.o type.c cc -std=c11 -g -fno-common -Wall -Wno-switch -c -o unicode.o unicode.c cc -std=c11 -g -fno-common -Wall -Wno-switch -o chibicc codegen.o hashmap.o main.o parse.o preprocess.o strings.o tokenize.o type.o unicode.o root@6ae32a5ffcde:/par/chibicc-main# cd ..

后面的步骤和tcc一样

root@6ae32a5ffcde:/par# /par/chibicc-main/chibicc -shared -fPIC -o libsudoku_c4.so dlxdll.c ld: warning: /tmp/chibicc-RZBje2: missing .note.GNU-stack section implies executable stack ld: NOTE: This behaviour is deprecated and will be removed in a future version of the linker root@6ae32a5ffcde:/par# ./duckdb155 DuckDB v1.5.5 (Variegata) Enter ".help" for usage hints. memory D force install luajit from community; memory D load luajit; memory D SELECT * FROM luajit_module(mode := 'compile', sql_name := 'sudoku_c', source := ' return function(p) local ffi = require("ffi") ffi.cdef[[ int sudoku_solve(const char *p, char *out); ]] local lib = ffi.load("/par/libsudoku_c4.so") local buf = ffi.new("char[82]") local rc = lib.sudoku_solve(p, buf) if rc ~= 1 then return NULL end return ffi.string(buf) end '); ┌─────────┬─────────┬─────────┬─────────┬─────────┬──────────┐ │ ok │ mode │ phase │ message │ detail │ sql_name │ │ boolean │ varchar │ varchar │ varchar │ varchar │ varchar │ ├─────────┼─────────┼─────────┼─────────┼─────────┼──────────┤ │ true │ compile │ compile │ OK │ │ sudoku_c │ └─────────┴─────────┴─────────┴─────────┴─────────┴──────────┘ memory D SELECT luajit_s('sudoku_c', '000001002000020030004500600007600050080090006100005800001004000070900003400030020'); ┌───────────────────────────────────────────────────────────────────────────────────────────────────────────┐ │ luajit_s('sudoku_c', '000001002000020030004500600007600050080090006100005800001004000070900003400030020') │ │ varchar │ ├───────────────────────────────────────────────────────────────────────────────────────────────────────────┤ │ 359461782716829534824573619947682351583197246162345897631254978275918463498736125 │ └───────────────────────────────────────────────────────────────────────────────────────────────────────────┘ memory D .timer on memory D SELECT max(luajit_s('sudoku_c', column0)) from (from read_csv('sudoku17.txt',header=0) limit 100); ┌───────────────────────────────────────────────────────────────────────────────────┐ │ max(luajit_s('sudoku_c', column0)) │ │ varchar │ ├───────────────────────────────────────────────────────────────────────────────────┤ │ 978654213645231798213879654796518432521347986384926175437182569159463827862795341 │ └───────────────────────────────────────────────────────────────────────────────────┘ Run Time (s): real 0.065 user 0.026620 sys 0.029178 memory D SELECT max(luajit_s('sudoku_c', column0)) from (from read_csv('sudoku17.txt',header=0) limit 1000); ┌───────────────────────────────────────────────────────────────────────────────────┐ │ max(luajit_s('sudoku_c', column0)) │ │ varchar │ ├───────────────────────────────────────────────────────────────────────────────────┤ │ 987563214124987653356412987671398542295174836843256179439825761562731498718649325 │ └───────────────────────────────────────────────────────────────────────────────────┘ Run Time (s): real 0.140 user 0.125244 sys 0.003991 memory D SELECT max(luajit_s('sudoku_c', column0)) from (from read_csv('sudoku17.txt',header=0) limit 10000); ┌───────────────────────────────────────────────────────────────────────────────────┐ │ max(luajit_s('sudoku_c', column0)) │ │ varchar │ ├───────────────────────────────────────────────────────────────────────────────────┤ │ 987652431164739582253481796375824619842916357619375824728163945431597268596248173 │ └───────────────────────────────────────────────────────────────────────────────────┘ Run Time (s): real 1.157 user 2.327257 sys 0.011661

chibicc编译出来的动态库比tcc编译的动态库执行速度慢一些,使用意义不大。
上述2种编译器都没有优化,再改用gcc -O3优化编译

memory D .system bash root@6ae32a5ffcde:/par# gcc -shared -fPIC -o libsudoku_c5.so dlxdll.c -O3 root@6ae32a5ffcde:/par# exit exit memory D SELECT * FROM luajit_module(mode := 'compile', sql_name := 'sudoku_c', source := ' return function(p) local ffi = require("ffi") ffi.cdef[[ int sudoku_solve(const char *p, char *out); ]] local lib = ffi.load("/par/libsudoku_c5.so") local buf = ffi.new("char[82]") local rc = lib.sudoku_solve(p, buf) if rc ~= 1 then return NULL end return ffi.string(buf) end '); ┌─────────┬─────────┬─────────┬─────────┬─────────┬──────────┐ │ ok │ mode │ phase │ message │ detail │ sql_name │ │ boolean │ varchar │ varchar │ varchar │ varchar │ varchar │ ├─────────┼─────────┼─────────┼─────────┼─────────┼──────────┤ │ true │ compile │ compile │ OK │ │ sudoku_c │ └─────────┴─────────┴─────────┴─────────┴─────────┴──────────┘ Run Time (s): real 0.008 user 0.010392 sys 0.000509 memory D SELECT max(luajit_s('sudoku_c', column0)) from (from read_csv('sudoku17.txt',header=0) limit 10000); ┌───────────────────────────────────────────────────────────────────────────────────┐ │ max(luajit_s('sudoku_c', column0)) │ │ varchar │ ├───────────────────────────────────────────────────────────────────────────────────┤ │ 987652431164739582253481796375824619842916357619375824728163945431597268596248173 │ └───────────────────────────────────────────────────────────────────────────────────┘ Run Time (s): real 0.458 user 0.438527 sys 0.001587

和tcc的结果没有明显差距。瓶颈好像不在动态库这边。

http://www.jsqmd.com/news/1405919/

相关文章:

  • 2026佛山房屋漏水维修避坑指南|正规修缮与乱象对比,少花冤枉钱 - 筑宅安
  • 亲测 APK Installer:不用模拟器在 Windows 上跑安卓应用的完整避坑笔记
  • 零信任架构实战:基于天远人企关联构建自动化准入审查网关
  • Flowframes完整实战指南:免费视频插帧工具如何把30fps视频流畅升级到120fps
  • 2026318川藏线攻略大全|从选车队到行程安排全覆盖 - 老金2026
  • 再论勾股定理成立的条件-8
  • 2026合肥房屋漏水维修避坑指南|正规修缮与乱象对比,少花冤枉钱 - 筑宅安
  • 为什么扫码必须 HTTPS?@zxing/ngx-scanner 生产环境部署安全指南
  • 天道 十九集
  • 2026哈尔滨房屋漏水维修避坑指南|正规修缮与乱象对比,少花冤枉钱 - 筑宅安
  • AI 时代的微前端开发:esmx validate 与 llms.md 驱动的 Agent 工作流
  • 华硕笔记本散热终极指南:G-Helper 完整上手与深度调优教程
  • 开源SCADA系统Scada-LTS实战:30分钟从零搭建你的工业监控平台
  • Revit模型转GLTF能有多快?Revit2GLTF 10分钟上手全记录
  • 理工科论文AI痕迹怎么消?2026年五款工具实测打分
  • Elasticsearch 学习笔记:从零到实战(Docker 部署 + Spring Boot 集成) - PC2005
  • 2026年内蒙古做智慧燃气安全监管平台的公司有哪些?
  • 网易智企两项大模型安全能力入选金融业人工智能安全工具首批权威目录
  • arXiv AI 论文日报 — 2026-08-15
  • 如何二次开发TYZRNEditor:扩展富文本功能与工具栏的完整指南
  • 台州热门轻食糕点培训机构|港焙学校真实测评 - 港焙西点-知美人美学
  • URP Blit Render Feature 兼容性路线图:从 Unity 2019 到 6.3 的分支选择与升级指南
  • 318川藏线跟车队费用多少钱?2026市场实价+隐形消费拆解 - 老金2026
  • WVP-PRO 实战指南:三步搭起基于 GB28181 的一体化视频监控平台
  • IRISMAN 体验记:一台吃灰多年的 PS3,是怎么被这款备份管理器救活的
  • PinView密码隐藏功能详解:setPasswordHidden与星号明文切换
  • DeepSeek‑Harness Windows 本地快速上手
  • 微信聊天记录如何永久保存?1 个免费工具,3 步导出 HTML、Word、CSV
  • OntoL产品设计思路—大模型是旁白,本体才是主角 - 北方的银狐
  • 机翻把我的排版全毁了?tri-translate 的跨格式等价救回来