news 2026/9/10 7:47:38

ABAP性能优化与代码整洁:从对抗到统一的项目实战指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
ABAP性能优化与代码整洁:从对抗到统一的项目实战指南

作为一个常年泡在SAP项目里的ABAP开发,我见过太多同事在“性能优化”和“代码整洁”之间来回拉扯。业务顾问上线前拉着你说报表太慢了,程序一多就崩;代码评审时,架构师又拎着你的SELECT *和循环内查库不放。于是很多人养成了“先写能跑的,再想能不能跑得快”的习惯,结果重构时发现比重写还累。

这篇东西其实是从我自己的项目经历里整理出来的一套打法,核心就一句话:性能与整洁不是单选题,它们本来就是同一件事的两面。一个结构干净的ABAP程序,往往更容易做性能分析,也更容易写出高性能的实现;反过来,刻意追求“快”的代码,如果写得很乱,后面反而会因为无法扩展、难以定位问题而拖慢整体效率。文章适合正在做报表优化、接口开发、增强开发的ABAP开发,也适合刚从其他语言转到ABAP、对Mind the performance这个概念还不够熟悉的同学。内容不是空谈,是能直接抄回项目里用的实战。

1. 性能与整洁:一对被误读的冤家

开局先泼一盆冷水:我见过很多“性能优化”其实是在给代码埋雷。比如为了减少一次数据库查询,把一大堆业务规则塞进一个方法里;为了让某个报表快几秒,把正常的数据结构拆成全局变量满天飞。这种代码上线后确实快了几天,等需求一变,改起来从半天变成一周,这账怎么算都不划算。

1.1 “二选一”的困局是怎么形成的

ABAP这个语言有个特点——它离业务太近了。SAP项目里绝大多数ABAP代码都是被业务需求推着走的:销售凭证增强、采购审批、生产订单状态检查、接口数据落库,每个需求都有明确的时间点,没人愿意等你把代码打磨到“完美”。于是不少开发形成了一种肌肉记忆:能用SELECT *就用SELECT *,循环里取数也能接受,变量命名能看懂就行。这种代码几周后连自己都看不懂,更别提优化。

另外一个原因是性能分析的滞后。通常在性能测试阶段才暴露问题,这时已经离上线很近,你的第一反应肯定是“哪里慢改哪里”,而不是“重构出干净的程序”。这种救火式的改法,往往换来的是另一个新坑,让人误以为优化和整洁天生互斥。

1.2 重新定义“性能”和“整洁”

性能不只是“跑得快”。真正的性能包含三层:单次执行速度、并发下的稳定性、以及当业务规模变化时的伸缩能力。整洁也不等于“注释多”。我见过注释比代码还多、逻辑还是一团乱麻的程序。整洁的标准是:读代码的人可以在脑子里跑通整个流程,并且能在不破坏其他功能的前提下做修改。

把这两个标准放在一起看,你会发现它们的交集非常大。一个方法只干一件事,你就能更快定位慢在哪个方法里;一个查询只取必要的字段,数据库侧的索引才能正常工作,这是性能和整洁共同的要求;一段循环内没有副作用,你才敢放心缓存数据。

1.3 整洁的代码降低性能劣化风险

这里有个很容易被忽视的点:业务是不断变化的。今天你的报表只有一万条数据,跑300毫秒,没人关心性能;明年数据量变成一千万,同样逻辑可能跑三分钟。这时候如果你的代码是整洁的,拆成清晰的模块,性能劣化的位置通常一眼就能锁定——某个SQL缺索引、某个循环内消耗高。反观那种一团糟的程序,你得先花一天搞清楚它在干什么,才谈得上优化。

所以,把整洁当成性能的“预防性维护”,一点都不夸张。

2. SQL查询层面:最直观的性能与整洁交汇点

ABAP应用慢,八成都慢在数据库访问上。而SQL写得好不好,恰好也是判断代码整洁与否的试金石。我在项目里做代码评审,先看程序里的SELECT长什么样,基本就能判断这个人的开发习惯。

2.1 不要在循环里反复查库

循环内查表是最常见、最容易被点评的性能反模式。比如遍历一个内表,在循环里用SELECT SINGLE取客户名称、物料描述,数据量一上来就是灾难。

LOOP AT lt_items INTO ls_item. SELECT SINGLE maktx FROM makt INTO ls_item-maktx WHERE matnr = ls_item-matnr AND spras = sy-langu. MODIFY lt_items FROM ls_item. ENDLOOP.

这段代码读起来很直观,但每一次循环都是一次数据库往返。如果lt_items有5000行,就是5000次查询,本地网络好一点还能忍,放到生产环境基本要被骂。整洁的写法是先把这批数据准备好,一次性取回:

IF lt_items[] IS NOT INITIAL. SELECT matnr, maktx FROM makt INTO TABLE lt_makt FOR ALL ENTRIES IN lt_items WHERE matnr = lt_items-matnr AND spras = sy-langu. ENDIF. SORT lt_makt BY matnr. LOOP AT lt_items ASSIGNING FIELD-SYMBOL(<fs_item>). READ TABLE lt_makt INTO ls_makt WITH KEY matnr = <fs_item>-matnr BINARY SEARCH. IF sy-subrc = 0. <fs_item>-maktx = ls_makt-maktx. ENDIF. ENDLOOP.

一次查询加一次SORT加一次二分查找,熟悉这套模式后,写起来也不比循环内SELECT麻烦多少。关键是,这种写法让数据库访问集中、清楚,读代码的人一眼看出“这里就查了一次库”,这就是整洁的力量。

2.2 字段列表和索引:从SELECT *到精确取列的性能跃迁

我在项目中几乎每次都强调:不要用SELECT *。很多人觉得ABAP语句写长了显得啰嗦,直接SELECT *省事。但省掉的并不是复杂度,而是把必要的约束从代码里抹掉了。

SELECT *带来几个问题:一是网络传输数据量大,二是ABAP层要分配大量不必要的内存,三是大概率无法命中最优索引。而明确列出字段列表,一方面让数据库优化器更容易选择覆盖索引,另一方面也逼着开发者思考“我到底需要哪些字段”,这本身就是个整理思路的过程。

配合索引时,字段列表更加重要。比如你经常用销售凭证号查一批数据,那么在凭证号字段上建索引,再写:

IF lt_header[] IS NOT INITIAL. SELECT vbeln, posnr, matnr, kwmeng FROM vbap INTO TABLE lt_vbap FOR ALL ENTRIES IN lt_header WHERE vbeln = lt_header-vbeln. ENDIF.

相比SELECT *,这种写法既减少了传输量,也能让数据库在索引上扫描更少的页。关于索引,建议开发在优化阶段主动用SE14或SE11查看表上现有索引,而不是等DBA来提醒。创建索引是件需要权衡的事,但基本共识是:查询频率高且查询字段区分度高的列,值得建。

2.3 FOR ALL ENTRIES 和 JOIN:不是非此即彼

关于取数方式,一直有争议。老派的ABAP开发喜欢FOR ALL ENTRIES(FAE),因为它在某些版本和数据库上效率稳定,而且对数据量不敏感。而新一些的项目里,大家更愿意直接写JOIN,因为JOIN逻辑上更整洁:表之间的关系写在SQL里,而不是靠内存里的临时集合去匹配。

我的经验是,两者都有适用场景,别迷信任何一个。FAE的本质是把你临时表里的值展开成一个IN条件,但它有个坑:临时表为空时会全表扫描,所以必须先判断非空。

IF lt_items[] IS NOT INITIAL. SELECT vbeln, posnr FROM vbap FOR ALL ENTRIES IN lt_items WHERE vbeln = lt_items-vbeln. ENDIF.

JOIN的好处是SQL清晰,但也要小心笛卡尔积和连接结果过大。多个内连接改成显式JOIN可以提升可读性,不过ABAP里的OPEN SQL对JOIN的支持比数据库原生SQL弱一些。在复杂的业务场景里,我通常建议:超过三个表的关联不要硬写成一个JOIN,拆分两步查询会更好维护。

2.4 别小看配置表:SM30带出描述的性能陷阱

SAP项目里到处都是配置表,比如状态、类型、文本描述。这些表数据量不大,但被访问的频率极高。我见过一个销售凭证增强,循环里对每行调用函数读取状态文本,结果状态多了,报表直接从2秒拖到20秒。

SM30配置表经常只需要“带出描述”,最简单的是调用功能模块,或者用配置视图直接查。但在批量场景里,最高效的做法还是把所有描述一次性缓存到内部表。

TYPES: BEGIN OF ty_status, stsma TYPE j_status-stsma, txt04 TYPE j_status-txt04, txt30 TYPE j_status-txt30, END OF ty_status. DATA lt_status_cache TYPE SORTED TABLE OF ty_status WITH UNIQUE KEY stsma txt04. SELECT stsma, txt04, txt30 FROM j_status INTO TABLE lt_status WHERE spras = sy-langu. INSERT LINES OF lt_status INTO TABLE lt_status_cache.

之后每次取描述就用READ TABLE,不会再碰数据库。这种“预加载+缓存”的模式,在ABAP里非常通用,而且代码写出来很整洁:数据从哪来、缓存在哪、怎么用,看代码就能懂。

3. 内部表操作的性能与整洁

数据库访问优化好之后,真正的战场就转到内存里的内部表处理。很多ABAP程序慢,不是数据库的问题,而是内表选型、排序、查找方式出了岔子。

3.1 内部表类型选型:STANDARD、SORTED还是HASHED?

刚开始学ABAP的时候,大家最常用的是STANDARD TABLE,因为创建起来不用动脑。但到了性能敏感的场景,类型选不对,代码再整洁也没用。

内表类型适用场景性能特征整洁度影响
STANDARD顺序处理、频繁修改、按索引访问二分查找需要先排序写法最自由,但需要自己维护排序
SORTED按关键字查找、数据量中等自动排序,READ TABLE默认二分声明后自动保证有序,代码更简单
HASHED大数据量、按唯一键精确查找哈希索引,按关键字查找极快只能按完整关键字访问,语义清晰但受限

一个常见的误区是:数据量大就用HASHED。其实HASHED的查找速度虽然快,但无法按非主键排序遍历,也无法部分匹配。如果后续需要顺序处理,还得转成STANDARD,反而多余。SORTED TABLE很多时候是“均衡之选”:有序可用于批量顺序访问,也可默认二分查找。

我个人的建议:如果表创建后主要按一个唯一键精确查找,使用HASHED;如果既要按关键字找,又要做顺序处理,使用SORTED;如果只是中间结果或者需要频繁修改,用STANDARD,然后SORT + READ TABLE ... BINARY SEARCH

3.2 二分查找不是自动发生的

在STANDARD TABLE上使用READ TABLE ... WITH KEY,默认是线性查找,数据量上千后性能就会肉眼可见地变差。很多人忘了先SORT再BINARY SEARCH。

SORT lt_data BY matnr. READ TABLE lt_data INTO ls_data WITH KEY matnr = lv_matnr BINARY SEARCH.

这个细节说起来简单,却是排查性能问题时最容易忽略的一个点。尤其数据来自多次APPEND,顺序是乱的,直接READ TABLE线性扫,扫到几万行时就会卡顿。

为了让这套逻辑保持整洁,我通常把“排序+查找”封装成一个局部方法:

METHODS get_by_matnr IMPORTING !iv_matnr TYPE matnr RETURNING VALUE(rs_data) TYPE ty_data. METHOD get_by_matnr. SORT me->mt_data BY matnr. READ TABLE me->mt_data INTO rs_data WITH KEY matnr = iv_matnr BINARY SEARCH. ENDMETHOD.

所有对内部表的访问都走这个方法,调用方代码简洁,且稳定高效。

3.3 避免不必要的复制和转换

ABAP对大数据量的复制开销非常敏感。比如用=把内表整体复制一遍,如果后续发现只是读取,就不如在变量声明时直接引用或使用FIELD-SYMBOL。

LOOP AT lt_result ASSIGNING FIELD-SYMBOL(<fs_result>). " 修改 <fs_result> 直接作用于内表,不需要 MODIFY ENDLOOP.

使用字段符号可以减少一次数据拷贝,代码上也少写MODIFY,看起来清爽。在循环内调用方法传内表时,如果方法不需要修改,用IMPORTING传引用比COPY更高效。循环里也尽量少做类型转换,尤其是字符串拼接和数值格式化,能提到循环外就提到循环外。

3.4 用运行计时量化性能改善

谈到性能优化,数据比感觉靠谱。ABAP里获取毫秒级的运行时间,通常用GET RUN TIME

DATA: lv_start TYPE i, lv_end TYPE i. GET RUN TIME FIELD lv_start. " 要测量的业务逻辑... GET RUN TIME FIELD lv_end. DATA(lv_elapsed_ms) = ( lv_end - lv_start ) / 1000. WRITE: / '执行耗时(毫秒):', lv_elapsed_ms.

GET RUN TIME返回的是运行计数,精度足以覆盖毫秒级比较。在优化前后各打一个点,轻轻松松就能量化优化效果。

我习惯每次做优化时,在修改前后各跑一次,记录耗时,这样才有说服力。不要只凭感觉说“快了很多”。拿报表真实数据量做对比,比如循环内查库改为批量查库后,从43秒降到2.1秒,这种数据一摆出来,谁都能理解改动价值。

4. 接口传输与集成场景:性能与整洁如何握手

SAP项目中接口开发占了很大比重,实际操作中性能问题也最容易在这里爆发。文件传输、HTTP接口、异步队列、权限校验,一个不慎就会造成大量数据堆积或超时。而这个场景恰恰需要代码整体设计整洁,才能让性能优化不失控。

4.1 大文件不要一次性读入内存

ABAP接口传文件是项目里特别常见的需求。比如定时从FTP读取供应商主数据,或者向银行发送付款文件。很多新手会习惯性用OPEN DATASET + READ TABLE把整个文件读进内存,文件一大就内存暴涨,甚至程序dump。

以文本文件为例,正确做法是逐行读取:

OPEN DATASET lv_filepath FOR INPUT IN TEXT MODE ENCODING DEFAULT. IF sy-subrc = 0. DO. READ DATASET lv_filepath INTO lv_line. IF sy-subrc <> 0. EXIT. ENDIF. " 处理当前行 ENDDO. CLOSE DATASET lv_filepath. ENDIF.

这种逐行处理方式,把内存占用压到最低,而且代码结构也非常清晰:打开文件、循环处理、关闭文件一目了然。配合批量提交,比如每100行或者每1000行调用一次BAPI写入,既避免了单次写入事务过大,也让处理进度可控。

传大文件时另外要注意:文件传输本身往往比ABAP处理更耗时,最好用异步Job定时拉取,而不是在同步对话中做。把“读文件”和“写数据库”拆成两个独立的步骤,也便于失败后重跑。

4.2 异步处理与队列:别让同步事务背锅

很多接口设计成同步,是因为业务要求即时返回结果。但如果是大批量数据,同步处理会让用户端干等,还容易超时。这时候可以考虑异步队列:用户请求先进队列,后台Job批量消化。

ABAP中可以用SMQR等队列机制,也可以自己写后台报表调度。无论走哪种,一个很重要的整洁原则是:队列处理程序的状态和日志必须完整。否则一旦某个批次失败,连开发都查不出问题在哪。

我通常在接口处理表里加一个状态字段(如PROC_STATUS:0待处理、1成功、2失败)和重试次数。每处理一条更新一次,这样出问题时可以直接查表。日志完整,排查方便,这本身就是对性能的一种保障——定位慢、定位失败的成本,往往比查一次程序慢还要高。

4.3 权限校验和业务校验尽量前置

接口开发中,权限校验是个典型的“又慢又乱”的点。有人写一个方法,在处理过程中反复做权限检查,结果每个循环都调一次AUTHORITY-CHECK

更好的做法是:在程序入口处做一次权限校验,整体校验失败就不继续处理。权限检查一般都很快,但不能放在循环里放大100倍。同理,业务校验(比如订单状态、物料合法性)也应该尽量批量查询出来,在循环里只做内存判断,不要循环里调BAPI或查询业务表。

这里可以结合ABAP请求提交中常见的授权校验来思考,虽然场景各有不同,但原则一样:能把校验数据一次捞出来,就别循环访问。

5. 增强开发中的性能与整洁边界

SAP项目基本绕不开增强。销售凭证VA03、采购订单ME23N、生产订单CO03,这些界面上到处是增强点。增强开发里性能问题特别隐蔽,因为用户感知到的往往是“界面卡一下”,而不是报表慢。而且增强代码分散在标准程序各处,一旦不规范,对后续维护就是噩梦。

5.1 找对增强点:性能与维护的最优解

以VA03销售凭证增强为例,如果业务需要显示额外的字段或按钮,可能在PBO/PAI、USEREXIT、BADI等不同入口都可以实现。选哪个增强点,直接决定了代码性能和后续可维护性。

我的建议是:能用BADI或显式增强点,就别用隐式增强;能在一次遍历中完成的事情,就别在界面的多个位置各写一段。增强点选得对,后续不会出现“这个字段在显示时改了,打印时却还是旧值”这种低级问题。而选错增强点,往往要靠多次调用和重复取值来补救,性能自然好不到哪去。

5.2 别在增强里画蛇添足

另一个常见问题是,增强代码里放了太多无关逻辑。特别是用户看到标准界面上有某个字段,就想顺手把其他相关的值也带出来,结果一个简单增强越写越长,每次显示都执行一大段SQL。

我见过一个VA03增强,只是为了显示一行备注,结果代码里又查了物料表、客户表、定价表,前后加起来四五次数据库访问。优化起来其实很简单:把所有的字段查询合并成一次SELECT,或者用缓存。但在增强点里,更重要的是克制:只做增强需求要求的事情,把复杂度挡在外面。

5.3 低调而整洁:隐式增强的纪律

隐式增强点(Implicit Enhancement)有时是不得不用的。用它的好处是侵入小,不需要修改标准代码,升级时不会冲突。但坏处是它看不见摸不着,维护的人常常不知道这里有逻辑。

所以用隐式增强时必须有纪律:第一,注释写清楚这个增强解决什么问题、为什么放在这里;第二,代码只增强,不改造标准逻辑;第三,定期排查有没有废弃增强。我见过一个系统里好几个隐式增强互相覆盖,每次查问题都要把所有增强点翻一遍。后来团队定了一个规矩:每个隐式增强必须写注释标明责任人、需求单号和修改日期,否则不允许提交。这其实就是把“整洁”制度化,而干净之后,性能定位也快了很多。

6. 性能分析实操:让工具替你说话

讲了这么多原则,落地时离不开工具。很多ABAP开发者一遇到性能问题就直接翻代码硬看,效率很低。正确的顺序应该是先用工具定位瓶颈,再有针对性地看相关代码。

6.1 SE30 / SAT:ABAP运行时分析的入门

SE30(新版本SAT)是最基础也最常用的ABAP性能分析事务码。跑完一个程序后,它会列出各个语句的耗时占比,比如某个SELECT占了总执行时间的60%,那么优化目标就有了。

整洁实践的思路是:在分析之前,先保证被测数据量和真实用户场景一致。拿一个只有几百条数据的测试环境去分析,结论基本没有参考价值。记录基线数据,优化后再跑一次,对比差异,这是给开发团队演示“性能提升”的最有说服力的材料。

6.2 ST05:SQL追踪的精准定位

ST05可以追踪数据库访问,看到每条SQL是怎么执行的、访问了多少行、耗时多少。它特别适合查循环内查询和缺失索引的问题。

使用流程也不复杂:

  1. 在ST05激活追踪,勾选SQL Trace;
  2. 运行或操作目标程序;
  3. 停止追踪,查看追踪结果。

在追踪结果里,重点看每个SQL语句的执行次数和总耗时。如果同一句SQL出现了几千次,那就可以判断是循环内查询了。修改为批量查询后,再追踪一次,执行次数会大幅下降。

6.3 代码评审中的性能嗅觉

最后想说,性能优化不只是跑工具的事。日常代码评审里,看到下面这些信号就要警觉:

  • 循环体内出现SELECT、CALL FUNCTION、外部调用;
  • 大数据量内部表用标准线性查找;
  • 使用SELECT *且未过滤关键条件;
  • 没有判断空表就使用FOR ALL ENTRIES;
  • 全局变量满天飞,方法之间隐式传值。

这些信号往往是性能和整洁同时出问题的征兆。把它们列成评审检查清单,比事后救火有效得多。

7. 常见性能问题排查实录

写到这里,分享几个我实际踩过的坑。这些问题在项目里反复出现,基本可以当成速查表来用。

7.1 问题一:报表越跑越慢

现象:某张库存报表,早期秒开,数据量增长后变成十几秒,用户频繁投诉。

初步排查:SE30显示主要耗时在某个内部表的READ TABLE上。进一步看代码,原来是STANDARD TABLE直接READ TABLE WITH KEY,没有排序也没有二分查找。

解决:把表声明改成SORTED TABLE,或先SORTREAD TABLE ... BINARY SEARCH。耗时从12.3秒下降到2.4秒。

心得:很多“报表越跑越慢”不是数据库问题,而是内存内表查找方式没有随数据量增长同步优化。内表类型一开始就要想清楚,别等到卡了才想到查。

7.2 问题二:接口处理数据大量堆积

现象:每日付款接口处理数万条记录,原本设计同步调用,用户反馈经常超时;队列里堆积大量消息,处理速度跟不上。

解决:把同步逻辑改造成异步队列,批量读取文件、批量写入数据库;同时增加重试机制和日志表。

心得:接口性能优化不能只盯着单次SQL或单次函数调用,要看整体处理链路是否匹配数据规模。同步调用天生不适合大批量,设计接口时就要定好“大文件分段、异步、断点续传”这些基调。

7.3 问题三:增强代码导致界面卡顿

现象:VA03显示销售凭证时明显卡顿。

排查:发现一个隐式增强在PBO中循环内多次调用BAPI和查询函数,界面每次刷新都触发。

解决:把这个增强移到用户操作时才触发,同时把循环内的大量取数改为批量读取。

心得:增强开发尤其要克制。界面每次刷新都执行的代码,必须保证极低的耗时;实在无法保证,就要想办法推迟执行或做缓存。

7.4 性能问题排查速查表

症状典型原因快速定位解决思路
报表响应慢循环内查库/READ TABLE线性查找SE30看语句耗时批量查询+缓存+二分查找
接口堆积同步处理大数据量队列日志/后台Job日志异步化、分批处理、重试机制
界面卡顿增强代码PBO频繁执行ST05追踪调用次数延迟加载、缓存、减少数据库往返
内存溢出大文件一次性读入内表ABAP dump类型逐行处理、分块提交

8. 写在后面的话

我在项目里反复讲一个观点:性能优化不是写到一半才发现的事,而是从设计代码那天起就该有的习惯。而保持整洁,正是让这个习惯持续下去的最有效方式。一个程序员可以把代码写得看起来“很猛”,各种花哨语法,但也正因为猛,后面没有人敢动。真正能长期维护、还能保持高性能的ABAP代码,往往读起来很朴素。

如果你正在接手一个别人留下的“又快又乱”的老程序,别急着全盘重写。先跑SE30/ST05定位真正的瓶颈,把循环内查询、线性查找这类问题逐个修掉,守住“改动最小、收益最大”的原则。等你手头的代码结构理顺了、运行时性能也稳了,自然就会认同这句话:性能与整洁从不矛盾,它俩本来就是同一个目标的两张面孔。

最后再分享一个习惯:每次写完一段性能优化代码,我都会在注释里记一下优化前后的耗时和当时的业务数据量。这看起来是小事,但等三个月后别人问起“这段逻辑为什么这样写”,你会庆幸当时的记录留下了答案。ABAP开发这行,最贵的永远不是CPU时间,是人的注意力和排查成本。把这两样省下来,性能自然就到位了。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/10 7:47:36

PHP事务实战:用mysqli+银行转账吃透ACID与并发

写 PHP 这么多年&#xff0c;我第一次真正意识到“事务”是干嘛的&#xff0c;是在一个支付项目线上出了 bug 之后。表面现象是用户支付成功、订单状态没更新&#xff0c;更深层看&#xff0c;是代码里扣款、写订单、记流水三个 SQL 操作分散在不同地方&#xff0c;中间某个环节…

作者头像 李华
网站建设 2026/9/10 7:46:01

大模型Checkpoint恢复基准:AWS存储方案实测与优化指南

如果你的训练任务在AWS上跑了三天&#xff0c;好不容易推进到第2000步&#xff0c;结果一个Spot实例回收通知下来&#xff0c;节点全没了。重新拉起之后&#xff0c;最想做的事情不是骂人&#xff0c;而是赶紧把Checkpoint读回来&#xff0c;继续跑。但等你真的开始做这件事&am…

作者头像 李华
网站建设 2026/9/10 7:45:40

AI Agent跨会话记忆系统:从Redis存储到RippleMem认知重建

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/10 7:45:30

STM32G4驱动IHM08M1电机模块实战指南

简介&#xff1a;本资源是一套基于STM32G431微控制器的电动窗帘电机控制完整工程&#xff0c;面向嵌入式开发工程师及智能硬件爱好者&#xff0c;解决直流电机精准启停、正反转与速度调节等核心控制问题&#xff0c;适用于智能家居场景下的窗帘自动化集成。压缩包含2000个文件&…

作者头像 李华
网站建设 2026/9/10 7:44:59

CANN/ge ACL算子形状推断API

aclopInferShape 【免费下载链接】ge GE&#xff08;Graph Engine&#xff09;是面向昇腾的图编译器和执行器&#xff0c;提供了计算图优化、多流并行、内存复用和模型下沉等技术手段&#xff0c;加速模型执行效率&#xff0c;减少模型内存占用。 GE 提供对 PyTorch、TensorFlo…

作者头像 李华