资讯动态

FrameworkBenchmarks 中的 IHP 基准测试实现:基于 Haskell 全栈框架的六项性能测试解析

发布时间:2026/10/15 3:24:48 来源:尧图企业网站定制
性能测试测试后端开发者工具【免费下载链接】FrameworkBenchmarksSource for the TechEmpower Framework Benchmarks project项目地址https://gitcode.com/gh_mirrors/fr/FrameworkBenchmarks点击查看免费下载本篇技术指南以 frameworks/Haskell/ihp/README.md 为纲结合仓库内 IHP 应用的源码、配置与构建脚本系统讲解 TechEmpower FrameworkBenchmarks 中 IHP 基准测试的实现方式六个测试端点的路由、控制器逻辑、数据库模型、视图渲染与性能调优参数以及本地验证这些端点的方法。读完本文你将能独立定位 IHP 基准实现的每一处代码理解queries参数边界规则与数据库连接池等关键配置的底层作用。一、IHP 基准测试概览IHPIntegrated Haskell Platform是一个面向生产环境的 Haskell 全栈 Web 框架。在 FrameworkBenchmarks 仓库中它的基准实现位于 frameworks/Haskell/ihp其定位由 config.toml 与 benchmark_config.json 共同声明ApproachRealistic贴近真实生产场景ClassificationFullstack全栈框架DatabasepostgresORMFull使用完整的 ORM 能力Platform / WebserverWai基于 WAI 接口与 Warp 服务器LanguageHaskellconfig.toml中同时登记了六个测试端点的 URL 映射这是基准测试工具定位路由的依据[main] urls.plaintext /plaintext urls.json /json urls.db /db urls.query /query?queries urls.update /update?queries urls.fortune /fortunes二、六项测试的实现源码位置根据 frameworks/Haskell/ihp/README.md 的指引所有测试逻辑集中在一个控制器文件 src/Web/Controller/FrameworkBenchmarks.hs 中各测试类型的实现位置如下测试类型源码位置行号对应 ActionJSONFrameworkBenchmarks.hs#L15JsonActionDBFrameworkBenchmarks.hs#L18DbActionQUERYFrameworkBenchmarks.hs#L23QueryActionFORTUNESFrameworkBenchmarks.hs#L32FortuneActionUPDATEFrameworkBenchmarks.hs#L39UpdatesActionPLAINTEXTFrameworkBenchmarks.hs#L52PlaintextAction控制器数据类型FrameworkBenchmarksController定义在 src/Web/Types.hs六个构造子与上表一一对应data FrameworkBenchmarksController JsonAction | PlaintextAction | DbAction | QueryAction | FortuneAction | UpdatesAction deriving (Eq, Show, Data)三、测试 URL 与路由映射README 列出了六项测试的完整访问地址基准容器监听 8080 端口测试URLJSONhttp://localhost:8080/jsonPLAINTEXThttp://localhost:8080/plaintextDBhttp://localhost:8080/dbQUERYhttp://localhost:8080/query?queriesUPDATEhttp://localhost:8080/update?queriesFORTUNEShttp://localhost:8080/fortunes这些路径的路由规则定义在 src/Web/Routes.hs通过 IHP 的parseRoute组合子完成字符串匹配与 action 的绑定instance CanRoute FrameworkBenchmarksController where parseRoute (string /json * endOfInput pure JsonAction) | (string /plaintext * endOfInput pure PlaintextAction) | (string /db * endOfInput pure DbAction) | (string /fortunes * endOfInput pure FortuneAction) | (string /query * endOfInput pure QueryAction) | (string /update * endOfInput pure UpdatesAction)注意endOfInput的存在意味着路径必须精确匹配/json/这类带尾斜杠的请求不会被匹配。路由解析后由 src/Web/FrontController.hs 挂载到应用前端控制器最终由 src/Main.hs 中的main IHP.Server.run config启动服务。四、数据库模型World 与 Fortune所有涉及数据库的测试DB、QUERY、UPDATE、FORTUNES都基于两张表其定义见 src/Application/Schema.sqlCREATE EXTENSION IF NOT EXISTS uuid-ossp; CREATE TABLE World ( id SERIAL PRIMARY KEY NOT NULL, randomnumber INT DEFAULT 0 NOT NULL ); CREATE TABLE Fortune ( id SERIAL PRIMARY KEY NOT NULL, message TEXT NOT NULL );World表对应id与randomnumber两个字段用于 DB / QUERY / UPDATE 测试Fortune表对应id与message用于 FORTUNES 测试。在控制器中这两个模型直接由 IHP 的 ORM 生成类型Generated.Types提供并通过自定义ToJSON实例控制 JSON 输出的字段名。注意randomnumber字段在 JSON 中被映射为驼峰式randomNumber见 FrameworkBenchmarks.hs#L8-L9instance ToJSON World where toJSON world object [(id . get #id world), (randomNumber . get #randomnumber world)]五、六个测试端点的实现详解5.1 JSON返回固定 JSON 消息实现于 FrameworkBenchmarks.hs#L15-L16。这是最轻量的测试不访问数据库直接通过renderJson输出action JsonAction do renderJson (toJSON (object [message . (Hello, World! :: Text)]))5.2 PLAINTEXT返回纯文本实现于 FrameworkBenchmarks.hs#L58-L59同样不访问数据库action PlaintextAction do renderPlain Hello, World!5.3 DB单条世界记录查询实现于 FrameworkBenchmarks.hs#L18-L21。逻辑为生成1..10000范围内的随机 id再按主键查询World记录并返回 JSONaction DbAction do randomNumber :: Int - randomRIO (1, 10000) randomWorld - query World | findBy #id (Id randomNumber) renderJson (toJSON randomWorld)这里使用了 IHP 的query World | findBy #id查询链即按id字段精确查找的 ORM 操作。5.4 QUERY多次随机查询支持 queries 参数实现于 FrameworkBenchmarks.hs#L23-L33。核心逻辑读取queries查询参数通过defaultParam容错参数缺失或非法时回退为1用toBoundaries将数量钳制到[1, 500]区间使用Async.mapConcurrently并发执行 N 次随机记录查询最后一次性renderJson返回结果数组。action QueryAction do let queries defaultParam (paramOrError Int queries) | toBoundaries let fetchRandomWorld i do randomWorldId :: Id World - Id $ randomRIO (1, 10000) fetch randomWorldId [1..queries] | Async.mapConcurrently fetchRandomWorld renderJson where defaultParam (Right a) a defaultParam _ 1边界钳制函数toBoundaries定义在文件末尾L61-L64这是基准测试对queries参数的强制约束toBoundaries n | n 1 1 | n 500 500 | otherwise n5.5 UPDATE读取并更新随机记录实现于 FrameworkBenchmarks.hs#L42-L56。与 QUERY 结构对称同样解析并钳制queries参数、同样用Async.mapConcurrently并发执行不同之处在于每次操作包含「取随机 id → 取记录 → 生成新的随机数 → 更新randomnumber字段 → 写回数据库」五步action UpdatesAction do let queries :: Int (defaultParam $ paramOrError Int queries ) | toBoundaries let updateRandomWorld i do randomWorldId :: Id World - Id $ randomRIO (1, 10000) newRandom :: Int - randomRIO (1, 10000) world - fetch randomWorldId world | set #randomnumber newRandom | updateRecord [1..queries] | Async.mapConcurrently updateRandomWorld renderJson where defaultParam (Right a) a defaultParam _ 1其中set #randomnumber newRandom | updateRecord是 IHP 的 ORM 更新链式写法先修改字段再调用updateRecord持久化。5.6 FORTUNES数据排序与 HSX 模板渲染实现于 FrameworkBenchmarks.hs#L35-L40是唯一需要完整页面渲染的测试取出全部Fortune记录新建一条消息为Additional fortune added at request time.的记录按message字段对合并后的列表排序通过renderHtml交给 HSX 视图渲染并响应。action FortuneAction do allFortunes :: [Fortune] - query Fortune | fetch let newFortune :: Fortune newRecord Fortune | set #message Additional fortune added at request time. let compareFortunes :: Fortune - Fortune - Ordering \f1 f2 - compare (get #message f1) (get #message f2) let fortunes :: [Fortune] sortBy compareFortunes (newFortune:allFortunes) renderHtml FortuneView { .. } respondHtmlHTML 模板定义在 src/Web/View/FrameworkBenchmarks/Fortune.hs使用 IHP 的 HSX 内嵌 HTML 语法生成符合规范的表格页面并通过preEscapedToHtml声明!DOCTYPE htmlinstance View FortuneView where beforeRender _ setLayout \v - v html FortuneView { .. } preEscapedToHtml (!DOCTYPE html :: Text) [hsx| html headtitleFortunes/title/head body table tr thid/th thmessage/th /tr {forEach fortunes renderFortunes} /table /body /html |]注意beforeRender中使用了setLayout \v - v恒等布局即绕过 src/Web/View/Layout.hs 中默认的defaultLayout页面壳直接输出最小化的测试页面避免额外 HTML 开销。六、运行配置与性能调优6.1 应用级配置src/Config/Config.hs 定义了应用启动参数其中有两项直接影响基准性能config :: ConfigBuilder config do option Production option (AppHostname localhost) option (RequestLoggerMiddleware $ \application - application) option (DBPoolIdleTime 10) option (DBPoolMaxConnections 512)Production强制生产模式与开发模式相比会加载/prod.css、/prod.js等精简资源见 Layout.hsDBPoolMaxConnections 512将数据库连接池上限抬升到 512支撑 QUERY / UPDATE 测试中的高并发查询并发由Async.mapConcurrently发起DBPoolIdleTime 10空闲连接回收时间秒。6.2 Docker 构建与启动参数ihp.dockerfile 采用 Nix 方式构建基于nixos/nix镜像、使用cachix use digitallyinduced获取 IHP 缓存并通过 flake 构建optimized-prod-server产物。关键运行时配置ENV DATABASE_URLpostgres://benchmarkdbuser:benchmarkdbpasstfb-database:5432/hello_world ENV PORT8080 EXPOSE 8080 CMD ./result/bin/RunProdServer RTS -A32m -N$(nproc) -qn2 -M2G -RTSDATABASE_URL连接基准环境的 PostgreSQL库名hello_world账号benchmarkdbuserPORT8080服务监听端口与 README 中的测试 URL 一致GHC RTS 参数-A32m扩大分配区减少 GC 次数、-N$(nproc)启用多核并行、-qn2限制并行 GC 线程、-M2G堆上限 2GB。6.3 Nix flake 依赖锁定flake.nix 将 IHP 版本锁定为v1.3.1并显式声明wai、text、cabal-install等构建依赖。nixpkgs-config.nix则通过make-nixpkgs-from-options.nix集成额外的 Haskell 包来源保证构建可复现。七、本地验证测试端点按 README 提供的 URL可以在构建并启动基准容器后逐一验证各测试端点# JSON 测试 curl http://localhost:8080/json # 期望输出: {message:Hello, World!} # PLAINTEXT 测试 curl http://localhost:8080/plaintext # 期望输出: Hello, World! # DB 测试 curl http://localhost:8080/db # 期望输出: {id:随机id,randomNumber:随机数} # QUERY 测试queries 指定查询条数 curl http://localhost:8080/query?queries10 # 期望输出: 10 条 World 记录的 JSON 数组 # UPDATE 测试queries 指定更新条数 curl http://localhost:8080/update?queries10 # 期望输出: 10 条更新后 World 记录的 JSON 数组 # FORTUNES 测试 curl http://localhost:8080/fortunes # 期望输出: 按 message 排序的完整 HTML 表格含追加的 fortune验证时可结合queries参数的边界规则传queries0或负数会被钳制为 1传超过 500 的值会被钳制为 500对应 FrameworkBenchmarks.hs#L61-L64 的toBoundaries缺省时回退为 1。八、实现要点总结综合 README 与源码可以归纳 IHP 基准实现的关键设计单一控制器承载全部测试六个 action 集中在 FrameworkBenchmarks.hs便于基准工具按行号定位实现queries参数三段式处理defaultParam容错回退 →paramOrError Int解析 →toBoundaries钳制[1, 500]QUERY 与 UPDATE 共用这套规则并发查询依赖库级能力借助Control.Concurrent.Async的mapConcurrently实现并行数据库访问配合 512 连接上限的连接池Config.hs支撑高并发负载FORTUNES 走完整渲染链路查询 → 追加记录 →sortBy排序 → HSX 模板输出且以恒等布局剥离多余页面壳保持输出与基准规范一致构建与运行链路清晰flake 锁定 IHP v1.3.1Dockerfile 以 Nix 产物RunProdServer启动数据库连接与端口通过环境变量注入。以上内容全部可从 frameworks/Haskell/ihp 目录下的 README、源码与配置文件中直接验证读者可按需深入各文件继续研究。赞分享性能测试测试后端开发者工具【免费下载链接】FrameworkBenchmarksSource for the TechEmpower Framework Benchmarks project项目地址https://gitcode.com/gh_mirrors/fr/FrameworkBenchmarks点击查看免费下载相关推荐FrameworkBenchmarks 中的 GojiGo基准测试基于极简 Web 框架的六项 TFB 测试实现解析FrameworkBenchmarks 中的 GojiGo基准测试基于极简 Web 框架的六项 TFB 测试实现解析 导读 本文以 FrameworkBe性能测试测试后端开发者工具FrameworkBenchmarks 中的 Hertz 基准测试Go 微服务框架的 TechEmpower 全栈实现解析FrameworkBenchmarks 中的 Hertz 基准测试Go 微服务框架的 TechEmpower 全栈实现解析 本文围绕 FrameworkBen性能测试测试后端开发者工具Luminus 框架在 TechEmpower FrameworkBenchmarks 中的基准测试实现全解析Luminus 框架在 TechEmpower FrameworkBenchmarks 中的基准测试实现全解析 Luminus 是 Clojure 社区主流的全性能测试测试后端开发者工具上一篇3分钟解决Windows无法预览iPhone照片的终极方案下一篇网盘直链下载助手完整教程告别限速困扰一键获取真实下载链接创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑