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

Unity UI 性能优化--Sprite 篇

🎯 Unity UI 性能优化终极指南 — Sprite篇


🧩 Sprite 是什么?—— 渲染的基石与性能的源头

在Unity的2D渲染管线中,Sprite 扮演着至关重要的角色。它不仅仅是2D图像资源本身,更是GPU进行渲染批处理(Batching)的基础单位。无论是UI系统(UGUI)、2D游戏场景中的角色/物件,还是粒子特效,都离不开Sprite的支撑。

  • 核心定义: Sprite是Unity中用于表示2D图像的资源类型。它通常由一张或多张图片(纹理)切割而成,每一块可独立渲染的区域被称为一个“精灵”。
  • 广泛依赖:
    • Image (UGUI): UI界面中最常用的组件,用于显示图片、图标。
    • RawImage (UGUI): 直接渲染纹理,通常用于显示动态纹理或不适合SpriteAtlas的图像。
    • SpriteRenderer: 2D游戏中的主要渲染组件,用于渲染游戏世界中的2D对象。
    • ParticleSystem: 粒子特效系统,粒子的渲染材质通常也引用Sprite或纹理。
  • 性能命脉: Sprite资源的组织、管理和使用方式,直接且深远地影响着游戏运行时的Draw Call数量、内存(尤其是显存)占用、CPU渲染开销以及纹理缓存(Texture Cache)的效率。 它是2D渲染性能优化中“牵一发而动全身”的核心要素。

一句话精髓: Sprite是UI和2D渲染的“食材”,决定了画质和内存;材质(Material)是“锅”,承载着渲染属性;批处理(Batching)是“厨艺”,将零散的“食材”高效地“烹饪”出来。三者协同,方能成就高性能的视觉盛宴。


🧩 生活化比喻——从外卖到定制时装,理解Sprite的优化哲学

为了更直观地理解Sprite的性能影响,我们来用生活中的例子进行类比:

概念生活比喻性能洞察
单独小图Sprite单份外卖,每份外卖都由一个骑手单独配送每次渲染都需要切换纹理,Draw Call 激增,GPU效率低下。
Atlas合图Sprite把多份外卖统一打包,由一个骑手一车送走将多张小图合并到一张大纹理上,减少纹理切换,实现批处理,大幅降低 Draw Call
大图未切分(如背景图)巨无霸披萨,一个人吃不完,很多都浪费了将不需要的部分也加载到内存,造成 显存浪费,且渲染小部分时,GPU仍需处理整张大图的数据。
多尺寸重复图同款衣服S、M、L码各存三件,库存爆炸为适配不同分辨率,将同一图片保存多套尺寸,导致 冗余内存 占用。
Sprite Variant按需定制尺寸,同款衣服裁不同大小,库存少,适配灵活基于原始Sprite生成不同分辨率的变体,按设备按需加载,兼顾画质与性能,避免资源冗余。
纹理压缩把食材冷冻或脱水,减小体积,方便存储和运输减少纹理在内存中的占用,降低加载时间,但可能牺牲一定画质。

🎯 Sprite 核心性能影响因素——数据流与渲染管线的瓶颈

Sprite的性能影响深入到渲染管线的每一个环节,从资源加载、内存占用,到CPU的绘制指令和GPU的渲染效率。

影响点说明核心性能影响
1. 纹理大小 (Texture Size)指Sprite所引用纹理的分辨率(如2048x2048)。纹理越大,其占用的显存和主存越多。同时,大纹理的加载时间更长,并且可能在GPU纹理缓存中造成更多的缓存未命中(Cache Miss),导致GPU频繁从显存中读取数据,效率降低。🚨 显存爆炸 + 加载慢 + GPU Cache Miss
2. 纹理压缩 (Texture Compression)未压缩的纹理(如RGBA32)占用巨大内存。合理的纹理压缩(如ASTC, ETC2, DXT)可以在可接受的画质损失下大幅减少内存占用。不合理的压缩(如低质量压缩或使用错误的格式)可能导致图像失真、色块或Alpha通道问题。💣 内存占用巨增 + 显示伪影
3. 不同Sprite源纹理混用Unity的批处理机制要求所有被批处理的Sprite必须引用来自同一个源纹理(Source Texture)。如果场景中渲染的Sprite引用了不同的纹理(即使它们是同一张合图中的不同Sprite),都会强制打断批处理,生成新的Draw Call。🔥 Draw Call激增 + 渲染开销大
4. 无Atlas打包(Sprite Atlas)Atlas(图集、合图)是将多个小Sprite合并到一张大纹理上的技术。如果小图没有被打包进Atlas,则每个小图都会有自己的独立纹理。渲染这些小图时,GPU需要频繁切换纹理,每次切换都会产生一个新的Draw Call。🐢 CPU + GPU双重开销 + 批处理失效
5. Sprite Variant未利用为适配不同分辨率(如iPhone 8和iPad Pro),如果只使用一套高分辨率的大图,低端设备会加载不必要的超大纹理,导致内存溢出或卡顿。如果为每个分辨率手动创建多套不同尺寸的图集,则资源管理复杂。Sprite Variant允许Unity根据设备DPI自动选择最适合的图集。🧨 低端掉帧 + 高端浪费性能 + 适配复杂
6. Overdraw(过度绘制)指屏幕上某个像素被多次绘制。虽然Sprite本身不是Overdraw的唯一原因,但大量透明或半透明Sprite的层叠,以及UI元素的不合理布局(如背景图被前景图完全覆盖但仍参与绘制),会显著增加GPU的像素填充率(Fill Rate),导致性能瓶颈。💨 GPU填充率瓶颈 + 功耗增加

🎯 量化性能数据(实测分析)—— 优化前后对比

以下数据模拟了典型场景下的性能差异,旨在量化Sprite优化带来的实际效益。测试环境为中端移动设备。

测试场景显存占用(MB)Draw Call帧率 (FPS)性能分析及优化建议
1024张单独小图(无Atlas)~512 MB500+38 fps显存分析: 每张小图独立纹理,虽然单张小,但累计占用巨大。Draw Call分析: 每张图一个Draw Call,GPU命令队列塞满。帧率分析: CPU忙于发送Draw Call,GPU忙于切换状态。<mark>优化重点: 必须合图!</mark>
合图Atlas打包(4096x4096)~256 MB3560 fps显存分析: 虽然合图尺寸大,但所有小图共享一张纹理,总占用减少。Draw Call分析: 大部分Sprite来自同一合图,实现静态批处理,Draw Call剧减。帧率分析: 批处理效率高,CPU/GPU开销降低。<mark>这是基础优化!</mark>
未压缩PNG纹理(RGBA32)~600 MB3558 fps显存分析: 即便合图,但未压缩导致纹理数据量庞大。Draw Call分析: 合图解决了Draw Call问题。帧率分析: 帧率尚可,但内存压力巨大,易触发OOM。<mark>优化重点: 务必压缩纹理!</mark>
使用ASTC压缩纹理~150 MB3559 fps显存分析: 在保持视觉质量前提下,内存占用大幅降低。Draw Call分析: 不变。帧率分析: 稳定,且内存压力小。<mark>最佳实践,移动端首选ASTC。</mark>
不同分辨率共用大图~512 MB3540 fps显存分析: 低分辨率设备加载了高分辨率图集,导致内存浪费。Draw Call分析: 合图依旧有效。帧率分析: 帧率下降可能是内存带宽瓶颈或CPU解压/处理大图开销。<mark>优化重点: 利用Sprite Variant按需加载。</mark>
用Sprite Variant按需切换~160 MB3560 fps显存分析: 根据设备DPI加载最合适的图集,内存占用合理。Draw Call分析: 不变。帧率分析: 稳定高效。<mark>现代游戏分辨率适配的关键技术。</mark>

🚨 Sprite 低性能代码示例(踩坑警告)—— 运行时动态加载的陷阱

以下代码展示了常见的、但极具性能危害的Sprite使用方式。在项目中务必避免!

// 🚨 每次动态Load Sprite,资源碎片化+GC Alloc,批处理断裂!
// 这种模式在生产环境中,尤其是在Update/LateUpdate中,是性能杀手!
void Update()
{// 假设UI/Icons/icon_X.png 是未经打包的单独小图// 或即便打包,但每次都通过Resources.Load或AssetBundle.LoadAsset同步加载,而非从预加载的缓存中获取Sprite sprite = Resources.Load<Sprite>("UI/Icons/icon_" + Time.frameCount % 100); // 假设有100张图标if (sprite != null){myImage.sprite = sprite;}// ⚠️ 每次Load都会创建一个新的Object,可能产生GC Alloc,且每次Load都会导致CPU解压纹理数据// ⚠️ 更重要的是,每次引用的Sprite都可能来自不同的纹理源,完全破坏批处理!
}// 另一个常见但隐蔽的问题:
// 尽管最终引用的是同一个Sprite Atlas,但如果Atlas的AssetBundle或Resources.LoadAll操作
// 在不恰当的时机(如频繁的UI切换)重复执行,仍会导致重复加载和GC。

⚠️ 深层问题剖析

  1. 高频GC Alloc: Resources.LoadAssetBundle.LoadAsset(同步加载)会为每次加载操作在托管堆上分配内存。如果在 UpdateLateUpdate 中频繁调用,将导致每帧产生大量GC(Garbage Collection)垃圾,进而频繁触发GC,造成游戏卡顿(Stutter)。
  2. 批处理失效(Batching Break): 每次动态加载的Sprite,即使它们最终来自同一个Atlas,在Unity运行时,如果加载方式不当,可能导致它们被视为不同的“源纹理”(即使纹理数据相同,但其运行时实例或引用路径不同),从而破坏批处理。GPU被迫为每个Sprite执行独立的Draw Call。
  3. 纹理缓存爆炸(Texture Cache Thrashing): 当频繁加载和卸载大量不同的Sprite时,GPU的纹理缓存(一个有限的高速缓存)会不断地被新的纹理数据冲刷,导致缓存命中率极低。GPU不得不频繁地从速度较慢的显存中获取纹理数据,严重影响渲染效率。
  4. CPU开销巨大: 动态加载操作涉及文件I/O、数据解压、纹理上传至GPU等耗时操作。在游戏运行时执行这些操作,会显著增加CPU负担,挤占游戏逻辑和物理计算的时间。

✅ Sprite 优化代码示例——预加载与统一引用

正确的Sprite管理策略是预加载统一引用,确保批处理的有效性,并避免运行时开销。

// ✅ 高效写法:预加载Sprite Atlas中的所有Sprite,并缓存引用。
// 适用于UI图标、表情等需要频繁切换且数量固定的Sprite集合。private Sprite[] _cachedIcons; // 缓存所有Sprite的引用
[SerializeField] private Image _myImage; // 绑定到Inspector的Image组件private void Awake()
{// 1. 通过Resources.LoadAll预加载整个Sprite Atlas的所有Sprite// 注意:Resources.LoadAll会加载指定路径下的所有对象,这里假设IconsAtlas是一个Sprite Atlas Asset// 更推荐通过AssetBundle异步加载,尤其对于大型项目_cachedIcons = Resources.LoadAll<Sprite>("UI/Icons/IconsAtlas"); // 或者,如果Atlas是独立打包的AssetBundle,推荐异步加载// StartCoroutine(LoadAtlasAsync("UI/Icons/IconsAtlasBundle"));
}/*
// 异步加载AssetBundle示例 (实际项目中更常用)
private IEnumerator LoadAtlasAsync(string bundleName)
{AssetBundleCreateRequest request = AssetBundle.LoadFromFileAsync(Application.streamingAssetsPath + "/" + bundleName);yield return request;AssetBundle atlasBundle = request.assetBundle;if (atlasBundle == null){Debug.LogError("Failed to load AssetBundle: " + bundleName);yield break;}AssetBundleRequest assetRequest = atlasBundle.LoadAllAssetsAsync<Sprite>();yield return assetRequest;_cachedIcons = System.Array.ConvertAll(assetRequest.allAssets, item => (Sprite)item);// atlasBundle.Unload(false); // 根据GC策略决定是否立即卸载AssetBundle,如果Sprite被引用则不能卸载
}
*/void Update()
{// 模拟UI图标的随机切换if (Time.frameCount % 30 == 0 && _cachedIcons != null && _cachedIcons.Length > 0){int randomIndex = Random.Range(0, _cachedIcons.Length);_myImage.sprite = _cachedIcons[randomIndex];// ✅ 核心:所有引用的Sprite都来自同一个预加载的Atlas纹理,保证批处理。// ✅ 避免了GC Alloc,因为是从已缓存的引用中获取。// ✅ 避免了文件I/O和解压开销,因为数据已在内存。}
}// 当UI界面关闭或不再需要这些Sprite时,可以考虑释放内存
private void OnDestroy()
{_cachedIcons = null; // 清空引用,让GC有机会回收内存// 如果是通过AssetBundle加载的,需要手动Unload AssetBundle// if (myAtlasBundle != null) myAtlasBundle.Unload(true);
}

🎯 优化思路详解

  1. ✅ 预加载到内存: 在场景加载或UI界面初始化时,一次性将所需的 Sprite Atlas 或其内部的 所有Sprite 预加载到内存中,并缓存它们的引用。这样,在后续的运行时,可以直接从内存中获取,避免了耗时的文件I/O和数据解压操作。
  2. ✅ 统一引用Atlas内Sprite,保障批处理: 通过 Resources.LoadAll<Sprite>("PathToAtlas")AssetBundle.LoadAllAssets<Sprite>() 获取的Sprite,它们都指向同一个底层纹理(即Sprite Atlas纹理)。当这些Sprite被用于 ImageSpriteRenderer 时,Unity的批处理机制就能高效地将它们合并到同一个Draw Call中,显著降低渲染开销。
  3. ✅ 减少频繁资源加载,降低GC Alloc: 一次性加载并缓存,避免了在 Update 等高频函数中重复调用 Resources.LoadAssetBundle.LoadAsset,从而消除了大量的临时内存分配,有效降低了GC压力,提升了游戏流畅度。
  4. ✅ 精细化内存管理: 在不需要这些Sprite时,及时清除对它们的引用,并考虑卸载相应的AssetBundle,以便内存能够被系统回收。

🧠 Sprite 性能优化技巧——从资源到运行时,全面提升

技巧说明
1. ✅ 打包Sprite Atlas(图集)核心! 这是2D渲染优化的基石。将大量小尺寸的UI图标、2D角色部件、粒子纹理等合并到一张或几张大尺寸的纹理(Atlas)上。Unity的 Sprite Packer 或第三方工具(如TexturePacker)能自动完成这项工作。作用: 减少纹理绑定切换次数,实现批处理(Batching),大幅降低 Draw Call,从而减轻CPU和GPU负担。
2. ✅ 控制Atlas尺寸并非越大越好! 推荐将单个Sprite Atlas的最大尺寸控制在 4096x4096 像素以内。过大的Atlas(如8192x8192)可能导致:<br/>- GPU纹理缓存未命中(Cache Miss)率增高:大纹理在GPU缓存中停留时间短,或无法完全载入,导致频繁从显存读取。<br/>- 显存占用过大:即便压缩,单张超大纹理仍会占用可观的显存。<br/>- 加载时间延长:加载一张超大纹理比加载多张小纹理更耗时。<br/>如果UI元素过多,应根据功能或模块 拆分多个Atlas,而非强行塞入一张巨型Atlas。
3. ✅ 使用纹理压缩 (Texture Compression)必备! 这是控制显存和主存占用最有效的手段。根据目标平台选择合适的压缩格式:<br/>- 移动端 (iOS/Android)ASTC 是目前最佳选择,支持多种块大小和比特率,压缩率高且画质损失小。其次是ETC2(Android)或PVRTC(iOS,较旧)。<br/>- 桌面端 (PC/Mac)DXT5 (RGBA) 或 DXT1 (RGB) 是主流选择,压缩率高,但不支持Alpha渐变(DXT5有Alpha但块状)。<br/>- 压缩设置: 在Texture Import Settings中,选择“Texture Type”为Sprite (2D and UI),然后根据平台选择“Format”,并调整“Compression”级别。平衡画质和压缩率,不要盲目选择最高压缩。

🧩 生活化理解总结——一句话,你的视觉资源管理之道

Sprite 就像你家里的食材,它需要你精心挑选、合理分类、高效打包和妥善储存。

  • 小包装送菜,交通爆堵;大餐盒整合配送,效率提升:形象比喻了 Atlas合图 的重要性。没有合图,每个小Sprite都是一个单独的Draw Call,如同每次外卖都单独派送一个骑手,交通(GPU指令队列)很快就堵塞了。合图则是将外卖统一打包,一个骑手送多份,效率翻倍。
  • 不压缩食材,冷藏爆仓:说明了 纹理压缩 的必要性。未经压缩的纹理就像未经处理的食材,体积巨大,迅速占满冰箱(显存),导致内存不足。
  • 菜品分量按人群定制,小孩餐/成人餐,省料省力:强调了 Sprite Variant 的作用。针对不同分辨率设备,提供对应尺寸的图集,就像为不同食量的人群定制餐点,既不浪费大尺寸食材的资源,又保证小食量人群的体验。

🎯 总结

小图合批(Batching),大图适度(Atlas Size),纹理压缩(Compression),按需变体(Sprite Variant)!
这是Sprite优化的四大核心原则,缺一不可。


🚀 最后的黄金口诀(PPT压轴)

图要打包,材要统一,纹要压缩,分要适配!


相关文章:

Unity UI 性能优化--Sprite 篇

&#x1f3af; Unity UI 性能优化终极指南 — Sprite篇 &#x1f9e9; Sprite 是什么&#xff1f;—— 渲染的基石与性能的源头 在Unity的2D渲染管线中&#xff0c;Sprite 扮演着至关重要的角色。它不仅仅是2D图像资源本身&#xff0c;更是GPU进行渲染批处理&#xff08;Batch…...

AI健康小屋+微高压氧舱:科技如何重构我们的健康防线?

目前&#xff0c;随着科技和社会的不断发展&#xff0c;人们的生活水平和方式有了翻天覆地的变化。 从吃饱穿暖到吃好喝好再到健康生活&#xff0c;观念也在逐渐发生改变。 尤其是在21世纪&#xff0c;大家对健康越来越重视&#xff0c;这就不得不提AI健康小屋和氧舱。 一、A…...

OpenCV C++ 学习笔记(五):颜色空间转换、数值类型转换、图像混合、图像缩放

文章目录 颜色空间转换cvtColor通道分离split通道合并merge数值类型转换convertTo图片混合addWeighted图片缩放resize 颜色空间转换cvtColor cvtColor 是 OpenCV 中用于将图像从一种色彩空间转换为另一种色彩空间的函数。它非常适用于各种图像处理任务&#xff0c;如灰度化、颜…...

如何做接口测试?

&#x1f345; 点击文末小卡片&#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 01、通用的项目架构 02、什么是接口 接口&#xff1a;服务端程序对外提供的一种统一的访问方式&#xff0c;通常采用HTTP协议&#xff0c;通过不同的url&#xff…...

【JMeter】性能测试知识和工具

目录 何为系统性能 何为性能测试 性能测试分类 性能测试指标 性能测试流程 性能测试工具&#xff1a;JMeter&#xff08;主测web应用&#xff09; jmeter文件目录 启动方式 基本元件&#xff1a;元件内有很多组件 jmeter参数化 jmeter关联 自动录制脚本 直连数据库…...

SOC-ESP32S3部分:25-HTTP请求

飞书文档https://x509p6c8to.feishu.cn/wiki/KL4RwxUQdipzCSkpB2lcBd03nvK HTTP&#xff08;Hyper Text Transfer Protocol&#xff09; 超文本传输协议&#xff0c;是一种建立在 TCP 上的无状态连接&#xff0c;整个基本的工作流程是客户端发送一个 HTTP 请求&#xff0c;说明…...

字符编码全解析:ASCII、GBK、Unicode、UTF-8与ANSI

UTF - 8(全球字符能被唯一标识)、GBK、Unicode、ANSI 区别与关联 qwen模型分词器文件 1. ASCII(基础铺垫,理解编码起源) 作用:最早期为处理英文文本设计,是字符编码的基础,后演变成其他编码兼容的一部分 。范围:共 128 个字符(0 - 127),包含英文大小写字母、数字…...

《前端面试题:HTML5、CSS3、ES6新特性》

现代前端开发中&#xff0c;HTML5、CSS3和JavaScript ES6共同构成了三大核心技术支柱。这些技术不仅显著提升了用户体验和性能表现&#xff0c;更大幅提高了开发效率。本文将从技术演进、核心特性到最佳实践&#xff0c;系统性地介绍这三大技术的应用之道。 我们将首先探讨HTM…...

MaxCompute开发UDF和UDTF案例

文章目录 一、Java开发UDF1、创建Maven项目2、创建UDF类3、打包上传资源4、创建函数MyUDF5、SQL验证 二、Java开发UDTF1、创建Maven项目2、创建UDTF类3、打包上传更新资源4、创建函数MyUDTF5、SQL验证 三、常见问题1、发布函数报错 一、Java开发UDF 1、创建Maven项目 创建Mav…...

49套夏日小清新计划总结日系卡通ppt模板

绿色小清新PPT模版&#xff0c;日系小清新PPT模版&#xff0c;粉红色PPT模版&#xff0c;蓝色PPT模版&#xff0c;草青色PPT模版&#xff0c;日系卡通PPT模版 49套夏日小清新计划总结日系卡通ppt模板&#xff1a;夏日小清新日系卡通PPT模版https://pan.quark.cn/s/9e4270d390fa…...

告别硬编码!用工厂模式优雅构建可扩展的 Spring Boot 应用 [特殊字符]

嗨&#xff0c;各位技术伙伴们&#xff01;&#x1f44b; 在日常的软件开发中&#xff0c;我们经常面临需求变更的挑战。如何构建一个既能满足当前需求&#xff0c;又能轻松应对未来变化的系统呢&#xff1f;答案往往藏在那些经典的设计模式中。 今天&#xff0c;我们就来聊聊…...

Express教程【006】:使用Express写接口

文章目录 8、使用Express写接口8.1 创建API路由模块8.2 编写GET接口8.3 编写POST接口 8、使用Express写接口 8.1 创建API路由模块 1️⃣新建routes/apiRouter.js路由模块&#xff1a; /*** 路由模块*/ // 1-导入express const express require(express); // 2-创建路由对象…...

mongodb集群之分片集群

目录 1. 适用场景2. 集群搭建如何搭建搭建实例Linux搭建实例(待定)Windows搭建实例1.资源规划2. 配置conf文件3. 按顺序启动不同角色的mongodb实例4. 初始化config、shard集群信息5. 通过router进行分片配置 1. 适用场景 数据量大影响性能 数据量大概达到千万级或亿级的时候&…...

Starrocks Full GC日志分析

GC日志样例&#xff1a; [2025-06-03T07:36:06.1770800] GC(227) Pause Full (G1 Evacuation Pause) [2025-06-03T07:36:06.1960800] GC(227) Phase 1: Mark live objects [2025-06-03T07:36:06.9480800] GC(227) Cleaned string and symbol table, strings: 47009 processed,…...

飞算 JavaAI 赋能老项目重构:破旧立新的高效利器

许多企业的 Java 老项目面临着代码陈旧、架构落后、维护困难等问题。老项目重构势在必行&#xff0c;却又因庞大的代码量、复杂的业务逻辑让开发团队望而却步。 老项目重构困境重重 传统的 Java 老项目往往在长期的迭代和维护中积累了诸多问题。一方面&#xff0c;代码质量堪…...

RockyLinux9安装Docker

如何在RockyLinux9下安装Docker RockyLinux采用了全新的dnf来进行包管理&#xff0c;dnf支持yum别名&#xff0c;还没习惯的可以将dnf替换为yum 确保dnf最新 sudo dnf update -y安装dnf-plugins-core包 sudo dnf install -y dnf-plugins-core yum-utils添加Docker的官方仓库…...

RequestRateLimiterGatewayFilterFactory

一、功能说明 RequestRateLimiterGatewayFilterFactory 是 Spring Cloud Gateway 的流量控制组件&#xff0c;用于实现 API 请求速率限制&#xff0c;核心功能包括&#xff1a; 限制单位时间内的请求数量&#xff08;如每秒10次&#xff09;防止服务被突发流量击垮&#xff0…...

解决 xmlsec.InternalError: (-1, ‘lxml xmlsec libxml2 library version mismatch‘)

解决 xmlsec.InternalError: (-1, ‘lxml & xmlsec libxml2 library version mismatch’) 错误信息如下&#xff1a; Traceback (most recent call last):File "/home/mobsf/Mobile-Security-Framework-MobSF/manage.py", line 18, in <module>execute_f…...

【Linux基础知识系列】第九篇-Shell脚本入门

在Linux世界中&#xff0c;Shell脚本是自动化任务和简化操作的重要工具。它可以帮助用户编写一系列命令&#xff0c;自动执行重复的任务&#xff0c;从而提高工作效率。在本篇文章中&#xff0c;我们将介绍Shell脚本的基本概念、编写方法、常用命令和结构。通过这些内容&#x…...

typescript的Interface和Type

类型别名和接口非常相似&#xff0c;在大多数情况下你可以在它们之间自由选择。 几乎所有的 interface 功能都可以在 type 中使用&#xff0c;关键区别在于不能重新开放类型以添加新的属性&#xff0c;而接口始终是可扩展的。 // window.ts.transpileModule(src, {}); 这是调…...

java后端生成心电图-jfreechart

用jfreechart生成心电图 先上成功的图片 上代码 1.导入包 implementation org.jfree:jfreechart:1.5.4implementation org.jfree:jcommon:1.0.242.实现代码 对数据进行滤波 转换单位 package com.shinrun.infrastructure.util;import java.util.ArrayList; import java.ut…...

算法/机理模型演示平台搭建(二)——算法接口部署(FastApi)

算法/机理模型演示平台搭建(二)—— 算法接口部署(FastApi) 1. 项目结构2. 构建 Docker 镜像3. 运行 Docker 容器4. 访问 API 文档5. 调用 API1. 项目结构 app app/algorithms app/models Dockerfile FROM python:3.9-slimWORKDIR /codeCOPY ./requirements.txt /code…...

动态规划-647.回文子串-力扣(LeetCode)

一、题目解析 这里的子字符串是连续的&#xff0c;与之前的子序列不同&#xff0c;这里需要我们统计回文子串的数目。 二、算法原理 这里也有其他算法可以解决该问题&#xff0c;如中心扩展算法 时间复杂度O(N^2)/空间复杂度O(1)&#xff0c;马拉车算法(具有局限性) 时间复杂…...

es 的字段类型(text和keyword)

Text 当一个字段是要被全文检索时&#xff0c;比如 Email 内容、产品描述&#xff0c;这些字段应该使用 text 类型。设置 text 类型以后&#xff0c;字段内容会被分析&#xff0c;在生成倒排索引之前&#xff0c;字符串会被分析器分词。text类型的字段不用于排序&#xff0c;很…...

Kotlin 中companion object {} 什么时候触发

在 Kotlin 中&#xff0c;companion object 的初始化触发时机是一个重要但容易被忽视的细节。以下是详细的解释&#xff1a; 1. 基本触发时机 companion object 的初始化发生在&#xff1a; 首次访问该类时&#xff08;无论是访问伴生对象成员、创建类实例&#xff0c;还是通过…...

仿真每日一练 | Workbench中接触种类及选择方法简介

Workbench中给我们提供的接触类型主要包括以下几种&#x1f447; ◆ 1、摩擦 ◆ 2、无摩擦 ◆ 3、绑定 ◆ 4、不分离 ◆ 5、粗糙 ◆ 6、强制滑移 下面通过最常用的摩擦和绑定给大家展示两者的区别&#xff0c;同时文末也给大家介绍了几种接触的选择方法。首先先给大家介绍一下…...

Go语言中的rune和byte类型详解

1. rune类型 1.1. 基本概念 1. rune是Go语言的内建类型&#xff0c;它是int32的别名&#xff0c;即32位有符号整数&#xff1b; 2. 用于表示一个Unicode码点&#xff0c;全拼Unicode code point&#xff1b; 3. 可以表示任何UTF-8编码的字符&#xff1b; 1.2. 特点 1. 每…...

superior哥AI系列第6期:Transformer注意力机制:AI界的“注意力革命“

&#x1f3ad; superior哥AI系列第6期&#xff1a;Transformer注意力机制&#xff1a;AI界的"注意力革命" 嘿&#xff01;小伙伴们&#xff01;&#x1f44b; 今天superior哥要带你们探索AI界最火的技术——Transformer&#xff01;这个家伙可了不得&#xff0c;它不…...

【java面试】redis篇

redis篇 一、适用场景&#xff08;一&#xff09;缓存1、缓存穿透1.1 解决方案1&#xff1a;缓存空数据&#xff0c;查询返回的数据为空&#xff0c;将空结果缓存1.2 解决方案2&#xff1a;布隆过滤器 2、缓存击穿1.1 解决方案1&#xff1a;互斥锁1.2 解决方案2&#xff1a;逻辑…...

高效易用的 MAC 版 SVN 客户端:macSvn 使用体验

高效易用的 MAC 版 SVN 客户端&#xff1a;macSvn 使用体验 下载安装使用总结 最近有个项目要使用svn, 但是mac缺乏一款像 Windows 平台 TortoiseSVN 那样全面、高效且便捷的 SVN 客户端工具, 直到博主找到了该工具本文将结合实际使用体验&#xff0c;详细介绍 macSvn工具的核心…...