首页 文章 精选 留言 我的

精选列表

搜索[AI替代],共10000篇文章
优秀的个人博客,低调大师

用 structuredClone 替代 JSON.parse(JSON.stringify()) 做深拷贝时,你会遇到哪些坑

处理表单回显、状态快照或者撤销重做时,深拷贝是躲不开的一步。早些年用 `JSON.parse(JSON.stringify(obj))` 是最省事的写法,但它会丢掉 `Date`、`RegExp`、`Map`、`Set`、函数、`undefined`,遇到循环引用直接抛错,`NaN` 和 `Infinity` 还会被改成 `null`。后来浏览器和 Node.js 陆续提供了 `structuredClone`,它基于结构化克隆算法,能处理循环引用、`Date`、`Map`、`Set`,甚至 `ArrayBuffer` 和 `File`。不过它也不是万能钥匙:函数、DOM 节点、原型链、`WeakMap` 都不在支持范围内,`Symbol` 键也会被忽略,某些内置对象克隆后原型会变成普通对象。下面结合几个真实开发场景,聊聊怎么判断该不该用它,以及遇到边缘数据时怎么兜底。 ## 一个常见的状态快照场景 假设你在写一个可视化编辑器,用户每次拖拽元素前都要保存一份当前状态到历史栈,用于撤销。状态对象长这样: ```js const state = { id: 'canvas-1', createdAt: new Date(), layers: new Map([ ['layer-1', { x: 0, y: 0, tags: new Set(['draft']) }], ]), meta: { theme: 'dark' }, }; state.self = state; // 循环引用 ``` 用 JSON 方案直接报错:`Converting circular structure to JSON`。换成 `structuredClone`: ```js const snapshot = structuredClone(state); console.log(snapshot.createdAt instanceof Date); // true console.log(snapshot.layers instanceof Map); // true console.log(snapshot.self === snapshot); // true ``` 循环引用、Map、Date 都保留了。这在撤销重做里很关键,因为历史记录一旦丢失类型,回滚后渲染逻辑就会崩。 ## 它到底不支持什么 `structuredClone` 走的是 HTML 规范里的结构化克隆算法,能安全穿越线程边界(所以 `postMessage` 也用它)。但也正因为要能跨线程传输,函数、闭包、DOM 节点、原型上的方法和 `WeakMap`、`WeakSet` 全都不行。下面这些调用会直接抛 `DataCloneError`: ```js structuredClone({ fn: () => {} }); structuredClone(document.body); structuredClone({ weak: new WeakMap() }); ``` 再看一个更隐蔽的:自定义类实例。 ```js class User { constructor(name) { this.name = name; } greet() { return `hi ${this.name}`; } } const cloned = structuredClone(new User('nina')); cloned.greet(); // TypeError: cloned.greet is not a function ``` `name` 属性被复制了,但原型链没有跟着过来,`greet` 自然找不到。遇到这种数据,得先转成普通对象,或者自己写 `clone` 方法。 ## getter、setter 和不可枚举属性 结构化克隆只复制可枚举的自有属性。如果对象里用了 `Object.defineProperty` 定义 getter: ```js const source = {}; Object.defineProperty(source, 'fullName', { get() { return 'a b'; }, enumerable: false, }); const copy = structuredClone(source); console.log(copy.fullName); // undefined ``` 不可枚举的 getter 不会被带过去。有些状态库会把计算属性挂在实例上,克隆后这些字段就消失了。开发时如果发现快照少了东西,先查查属性描述符。 ## 和 postMessage 的关系 `structuredClone` 和 `postMessage` 的序列化规则一致,所以用它来模拟跨线程数据传递很合适。但反过来,`postMessage` 能传的 `Transferable` 对象(比如 `ArrayBuffer`)在 `structuredClone` 里也能用: ```js const buffer = new ArrayBuffer(8); const cloned = structuredClone(buffer); console.log(cloned.byteLength); // 8 ``` 这里默认是拷贝,原 buffer 不受影响。如果要做所有权转移,可以传第二个参数: ```js const transferred = structuredClone(buffer, { transfer: [buffer] }); console.log(buffer.byteLength); // 0 ``` 转移之后原 buffer 会变成 `0` 字节,这个行为在 worker 通信里很常见,但用在普通深拷贝时要小心,别误伤原数据。 ## 兼容性与降级 `structuredClone` 在 Chrome 98、Firefox 94、Safari 15.4 之后才可用。如果项目还要支持旧浏览器,直接调用会报 `structuredClone is not defined`。常见的降级做法是判断一下,没有就用 `MessageChannel` 或者退回 JSON 方案: ```js function deepClone(value) { if (typeof structuredClone === 'function') { try { return structuredClone(value); } catch (err) { console.warn('structuredClone failed, fallback to JSON', err); } } return JSON.parse(JSON.stringify(value)); } ``` 注意 JSON 兜底也会在循环引用时崩,所以更稳妥的做法是接一个支持循环引用的第三方库,或者自己写递归加 `WeakMap` 记录已拷贝对象。 ## 什么时候该避开它 如果对象里混了函数、类实例、DOM 引用,或者你依赖原型上的方法,`structuredClone` 并不合适。它的定位是“结构化数据”的深拷贝,不是万能的 `cloneDeep`。在纯数据(JSON-like)场景下,它比 JSON 方案更强也更安全;在复杂对象图里,还是得用 lodash 的 `cloneDeep` 或者手写针对性的拷贝逻辑。 另外,`structuredClone` 对 `Error` 对象支持得也不完整,某些浏览器里 `stack` 会丢,`cause` 可能保留也可能不保留,别指望用它来复制错误上下文。 推荐查看天气:http://www.362tq.com/mizhi/10tian.html 推荐查看天气:http://www.362tq.com/mizhi/15tian.html 推荐查看天气:http://www.362tq.com/mizhi/40tian.html 推荐查看天气:http://www.362tq.com/jiaxian/ 推荐查看天气:http://www.362tq.com/jiaxian/zuotian.html 推荐查看天气:http://www.362tq.com/jiaxian/7tian.html 推荐查看天气:http://www.362tq.com/jiaxian/10tian.html 推荐查看天气:http://www.362tq.com/jiaxian/15tian.html 推荐查看天气:http://www.362tq.com/jiaxian/40tian.html 推荐查看天气:http://www.362tq.com/wubao/ 推荐查看天气:http://www.362tq.com/wubao/zuotian.html 推荐查看天气:http://www.362tq.com/wubao/7tian.html 推荐查看天气:http://www.362tq.com/wubao/10tian.html 推荐查看天气:http://www.362tq.com/wubao/15tian.html 推荐查看天气:http://www.362tq.com/wubao/40tian.html 推荐查看天气:http://www.362tq.com/qingjian/ 推荐查看天气:http://www.362tq.com/qingjian/zuotian.html 推荐查看天气:http://www.362tq.com/qingjian/7tian.html 推荐查看天气:http://www.362tq.com/qingjian/10tian.html 推荐查看天气:http://www.362tq.com/qingjian/15tian.html 推荐查看天气:http://www.362tq.com/qingjian/40tian.html 推荐查看天气:http://www.362tq.com/zizhou/ 推荐查看天气:http://www.362tq.com/zizhou/zuotian.html 推荐查看天气:http://www.362tq.com/zizhou/7tian.html 推荐查看天气:http://www.362tq.com/zizhou/10tian.html 推荐查看天气:http://www.362tq.com/zizhou/15tian.html 推荐查看天气:http://www.362tq.com/zizhou/40tian.html 推荐查看天气:http://www.362tq.com/ankang/ 推荐查看天气:http://www.362tq.com/ankang/zuotian.html 推荐查看天气:http://www.362tq.com/ankang/7tian.html 推荐查看天气:http://www.362tq.com/ankang/10tian.html 推荐查看天气:http://www.362tq.com/ankang/15tian.html 推荐查看天气:http://www.362tq.com/ankang/40tian.html 推荐查看天气:http://www.362tq.com/hanbin/ 推荐查看天气:http://www.362tq.com/hanbin/zuotian.html 推荐查看天气:http://www.362tq.com/hanbin/7tian.html 推荐查看天气:http://www.362tq.com/hanbin/10tian.html 推荐查看天气:http://www.362tq.com/hanbin/15tian.html 推荐查看天气:http://www.362tq.com/hanbin/40tian.html 推荐查看天气:http://www.362tq.com/hanyin/ 推荐查看天气:http://www.362tq.com/hanyin/zuotian.html 推荐查看天气:http://www.362tq.com/hanyin/7tian.html 推荐查看天气:http://www.362tq.com/hanyin/10tian.html 推荐查看天气:http://www.362tq.com/hanyin/15tian.html 推荐查看天气:http://www.362tq.com/hanyin/40tian.html 推荐查看天气:http://www.362tq.com/shiquan/ 推荐查看天气:http://www.362tq.com/shiquan/zuotian.html 推荐查看天气:http://www.362tq.com/shiquan/7tian.html 推荐查看天气:http://www.362tq.com/shiquan/10tian.html 推荐查看天气:http://www.362tq.com/shiquan/15tian.html 推荐查看天气:http://www.362tq.com/shiquan/40tian.html 推荐查看天气:http://www.362tq.com/ningshan/ 推荐查看天气:http://www.362tq.com/ningshan/zuotian.html 推荐查看天气:http://www.362tq.com/ningshan/7tian.html 推荐查看天气:http://www.362tq.com/ningshan/10tian.html 推荐查看天气:http://www.362tq.com/ningshan/15tian.html 推荐查看天气:http://www.362tq.com/ningshan/40tian.html 推荐查看天气:http://www.362tq.com/ziyangxian/ 推荐查看天气:http://www.362tq.com/ziyangxian/zuotian.html 推荐查看天气:http://www.362tq.com/ziyangxian/7tian.html 推荐查看天气:http://www.362tq.com/ziyangxian/10tian.html 推荐查看天气:http://www.362tq.com/ziyangxian/15tian.html 推荐查看天气:http://www.362tq.com/ziyangxian/40tian.html 推荐查看天气:http://www.362tq.com/langao/ 推荐查看天气:http://www.362tq.com/langao/zuotian.html 推荐查看天气:http://www.362tq.com/langao/7tian.html 推荐查看天气:http://www.362tq.com/langao/10tian.html 推荐查看天气:http://www.362tq.com/langao/15tian.html 推荐查看天气:http://www.362tq.com/langao/40tian.html 推荐查看天气:http://www.362tq.com/pingli/ 推荐查看天气:http://www.362tq.com/pingli/zuotian.html 推荐查看天气:http://www.362tq.com/pingli/7tian.html 推荐查看天气:http://www.362tq.com/pingli/10tian.html 推荐查看天气:http://www.362tq.com/pingli/15tian.html 推荐查看天气:http://www.362tq.com/pingli/40tian.html 推荐查看天气:http://www.362tq.com/zhenping/ 推荐查看天气:http://www.362tq.com/zhenping/zuotian.html 推荐查看天气:http://www.362tq.com/zhenping/7tian.html 推荐查看天气:http://www.362tq.com/zhenping/10tian.html 推荐查看天气:http://www.362tq.com/zhenping/15tian.html 推荐查看天气:http://www.362tq.com/zhenping/40tian.html 推荐查看天气:http://www.362tq.com/xunyang/ 推荐查看天气:http://www.362tq.com/xunyang/zuotian.html 推荐查看天气:http://www.362tq.com/xunyang/7tian.html 推荐查看天气:http://www.362tq.com/xunyang/10tian.html 推荐查看天气:http://www.362tq.com/xunyang/15tian.html 推荐查看天气:http://www.362tq.com/xunyang/40tian.html 推荐查看天气:http://www.362tq.com/baihe/ 推荐查看天气:http://www.362tq.com/baihe/zuotian.html 推荐查看天气:http://www.362tq.com/baihe/7tian.html 推荐查看天气:http://www.362tq.com/baihe/10tian.html 推荐查看天气:http://www.362tq.com/baihe/15tian.html 推荐查看天气:http://www.362tq.com/baihe/40tian.html 推荐查看天气:http://www.362tq.com/shangluo/ 推荐查看天气:http://www.362tq.com/shangluo/zuotian.html 推荐查看天气:http://www.362tq.com/shangluo/7tian.html 推荐查看天气:http://www.362tq.com/shangluo/10tian.html 推荐查看天气:http://www.362tq.com/shangluo/15tian.html 推荐查看天气:http://www.362tq.com/shangluo/40tian.html 推荐查看天气:http://www.362tq.com/shangzhou/ 推荐查看天气:http://www.362tq.com/shangzhou/zuotian.html 推荐查看天气:http://www.362tq.com/shangzhou/7tian.html 推荐查看天气:http://www.362tq.com/shangzhou/10tian.html 推荐查看天气:http://www.362tq.com/shangzhou/15tian.html 推荐查看天气:http://www.362tq.com/shangzhou/40tian.html 推荐查看天气:http://www.362tq.com/luonan/ 推荐查看天气:http://www.362tq.com/luonan/zuotian.html 推荐查看天气:http://www.362tq.com/luonan/7tian.html 推荐查看天气:http://www.362tq.com/luonan/10tian.html 推荐查看天气:http://www.362tq.com/luonan/15tian.html 推荐查看天气:http://www.362tq.com/luonan/40tian.html 推荐查看天气:http://www.362tq.com/danfeng/ 推荐查看天气:http://www.362tq.com/danfeng/zuotian.html 推荐查看天气:http://www.362tq.com/danfeng/7tian.html 推荐查看天气:http://www.362tq.com/danfeng/10tian.html 推荐查看天气:http://www.362tq.com/danfeng/15tian.html 推荐查看天气:http://www.362tq.com/danfeng/40tian.html 推荐查看天气:http://www.362tq.com/shangnan/ 推荐查看天气:http://www.362tq.com/shangnan/zuotian.html 推荐查看天气:http://www.362tq.com/shangnan/7tian.html 推荐查看天气:http://www.362tq.com/shangnan/10tian.html 推荐查看天气:http://www.362tq.com/shangnan/15tian.html 推荐查看天气:http://www.362tq.com/shangnan/40tian.html 推荐查看天气:http://www.362tq.com/shanyang/ 推荐查看天气:http://www.362tq.com/shanyang/zuotian.html 推荐查看天气:http://www.362tq.com/shanyang/7tian.html 推荐查看天气:http://www.362tq.com/shanyang/10tian.html 推荐查看天气:http://www.362tq.com/shanyang/15tian.html 推荐查看天气:http://www.362tq.com/shanyang/40tian.html 推荐查看天气:http://www.362tq.com/zhenan/ 推荐查看天气:http://www.362tq.com/zhenan/zuotian.html 推荐查看天气:http://www.362tq.com/zhenan/7tian.html 推荐查看天气:http://www.362tq.com/zhenan/10tian.html 推荐查看天气:http://www.362tq.com/zhenan/15tian.html 推荐查看天气:http://www.362tq.com/zhenan/40tian.html 推荐查看天气:http://www.362tq.com/zuoshui/ 推荐查看天气:http://www.362tq.com/zuoshui/zuotian.html 推荐查看天气:http://www.362tq.com/zuoshui/7tian.html 推荐查看天气:http://www.362tq.com/zuoshui/10tian.html 推荐查看天气:http://www.362tq.com/zuoshui/15tian.html 推荐查看天气:http://www.362tq.com/zuoshui/40tian.html 推荐查看天气:http://www.362tq.com/lanzhou/ 推荐查看天气:http://www.362tq.com/lanzhou/zuotian.html 推荐查看天气:http://www.362tq.com/lanzhou/7tian.html 推荐查看天气:http://www.362tq.com/lanzhou/10tian.html 推荐查看天气:http://www.362tq.com/lanzhou/15tian.html 推荐查看天气:http://www.362tq.com/lanzhou/40tian.html 推荐查看天气:http://www.362tq.com/chengguan/ 推荐查看天气:http://www.362tq.com/chengguan/zuotian.html 推荐查看天气:http://www.362tq.com/chengguan/7tian.html 推荐查看天气:http://www.362tq.com/chengguan/10tian.html 推荐查看天气:http://www.362tq.com/chengguan/15tian.html 推荐查看天气:http://www.362tq.com/chengguan/40tian.html 推荐查看天气:http://www.362tq.com/qilihe/ 推荐查看天气:http://www.362tq.com/qilihe/zuotian.html 推荐查看天气:http://www.362tq.com/qilihe/7tian.html 推荐查看天气:http://www.362tq.com/qilihe/10tian.html 推荐查看天气:http://www.362tq.com/qilihe/15tian.html 推荐查看天气:http://www.362tq.com/qilihe/40tian.html 推荐查看天气:http://www.362tq.com/xigu/ 推荐查看天气:http://www.362tq.com/xigu/zuotian.html 推荐查看天气:http://www.362tq.com/xigu/7tian.html 推荐查看天气:http://www.362tq.com/xigu/10tian.html 推荐查看天气:http://www.362tq.com/xigu/15tian.html 推荐查看天气:http://www.362tq.com/xigu/40tian.html 推荐查看天气:http://www.362tq.com/anning/ 推荐查看天气:http://www.362tq.com/anning/zuotian.html 推荐查看天气:http://www.362tq.com/anning/7tian.html 推荐查看天气:http://www.362tq.com/anning/10tian.html 推荐查看天气:http://www.362tq.com/anning/15tian.html 推荐查看天气:http://www.362tq.com/anning/40tian.html 推荐查看天气:http://www.362tq.com/honggu/ 推荐查看天气:http://www.362tq.com/honggu/zuotian.html 推荐查看天气:http://www.362tq.com/honggu/7tian.html 推荐查看天气:http://www.362tq.com/honggu/10tian.html 推荐查看天气:http://www.362tq.com/honggu/15tian.html 推荐查看天气:http://www.362tq.com/honggu/40tian.html 推荐查看天气:http://www.362tq.com/yongdeng/ 推荐查看天气:http://www.362tq.com/yongdeng/zuotian.html 推荐查看天气:http://www.362tq.com/yongdeng/7tian.html 推荐查看天气:http://www.362tq.com/yongdeng/10tian.html 推荐查看天气:http://www.362tq.com/yongdeng/15tian.html 推荐查看天气:http://www.362tq.com/yongdeng/40tian.html 推荐查看天气:http://www.362tq.com/gaolan/ 推荐查看天气:http://www.362tq.com/gaolan/zuotian.html 推荐查看天气:http://www.362tq.com/gaolan/7tian.html 推荐查看天气:http://www.362tq.com/gaolan/10tian.html 推荐查看天气:http://www.362tq.com/gaolan/15tian.html 推荐查看天气:http://www.362tq.com/gaolan/40tian.html 推荐查看天气:http://www.362tq.com/yuzhong/ 推荐查看天气:http://www.362tq.com/yuzhong/zuotian.html 推荐查看天气:http://www.362tq.com/yuzhong/7tian.html 推荐查看天气:http://www.362tq.com/yuzhong/10tian.html 推荐查看天气:http://www.362tq.com/yuzhong/15tian.html 推荐查看天气:http://www.362tq.com/yuzhong/40tian.html 推荐查看天气:http://www.362tq.com/jiayuguan/ 推荐查看天气:http://www.362tq.com/jiayuguan/zuotian.html 推荐查看天气:http://www.362tq.com/jiayuguan/7tian.html 推荐查看天气:http://www.362tq.com/jiayuguan/10tian.html 推荐查看天气:http://www.362tq.com/jiayuguan/15tian.html

优秀的个人博客,低调大师

Python+同花顺问财:我用ROE+FCF+分红三连筛,替代"价值感觉"

很多人谈价值投资只靠感觉。我把"企业持续创造价值的能力"拆成三个可量化的财务指标:ROE、自由现金流、分红率,用问财导出数据后用Python一键打分。这里没有玄学,只有算式。 一、问财选股公式 先在问财里圈出候选池: > 非ST,ROE连续3年大于10%,经营现金流净额连续3年大于0,股息率大于2% 导出后得到宽表,字段包括:股票代码、名称、ROE(%)、净利润、经营现金流净额、自由现金流、股息率(%)、市净率。 二、Python评分:价值创造三因子 ```javascript import csv def value_score(row): roe = float(row.get("ROE", 0).replace("%", "")) / 100 ocf = float(row.get("经营现金流净额", 0)) fcf = float(row.get("自由现金流", 0)) div = float(row.get("股息率", 0).replace("%", "")) / 100 pb = float(row.get("市净率", 1)) score = 0 if roe > 0.15: score += 3 elif roe > 0.10: score += 2 if fcf > 0 and fcf > ocf * 0.3: score += 3 elif fcf > 0: score += 1 if div > 0.03: score += 2 elif div > 0.02: score += 1 if pb 10%,说明企业能用股东的钱持续赚钱。 自由现金流 看利润质量。利润表好看但现金流差,只是纸面富贵。 股息率 看回报股东的真实意愿。能分钱,说明赚到的不是幻象。 四、和马政框架的对应 ROE+FCF 对应"剩余价值创造能力"——企业真赚钱,股价才有长期支撑。 分红率 对应"资本回流"——利润不回流股东,就可能在体系内空转。 低PB 是安全边际,避免在"价格异化"的高点接盘。 五、接入排雷扫描 评分高的票再过 master_scan 扫一遍:高质押、商誉、应计异常、内部人减持,有雷的拿下。价值和排雷不冲突,是前后两道门。 注师关键点 财务指标是线索不是结论。ROE可以靠杠杆堆,FCF可以靠压供应商账期,分红可以借债分。三连筛后必须看报表附注和审计意见,才能下判断。 哲学点题 看不清钱从哪来,就永远在价格里晕船。 互动钩子 你平时看价值股,最先用哪个指标排序?ROE、PE还是股息率?评论区报你的排序。 ——会计师事务所的一名注册会计师

优秀的个人博客,低调大师

大模型激活函数迭代演进:SwiGLU替代传统ReLU/GELU激活逻辑提升模型性能18.9

# 一、前言 在前一期《[大模型主流激活函数解析:ReLU/GELU/SwiGLU 原理差异,拆解 FFN 前向逻辑](https://cloud.tencent.com/developer/article/2722742)》内容中,我们已经系统认识了神经网络激活函数的基础作用:线性矩阵运算无法拟合复杂语义规律,只有加入非线性激活,Transformer才能学习语言逻辑、上下文关联与世界知识。相信在我们初步了解后在对比 ReLU、GELU两种经典激活后都会产生疑问:既然ReLU计算简单高效、GELU平滑稳定适配早期模型,为什么如今ChatGLM3、Qwen-7B这类主流开源大模型,全都全面切换为SwiGLU门控激活? 这并不是行业架构跟风迭代,而是随着大模型参数量暴涨、深层网络堆叠、超长上下文理解、低成本量化部署、MoE稀疏专家架构、下游领域微调等需求不断升级,传统 ReLU极易出现神经元死亡、GELU深层梯度持续衰减、长文本记忆薄弱、知识存储上限不足、量化精度损失严重等短板被持续放大。 Transformer中FFN前馈层是大模型存放常识、专业知识、语义逻辑的核心载体,激活函数直接决定FFN特征表达上限。今天我们结合Qwen-7B-Chat本地真实开源模型,继续拆解三种激活曲线差异、梯度变化规律、原生FFN架构区别,讲透SwiGLU全方位碾压ReLU、GELU,成为千亿万亿大模型标配激活的底层逻辑。 ![](https://developer.qcloudimg.com/http-save/yehe-11883445/03a44e4591b4b79063bbdd255b5a1261.jpg) # 二、激活函数回顾 ## 1. 传统激活作用 神经网络本质是多层线性矩阵运算,单纯线性叠加无论堆叠多少层,最终都等价于单层线性变换,无法拟合语言、图像复杂非线性语义规律。 激活函数核心作用就是引入非线性变换,打破线性局限,让Transformer具备理解上下文语义、逻辑推理、长文本关联、知识记忆的能力。没有优质激活函数,再大参数量模型都无法学习有效语言规律。 早期CV模型普遍使用ReLU,BERT时代全面普及GELU,二者长期占据深度学习主流。但Transformer大模型走向千亿参数、长上下文、低成本推理、MoE稀疏架构后,两种激活缺陷被无限放大,彻底无法适配大模型应用落地需求。 ## 2. 大模型专属FFN结构特点 Transformer分为注意力Self-Attention与前馈神经网络FFN两大核心模块。 - 注意力负责上下文关联、语义对齐; - FFN负责模型知识存储、语义转换、特征加工。 大模型90%以上参数量都集中在FFN层,模型记忆力、问答准确率、逻辑能力、专业领域素养,几乎完全由FFN决定。激活函数内嵌在FFN计算流程中,直接掌控FFN表达能力、训练难易、显存消耗、推理速度。 千亿大模型参数量膨胀,FFN扩维比例不断提升,传统激活梯度消失、饱和失效、训练震荡、显存浪费问题频发,SwiGLU顺势成为最优解。 # 三、ReLU&GELU原生缺陷 ## 1. ReLU函数致命短板 ReLU公式简单、计算极快,单侧抑制、单侧激活,负值直接置0。在小模型、CV 视觉任务表现优异,但大语言模型场景缺陷致命: - 1. 神经元死亡:大量负值输入永久梯度归零,参数不再更新,FFN大量神经元失效,模型知识记忆残缺 - 2. 无负向语义表达:语言语义存在正反关联、否定逻辑,ReLU无法拟合双向语义特征 - 3. 梯度不稳定:深层堆叠极易梯度爆炸、消失,千亿模型无法稳定收敛 - 4. 非线性表达贫瘠,无法支撑复杂长文本语义逻辑 ## 2. GELU迭代局限 GELU在ReLU基础加入高斯概率加权平滑,解决神经元死亡问题,适配BERT类编码器模型,成为初代大模型标配。 但面对深层Decoder大模型依然存在硬伤: - 1. 非线性拟合上限低,复杂知识特征无法深度抽象 - 2. 训练后期容易梯度饱和,深层FFN收敛变慢 - 3. 显存占用偏高,推理吞吐量偏低 - 4. 无法与MoE门控逻辑天然结合,稀疏大模型适配极差 - 5. 低比特量化效果差,边缘部署、轻量化落地损耗严重 随着模型参数从十亿迈向千亿、万亿,GELU表达瓶颈彻底暴露,无法支撑更高维度语义知识建模。 ## 3. 函数曲线直观体现 ![](https://developer.qcloudimg.com/http-save/yehe-11883445/db50c9967a4e9e6032a79efe2a2a2fe9.png) **ReLU:** - x0:梯度恒 = 1,深层极易梯度爆炸 **GELU梯度:** - 全程平滑,但两端快速趋近0 - 深层堆叠梯度持续衰减,长文本、高层语义学不到 **SwiGLU梯度:** - 大范围区间梯度稳定在0~1之间 - 无归零、无饱和、无剧烈波动 - 上千层Transformer堆叠依然稳定收敛 ## 5. FFN结构本质对照 **ReLU/GELU FFN:** - 单一路线: - 输入 → Wup → 激活 → Wdown → 输出 - 只有一次非线性变换,表达上限极低 **SwiGLU FFN:** - 双支路并行: - 支路 A:原始特征映射 - 支路 B:门控权重 → SiLU 激活 - 两路逐元素相乘 = 高阶二次非线性,语义拟合能力指数级提升 ![](https://developer.qcloudimg.com/http-save/yehe-11883445/346891dfef027b82758fa93d8c9578b7.png) # 四、SwiGLU核心原理 ## 1. 门控线性单元基础逻辑 GLU门控线性单元,打破单一激活模式,将FFN隐藏层拆分为主特征支路 + 门控权重支路。一条支路负责特征变换,一条支路动态控制特征输出权重,自动筛选有效语义信息、抑制无用噪声特征。 SwiGLU是Swish激活改良版GLU结构,融合Swish平滑门控特性 + GLU双支路门控机制,是专门为Transformer Decoder大模型定制最优激活。不再单纯非线性映射,而是动态门控加权非线性变换,语义特征筛选能力呈指数级提升。 ## 2. SwiGLU完整数学逻辑 **标准FFN流程:**输入→升维矩阵相乘→激活函数→降维矩阵输出 **SwiGLU FFN流程:** - 输入特征拆分两路并行计算 - 支路 1:线性变换特征通道 - 支路 2:Swish 门控权重计算 - 两路逐元素相乘融合,再完成降维输出 双支路结构自带更强非线性,门控自适应调节强弱特征,不会梯度饱和、不会神经元死亡,深层堆叠无限稳定。 ## 3. 大模型适配底层优势 - 语言上下文长短不一、语义重要程度差异极大,注意力负责关联位置,SwiGLU负责动态加权重要语义。 - 无关上下文自动弱化,关键知识、逻辑重点自动增强,完美契合自然语言分布规律。 - 同时梯度传播顺滑连续,深层千亿模型上千层堆叠依然稳定训练。 # 五、非线性表达能力对比 ## 1. 单阶非线性差距 - ReLU 是分段线性,非线性能力最弱,仅能分段拟合简单特征。 - GELU 平滑非线性,拟合能力中等,适合浅层语义建模。 - SwiGLU 双支路相乘非线性,属于高阶复合非线性,能够拟合复杂嵌套语义、多层逻辑推理、长距离知识关联。 大模型需要学习海量世界常识、专业知识、因果逻辑、多轮对话上下文,单一平滑激活完全不足以覆盖复杂语义分布,只有门控复合非线性才能匹配大模型知识复杂度。 ![](https://developer.qcloudimg.com/http-save/yehe-11883445/df22d9c51d3b5bd5b27959abcc6c3f52.png) ## 2. 长文本语义建模差异 长上下文大模型,上下文距离越远语义关联越微弱: - ReLU/GELU 远距离特征衰减严重,长文本逻辑混乱、上下文遗忘。 - SwiGLU 门控长效保留关键远距离语义特征,长上下文记忆不衰减,大幅提升长文档理解、超长对话连贯性。 ![](https://developer.qcloudimg.com/http-save/yehe-11883445/6f44d2cb7cffbd21f43a436fd9a9e908.png) ## 3. 知识抽象与泛化能力 FFN 依靠激活拟合抽象知识规律,SwiGLU可以更好提取隐层语义特征、抽象常识逻辑、跨领域知识关联。 - 相同参数量下,SwiGLU模型知识密度更高,问答更准确、幻觉更少、逻辑更严谨。 - 相同效果下,SwiGLU模型可以用更少参数达到传统激活模型性能,大幅降低训练与部署成本。 # 六、扩维比例与训练稳定性 ## 1. FFN经典扩维系数逻辑 Transformer标准FFN隐藏层扩维倍数,传统GELU模型一般4倍扩维。更换SwiGLU后,行业通用调整为8、12倍扩维,双支路结构天然适配高扩维,进一步拉高模型知识容量。 - 扩维过小:模型知识上限不足,笨重大模型依然低智商 - 扩维过大:梯度震荡、训练发散、显存爆显存、收敛极慢 ## 2. 激活缩放系数调节作用 - SwiGLU自带输出缩放归一化特性,配合RMSNorm层,自动稳定深层梯度幅值。 - 合理缩放可以避免深层梯度爆炸、梯度消失,千亿模型从零训练平稳收敛,无需复杂学习率调参、无需频繁梯度裁剪。 - ReLU极易梯度剧烈波动,GELU缩放适配差,深层训练极易崩掉。 - SwiGLU梯度分布均匀平滑,训练容错率极高,大幅降低大模型炼丹调参难度。 ## 3. 深浅层统一稳定特性 大模型底层学习字词基础特征,中层学习短语语法,高层学习逻辑推理与全局知识。 - ReLU/GELU深浅层梯度差异巨大,高层极易训练失效。 - SwiGLU全层级梯度稳定一致,底层中层高层同步收敛,模型整体训练效率翻倍。 # 七、FFN决定模型知识上限 ## 1. 大模型知识存储逻辑 在没有深入了解前通常会误以为注意力层存储知识,实际完全相反: - Transformer注意力只做上下文关联匹配,所有世界知识、常识、专业数据、语言规律,全部存储在FFN权重参数中。 - FFN相当于大模型长期记忆库,激活函数就是记忆读写规则。规则越好,记忆容量越大、提取越准、遗忘越少。 ## 2. 激活函数约束记忆天花板 - ReLU神经元大量失效,记忆碎片化残缺。 - GELU非线性有限,复杂知识无法深度编码存储。 - SwiGLU双支路门控高密度编码,同等参数量FFN知识存储容量提升数倍,模型记住更多常识、专业内容、逻辑规则。 ## 3. 知识调用与推理流畅度 模型生成回答,本质是FFN调取存储知识,经过语义组合输出: - SwiGLU特征筛选精准,知识调取无冗余混乱,回答逻辑连贯、专业性强、幻觉概率显著降低。 - 传统激活知识杂乱堆砌,容易胡编乱造、逻辑断裂、上下文矛盾。 # 八、量化显存推理对比 ## 1. 显存占用实测差异 - SwiGLU双支路看似计算更多,实际配合优化结构,训练显存更低、推理显存更省。 - ReLU稀疏性不稳定,显存浪费严重;GELU 浮点计算密集,显存占用居高不下。 大模型批量推理、长上下文推理,SwiGLU显存优势被无限放大,同等显卡可承载更大批次、更长文本。 ## 2. 推理速度吞吐量对比 - ReLU计算最快但无效参数多,实际有效吞吐低。 - GELU计算复杂,浮点运算量大,推理延迟高。 - SwiGLU运算规整、硬件算子友好,GPU加速效率极高,推理速度全面超越GELU,接近ReLU推理效率。 ## 3. INT8/INT4量化友好度 大模型落地必做低比特量化压缩: - ReLU量化极易精度崩塌; - GELU量化损失严重; - SwiGLU分布平滑均匀、无极端极值,低比特量化几乎无损精度,完美适配云端服务、边缘设备、手机端大模型部署。是目前唯一全量化链路适配最优激活函数。 # 九、微调提升模型专业能力 ## 1. 注意力 vs FFN微调差异 - 注意力层负责上下文格式、对话风格、句式结构。 - FFN层负责专业知识、行业规则、专业术语、垂直领域逻辑。 大模型通用转行业专用,微调FFN层收益远大于微调注意力层。 ## 2. SwiGLU适配指令微调特性 - SwiGLU门控可以快速适配新领域知识权重,冻结底层通用模型,仅微调FFN少量参数,即可快速掌握医疗、法律、金融、编程等专业内容。 - ReLU/GELU微调极易灾难性遗忘,通用能力丢失,新专业能力提升有限。 - SwiGLU新旧知识融合自然,不遗忘通用常识,快速叠加垂直专业能力。 ## 3. LoRA轻量化微调最优搭配 - LoRA微调大模型主流方案,SwiGLU FFN与LoRA结合效果极佳。 - 小参数量微调,低成本快速领域适配,不掉通用对话能力,不掉长文本能力,不掉逻辑推理能力。成为行业私有大模型微调标准架构。 # 十、MoE与SwiGLU架构联动 ## 1. MoE混合专家模型核心逻辑 - MoE稀疏大模型,将FFN拆分为多个专家模块,输入动态选择对应专家计算,千亿万亿模型低成本扩容,算力不随参数线性暴涨。 - MoE核心就是门控路由机制,动态分配特征到对应专家FFN。 ## 2. 天然架构协同适配 - SwiGLU本身就是门控结构,MoE全局路由门控 + FFN内部SwiGLU局部门控,双层门控完美配合。 - 全局筛选专家,局部筛选语义特征,稀疏计算效率拉满。 - ReLU、GELU无门控特性,MoE专家分配混乱,专家负载不均衡,训练极易崩溃,性能提升极低。 ## 3. 万亿级大模型必备组合 - 当前所有开源闭源万亿MoE大模型,无一例外全部采用SwiGLU激活。 - 双层门控大幅降低算力消耗,提升专家利用率,稳定超大规模稀疏模型训练,支撑超大参数模型持续迭代。 # 十一:Qwen-7B SwiGLU结构展示 加载Qwen-7B本地模型,打印真实FFN(w1/w2/c_proj)三路结构,逐步拆解SwiGLU门控×特征的融合计算链路,输出每层张量维度变化,并绘制SwiGLU函数曲线、梯度分布与FFN架构图,最后用长文本推理验证SwiGLU相比GELU的长上下文优势。 ``` import torch import numpy as np import matplotlib import warnings warnings.filterwarnings("ignore") matplotlib.use('Agg') # 非交互后端,避免 plt.show() 无窗口报错 import matplotlib.pyplot as plt from transformers import AutoModelForCausalLM, AutoTokenizer # ===================== Qwen 本地模型路径 ===================== model_path = "/home/model/Qwen/Qwen-7B-Chat/" # 全局中文不乱码 plt.rcParams['font.sans-serif'] = ['SimHei', 'WenQuanYi Micro Hei'] plt.rcParams['axes.unicode_minus'] = False # ===================== 1. 加载 Qwen-7B 原生模型 ===================== tokenizer = AutoTokenizer.from_pretrained(model_path, trust_remote_code=True) model = AutoModelForCausalLM.from_pretrained( model_path, trust_remote_code=True, torch_dtype=torch.float16 ).cuda().eval() print("="*60) print("Qwen-7B-Chat 原生加载成功") print("模型原生激活:标准独立双支路 SwiGLU") print("="*60) # ===================== 2. 打印 Qwen 真实 FFN(Mlp) 结构 ===================== # Qwen-7B 使用 LLaMA 架构:transformer.h[0].mlp(非 .layers) mlp = model.transformer.h[0].mlp print("\n【Qwen-7B 原生FFN结构】") print(mlp) print("\nFFN权重模块:", mlp._modules.keys()) # w1 = gate门控线性 # w2 = up特征线性 # c_proj = 降维输出 # ===================== 3. 模拟模型输入,完整走一遍SwiGLU前向 ===================== batch, seq_len, hidden_dim = 1, 256, 4096 # 动态匹配模型实际 dtype(bfloat16 / float16),避免 Half != BFloat16 报错 hidden = torch.randn(batch, seq_len, hidden_dim).to(dtype=model.dtype, device='cuda') # Qwen标准SwiGLU分步计算 gate_h = mlp.w1(hidden) # 支路1:门控信号 up_h = mlp.w2(hidden) # 支路2:原始语义特征 silu_gate = torch.nn.functional.silu(gate_h) # SiLU门控激活 swiglu_out = up_h * silu_gate # SwiGLU核心相乘融合 final_out = mlp.c_proj(swiglu_out) # 降维还原维度 print("\n【SwiGLU逐层张量维度变化】") print(f"输入特征维度:{hidden.shape}") print(f"门控支路w1输出:{gate_h.shape}") print(f"特征支路w2输出:{up_h.shape}") print(f"SiLU门控加权后:{silu_gate.shape}") print(f"SwiGLU融合输出:{swiglu_out.shape}") print(f"最终降维输出:{final_out.shape}") # ===================== 4. 数学曲线:Qwen同款SwiGLU函数+梯度 ===================== x = np.linspace(-6, 6, 1200) def silu(x): return x / (1 + np.exp(-x)) def swiglu(x): return x * silu(x) y_swig = swiglu(x) dx = x[1]-x[0] grad_swig = np.gradient(y_swig, dx) # 单独保存SwiGLU曲线图 plt.figure(figsize=(9,5), dpi=130) plt.plot(x, y_swig, c='#27ae60', lw=2.8, label='Qwen-7B SwiGLU 函数曲线') plt.plot(x, grad_swig, c='#2ecc71', lw=2, ls='--', label='SwiGLU 反向传播梯度') plt.axhline(0,c='k',ls='--',alpha=0.4) plt.axvline(0,c='k',ls='--',alpha=0.4) plt.title("Qwen-7B-Chat 原生SwiGLU 函数与梯度分布", fontsize=14) plt.xlabel("输入特征 x") plt.ylabel("输出值 / 梯度大小") plt.legend() plt.grid(alpha=0.3) plt.tight_layout() plt.savefig("Qwen7B_SwiGLU函数梯度图.png", dpi=150, bbox_inches='tight', facecolor='white', edgecolor='none') plt.close() # ===================== 5. Qwen标准双支路FFN架构图 ===================== plt.figure(figsize=(11,4.5), dpi=130) plt.axis('off') plt.title("Qwen-7B-Chat 行业标准独立双支路 SwiGLU FFN架构", fontsize=14, color='#27ae60') plt.text(0.04, 0.86, '输入语义特征 4096', fontsize=12) plt.arrow(0.17,0.86,0.07,-0.23,width=0.009) plt.arrow(0.17,0.86,0.07,0.23,width=0.009) plt.text(0.28, 0.60, 'W1 独立门控权重', color='#27ae60') plt.text(0.28, 1.08, 'W2 独立特征权重', color='#2ecc71') plt.arrow(0.41,0.60,0.06,0.16,width=0.008) plt.arrow(0.41,1.08,0.06,-0.16,width=0.008) plt.text(0.51, 0.78, 'Gate → SiLU平滑门控', fontweight='bold') plt.text(0.60, 0.78, '×', fontsize=16) plt.text(0.66, 0.78, 'Value原始特征', fontweight='bold') plt.arrow(0.76,0.78,0.09,0,width=0.01) plt.text(0.86, 0.78, 'C_proj 降维 → 输出4096') plt.text(0.08, 0.42, '✅ 两路权重完全独立,不共用参数') plt.text(0.08, 0.30, '✅ 梯度全程平稳,长上下文无衰减') plt.text(0.08, 0.18, '✅ 完美适配INT4量化、MoE混合专家、LoRA微调') plt.xlim(0,1) plt.ylim(0,1) plt.tight_layout() plt.savefig("Qwen7B_SwiGLU_FFN架构图.png", dpi=150, bbox_inches='tight', facecolor='white', edgecolor='none') plt.close() # ===================== 6. 长文本真实推理:体现SwiGLU长记忆优势 ===================== long_text = "大语言模型Transformer架构中,FFN层依靠SwiGLU门控激活存储海量世界知识、逻辑推理、上下文语义规律,相比GELU梯度不衰减,长文本上下文记忆更强" * 40 inputs = tokenizer(long_text, return_tensors="pt").to("cuda") with torch.no_grad(): out = model(**inputs) print(f"\n长文本Token长度:{inputs.input_ids.shape[1]}") print("Qwen-7B 使用SwiGLU,超长上下文逻辑连贯、不遗忘、不混乱") print("对比ChatGLM2(GELU),长文本极易梯度衰减、前言不搭后语") ``` ![](https://developer.qcloudimg.com/http-save/yehe-11883445/09951d356c9a775315350de6264f25cf.png) 输出结果: > ============================================================ Qwen-7B-Chat 原生加载成功 模型原生激活:标准独立双支路 SwiGLU ============================================================ 【Qwen-7B 原生FFN结构】 QWenMLP( (w1): Linear(in_features=4096, out_features=11008, bias=False) (w2): Linear(in_features=4096, out_features=11008, bias=False) (c_proj): Linear(in_features=11008, out_features=4096, bias=False) ) FFN权重模块: dict_keys(['w1', 'w2', 'c_proj']) 【SwiGLU逐层张量维度变化】 输入特征维度:torch.Size([1, 256, 4096]) 门控支路w1输出:torch.Size([1, 256, 11008]) 特征支路w2输出:torch.Size([1, 256, 11008]) SiLU门控加权后:torch.Size([1, 256, 11008]) SwiGLU融合输出:torch.Size([1, 256, 11008]) 最终降维输出:torch.Size([1, 256, 4096]) 长文本Token长度:1920 Qwen-7B 使用SwiGLU,超长上下文逻辑连贯、不遗忘、不混乱 对比ChatGLM2(GELU),长文本极易梯度衰减、前言不搭后语 Qwen标准双支路SwiGLU FFN架构图: ![](https://developer.qcloudimg.com/http-save/yehe-11883445/6c2c93629799f41492d6441b6fba89d8.png) **“×” 标记的含义:** 图中的 “×” 符号表示逐元素相乘(Element-wise Multiplication)运算: - 左侧输入:Gate支路经过SiLU激活函数后产生的门控权重(0-1之间的值) - 右侧输入:Value支路的原始语义特征 - 运算作用:门控权重与原始特征逐元素相乘,筛选重要语义信息、压制无用特征 - 等效效果:类似于一个可学习的“注意力开关”,决定哪些信息保留、哪些过滤 **架构核心特点:** - W1(门控权重):独立学习门控系数,决定特征保留程度 - W2(特征权重):独立学习原始语义特征 - SiLU激活:平滑门控,避免梯度消失 - 逐元素相乘(×):融合门控与特征,实现自适应筛选 - C_proj降维:将4倍扩维后的特征压缩回原始维度 这种双支路结构是SwiGLU的核心优势:门控与特征解耦学习,相比传统FFN表达能力更强、收敛更稳定。 ![](https://developer.qcloudimg.com/http-save/yehe-11883445/f4d7a11d7824439421c212cd95ab0429.png) # 十二、总结 从ReLU到GELU,再到如今全面普及SwiGLU,大模型激活函数迭代从来不是跟风,而是模型规模、知识容量、训练稳定、推理部署、MoE 稀疏架构、行业落地全维度需求倒逼升级。 ReLU赢在简单,GELU赢在平滑,而SwiGLU赢在全面适配大模型所有痛点:更强高阶非线性、极致训练稳定、更高知识记忆上限、更低显存占用、更快推理速度、无损量化部署、完美适配MoE稀疏架构、微调大幅提升专业领域能力。 FFN作为大模型知识心脏,SwiGLU 就是心脏最优动力引擎。未来更长上下文、万亿 MoE、端边云全场景大模型,SwiGLU 依然会是长期标配激活函数。理解SwiGLU底层逻辑,就打通了Transformer FFN核心、大模型训练调参、模型微调、部署量化、MoE架构全套关键知识点,也是进阶大模型架构研发、模型炼化、私有化部署必备底层认知。 ![](https://developer.qcloudimg.com/http-save/yehe-11883445/8817020f3e0f589cd55d20998d51fb7c.png)

优秀的个人博客,低调大师

以替代 MyBatis 为己任,融合 JPA 和超强 SQL 功能 sqltoy-orm 5.6.26 发版了

兄弟们,让mybatis退出历史舞台吧,mybatis的存在引发了反xml之争、反sql之争,产生了成百个的plus系列,无尽的争吵、无尽的后来者开发plusplus! 开源地址: github:https://github.com/sagframe/sagacity-sqltoy gitee:https://gitee.com/sagacity/sagacity-sqltoy idea 插件 (可直接在 idea 中检索安装):https://github.com/imyuyu/sqltoy-idea-plugin sqltoy 脚手架项目:https://gitee.com/momoljw/sss-rbac-admin sqltoy lambda 项目:https://gitee.com/gzghde/sqltoy-plus 更新内容 1、针对batchUpdate、saveAll、updateAll、saveOrUpdateAll、loadAll等批量操作,针对超大数据集场景提供并行执行机制 @Test public void testDeleteAll() { List entites = new ArrayList(); for (int i = 1; i < 3000; i++) { entites.add(new ComplexpkHeadVO(LocalDateTime.parse("2020-09-08T12:11:20"), "S000" + i)); } // 最小1000作为一个并行分组,并行度10、最大等待时间120秒 lightDao.delete().parallelConfig(ParallelConfig.create().groupSize(1000) .maxThreads(10).maxWaitSeconds(120)).many(entites); //批量修改 //lightDao.update().parallelConfig(ParallelConfig.create().groupSize(1000)).many(entites); //批量保存 //lightDao.save().parallelConfig(ParallelConfig.create().groupSize(1000)).many(entites); //批量saveOrUpdate,saveMode(SaveMode.UPDATE)存在则修改 //lightDao.save().saveMode(SaveMode.UPDATE).parallelConfig(ParallelConfig.create() // .groupSize(1000)).many(entites); //lightDao.batch().sql(sql).dataSet(batchDataSet).parallelConfig(ParallelConfig.create().groupSize(1000)).submit() } 2、sql支持if\elseif\else 逻辑 String sql = """ select * from table where 1=1 #[@if(:flag==1) and status=:status #[@if(:operateType==2) and saleType is not :saleType] #[@else and saleType is :saleType] ] #[@elseif(:flag==2) and name like :name] #[@else and orderType=:orderType] #[@if(:tenantId==4) and tenant=1] #[@elseif(:tenantId==3) and tenant=3] """; SqlToyResult result = SqlConfigParseUtils.processSql(sql,new String[] { "flag", "status", "name", "orderType", "saleType", "operateType", "tenantId" },new Object[] { 1, 1, "张", "SALE", null, 4, 3 }); JPA 部分 类似 JPA 的对象化 CRUD、对象级联加载和新增、更新 支持通过 POJO 生成 DDL 以及直接向数据库创建表 强化 update 操作,提供弹性字段修改能力,不同于 hibernate 先 load 后修改,而是一次数据库交互完成修改,确保了高并发场景下数据的准确性 改进了级联修改,提供了先删除或者先置无效,再覆盖的操作选项 增加了 updateFetch、updateSaveFetch 功能,强化针对强事务高并发场景的处理,类似库存台账、资金台账,实现一次数据库交互,完成锁查询、不存在则插入、存在则修改,并返回修改后的结果 增加了树结构封装,便于统一不同数据库树型结构数据的递归查询 支持分库分表、支持多种主键策略 (额外支持基于 redis 的产生特定规则的业务主键)、加密存储、数据版本校验 提供了公共属性赋值 (创建人、修改人、创建时间、修改时间、租户)、扩展类型处理等 提供了多租户统一过滤和赋值、提供了数据权限参数带入和越权校验 查询部分 极为直观的 sql 编写方式,便于从客户端 <--> 代码 双向快速迁移,便于后期变更维护 支持缓存翻译、反向缓存匹配 key 代替 like 模糊查询 提供了跨数据库支持能力:不同数据库的函数自动转换适配,多方言 sql 根据实际环境自动匹配、多数据库同步测试,大幅提升了产品化能力 提供了取 top 记录、随机记录等特殊场景的查询功能 提供了最强大的分页查询机制:1) 自动优化 count 语句;2) 提供基于缓存的分页优化,避免每次都执行 count 查询;3) 提供了独具特色的快速分页;4) 提供了并行分页 提供了分库分表能力 提供了在管理类项目中极为价值的:分组汇总计算、行列转换 (行转列、列转行)、同比环比、树形排序、树形汇总 相关算法自然集成 提供了基于查询的层次化数据结构封装 提供了大量辅助功能:数据脱敏、格式化、条件参数预处理等 支持多种数据库 常规的 mysql、oracle、db2、postgresql、 sqlserver、dm、kingbase、sqlite、h2、 oceanBase、polardb、guassdb、tidb 支持分布式 olap 数据库: clickhouse、StarRocks、greenplum、impala (kudu) 支持 elasticsearch、mongodb 所有基于 sql 和 jdbc 各类数据库查询 sqltoy 特点介绍: sqltoy 的核心构建思想 sqltoy 的对比 mybatis (plus) 的核心点:查询语句编写、可阅读性、可维护性 对象化 crud 是基础,但 sqltoy 有针对性的改进:update、updateSaveFetch、updateFetch 等 sqltoy 的缓存翻译,大幅减少表关联简化 sql,让你的查询性能成几何级提升 极致的分页,同样帮助你实现查询的性能大幅提升 快速分页:@fast () 实现先取单页数据然后再关联查询,极大提升速度 分页优化器:page-optimize 让分页查询由两次变成 1.3~1.5 次 (用缓存实现相同查询条件的总记录数量在一定周期内无需重复查询 sqltoy 的分页取总记录的过程不是简单的 select count (1) from (原始 sql);而是智能判断是否变成:select count (1) from 'from 后语句 ', 并自动剔除最外层的 order by sqltoy 支持并行查询:parallel="true",同时查询总记录数和单页数据,大幅提升性能 便利的跨数据库统计计算:数据旋转 便利的跨数据库统计计算:无限极分组统计 (含汇总求平均) 便利的跨数据库统计计算:同比环比 5、树形表排序汇总 6、扩展集成

优秀的个人博客,低调大师

vue2的$refs在vue3组合式API中的替代方法

如果你有过vue2的项目开发经验,那么对$refs就很熟悉了。由于vue3的断崖式的升级,在vue3中如何使用$refs呢?想必有遇到过类似的问题,我也有一样的疑惑。通过搜索引擎和github,基本掌握如何使用$refs。在vue3中使用组合式API的函数ref来代替静态或者动态html元素的应用。 最近业余在学习vue3项目《蜡笔(Crayon)管理模板:Vue3 + Vuex4 + Ant Design2》开发,这两天迭代推进了一点,实现了chart图表组件,写文章的时候发现提交代码的commit有错别字。 在vue3中使用组合式API的setup()方法的时候,无法正常使用this.$refs,但可以使用新的函数ref()。 下面代码摘自:https://github.com/QuintionTang/crayon/blob/feat-dashboard/src/qtui/components/Chart.vue <template> <canvas ref="refChart" :height="setHeight"></canvas> </template> <script> import { defineComponent, onMounted, ref, inject, watch } from "vue"; import Chart from "chart.js"; import { deepCopy } from "@/helper/index"; export default defineComponent({ name: "QtChart", props: { type: { type: String, required: true, default: "line", }, data: { type: Object, required: true, default: () => ({}), }, options: { type: Object, default: () => ({}), }, height: { type: Number, default: 0, }, refKey: { type: String, default: null, }, }, setup(props) { const refChart = ref(); // 初始化方法 const init = () => { const canvasChart = refChart.value?.getContext("2d"); const chartHelper = new Chart(canvasChart, { type: props.type, data: deepCopy(props.data), options: props.options, }); watch(props, () => { chartHelper.data = deepCopy(props.data); chartHelper.options = props.options; chartHelper.update(); }); // 附加一个实例给refChart refChart.value.instance = chartHelper; }; // 设置高度 const setHeight = () => { return { height: props.height, }; }; // 绑定一个实例,使用inject注入 const bindInstance = () => { if (props.refKey) { const bind = inject(`bind[${props.refKey}]`); if (bind) { bind(refChart.value); } } }; onMounted(() => { bindInstance(); init(); }); return { refChart, setHeight, }; }, }); </script> 这段代码完整的实现了一个图表组件Chart,其中自定义了属性props,通过把参数传递给setup方法来使用其属性值。html中定义一个ref="refChart"来作为图表的dom对象,在setup方法中通过方法ref方法来定义响应式可变对象,并在setup函数结尾作为返回值。 const refChart = ref(); 需要注意的是,返回值的属性名必须和html中的ref值一致。 下面代码是可以正常执行的。 <template> <canvas ref="refChart" :height="setHeight"></canvas> </template> <script> import { defineComponent, onMounted, ref, inject, watch } from "vue"; import Chart from "chart.js"; import { deepCopy } from "@/helper/index"; export default defineComponent({ name: "QtChart", props: { // ... }, setup(props) { const refChartBox = ref(); // ... return { refChart:refChartBox, }; }, }); </script> 下面的情况,会出现程序错误,无法达到预期效果。应为html中定义的ref="refChart"和setup返回的refChartBox不一致。 <template> <canvas ref="refChart" :height="setHeight"></canvas> </template> <script> import { defineComponent, onMounted, ref, inject, watch } from "vue"; import Chart from "chart.js"; import { deepCopy } from "@/helper/index"; export default defineComponent({ name: "QtChart", props: { // ... }, setup(props) { const refChartBox = ref(); // ... return { refChartBox, }; }, }); </script> 结论 本文只是简单的介绍ref方法的使用,正好在项目中用到,后续将继续边学边推进项目并做好笔记。

优秀的个人博客,低调大师

Cursor 用 S3 上的 WAL 替代副本协调,Push 吞吐量超过每秒 300 次

## 背景 传统的大规模 Git 托管架构依赖多副本协调。GitHub 的 Spokes 架构在多个 NVMe 设备上维护仓库副本,通过三阶段提交更新 Git 引用,确保副本间同步。这种方法的问题在于副本数量增加时,协调开销随之上升。对于需要支撑大量 CI 负载的单体仓库,或者 Coding Agent 创建的海量小型仓库,副本协调会成为瓶颈。 Cursor 面临的实际需求促使他们重新设计存储架构。他们需要一种既能应对重度 CI 负载的大型代码仓库,又能高效管理数量庞大的小型仓库的方案。Continuity 架构放弃了副本协调这一传统路径,转向将对象存储作为事实来源的设计思路。这一转变带来的不仅是性能提升,还重新定义了本地副本的角色。 ## 核心原理 Continuity 将 S3 上的预写日志(WAL)设为持久化存储的唯一事实来源。当用户执行 Push 操作时,系统先将数据上传到 S3,再把引用更新记录到 WAL 中。只有数据完成持久化后,系统才会确认 Push 成功。Cursor 通过批处理操作降低 S3 PUT 请求延迟对吞吐量的影响。 本地 NVMe 上的 Git 仓库被重新定义为温缓存,不再是权威副本。系统使用 Rendezvous Hashing 选择优先处理请求的节点,同时利用 S3 的原子比较并交换(Compare-and-Swap)操作,让任意服务器都能接受 Push 请求。如果某台服务器本地没有仓库副本,它可以根据 WAL 重新生成。 WAL 更新通过 UDP Gossip 协议在节点间传播,系统通过带条件的 S3 读取校验副本状态。Cursor 称这类读取的平均耗时不到 10 毫秒。Gossip 消息即使丢失也不会影响数据正确性,因为 S3 始终是事实来源。这种设计让系统容忍了网络不可靠性,不再需要副本间的强一致性协调。 副本扩展和 Git 压缩的处理方式也发生了变化。单体仓库可以为 CI 工作负载扩展到数百个副本,暂时无活动的仓库则可以等到需要时再生成本地副本。Git 压缩只由主副本执行,其他副本直接从 S3 下载压缩后的 packfile,减少了重复的 CPU 开销,代价是增加了带宽消耗。 ## 局限 Cursor 公布的性能数据尚未经过独立验证。在使用自己的 everysphere 单体仓库进行的合成测试中,使用 S3 Standard 时每秒最多处理 120 次 Push,换用 S3 Express One Zone 后超过 300 次。当吞吐量进一步提高时,Git 压缩成为新的性能瓶颈。 这种架构需要依靠存储校验和异步传播来保证副本状态,并付出额外的带宽成本以减少副本协调开销。从数据库设计角度看,Continuity 相当于把 Git 存储当作数据库来处理,Push 的一致性保证、Force Push 涉及的事务以及时间点恢复等问题都值得关注。 本地副本降级为缓存后,系统对 S3 的依赖程度提高。如果 S3 出现延迟波动或可用性问题,会直接影响整个存储系统的表现。批处理操作虽然降低了延迟影响,但也引入了额外的复杂性。 ## 对开发者的意义 Continuity 展示了将对象存储作为分布式系统事实来源的可行性。它不再要求多个副本通过同步协调维持一致状态,而是让各个本地仓库独立向 S3 中记录的状态收敛。这种设计思路可以应用到其他需要大规模存储和高吞吐量的系统中。 对于需要支撑大量 CI 负载的团队,Continuity 提供了一种新的扩展路径。单体仓库可以为 CI 工作负载扩展到数百个副本,读取能力随副本数量线性增长。对于管理大量小型仓库的场景,按需生成本地副本的能力可以节省存储资源。 Cursor 工程师 Vicent Martí 公开的设计细节显示,从副本协调转向对象存储作为事实来源,是一个值得验证的架构方向。系统在测试中满足线性一致性要求,数据在请求确认前已持久化到外部存储,Clone 操作也始终保持一致性。高级软件工程师 Maksim Al Dandan 指出,这一思路将 Git 存储问题转化为数据库设计问题,后续需要解决的是 Push 一致性、事务处理和恢复能力等传统数据库关注的问题。

资源下载

更多资源
腾讯云软件源

腾讯云软件源

为解决软件依赖安装时官方源访问速度慢的问题,腾讯云为一些软件搭建了缓存服务。您可以通过使用腾讯云软件源站来提升依赖包的安装速度。为了方便用户自由搭建服务架构,目前腾讯云软件源站支持公网访问和内网访问。

Spring

Spring

Spring框架(Spring Framework)是由Rod Johnson于2002年提出的开源Java企业级应用框架,旨在通过使用JavaBean替代传统EJB实现方式降低企业级编程开发的复杂性。该框架基于简单性、可测试性和松耦合性设计理念,提供核心容器、应用上下文、数据访问集成等模块,支持整合Hibernate、Struts等第三方框架,其适用范围不仅限于服务器端开发,绝大多数Java应用均可从中受益。

Sublime Text

Sublime Text

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。

WebStorm

WebStorm

WebStorm 是jetbrains公司旗下一款JavaScript 开发工具。目前已经被广大中国JS开发者誉为“Web前端开发神器”、“最强大的HTML5编辑器”、“最智能的JavaScript IDE”等。与IntelliJ IDEA同源,继承了IntelliJ IDEA强大的JS部分的功能。

用户登录
用户注册