2024 抖音欢笑中国年(二):AnnieX互动容器创新玩法解析

news2024/11/17 0:47:11

本文基于24年抖音春节活动业务背景,介绍了字节跨端容器AnnieX在游戏互动套件上的探索,致力于提升容器在游戏互动场景的优化能力。

业务背景

AnnieX作为字节一方游戏统一容器,服务字节内部电商、直播、UG等跨端场景业务。在字节一方游戏互动场景,有大量的一方游戏业务对容器有特定的流量、端能力和游戏优化的诉求。因此我们不断深入互动游戏业务特点,为字节游戏提供完善游戏端能力和流量运营能力,同时提供游戏互动场景极致优化能力,提升游戏业务的整体性能。

养羊赚钱

种树赚钱

6699998c85f35a3ff42ba6bd7d047359.gif

f27d8dc4f5f072ea8b2eab508dd42597.gif

萌宠旅行家

新周中/周末

outside_default.png

dc614a6f7bc65ab28dd6a16914224874.gif

今年是抖音春节活动的第7年,我们跨端容器已经具备丰富的端能力的同时,也提供了一些对于跨端容器常规的一些优化手段,例如:资源预加载、网络预请求等手段,并且在往年春节活动中取得了不错的优化效果。而今年,我们希望能够基于游戏场景,逐渐深挖游戏互动场景的特点,为春节等游戏场景去提供更加丰富和专业的游戏优化能力

春节-神龙寻宝

春节-守卫现金

db39de3191245c4c5a1b9dadd9a01fbb.gif

dc0939ac00ee03bba5eef54b2956f348.gif

春节-摇福签

春节-神龙探宝

6bc9d3e98087576784263418604812d0.gif

6dd28bb2b7f84752dcf654dda68d0e82.gif

互动套件介绍

因此我们基于24年抖音春节活动,在容器侧提出了互动套件的建设,希望为游戏互动场景提供优化解决方案。24年春节我们完成游戏引擎预热和游戏资产公共离线库的相关优化,在24年春节得到了不错的优化效果;同时我们完成了游戏资源(解)压缩的探索和更高效的物理引擎探索,希望能够在25年春节完成压缩和物理引擎的落地,从而丰富游戏互动玩法的同时,提升游戏的整体性能。

4ee1d79e00b4ecea43a48855e84c1732.png

资产离线公共库是一个重要的资源管理工具,管理了游戏互动业务所需要的游戏引擎资源。通过对游戏主包拆包和引擎资源的统一管理,资产离线公共库能够有效地帮助降低游戏包的大小,从而提高游戏的运行效率。此外,资产离线公共库还能够通过复用本地离线公共库的引擎版本,进一步降低游戏包下载的整体耗时和带宽成本。

引擎预热是一种提供了与游戏引擎优化相关的能力的技术。其原理是在游戏启动过程中,对游戏引擎进行预热,以便游戏逻辑执行过程中更快地加载游戏引擎包,从而提高游戏加载速度。通过提前准备游戏引擎,在游戏启动时,就可以更快地进入游戏世界,减少等待时间。这种技术可以为玩家带来更好的游戏体验。

资源的压缩与解压缩可以极大地提高资源利用率,有效降低资源包体积和网络加载时长。资源的压缩处理是在引擎编辑器的打包构建阶段做的资源预处理,而资源的解压缩则被放在了互动容器中,在游戏载入过程中实时进行处理。

物理引擎,目前前端游戏开发者主要依赖js或者wasm版本的物理引擎,在游戏性能和体验上存在较大的优化空间,因此我们探索在容器侧提供更高效的物理引擎方案,从而为游戏开发者和设计师提供更好的物理引擎解决方案,丰富游戏互动玩法体验。

本文主要介绍24年在春节场景落地的引擎预热和资产公共离线库相关的优化手段。同时介绍、探讨我们游戏资源(解)压缩方案的探索和在探索中遇到的问题

名词解释

67caebe43a6690c12be91312891e028b.png

引擎预热&资产离线公共库

业务痛点

8dbeae53f161b4d73400eb3bf2bb191f.png

基于游戏业务已有的数据进行分析,我们发现游戏互动场景有以下2个特点

  • 依赖游戏引擎:在游戏中,游戏互动场景的创建和运行需要依赖于游戏引擎的加载和初始化逻辑。这个过程会消耗大约200ms~300ms的时间,这可能会对游戏的性能产生一定的影响。因此,为了提高游戏的响应速度和流畅度,游戏开发者需要尽可能地优化引擎加载和初始化逻辑的执行效率。

  • 游戏加载耗时和用户异常流失率呈正比:启动性能对于游戏的用户体验至关重要,因为如果游戏启动没有优化好,用户需要等待很长时间才能看到游戏画面。这样很可能会导致许多用户在游戏加载完成之前就退出游戏。根据已有的游戏数据分析,游戏加载时间在1.5秒后,每0.5秒左右就会有4%左右的用户异常流失。因此,游戏开发者需要高度重视游戏启动性能的优化,以确保游戏能够快速启动,让用户尽快进入游戏世界。

因此我们针对游戏互动场景完成了引擎预热的方案,整体在24年春节场景落地,双端取得了不错的加载收益。

整体思路

051152242c6770dd7b0deff4adb7e147.png

在优化之前,在容器加载游戏主包完成之后,才会开始渲染游戏首屏页面和执行游戏业务逻辑。当游戏的业务逻辑在执行的过程中,必须等待容器完成游戏引擎资源的加载和初始化,这部分在线上存在一定的耗时。因此,为了解决这个问题,我们在容器侧和前端工具链完成了一系列改造,以提高游戏页面的加载速度。

具体地来说我们在容器打开游戏页面路由阶段,就完成了游戏引擎的预加载,并在跨端框架完成初始化之后,充分利用JS线程空闲的时间,完成游戏引擎的预热,并将预热好的实例挂载在全局对象中,这样当游戏页面真正执行的时候,就能直接通过全局对象中的获取到游戏引擎实例,从而完成后续的游戏业务逻辑。

技术细节

开发工具链改造

df77f7586ff0307e823a5d0e991a7d7c.png

前端工具链方面,在构建工具中接入speedy-split-chunks插件,在游戏打包的过程中,将游戏引擎包从游戏主包中拆分出去,并将引擎库发布到静态资源分发平台公共离线库下;封装split-engine-adapter组件,完成引擎预热的前端代码插桩,并在引擎预热时,提供兜底逻辑,保障业务的稳定性。在剔除游戏引擎包同时,并将剔除出来的引擎包和对应的meta文件部署到静态资源分发平台公共离线库,通过meta文件来维护离线公共库的游戏引擎资源版本,供多个游戏互动业务使用,从而降低带宽成本。

另一方面,我们的split-engine-adapter插件可以在请求加载引擎资源文件时,完成对requireModule函数的hook。在这个过程中,如果发现全局对象上不存在的引擎实例,那么就会通过requireModule请求拆包引擎包作为兜底措施。通过这种方式,可以避免因引擎实例不存在而导致的错误,从而提高系统的稳定性和可靠性。

预热游戏引擎

98acf2b35479dc75991c453a82acbddb.png

客户端通过前端拆包的meta文件,进行公共库离线库资源版本管理。当客户端页面schema中打开引擎预热的能力时,客户端会在页面路由时,根据meta查找对应的引擎版本,提前去预加载游戏引擎。由于离线公共库存在客户端本地,为了防止替换客户端本地引擎JS文件,整体加载过程中会对游戏引擎资源进行验签,从而达到避免JS注入攻击的风险。同时,在跨端容器创建的过程中,将游戏引擎文件在JS线程进行预热,最终将游戏引擎实例挂载到全局对象上,以确保游戏引擎的正常运行。

当前端业务逻辑执行时,可以通过全局对象访问游戏引擎实例。如果引擎预热失败,前端业务会通过兜底的逻辑,请求游戏引擎资源进行使用,从而提升整体方案的稳定性和可靠性。

业务收益

1280f78a84a3fbc7c61dbf4502089bd1.png

在游戏互动场景中,AnnieX互动容器通过提供引擎预热和依赖资产公共离线库托管游戏引擎的方案,实现了游戏引擎的快速加载和初始化,从而提升了游戏业务的整体性能。这一方案成功地帮助完成了24年抖音春节活动的落地,游戏主包大小降低了28.05%。通过复用公共离线包引擎资源,节约了数万元网络带宽的成本

959899d12382391bee70f2812471950c.png

在游戏加载耗时方面,双端在不同游戏的表现中存在200ms~500ms左右的优化幅度。由于iOS整体性能更佳,因此优化幅度整体上相较于Android用户优化幅度更大。在Android端中,PCT90有32.12%的优化幅度,PCT50有20.75%的优化幅度;在iOS端中,PCT90有47.24%,PCT50有33.89%的优化幅度

资源压缩

业务痛点

3D资源往往文件体积较大,在需要网络传输的场景,对这些资源的压缩通常能够有效提升资源的加载速度,节约网络流量传输成本。

目前,常用的3D资源文件格式主要有glTF、fbx、obj等,这些资源通常包含了3D资源的几何体、骨骼、动画、材质等等所有数据,因此围绕着24年抖音春节活动,我们开始了基于游戏3D资源的压缩和解压缩的探索和调研。

整体思路

这里主要介绍AnnieX互动容器对于几何体和动画数据的压缩算法及其具体实现方式,分别是:量化(Quantization)、稀疏访问器(Sparse Accessor)和网格优化(meshopt)。

e938f27fa19b005524e9de0effa43d24.png

技术细节

几何体的压缩与解压缩

在SAR Creator中,几何体(Geometry)除了包含了顶点的坐标(Position)、纹理坐标(UV)、法向量(Normal)、切向量(Tangent)、颜色(Color)等数据之外,还包含了组成三角形的顶点索引(Index)、骨骼(Skeleton)和混合变形(Blend Shape)等数据。

由于这些不同的数据有着不同的格式和特性,所以往往需要分别应用不同的压缩格式,用以在尽可能保证数据精度的同时尽量提高压缩效率。

这里介绍几种SAR Creator中使用到的压缩算法:量化、稀疏访问器和meshopt。

量化(Quantization)

量化是一种常用的简单且高效的资源压缩方式,通常用于顶点数据的压缩,是一种有损压缩

量化是将32位浮点值转换为16位或8位的整数进行存储的过程,可以达到50%甚至25%的压缩率

转换公式

a89ff5020f7f516ea55b5851e356d71c.png

详情

由上述转换说明易知,量化是一个有损的压缩,其压缩和解压缩均只需要对所有原始数据做当且仅当一次乘法/除法运算,算法复杂度为O(n),开销较低。

量化对原始浮点数的范围有一个前提要求,其范围必须在0到1之间(可转换到无符号整数)或-1到1之间(可转换到有符号整数)。当原始浮点数的值不在这个范围内的话,需要预先做一次归一化处理,使其落在需要的范围内,才能继续进行量化处理。

本质上,量化是建立了一个浮点数和整数的对应关系,整数的存储位数越大,对应的浮点数精度越高。理论上可以实现任意位数的整数跟浮点数的转换。

在SAR Creator中,因为不同的数据对于精度的要求不同,故在实际应用时对于不同类型的数据使用了不同位数的整数进行存储,具体如下:

  • position:14

  • uv:12

  • normal:10

  • tangent:12

  • color:8

  • blend shape:8

以上不同类型数据的存储位数的配置选择参考自业界经验,可以在尽量保证数据精度的同时提高压缩率。在对精度要求较高的情况下,可以对该配置进行调整优化,一般最大值不会超过16位。

稀疏访问器(Sparse Accessor)

这里的稀疏访问器来自于glTF规范中的稀疏访问器(Sparse Accessor),特别适合用来存储混合变形(BlendShape,以下简称BS)数据,因为BS数据中往往存在较多的“0”。

在glTF规范中,Sparse Accessor会把一个较大的vector2/3/4的数组(Buffer),拆分成3个部分:非0值数组(Values Array)、索引下标数组(Indices Array)和原始长度值(Count)。通过这样仅存储非0值及其下标的方式,结合一个原始长度,就可以很方便地还原出原始数据。

在SAR Creator中会基于glTF的Sparse Accessor的格式再进一步做优化调整,仅会存储非0的vector2/3/4的非0通道的数据,而不是glTF规范中必须是Vector2/3/4中所有通道的数据均为0才不去存储,这样可以进一步减少序列化后存储数据的文件体积大小。同时,由于SAR的AssetBundle格式对于数组存储采用了特殊的方式,所以这里还可以少存一个Int32的Count值。

转换格式

转换格式示意图如下:

42338287c41339a8cd6dd3c0e5bf1aa1.jpeg

由上图可知,稀疏访问器是无损压缩,且其压缩和解压缩的流程简单,算法复杂度为O(n),但实际的解压缩过程并不需要对所有的数据进行处理,只需要创建跟原先相同大小的buffer,按下标将所有的非零值填进去即可,故而开销很低

详情

另外,由于稀疏访问器仅在当BS数据的0值较多时,才会有较高的压缩效率,否则反而会降低压缩效率。SAR Creator默认会自动判断应用了稀疏访问器后是否会减少资源文件体积,来决定是否采用稀疏访问器,不需要手动开启。

附:真实业务(虚拟形象)中的glTF文件为例,仅采用Sparse Accessor能减少53%左右的文件体积,如果采用Sar的Asset Bundle中优化后的数据格式,可以减少78%左右的文件体积。

值得一提的是,稀疏访问器可以跟量化一起叠加同时应用在几何体数据上,两者互不影响,互不冲突,最终的精度损失仅为量化的损失。

网格优化(meshopt)

meshopt是glTF规范中的一个扩展:EXT_meshopt_compression,该扩展可以对glTF文件中的几何体和动画数据进行优化与压缩。在SAR Creator中,几乎全量移植了这个扩展的具体实现,使得SAR Creator的Asset Bundle中的几何体和动画数据同样支持了meshopt压缩。

由于meshopt压缩和解压缩的算法较为复杂,SAR Creator在实现时应用了wasm的方式(同时用asm.js做兜底),这里使用了开源项目meshoptimizer,它提供了对Mesh进行优化压缩相关算法的C/C++接口,也可以编译为wasm使用。

压缩流程

meshopt在压缩前需要先优化顶点和索引数据,用于提高压缩效率,同时也可以提高解压缩后的渲染效率(GPU缓存)。meshopt提出了三种不同的模式(mode:attribute、triangles、indices)的和三种不同的过滤器(filter:octahedral、quaternion、exponential),针对不同的数据类型应用不同的模式和过滤器,可以最大化压缩率。

对于几何体的meshopt压缩,SAR Creator实现时的具体流程如下:

  1. 优化索引顺序

    1. 优化索引顺序,可以最大限度地利用附近的顶点数据,从而尽量复用在GPU硬件中的缓存。

  2. 优化顶点顺序

    1. 顶点顺序应按照顶点在索引数据中出现的顺序进行顺序排列,以而可以最大化索引数据的压缩率。

需要注意的是:有时候更高的压缩率反而会降低渲染效率,需要取好平衡点。

  1. 压缩顶点数据

    1. 顶点数据需要先进行量化(quantized),才能进行后续的压缩处理;

    2. 量化后的顶点数据需要用attributes模式来进行二进制比特流存储;

    3. 对于normal/tangent的数据,使用octahedral的filter可以进一步提高压缩率,对于position或其他数据,可以使用exponential的filter进行处理;

  2. 压缩索引数据

    1. 索引数据用indices模式进行存储,也可以用triangles模式进行存储;

    2. 其中,triangles模式仅支持三角形列表的存储,indices模式可以支持其他拓扑类型的索引数据存储;

  3. 压缩BS数据

    1. BS数据可以完全当作顶点数据来进行处理,也需要先进行量化(quantized),之后再以attributes模式进行二进制比特流存储;

    2. BS数据因为是增量(relative/delta)的值,故也可以选用比顶点数据在量化后更小的比特位来进行存储;

解压缩流程

对于几何体的meshopt解压缩,则需要反过来进行,互动容器中实现的具体流程如下

  1. 解压缩顶点数据

    1. 按attributes模式进行解压缩;

    2. 对于采用了对应filter的数据,还需要再进行filter的解压缩;

    3. (可选)如果有必要,在进行反量化转换(de-quantized)处理;

  2. 解压缩索引数据

    1. 直接按压缩时采用的indices或triangles模式进行解压缩即可;

  3. 解压缩BS数据

    1. 同顶点数据的解压,不再赘述;

详情

对于几何体数据应用meshopt压缩,往往可以带来10%-20%的压缩率,可以极大减少资源体积。但由于其复杂度较高,需要使用wasm加速压缩和解压缩的过程

对于不支持wasm的环境,SAR Creator使用了asm.js作为兜底方案。实际测试结果显示,asm.js会比wasm慢2-4倍。在后续版本的SAR中,可能会直接使用C++的方案加速运行时对meshopt压缩后的资源进行解压缩,加速资源加载和解析的整个流程。

另:SAR Creator对于几何体数据的meshopt压缩实现,目前仍在feature分支,未经过全面测试,仅上线了对于动画数据的meshopt压缩。

动画的压缩与解压缩

动画(Animation)数据是由一系列的关键帧(keyframe)组成的。所以动画数据是由两部分组成的:关键帧的时间数组(times)和关键帧的值数组(values)。

网格优化(meshopt)

SAR Creator中对于动画(Animation)数据的压缩,也是移植自上述meshopt扩展。

压缩流程

对于动画数据的meshopt压缩,SAR Creator实现时的具体流程如下:

  1. 对动画数据进行重采样

    1. 对动画数据的压缩,最有收益的是进行重采样(resample),这样可以减少存储的关键帧数量,进而减少动画数据的文件存储体积;

    2. 具体实现使用开源库:keyframe-resample-wasm,它提供了WebAssembly版本的重采样方式,会比纯js的版本快一些,而且这个库的重采样过程是无损的。

  2. 压缩关键帧的times数据

    1. 如果times数据是均匀的,仅使用attribute模式而不使用任何过滤器已经能取得比较高的压缩率了;

    2. 为了保证最终的动画不变形,一般不建议对关键帧的times数据进行filter处理,也可以继续使用具有最大尾数位数(23)的exponential过滤器进行处理,从而保证最小的精度损失;

    3. 最后使用attributes模式进行存储;

  3. 压缩关键帧的values数据

    1. 旋转的数据可以使用16-bit进行量化处理,并应用quaternion过滤器进行处理;

    2. 位移和缩放数据可以应用exponential过滤器应用相同的指数进行处理;

    3. 最后使用attributes模式进行存储;

解压缩流程

对于动画数据的meshopt解压缩,互动容器中的实现具体流程如下:

  1. 解压缩关键帧的times数据

    1. 按attributes模式进行解压缩;

    2. 如果压缩时采用了exponential的过滤器(filter),还需要再进行exponential的过滤器解压缩;

  2. 解压缩关键帧的values数据

    1. 按attributes模式进行解压缩;

    2. 旋转的数据还需要用quaternion过滤器进行解压缩;

    3. 位移和缩放数据还需要用exponential过滤器进行压缩时相同指数的解压缩;

详情

对于动画数据的meshopt压缩,同样也是有损的,往往有40%左右的压缩率,同样采用了wasm的方式加速压缩和解压缩的过程。

附:真实业务(招财神龙)中的动画资源文件为例,有38.50%的压缩率,可以减少1.9MB的资源包体积。

另:招财神龙业务中,考虑中低端机在跨端框架下wasm的兼容性问题,开发时直接默认启用了asm.js的降级方案,但在后来的性能测试环节中发现meshopt解压缩的asm.js在iOS的JSC运行时下效率较低,会严重增加资源的解析耗时,最终上线时并没有启用动画数据的meshopt压缩。

未来规划

24年春节我们完成了引擎预热、资产公共离线库的落地,取得了不错的游戏优化效果。但在业务落地的过程中,我们也发现一些存在的问题,例如引擎预热逻辑命中率双端平均只达到81.33%,整体上还存在优化的空间;另一方面随着资产公共离线库的托管的引擎类型和版本越来越多,体积越来越大,我们需要加强对离线公共库的版本管理,识别和控制ROI整体较低的引擎和版本,从而更好的控制离线公共库的带宽成本。

而在资源压缩方面,我们完成了相关方案js和wasm版本的流程的调研和探索,以24年春节玩法招财神龙为例,我们取得了不错的资源体积优化效果,降低整体游戏包的大小。但在资源压缩方面,由于低端机和部分iOS手机上对于网格优化的解压缩效率低下,甚至部分机型适用wasm会有崩溃的情况存在,所以虽然完成了整体的技术方案落地,但考虑到稳定性并没有在线上启用。后续会进一步优化这一方面的兼容性问题,解压的性能问题上也会直接采用C++而非wasm的方案,将资源压缩方案完整在正式的游戏业务落地,同时覆盖更多的游戏业务场景。

另外,在3D游戏场景下,一般意义上的资源还包括图片、视频、字体、脚本以及特定编辑器导出的资源(如lottie、spine等),对于这些资源文件的压缩也有着明显的意义,我们将在后续进一步探索相关资产的压缩,从而优化整体游戏的资产大小。

团队介绍

我们是抖音前端架构-互动体验技术团队,主要为字节跳动业务提供互动技术解决方案。技术产品包含面向互动 / 小游戏研发场景的 SAR Creator、高性能动效渲染引擎 Simple Engine、互动场景端能力套件 AnnieX 互动容器

在这些技术建设与业务落地上,和抖音前端-互动创作团队跨端框架团队、开放平台小游戏团队、用户增长-激励前端团队一同推进,不断探索字节跳动应用生态下的创新业务形态。

下期预告

系列下期主题是编辑器技巧与实践。作为字节互动方案的主要工具,其提供各类完善的系统方便用户使用快速搭建互动场景,并提供丰富的配置能力,解决了预览调试到构建打包的一系列流程问题,可配合业务定制高效的内容生产工作流。敬请期待。

往期回顾

2024 抖音欢笑中国年(一):招财神龙互动技术揭秘

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1574882.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

YOLOv8模型剪枝实战:Network Slimming网络瘦身方法

课程链接:YOLOv8模型剪枝实战:Network Slimming网络瘦身方法_在线视频教程-CSDN程序员研修院 YOLOv8是一个当前非常流行的目标检测器,本课程使用Network Slimming(网络瘦身)剪枝方法对YOLOv8进行模型剪枝,…

springboot国际化多语言

1,新建国际化多语言文件 在resources目录下新建 messages.properties 其他语言的文件 编辑messages.properties文件,下方从text切换到Resource Bundle ,即可对照着编辑多语言文件 (如果没有找到Resource Bundle,先在settings->plugins中安装Resource Bundle Editor) 2,配…

学习 MongoDB:打开强大的数据库技术大门

一、基本概念 MongoDB 是一个基于分布式文件存储的文档数据库,由 C 语言编写。它旨在为 Web 应用提供可扩展的高性能数据存储解决方案。 相信MySQL我们非常的熟悉,那么MySQL的表结构与MongoDB的文档结构进行类比的话可能更好理解MongoDB。 MySQL的数据…

Spyder无法载入(load)或者闪退问题

在Anaconda prompt中直接输入spyder,报错如下 Traceback (most recent call last):File "C:\Users\user\.conda\envs\KB\Scripts\spyder-script.py", line 10, in sys.exit(main())File "C:\Users\user\.conda\envs\KB\lib\site-packages\spyder\a…

baseline SE SP YI是什么?

SE、SP和YI是评估分类模型性能时常用的几个统计指标,特别是在医学影像处理、疾病诊断等领域,这些指标帮助了解模型对于正负类样本的识别能力。 SE (Sensitivity),也称为真正率(True Positive Rate, TPR)或召回率&#…

泛型(java学习)

目录 1.泛型介绍: 2.泛型的好处: 3.泛型的语法 4.泛型的细节 5.自定义泛型 6.自定义泛型接口 8.泛型的继承和通配符 1.泛型介绍: 1)泛型又称参数化类型,解决数据类型的安全性问题。 2)在类声明或实例…

5.3 用栈翻转数组,动态规划求斐波那契数列

5.3 用栈翻转数组,动态规划求斐波那契数列 1. 用栈翻转数组 assume cs:code,ds:data,ss:stack data segmentarr dw 1111h,2222h,3333h,4444h,5555h,6666h,7777h,8888hres db 800 dup(0) data endsstack segmentdb 100 dup(0) stack endscode segmentstart:mov ax,…

计算机视觉入门:开启图像理解之旅

🧑 作者简介:阿里巴巴嵌入式技术专家,深耕嵌入式人工智能领域,具备多年的嵌入式硬件产品研发管理经验。 📒 博客介绍:分享嵌入式开发领域的相关知识、经验、思考和感悟,欢迎关注。提供嵌入式方向的学习指导…

【算法篇】三道题理解算法思想——认识BFS

BFS(宽搜) 宽度优先遍历和深度优先遍历组成了大家熟悉的搜索算法,这两种算法也是蓝桥杯之类竞赛题的常考思想,正巧马上蓝桥杯临近,博主也是刷了很多BFS相关的题型,在这篇文章中会从力扣上选取三道简单的宽搜…

小象超市(原美团买菜) 的大屏图表

文章目录 概要技术细节技术名词解释小结 概要 20203年12月1日,美团旗下自营零售品牌“美团买菜”升级为全新品牌“小象超市”。 ,“小象超市”坚持美团自营零售模式,通过在社区设立的集存储、分拣、配送为一体的便民服务站,为社区…

关于16:9和4:3的有关知识,看这篇文章就差不多了

序言 在你拍照或录制视频之前,你需要考虑使用哪个纵横比。最常见的两种纵横比是16:9和4:3,但哪一种最适合你? 16:9的纵横比最适合视频,因为宽度比高度宽78%,这使你更容易在水平方向上适应更多画面,同时优化视频以适应现代屏幕。 同时,4:3的纵横比更适合摄影,因为宽度…

书籍《笔记的方法》读后感

读完《笔记的方法》有几周的时间,书里有些记录的内容,觉得非常有价值的,自己的观点,当下读书,其实并没有那么高大尚,就是存粹陶冶下情操,读书还是有一定作用的,毕竟看书只能慢慢来&a…

【PDF-XSS攻击】Java项目-上传文件-解决PDF文件XSS攻击

文章目录 背景解决pdfbox依赖控制器代码PdfUtils工具类 验证最后源码参考 背景 上传xss-pdf造成存储型xss因为在浏览器直接预览的PDF,而不是预览,所以安全部门认为会有XSS漏洞 解决 安全部门修复建议 1、根据白名单的标签和属性对数据进行过滤&#…

C++后端程序员如何在缺乏相关外包项目中寻找赚取外快的途径

作为一位专业的C后端程序员,你拥有扎实的技术功底和丰富的编程经验,然而在寻求外包项目的道路上,可能时常会发现市场上的项目并不都与C直接相关。但这并不意味着你就无法利用自己的技能来获取额外收入。本文将为你揭示一些即使在当前环境下&a…

力扣热题100_链表_138_随机链表的复制

文章目录 题目链接解题思路解题代码 题目链接 138. 随机链表的复制 给你一个长度为 n 的链表,每个节点包含一个额外增加的随机指针 random ,该指针可以指向链表中的任何节点或空节点。 构造这个链表的 深拷贝。 深拷贝应该正好由 n 个 全新 节点组成&a…

【算法】动态规划练习(一)

目录 1137. 第 N 个泰波那契数 分析 代码 面试题 08.01. 三步问题 分析 代码 746. 使用最小花费爬楼梯 分析 代码 泰波那契序列 Tn 定义如下: T0 0, T1 1, T2 1, 且在 n > 0 的条件下 Tn3 Tn Tn1 Tn2 给你整数 n,请返回第 n 个泰波…

软件测试人员如何避免成为“背锅侠”

作为一名软件测试工程师,我们的角色可以算是“战场上的后勤”,战役的胜败和所有团队人员都息息相关。 但是难免碰到战役失败后,很多团队互相推脱的局面,而测试人员就是所有团队中的弱势群体,自然是首当其冲的背锅侠&a…

34.Python从入门到精通—Python3 正则表达式检索和替换

34.从入门到精通:Python3 正则表达式检索和替换 repl 参数是一个函数 正则表达式对象 正则表达式修饰符 - 可选标志 正则表达式模式* 正则表达式实例 检索和替换repl 参数是一个函数正则表达式对象正则表达式修饰符 - 可选标志正则表达式模式*正则表达式实例 检索和…

JAVA并发编程(一)

JAVA并发编程(一) 1.1JAVA线程API 1.1.1currentThread package com.lisus2000.thread;/** * 当前线程 * */ public class Test07 extends Thread {public Test07() {System.out.println("new Test07()......" Thread.currentThread().getNa…

全网短剧搜索前端源码开源分享可改自己的接口

全网短剧搜索前端源码 内含7000短剧资源(不支持在线播放) 源码全开源,可以修改成自己的接口 178、226、347行修改 源码免费下载地址抄笔记 (chaobiji.cn)https://chaobiji.cn/