JMH 基准测试实战:Java 性能对比的正确打开方式!
📖 摘要
在Java开发中,我们经常需要比较不同实现方式的性能差异。但如何科学、准确地进行性能测试呢?本文将带你深入理解JMH(Java Microbenchmark Harness)工具,通过实战演示如何正确编写和运行基准测试,避免常见的性能测试陷阱,让你的性能对比结果真实可靠!
📚 目录
- 为什么需要JMH?
- JMH基础概念
- 环境准备
- 第一个JMH基准测试
- 常用注解详解
- 避免性能测试陷阱
- 实战案例:字符串拼接性能对比
- 高级特性
- 总结
🤔 为什么需要JMH?
在日常开发中,我们经常会遇到这样的场景:
long start = System.currentTimeMillis();
// 测试代码
long end = System.currentTimeMillis();
System.out.println("耗时:" + (end - start) + "ms");
这种简单粗暴的性能测试方式存在很多问题:
- JVM预热问题:JVM需要时间"热身",初始执行的代码通常比后续执行慢
- 编译器优化:JIT编译器可能会优化掉"无用"代码
- 统计误差:单次测试结果不具有代表性
- 环境干扰:GC、CPU调度等都会影响结果
JMH是OpenJDK团队开发的专门用于Java微基准测试的工具,它能解决上述所有问题,提供科学、准确的性能测试结果。
📖 JMH基础概念
JMH中有几个核心概念需要理解:
- @Benchmark:标记要测试的方法
- Mode:测试模式,如吞吐量(Throughput)、平均时间(AverageTime)等
- Warmup:预热阶段,让JVM达到稳定状态
- Measurement:实际测量阶段
- Fork:在独立的JVM进程中运行测试,避免相互干扰
- State:测试状态,可用于共享数据
🛠️ 环境准备
1. 添加JMH依赖
使用Maven项目,添加以下依赖:
org.openjdk.jmhjmh-core1.36org.openjdk.jmhjmh-generator-annprocess1.36provided
2. IDE插件(可选)
IntelliJ IDEA有JMH插件,可以方便地运行单个基准测试方法。
🚀 第一个JMH基准测试
让我们从一个最简单的例子开始:
import org.openjdk.jmh.annotations.*;
import java.util.concurrent.TimeUnit;@BenchmarkMode(Mode.AverageTime) // 测试平均执行时间
@OutputTimeUnit(TimeUnit.NANOSECONDS) // 输出结果的时间单位
@Warmup(iterations = 3, time = 1, timeUnit = TimeUnit.SECONDS) // 预热3轮,每轮1秒
@Measurement(iterations = 5, time = 1, timeUnit = TimeUnit.SECONDS) // 测试5轮,每轮1秒
@Fork(1) // 使用1个进程
@State(Scope.Thread) // 每个测试线程一个实例
public class FirstBenchmark {@Benchmarkpublic void testMethod() {// 这里是被测试的方法int a = 1;int b = 2;int sum = a + b;// 防止被JIT优化掉if (sum != 3) {throw new AssertionError();}}public static void main(String[] args) throws Exception {org.openjdk.jmh.Main.main(args);}
}
运行这个基准测试,你会看到类似如下的输出:
Benchmark Mode Cnt Score Error Units
FirstBenchmark.testMethod avgt 5 0.321 ± 0.012 ns/op
这表示我们的测试方法平均每次执行耗时0.321纳秒。
🏷️ 常用注解详解
JMH提供了丰富的注解来配置基准测试,下面介绍最常用的几个:
1. @BenchmarkMode
定义测试模式,可选值:
Throughput
:吞吐量,单位时间内的操作数AverageTime
:平均时间,每次操作耗时SampleTime
:采样时间SingleShotTime
:单次执行时间All
:所有模式
@BenchmarkMode({Mode.Throughput, Mode.AverageTime})
2. @Warmup
配置预热参数:
iterations
:预热轮数time
:每轮时间timeUnit
:时间单位
@Warmup(iterations = 3, time = 100, timeUnit = TimeUnit.MILLISECONDS)
3. @Measurement
配置实际测量参数:
iterations
:测量轮数time
:每轮时间timeUnit
:时间单位
@Measurement(iterations = 5, time = 100, timeUnit = TimeUnit.MILLISECONDS)
4. @Fork
指定fork的进程数,避免测试间相互干扰:
@Fork(2) // 使用2个独立进程
5. @State
定义状态对象,用于在不同测试方法间共享数据:
@State(Scope.Thread) // 每个线程一个实例
public class MyState {public int a = 1;public int b = 2;
}@Benchmark
public void testMethod(MyState state) {int sum = state.a + state.b;
}
⚠️ 避免性能测试陷阱
1. 死代码消除(Dead Code Elimination)
JIT编译器会优化掉没有实际效果的代码。例如:
@Benchmark
public void wrongTest() {Math.log(1.0); // 结果没有被使用,会被优化掉
}
正确做法是返回计算结果或使用Blackhole
:
@Benchmark
public double correctTest() {return Math.log(1.0);
}// 或者
@Benchmark
public void correctTest2(Blackhole blackhole) {blackhole.consume(Math.log(1.0));
}
2. 常量折叠(Constant Folding)
JIT会预先计算常量表达式:
@Benchmark
public int wrongTest() {return 1 + 2; // 会被优化为return 3
}
使用@State
注入变量:
@State(Scope.Thread)
public class MyState {public int a = 1;public int b = 2;
}@Benchmark
public int correctTest(MyState state) {return state.a + state.b;
}
3. 循环展开(Loop Unrolling)
JMH会自动处理循环问题,不要手动写循环:
// 错误做法
@Benchmark
public void wrongTest() {for (int i = 0; i < 10000; i++) {// 测试代码}
}// 正确做法
@Benchmark
public void correctTest() {// 单次操作的代码
}
JMH会自动控制迭代次数来获得准确的测量结果。
🎯 实战案例:字符串拼接性能对比
让我们通过一个实际案例来比较不同字符串拼接方式的性能差异:
import org.openjdk.jmh.annotations.*;
import java.util.concurrent.TimeUnit;@BenchmarkMode(Mode.Throughput)
@OutputTimeUnit(TimeUnit.MILLISECONDS)
@Warmup(iterations = 3, time = 1, timeUnit = TimeUnit.SECONDS)
@Measurement(iterations = 5, time = 1, timeUnit = TimeUnit.SECONDS)
@Fork(1)
@State(Scope.Thread)
public class StringConcatBenchmark {private String str1 = "Hello";private String str2 = "World";private String str3 = "JMH";private String str4 = "Benchmark";@Benchmarkpublic String concatWithPlus() {return str1 + str2 + str3 + str4;}@Benchmarkpublic String concatWithStringBuilder() {StringBuilder sb = new StringBuilder();sb.append(str1);sb.append(str2);sb.append(str3);sb.append(str4);return sb.toString();}@Benchmarkpublic String concatWithStringBuffer() {StringBuffer sb = new StringBuffer();sb.append(str1);sb.append(str2);sb.append(str3);sb.append(str4);return sb.toString();}@Benchmarkpublic String concatWithStringFormat() {return String.format("%s%s%s%s", str1, str2, str3, str4);}
}
运行结果可能如下:
Benchmark Mode Cnt Score Error Units
StringConcatBenchmark.concatWithPlus thrpt 5 12345.678 ± 234.567 ops/ms
StringConcatBenchmark.concatWithStringBuilder thrpt 5 23456.789 ± 345.678 ops/ms
StringConcatBenchmark.concatWithStringBuffer thrpt 5 12345.678 ± 123.456 ops/ms
StringConcatBenchmark.concatWithStringFormat thrpt 5 1234.567 ± 45.678 ops/ms
从结果可以看出:
StringBuilder
性能最好+
操作符在现代Java版本中会被优化为StringBuilder
,性能也不错StringBuffer
由于同步开销,性能稍差String.format
性能最差
🚀 高级特性
1. 参数化基准测试
使用@Param
注解可以测试不同参数下的性能:
@State(Scope.Thread)
public class ParamBenchmark {@Param({"10", "100", "1000"})public int length;private String str;@Setuppublic void setup() {str = new String(new char[length]).replace('\0', 'x');}@Benchmarkpublic String testToUpperCase() {return str.toUpperCase();}
}
2. 分组测试
可以分组比较不同实现:
@Benchmark
@Group("stringCompare")
public boolean compareWithEquals() {return str1.equals(str2);
}@Benchmark
@Group("stringCompare")
public boolean compareWithEqualsIgnoreCase() {return str1.equalsIgnoreCase(str2);
}
3. 时间控制
精确控制测试时间:
@Benchmark
@BenchmarkMode(Mode.SingleShotTime)
@Measurement(batchSize = 10000) // 每轮执行10000次
public void testMethod() {// ...
}
📌 总结
- JMH是Java微基准测试的事实标准工具,能提供科学准确的性能数据
- 基准测试需要考虑JVM预热、编译器优化等多种因素
- 使用
@State
管理测试状态,避免常量折叠等问题 - 使用
Blackhole
防止死代码消除 - 不要手动写循环,JMH会自动处理迭代
- 实际项目中,应该针对关键路径进行基准测试
- 测试结果要结合具体场景分析,没有绝对的"最优"
通过本文的学习,你应该已经掌握了JMH的基本用法和核心概念。在实际项目中,合理使用JMH可以帮助你做出更科学的性能优化决策,避免过早优化和错误优化。
记住:基准测试只是工具,真正的性能优化应该基于实际业务场景和性能分析!
🔔 最后提醒:性能优化应该遵循"三原则":
- 先测量,再优化
- 优化关键路径
- 保持代码可读性
Happy benchmarking! 🎉
推荐阅读文章
-
由 Spring 静态注入引发的一个线上T0级别事故(真的以后得避坑)
-
如何理解 HTTP 是无状态的,以及它与 Cookie 和 Session 之间的联系
-
HTTP、HTTPS、Cookie 和 Session 之间的关系
-
什么是 Cookie?简单介绍与使用方法
-
什么是 Session?如何应用?
-
使用 Spring 框架构建 MVC 应用程序:初学者教程
-
有缺陷的 Java 代码:Java 开发人员最常犯的 10 大错误
-
如何理解应用 Java 多线程与并发编程?
-
把握Java泛型的艺术:协变、逆变与不可变性一网打尽
-
Java Spring 中常用的 @PostConstruct 注解使用总结
-
如何理解线程安全这个概念?
-
理解 Java 桥接方法
-
Spring 整合嵌入式 Tomcat 容器
-
Tomcat 如何加载 SpringMVC 组件
-
“在什么情况下类需要实现 Serializable,什么情况下又不需要(一)?”
-
“避免序列化灾难:掌握实现 Serializable 的真相!(二)”
-
如何自定义一个自己的 Spring Boot Starter 组件(从入门到实践)
-
解密 Redis:如何通过 IO 多路复用征服高并发挑战!
-
线程 vs 虚拟线程:深入理解及区别
-
深度解读 JDK 8、JDK 11、JDK 17 和 JDK 21 的区别
-
10大程序员提升代码优雅度的必杀技,瞬间让你成为团队宠儿!
-
“打破重复代码的魔咒:使用 Function 接口在 Java 8 中实现优雅重构!”
-
Java 中消除 If-else 技巧总结
-
线程池的核心参数配置(仅供参考)
-
【人工智能】聊聊Transformer,深度学习的一股清流(13)
-
Java 枚举的几个常用技巧,你可以试着用用
-
由 Spring 静态注入引发的一个线上T0级别事故(真的以后得避坑)
-
如何理解 HTTP 是无状态的,以及它与 Cookie 和 Session 之间的联系
-
HTTP、HTTPS、Cookie 和 Session 之间的关系
-
使用 Spring 框架构建 MVC 应用程序:初学者教程
-
有缺陷的 Java 代码:Java 开发人员最常犯的 10 大错误
-
Java Spring 中常用的 @PostConstruct 注解使用总结
-
线程 vs 虚拟线程:深入理解及区别
-
深度解读 JDK 8、JDK 11、JDK 17 和 JDK 21 的区别
-
10大程序员提升代码优雅度的必杀技,瞬间让你成为团队宠儿!
-
探索 Lombok 的 @Builder 和 @SuperBuilder:避坑指南(一)
-
为什么用了 @Builder 反而报错?深入理解 Lombok 的“暗坑”与解决方案(二)
相关文章:
JMH 基准测试实战:Java 性能对比的正确打开方式!
📖 摘要 在Java开发中,我们经常需要比较不同实现方式的性能差异。但如何科学、准确地进行性能测试呢?本文将带你深入理解JMH(Java Microbenchmark Harness)工具,通过实战演示如何正确编写和运行基准测试&a…...
etf可以T+0交易吗?
在我国的A股市场中,部分ETF基金支持T0交易,这为投资者提供了更灵活的交易策略。 支持T0交易的ETF基金类型包括: 货币型ETF:主要投资于货币市场工具,如短期债券和银行存款,具有较高的流动性。 债券型ETF&…...
解决问题:Vscode 自动更新不匹配远程服务器版本
避免自动更新: 1. 打开:文件 - 首选项 - 设置 - 应用程序 - 更新; 2. 设置下列选项: 如果已自动更新,如何回退至原有的历史版本 : 去官网下载所需的历史版本,然后直接按流程安装,…...
【Leetcode-Hot100】盛最多水的容器
题目 解答 目的是求面积最大,面积是由两个下标和对应的最小值得到,因此唯一的问题就是如何遍历这两个下标。我采用begin和end两个变量,确保begin是小于end的,使用它们二者求面积,代码如下: 很不幸 出错了…...
FFMEPG常见命令查询
基本参数 表格1:主要参数 参数说明-i设定输入流-f设定输出格式(format) 高于后缀名-ss开始时间-t时间长度codec编解码 表格2:音频参数 参数说明-aframes设置要输出的音频帧数-f音频帧深度-b:a音频码率-ar设定采样率-ac设定声音的Channel数-acodec设定…...
欢迎来到 Codigger Store:Boby周边专区
亲爱的 Codigger 用户们,感谢你们一直以来的支持与热爱!你们的每一次代码跳跃、每一次项目成功,都离不开你们对编程的热情和对 Codigger 的信任。为了回馈大家的厚爱,我们在 Codigger Store 中特别开设了 Boby 周边专区࿰…...
决策树模型
决策树(TDS) 注意1:决策树有很多种算法,比如:ID3算法,C4.5算法,CART算法,这三个算法的区别是选择最优划分属性的方法不同,第一个是根据信息增益来选;第二个是找出信息增益高于平均水…...
解锁深度学习激活函数
在深度学习的广袤天地里,激活函数宛如隐匿于神经网络架构中的神奇密码,掌控着模型学习与表达的关键力量。今天,就让我们一同深入探究这些激活函数的奇妙世界,揭开它们神秘的面纱。 一、激活函数为何不可或缺? 想象一…...
Kubernetes 深入浅出系列 | 容器剖析之容器安全
目录 1、容器真的需要privileged权限吗?一、什么是 --privileged 权限?二、privileged 的风险到底有多大?三、常见需求场景及更安全的替代方式四、如何判断容器是否真正需要特权? 2、不以 Root 用户运行容器,真的更安全吗&#x…...
Spring Boot应用中可能出现的Full GC问题
Full GC的原理与触发条件 原理 标记-清除:首先遍历所有对象,标记可达的对象,然后清除不可达的对象。复制算法:将内存分为两部分,每次只使用其中一部分。当这部分内存用完时,将存活的对象复制到另一部分&a…...
Maven 的安装与配置(IDEA)
2025/4/9 向 一、什么是Maven Maven 是一个基于项目对象模型(Project Object Model,POM)概念的项目构建工具(所以就是一个工具),它主要用于自动化项目的构建过程,包括编译、测试、打包、部署等…...
软考中级-软件设计师 2022年下半年上午题真题解析:通关秘籍+避坑指南
📚 目录(快速跳转) 选择题(上午题)(每题1分,共75分)一、 计算机系统基础知识 🖥️💻 题目1:计算机硬件基础知识 - RISC(精简指令集计算…...
全栈开发套件Telerik DevCraft——赋能现代化应用构建
Telerik DevCraft包含一个完整的产品栈来构建您下一个Web、移动和桌面应用程序。它使用HTML和每个.NET平台的UI库,加快开发速度。Telerik DevCraft提供完整的工具箱,用于构建现代和面向未来的业务应用程序,目前提供UI for ASP.NET MVC、Kendo…...
Windows + vmware + ubuntu+docker + docker-android实现Android模拟器构建和启动
文章目录 引言编译启动过程玩下adb最后 引言 Windows vmware ubuntudockerdocker-android实现Android模拟器启动 编译启动过程 #下载docker-android git clone https://github.com/budtmo/docker-android.gitmaqiubuntu:~/docker-android$ git remote -v origin https://…...
远程团队协作效率低,如何优化
在远程工作的环境中,团队协作效率低下成为许多企业面临的一大挑战。随着全球化和技术进步,远程团队的出现成为企业的常态,但由于沟通不畅、任务管理不明确、缺乏团队凝聚力等问题,往往会影响团队的整体效率。为了优化远程团队的协…...
Oracle 19C 通过 ODBC 连接 SQL Server 数据库指南 (Red Hat 7)
前言 本指南详细说明如何在 Red Hat Enterprise Linux 7 系统上配置 Oracle 19C 通过 ODBC 连接 SQL Server 数据库。这种异构数据库连接方式称为 Oracle Heterogeneous Services,允许 Oracle 数据库直接访问非 Oracle 数据源。 系统要求 操作系统:Red Hat Enterprise Linu…...
【MYSQL从入门到精通】数据类型及建表
一些基础操作语句 1.使用客户端工具连接数据库服务器:mysql -uroot -p 2.查看所有数据库:show databases; 3.创建属于自己的数据库: create database 数据库名;create database if not exists 数据库名; 强烈建议大家在建立数据库时指定编…...
鸿蒙开发中的并发与多线程
文章目录 前言异步并发 (Promise和async/await)多线程并发并发能力选择耗时任务并发执行场景常见业务场景 常驻任务并发执行场景常见业务场景 传统共享内存并发业务长时任务并发执行场景常见业务场景 并发任务管理线程间通信同语言线程间通信(ArkTS内)线…...
ruby self
在 Ruby 中,self 是一个指向当前对象的特殊变量,它的值根据代码的上下文动态变化。理解 self 的指向是掌握 Ruby 面向对象编程的关键。以下是详细解析: 一、self 的核心规则 self 始终指向当前方法的执行者(即调用方法的对象&…...
Kotlin 学习-集合
/*** kotlin 集合* List:是一个有序列表,可通过索引(下标)访问元素。元素可以在list中出现多次、元素可重复* Set:是元素唯一的集合。一般来说 set中的元素顺序并不重要、无序集合* Map:(字典)是一组键值对。键是唯一的…...
封装方法的辨析
equals //字符串 str1.equals(str2); //list的两个实现类 list1.equals(list2); //map的两个实现类 //比较所有的键值对是否相同 map1.equals(map2); //数组(包括string类型) //比较内容是否相同 Arrays.equals(array1, array2); contains 基本都有…...
解决 IntelliJ IDEA 中 Maven 项目左侧项目视图未显示顶层目录问题的详细步骤说明
以下是解决 IntelliJ IDEA 中 Maven 项目左侧项目视图未显示顶层目录问题的详细步骤说明: 1. 切换项目视图模式 默认情况下,IDEA 的项目视图可能处于 Packages 模式,仅显示代码包结构,而非物理目录。 操作步骤: 点击…...
CMIP6数据分析与可视化、降尺度技术与气候变化的区域影响、极端气候分析
当前的CMIP6计划相较于前代模型,在空间分辨率、物理过程表达和地球系统组件耦合等方面均有显著提升。 一:气候变化研究的AI新视角 1、气候模型基础与全球气候模型(GCM) 全球气候(环流)模型的基本原理、发…...
如何精准控制大模型的推理深度
论文标题 ThinkEdit: Interpretable Weight Editing to Mitigate Overly Short Thinking in Reasoning Models 论文地址 https://arxiv.org/pdf/2503.22048 代码地址 https://github.com/Trustworthy-ML-Lab/ThinkEdit 作者背景 加州大学圣迭戈分校 动机 链式推理能显…...
1. Git 下载和安装
文章目录 Git 下载Git 安装(以windows为例)Git 使用(以windows为例) Git 下载 1.进 Git 官网 https://git-scm.com/downloads 2.选择对应的操作系统 3.选择对应的操作系统位数 Git 安装(以windows为例)…...
git回滚指定版本并操作
你可以通过以下步骤切换到第三个版本。根据你的需求,有两种主要方法: 方法 1:临时查看第三个版本(不修改当前分支) 适用于仅查看或测试旧版本,不保留后续修改: 找到第三个版本的提交哈希&#…...
FastAdmin和thinkPHP学习文档
介绍 - FastAdmin框架文档 - FastAdmin开发文档https://doc.fastadmin.net/doc目录结构 ThinkPHP5.0完全开发手册 看云ThinkPHP V5.0是一个为API开发而设计的高性能框架——是一个颠覆和重构版本,采用全新的架构思想,引入了很多的PHP新特性,…...
通过HTTP协议实现Git免密操作的解决方案
工作中会遇到这样的问题的。 通过HTTP协议实现Git免密操作的解决方案 方法一:启用全局凭据存储(推荐) 配置凭证存储 执行以下命令,让Git永久保存账号密码(首次操作后生效): git config --g…...
git 查看某一文件夹下所有文件 修改记录
git: 如何查询某个文件或者某个目录的更新历史_git 查看指定文件夹的记录-CSDN博客 git log --follow path/to/your/file git log -p --follow path/to/your/file git log --stat --follow path/to/your/file这是最常用的方法,可以显示指定文件的所有提交历史…...
测试(一)
软件的生命周期: 需求分析——计划——设计——编码——测试——运行维护 常见的开发模型: 瀑布模型: 最基本的开发模型,绝大多数开发模型的基本框架。 特点:线性的开发流程 使用场景:需求固定ÿ…...
解决华硕主板Z890m下载ubuntu20.04后没有以太网问题
问题描述: 华硕主板Z890m下载双系统ubuntu20.04后,发现ubuntu不能打开以太网。 问题原因: 华硕主板的网卡驱动是r8125,而ubuntu20.04的驱动版本是r8169,所以是网卡驱动不匹配造成 解决方案 开机界面按下F2进入BOIS模式&#…...
从零推导飞机小扰动运动线性方程——0. 学习目录
第0期文章——学习目录 如图,本专栏将连载以下学习内容,带你从零开始学习飞机小扰动方程!...
Agentic AI 干货!DeepSeek + OpenAI SDK 构建 Agent 实战
引言: DeepSeek-R1、OpenAI-o1 等具备内化的假设、反思、验证等优秀推理能力的 LLM 大型推理模型将 AI 发展推进到智能体 AI 时代,将使 AI Agent 迸发出远超上一代由外化的手搓式简单推理 Agent 不可比拟的发展势能。 在 GTC2025 大会上,英伟…...
【语法】C++的list
目录 为什么会有list? 迭代器失效: list和vector的迭代器不同的地方: list的大部分用法和vector都很像,例如push_back,构造,析构,赋值重载这些就不再废话了,本篇主要讲的是和vecto…...
Java接口性能优化面试问题集锦:高频考点与深度解析
1. 如何定位接口性能瓶颈?常用哪些工具? 考察点:性能分析工具的使用与问题定位能力。 核心答案: 工具:Arthas(在线诊断)、JProfiler(内存与CPU分析)、VisualVM、Prometh…...
基于STM32与应变片的协作机械臂力反馈控制系统设计与实现---5.2 工业机械臂系统性能测试全方案(专业工程级)
5.2 工业机械臂系统性能测试全方案(专业工程级) 一、测试体系架构设计 1.1 三级测试体系 #mermaid-svg-A55VxjZ7ENKNWAli {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-A55VxjZ7ENKNWAli .error-icon{fill:#55…...
VM——相机拍照失败
1、问题:相机频闪触发,在MVS中正常出图,在VM中出现拍照失败 2、解决: 1、首先排查网络设置(巨帧是否设置) 2、电脑的所有防火墙是否关闭 3、在MVS中恢复相机的设置参数为默认参数,删除VM中的全…...
图解力扣回溯及剪枝问题的模板应用
文章目录 选哪个的问题17. 电话号码的字母组合题目描述解题代码图解复杂度 选不选的问题78. 子集题目描述解题代码图解复杂度 两相转化77. 组合题目描述解题代码法一:按选哪个的思路法二:按选不选的思路 图解选哪个:选不选 复杂度 选哪个的问…...
Trae + LangGPT 生成结构化 Prompt
Trae LangGPT 生成结构化 Prompt 0. 引言1. 安装 Trae2. 克隆 LangGPT3. Trae 和 LangGPT 联动4. 集成到 Dify 中 0. 引言 Github 上 LangGPT 这个项目,主要向我们介绍了写结构化Prompt的一些方法和示例,我们怎么直接使用这个项目,辅助我们…...
模糊测试究竟在干什么
目录 1.软件漏洞和缺陷 2.模糊测试与传统测试 3.汽车领域中的模糊测试 4.常见工具总结 1.软件漏洞和缺陷 提单、上票、拒收,这是开发和测试的日常博弈。大多数时候,我们是根据自己对需求的理解来进行开发和测试,这基本是属于功能层级。 …...
【RTD200P04 MCAL 篇3】 S32M244 PWM PDB ADC控制
【RTD200P04 MCAL 篇3】 S32M244 PWM PDB ADC控制 一,文档简介二,PWMTRGMUXPDBADC 2ch 软件配置与实现2.1 软硬件版本平台2.2 MCAL工程以及模块配置2.2.1 Dio 模块配置2.2.2 Adc模块配置2.2.3 Mcu模块配置2.2.4 Platform模块配置2.2.5 Port模块配置2.2.6…...
03--Deepseek服务器部署与cjson解析
一、ollama部署deepseek模型 1、Ollama 是一个开源的本地大语言模型运行框架,专为在本地机器上便捷部署和运行大型语言模型(LLM)而设计。 Ollama 教程:从 0 到 1 全面指南 教程【全文两万字保姆级详细讲解】 -CSDN博客 1.下载o…...
实现抗隐私泄漏的AI人工智能推理
目录 什么是私人AI? 什么是可信执行环境? TEE 如何在 AI 推理期间保护数据? 使用 TEE 是否存在风险? 有哪些风险? Atoma 如何应对这些风险 为什么去中心化网络是解决方案 人工智能推理过程中还有其他保护隐私的方法吗? 私人人工智能可以实现什么? 隐私驱动的应…...
Kotlin 学习--数组
一、关于数组的基础知识和常用方式 /*** kotlin 数组* 使用arrayOf创建数组,必须指定数组的元素,可以是任意类型* */val arrayNumber arrayOf(1, 2, 3, 4)/*** 集合中的元素可以是任意类型* kotlin 中的Any 等价于 java 中的Object 对象的意思* */val a…...
Spring Boot 启动后自动执行 Service 方法终极指南
**导语:**在 Spring Boot 开发中,我们经常需要在应用启动后立即执行初始化任务(如加载配置、预热缓存、启动定时任务)。本文将深度解析 5 种主流实现方案,包含完整代码示例、执行顺序控制技巧和避坑指南&a…...
STM32 HAL库之GPIO示例代码
LED灯不断闪烁 GPIO初始化,main文件中的 MX_GPIO_Init(); 也就是在 gpio.c文件中 void MX_GPIO_Init(void) {GPIO_InitTypeDef GPIO_InitStruct {0};/* GPIO Ports Clock Enable */__HAL_RCC_GPIOE_CLK_ENABLE();__HAL_RCC_GPIOC_CLK_ENABLE();__HAL_RCC_GPIOA_C…...
中间件-消息队列
SpringAMQP 任何语言只要遵循AMAP协议,都可以与RabbitMQ交互 生产者、队列、交换机、消费者 生产者Publisher:生产消息,发给交换机 交换机Exchange:接收生产者发送的消息。知道如何处理消息,例如递交给某个特别队列、…...
go游戏后端开发32:自摸杠处理逻辑
当我们在自摸杠时,实际上在杠完之后,我们还需要进行一个删除操作。因此,我们需要在上面拷贝一个删除操作。由于这是自摸杠,所以这个地方需要删除四次。在这里,我们需要注意的是,自摸杠时,传过来…...
AI创业风向标:构建下一代「AI叙事创作平台」
随着技术的进步和市场需求的爆发,AI故事叙述平台正成为投资者和创业者关注的焦点。本文将探讨为何这一赛道值得关注,并提供一些关于如何构建成功的AI叙事创作平台的战略建议。 一、为什么这是2025年值得关注的赛道? 1. 底层需求的爆发 人类永恒的故事需求:全球每月有超过…...
拜特科技签约惠生工程,携手打造高效资金管理系统
近日,拜特科技成功签约惠生工程(中国)有限公司(以下简称“惠生工程”)资金管理系统项目。此次双方携手打造一套先进的资金管理系统,为惠生工程的战略发展注入强劲新动力,推动其资金管理迈向更高水平。 惠生工程作为行…...