Monorepo 解决方案 — 基于 Bazel 的 Xcode 性能优化实践

这篇具有很好参考价值的文章主要介绍了Monorepo 解决方案 — 基于 Bazel 的 Xcode 性能优化实践。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

背景介绍

书接上回《Monorepo 解决方案 — Bazel 在头条 iOS 的实践》,在头条工程切换至 Bazel 构建系统后,为了支持用户使用 Xcode 开发的习惯,我们使用了开源项目 Tulsi 作为生成工具,用于将 Bazel 工程转换为 Xcode 工程。但是在使用的过程中,我们发现了一些问题,其中影响较大的是,

  • Xcode 工程卡顿:对于头条这种大型项目来说,Xcode 卡顿一直是本地研发的痛点问题,在切换 Bazel 构建系统之后卡顿现象明显加剧。

  • Xcode 功能支持受限:Tulsi 支持的功能有限,很多功能都年久失修,并未持续适配 Bazel 与 rules 的更新。

在做了一些前期调研后,我们发现 rules_xcodeproj 提供了更好的解决方案。rules_xcodeproj 是一个由一系列 Bazel rules 组成的开源项目,使用它可以从一个 Bazel 工程生成对应的 Xcode 工程,实现在 Xcode 中写代码同时使用 Bazel 进行真正的构建任务,相比于 Tulsi,rules_xcodeproj 在以下几个方面有着更为明显的优势。

  • Xcode 工程更加流畅: 头条工程迁移到 rules_xcodeproj 后,工程首次冷启、二次启动和文件增删操作的时间有了明显缩短,工程卡顿情况也明显好转。

  • Xcode 功能支持度更高: rules_xcodeproj 对 Xcode 的支持更全面(包括单元测试、SwiftUI Previews),能够更好地满足我们的需求。

  • 社区更加活跃:随着 rules_xcodeproj 在 2023 年 2 月份发布正式版,Tulsi 项目也正式宣布停止维护,这意味着对于新版本的 Bazel,Tulsi 将不再提供适配和支持;同时 rules_xcodeproj 几乎每月都会更新一个中版本,对于后续适配 Bazel 更新的成本会更低。

  • 更符合 BitSky 的演进路线:由 Bazel 驱动的工程生成方式更符合 BitSky 的 Bazel Native 演进路线,可以完全在 Bazel 环境下生成工程。

因此,我们将 Xcode 生成工具从 Tulsi 迁移到了 rules_xcodeproj,并对 BitSky 工具链进行了适配。适配过程中,我们在修复 rules_xcodeproj 索引问题的同时,对工程结构进行了一些优化,进一步提升了工程流畅度。头条 iOS 工程的测试数据如下:

测试设备 MacBook Pro,芯片 M1 Pro,内存 32GB

ps. 本文介绍均基于 rules_xcodeproj 1.4.0 版本,build with bazel 模式

pps. 由于 Xcode 主线程的卡顿较难监测,此处用主动操作的执行时间衡量流畅度


Tulsi rules_xcodeproj
工程首次冷启 47s 16s
二次启动 33s 12s
文件操作 新增 20s
删除 23s
新增 8s
删除 6s

下面来看下我们具体做的适配工作。

适配过程

从 Tulsi 迁移到 rules_xcodeproj 后,我们发现 Xcode 卡顿有明显改善,仔细分析发现 Tulsi 工程的卡顿主要有两方面原因:

  1. 头条工程中组件数量多、依赖关系复杂:Tulsi 的索引方案需要 Xcode Target 之间保留这些依赖关系,但这些依赖关系并不会被 Xcode 构建消费,却增加了 Xcode 对工程进行解析和计算的成本。

图中 Pod X_A 与 Pod X_B 为 Pod X 分别在 App A 与 App B 下被引用的 Target

monorepo bazel,xcode,macos,ide
  1. 全源码构建:我们在切换 Bazel 时还推进了工程的全源码构建,源码数量大幅增加,也给索引任务带来更大的压力。

接下来详细说明整个分析和适配过程,带大家更全面地了解我们结合 rules_xcodeproj 在 Xcode 背后做了什么。

在 Xcode 中开发时主要会用到三部分功能:构建、索引和调试。而 Xcode 并不能直接理解 Bazel 项目的工程文件(BUILD 和 WORKSPACE),所以我们需要通过工具(rules_xcodeproj 或 Tulsi)将 Bazel 的工程文件转换为 Xcode 可以理解的 .xcodeproj来支持这些功能正常工作。

各功能的适配点如下表所示。

monorepo bazel,xcode,macos,ide

rules_xcodeproj 原生方案的调试模块基本能正常工作,而索引和构建两个模块中我们对原生方案的改造较大,因此本文主要对这两个模块进行展开介绍。

索引

前面提到支持 Xcode 索引功能需要提供各个源文件的编译参数,rules_xcodeproj 实现这一点的工作流程是:

  1. rules_xcodeproj 在 Bazel 的分析阶段获取到源码文件和编译参数;

  2. 用这些信息创建 Xcode Target 的 Compile Sources 和 Build Setting 产出工程文件 .xcodeproj

  3. Xcode 加载工程文件,获取源码文件对应的索引参数,调用 clang 或 swiftc 执行索引命令。

迁移过程中我们注意到 rules_xcodeproj 工程的索引在多 Target 共用源文件的场景存在语法高亮异常的问题,对比 Tulsi 工程的处理方式后我们得出两个结论:

  • 索引异常是由于 rules_xcodeproj 移除了所有 Library Target 间的依赖导致的;

  • Tulsi 工程中 Library Target 间的依赖关系正是导致 Tulsi 工程更为卡顿的关键原因。

后文会先分析依赖关系在索引中发挥的作用,以及 rules_xcodeproj 如何处理依赖关系移除带来的问题,然后介绍我们如何通过源码合并方案解决 rules_xcodeproj 索引方面的缺陷。

依赖关系在索引中的作用

这里提到的“依赖关系”主要是指 Xcode 工程文件(.xcodeproj,准确来说是其中的project.pbxproj文件)中记录的 Xcode Target 之间的依赖关系。

需要明确的是这部分依赖关系只会在 Xcode 索引过程被用到,被移除后也只会影响 Xcode 的索引功能。构建时用到依赖关系 Bazel 会从 BUILD 文件中获取,不会关心 .xcodeproj 中的信息。

这些依赖关系在 Xcode 中的表现形式如下图所示,既有直接在 Build Phases 的 Target Dependencies 中声明的依赖,也会对声明在 Link Binary With Libraries 中 Target 产生依赖。

monorepo bazel,xcode,macos,ide

概括来说依赖关系在 Xcode 的索引过程中发挥着以下两方面作用:

  • 正确的中间产物生成顺序:clang/Swift Module 中间产物的生成需要依赖关系来确定构建顺序;

  • 正确的多 Target 编译参数:多 Target 共用源文件时应用正确的编译参数,以便于正确地高亮代码。

下面分别对其进行展开介绍。

中间产物生成顺序

以一个 Swift 组件为例,当它被 OC 组件引用时,需要生成一个 XX-Swift.h 文件,把方法和声明暴露给 OC 组件,当它被其他 Swift 组件引用时,也需要生成一个 swiftmodule 文件供其他 Swift 组件引用。XX-Swift.h 和 swiftmodule 并不是原始的源码文件,也不是最终的二进制产物,是构建时的中间产物。在 Xcode 对一个组件的源代码索引时,需要这个组件的依赖组件已经准备好中间产物供索引时消费。这里,我们先分析下 Xcode 是怎样解决这个问题的。

首先,Xcode 通过 Target 来描述产物是如何构建出来的,每个 Target 拥有自己的 Build PhasesBuild Settings(通常一个组件对应一个 Target)。Build Phases 中的 Compile Sources 记录了构建这个 Target 需要编译哪些源码文件。Build Settings 里记录了构建这个 Target 时的各种配置,这其中就包括了编译参数。Xcode 可以从 Build Settings 里去获取编译参数,然后对 Compile Sources 中记录的源码文件进行索引编译。

monorepo bazel,xcode,macos,ide

一个 Target 引用另外一个 Target 时,需要将依赖关系添加到 Build PhasesTarget Dependencies 中。Xcode 在构建时会根据这些依赖关系来决定构建 Target 的顺序,保证一个 Target 构建时,它依赖的 Target 已经完成构建。

索引时也是类似的处理,Xcode 有一个 Index Build 的阶段,在这个阶段也会根据依赖关系按照顺序去触发 Target 的 Build Phase,完成之后才会开始索引这个 Target 的源码文件。

monorepo bazel,xcode,macos,ide

这里有一个例子,SwiftDemo 依赖了 HelloLib,两个 Target 均为 Swift 组件。

monorepo bazel,xcode,macos,ide

在对 SwiftDemo 的源码文件进行索引编译之前,会先触发 Index BuildIndex Build 时根据依赖关系,先 Build HelloLib,这个时候会进行 Compile Swift source files,参数中包含 -emit-module -emit-module-path /path,最终会生成 swiftmodule 。

monorepo bazel,xcode,macos,ide

如果将 HelloLib 从 SwiftDemo 的 Target Dependencies 中移除,在 SwiftDemo 的 Index Build 时,不会先 Build HelloLib,并且在 HelloLib 的 Index Build 中,也不会生成 swiftmodule。

可以看出,Xcode 正是通过依赖关系来保证构建时的顺序,索引也依赖构建顺序来保证 Module 中间产物的生成时机。

在 Tulsi 生成的 Xcode 工程中,依然保留了 Target 之间的依赖关系,用于解决索引的中间产物生成问题。这里就不做过多介绍。

而在 rules_xcodeproj 生成的工程中,Target 之间的依赖关系是完全去掉的,每个 Target 都有且仅有一个额外添加的依赖 BazelDependencies。对于 Module 中间产物的处理,在生成的 Xcode Target 中,我们可以看到这样一条 Build Phase

monorepo bazel,xcode,macos,ide

原理是在 Index Build 阶段,执行到这 Target 时去跑一个 shell 脚本。

以 NewsInHouse 这个 Target 为例,这个脚本里经过一系列的处理,最终会去调用这样一条 Bazel Build 命令,

monorepo bazel,xcode,macos,ide

在这条命令中有一些关键信息:

@rules_xcodeproj_generated//generator/xcodeproj:xcodeproj

Bazel Build 的 Target,可以认为是我们使用 rules_xcodeproj 定义的生成工程的 Bazel Target。

bc //Article:NewsInHouse applebin_ios-*

在上述 Target 里 rules_xcodeproj 添加了一些 OutputGroupInfo。Bazel Build 时可以通过 --output_groups 参数指定输出产物。

这一条 output group 对应的是 //Article:NewsInHouse 及其依赖 Target 的产物中, swiftmodule 之类的编译依赖部分。

bg //Article:NewsInHouse applebin_ios-*

这一条 output group 对应的是 //Article:NewsInHouse 及其依赖 Target 的输入文件中的非源文件的部分,比如编译时依赖的 hmap 。

这样的 Bazel Build 命令可以在 Index Build 时将 hmap 和 swiftmodule 之类的索引中间产物生成出来,然后再索引具体文件时就不会因为缺少这些中间产物而失败。

并且这里的依赖关系是由 Bazel 去处理的,不是必须像 Xcode 原生机制那样,按照依赖关系来决定 Index Build 中 Target 的顺序。

所以仅从 "Module 中间产物" 这方面来说,Xcode 中的依赖关系并不是必需的。

多 Target 编译参数

除了中间产物生成之外,依赖关系在多个 Target 共用源文件时的编译参数计算也发挥着作用。这里的“编译参数计算”是指当一个源文件被不同 Target 引用时,应用的编译参数可能不同的情况。这么介绍比较抽象,来看下具体的例子:

下面 Demo 工程中有两个 App Target:AppA 和 AppB

  • 在两个 App Target 的 Build Settings 中分别注入了宏IS_APP_AIS_APP_B

monorepo bazel,xcode,macos,idemonorepo bazel,xcode,macos,ide
  • 有一份公共的代码文件 public.m 分别被添加到两个 App Target 的 Compile Sources 中。

monorepo bazel,xcode,macos,idemonorepo bazel,xcode,macos,ide
  • public.m 内用预编译宏隔离了存在差异的逻辑

  • 随着我们切换构建的 App Scheme,由于编译参数的差异,宏作用域中高亮的代码区域也会随之变化(如下图)。

monorepo bazel,xcode,macos,idemonorepo bazel,xcode,macos,ide

此时的工程结构如下图所示,Xcode 可以通过选中的 AppA Scheme 获取到 AppA Target 的 Build Settings(图中红线路径),正确地传递编译参数-DIS_APP_A=1

monorepo bazel,xcode,macos,ide

实际的情况会复杂一些,因为工程的组件化建设将代码下沉到了一个个组件内,而非直接与 App Target 关联。此时同一份代码文件在不同 App Target 内的索引参数计算,则是通过 Target 之间的依赖关系实现的。

对应到 Xcode 中,Xcode 可以通过 App Target -> Library Target 的依赖关系,应用对应的 Build Settings 生成索引。

monorepo bazel,xcode,macos,ide

此时的工程结构则变成了下图的模式,Xcode 依然可以通过 AppA Target 与 PublicLibraryA Target 的依赖关系应用正确的编译参数(图中红线路径)。

monorepo bazel,xcode,macos,ide

Xcode 原生工程和 Tulsi 生成的 Xcode 工程都是通过这种依赖关系来保证编译参数的正确计算的。

而 rules_xcodeproj 生成的工程完全移除了 Target 之间的依赖关系,转而给所有 Target 都添加了对 BazelDependencies 的依赖(如下图所示)。

monorepo bazel,xcode,macos,ide

从图中可以看到,在缺少 AppA Target 对 PublicLibraryA Target 依赖的情况下,对于同时被 PublicLibraryA 和 PublicLibraryB 引用的 public.m ,Xcode 无法感知应该应用哪个 Target 中的编译参数(图中红线路径无法关联 AppA Scheme 与 public.m)。此时 Xcode 触发索引时应用的 Build Settings 是固定的,不会随着构建 App Scheme 切换而更改。

具体的表现当构建目标从 AppB 切换到 AppA 时,IS_APP_B宏中的代码仍然会展示为高亮,而不会随之切换,从而给开发者带来困惑。

monorepo bazel,xcode,macos,ide

对于这个问题,rules_xcodeproj 可以通过构建索引解决,因为依赖信息在 Bazel 侧(BUILD 文件中)是完整的,所以触发构建后可以让代码高亮正确展示。

但由于编辑索引使用的参数是 Xcode 从文件所属的 Library Target 的 Build Settings 中获取的,因此在代码编辑过程中仍然会出现高亮错误的问题。

构建索引:指在构建过程中输出索引产物,需要通过 index-import 导入 Xcode 缓存目录(Derived Data)下供 Xcode 消费。

编辑索引:在代码编辑过程中实时生成的索引,在内存中消费索引结果,不会将产物写入磁盘。

在这个场景下,rules_xcodeproj 移除依赖的做法是有缺陷的

那么我们要在 rules_xcodeproj 恢复 Target 间的依赖关系么?

答案是不需要。首先,前文有提及大量复杂的依赖关系会导致 Xcode 卡顿,不应恢复;其次,要解决这类代码高亮错误的问题,需要的其实并不是所有 Target 之间的依赖关系,而是源码文件当前构建 App Target 的关系。

回顾一下 Demo 工程最简单的结构,当源码文件直接被对应 App Target 引用时,是不需要 Library Target 间的依赖关系来建立联系的。

monorepo bazel,xcode,macos,ide

基于这一思路,我们将所有 Library Target 的源码合并到了对应 App Target。当然,直接合并源码以后索引并不能正常工作,需要对受影响的功能点进行适配,这些适配将在下一节源码合并方案中展开介绍。

源码合并方案
索引参数接管

将所有源码合并至 App Target 虽然能解决文件与 App 的关联问题,但各个 Library Target 编译参数是不同的,聚合之后不同 Target 下源文件的参数就无法通过 Build Settings 区分了。

对于这个问题,我们是通过 XCBBuildServiceProxy 接管索引参数计算解决的。

索引构建时,Xcode 会先将文件所属 Target 的 Build Settings 发送给 XCBBuildService 处理成编译器理解的参数,再交给 SKAgent 触发编译器进行实际编译行为。而我们在 XCBBuildServiceProxy 的基础上实现了 BitSkyXCBBuildService,可以拦截 Xcode 发给 XCBBuildService 的请求,通过 Bazel aquery 查询到具体文件的编译参数,直接返回给 Xcode 完成后续的索引构建行为。

monorepo bazel,xcode,macos,ide

完成源码合并索引参数接管这两步改造以后,工程结构如下图所示。可以看到 AppA Scheme 能够直接通过 AppA Target 关联到  public.m(图中红线),从而正确地应用编译参数,高亮对应代码块。rules_xcodeproj 移除依赖关系的副作用也完全被修复。

monorepo bazel,xcode,macos,ide
Library Target 移除

完成源码合并以及索引参数的接管之后,Library Target 中的主要信息( Build Settings 和源码)都不再有意义了,是否能将这些 Target 信息直接移除呢?

经过梳理,Library Target 主要有以下三个作用,在完成源码合并以及索引参数接管后,仅需对“Module 中间产物生成”进行一些改造即可将几百个 Library Target 的信息进行移除,大幅精简工程文件的内容。

Library Target 作用 说明 适配方案
触发 Xcode 索引 Xcode 只会对添加到 Build Phase - Compile Sources 中的源码文件生成索引 将源码添加到 App Target 的 Compile Sources 中有相同的效果;
按 Target 维度隔离 Build Settings Xcode 原生的索引功能会通过 Build Settings 生成文件的编译参数 通过 XCBBuildServiceProxy 接管索引参数请求,交由 Bazel aquery 查询具体文件的编译参数
Module 中间产物生成 在 Library Target 的 Build Phase 触发各个 Target 维度的中间产物生成 将所需产物聚合到各个 App Target 的 Build Phase 触发生成

最终的工程结构如下图所示。

monorepo bazel,xcode,macos,ide

整体方案上线后,头条工程文件(project.pbxproj)行数从 45w 减少至 35w,工程启动与文件操作耗时也比原来的 Tulsi 工程减少了 60% 以上


Tulsi rules_xcodeproj(原生) rules_xcodeproj(源码合并)
工程首次冷启 47s 22s 16s
二次启动 33s 16s 12s
文件操作 新增 20s
删除 23s
新增 13s
删除 11s
新增 8s
删除 6s

p.s. 源码合并后存在一个副作用是 Xcode Build Phase 页面加载时间会增加很多,但考虑到使用 bazel 构建后我们并不需要在 Build Phase 修改配置,这个副作用是可以接受的。

构建

rules_xcodeproj 目前提供了两种 Build 模式,分别是 "Build with Xcode" 和 "Build with Bazel"。

  • "Build with Xcode" 模式下,构建行为是由 Xcode 接管的。

  • "Build with Bazel" 模式下,构建行为是由 Bazel 接管的。

据 rules_xcodeproj 官方介绍,"Build with Xcode" 模式在 Bazel 7 下将很难支持,并且即将到来的新的增量生成模式也会放弃 "Build with Xcode" 。

所以这里主要看一下 "Build with Bazel" ,这个模式生成的工程中,宿主 Target 对应一个 XCScheme,这个 Scheme 的 Build Pre-actions 里生成一个 SCHEME_Target_IDS_FILE 用于记录 Target 的 Bazel Label。然后宿主 Target 依赖了 Target BazelDependencies,Xcode 在构建宿主 Target 之前会先构建 BazelDependencies。BazelDependencies 通过 Build Phase 去调用 Bazel Build,这个时候会解析 SCHEME_Target_IDS_FILE 获取需要构建的 Bazel Target。BazelDependencies 构建完成后,宿主 Target 的 Build Phase 里会去把相应的 Bazel 的产物拷贝到 Xcode Derivedata 目录下。

monorepo bazel,xcode,macos,ide

另外,在 rules_xcodeproj 的规划中,未来还会提供一种新的模式,叫做 "Build with Proxy",在这个模式下,会通过 XCBBuildServiceProxy 完全绕过 Xcode build system,由 Bazel 控制整个 build 过程。相比 "Build with Bazel" ,这个模式可以带来一些更贴近原生的 Xcode 使用体验,比如:

  • 无需添加 BazelDependencies Target

  • 可以去掉重复的 warnings/errors

  • 可以有更稳定的索引效果

  • 可以在进度条展示更多信息

  • 可以有更详细的 Build 报告

当然这种模式也存在比较大的问题

  • 在不同 Xcode 版本之间,Xcode 和 XCBBuildService 交互的 API 可能会有一些破坏性的变更,需要逐一适配

  • 需要在 Xcode 启动时注入环境变量,将 XCBBuildService 指向自定义的 XCBBuildServiceProxy

BitSky 目前采用的方案和 "Build with Proxy" 是类似的,通过 BitSkyXCBBuildService 接管 Xcode 的 build 行为。在用户点击 Build 时,BitSkyXCBBuildService 里可以从宿主 Target 的 Build Settings 里解析获取对应的 Bazel Target,然后再由 BitSky 生成调用 Bazel Build 的命令,这样可以保证 Bazel Build 的参数完全由 BitSky 控制,同时可以通过 Bazel 的 Build Event Protocol 来更好的提供 Xcode 的进度 和 Build 日志展示。

monorepo bazel,xcode,macos,ide

同时为了保证在打开生成的 Xcode 工程时,都能够使用 BitSkyXCBBuildService,BitSky 在生成工程同时,会生成一个 Xcode 的影子分身 BitSkyXcode。使用这个 BitSkyXcode 打开工程,无需手动注入环境变量,体验上和使用原生 Xcode 打开工程基本一致。

总结

本文主要介绍了我们将 Xcode 工程生成工具切换到 rules_xcodeproj 过程中做的一些适配和优化工作:

  • 索引方面:

    • 在分析 Tulsi 与 rules_xcodeproj 工程文件的过程中我们注意到最大的差异在于 rules_xcodeproj 移除了 Library Target 间的依赖关系,这也是 Tulsi 工程更加卡顿的罪魁祸首。

    • rules_xcodeproj 移除依赖关系后会导致多 Target 共用的源文件语法高亮异常,我们通过源码合并方案解决了这个问题,并且精简了工程文件信息,提升了 Xcode 流畅度。

  • 构建方面:

    • 我们通过 BitSkyXCBBuildService 接管了 Xcode 的 build 行为,能够更好地管理构建参数并在 Xcode 提供构建进度和日志的展示。

在完成切换之后,虽然 Xcode 代码编辑过程中的卡顿得到了明显的缓解,但本地研发的调试过程,仍然存在 Xcode 卡顿/卡死等现象,对研发同学的开发工作存在较大困扰。后续,我们将针对调试体验,从生成工程的角度做一些优化工作。

目前考虑基于 Focus Mode 的理念,从底层能力上支持研发同学仅关注与当前需求开发相关联的部分代码,比如:

  • 裁剪 Xcode 工程中需要索引的源代码;

  • 裁剪构建过程中需要执行编译源代码;

  • 裁剪调试时调试器需要加载调试信息;

另外在用户侧,通过策略智能帮助研发同学,选择和添加需要 "Focus" 的源码。

参考文档

Tulsi (https://github.com/bazelbuild/tulsi)

rules_xcodeproj (https://github.com/MobileNativeFoundation/rules_xcodeproj)

Migrating from Xcode to Bazel (https://bazel.build/migrate/xcode)

Monorepo 解决方案 — Bazel 在头条 iOS 的实践

哔哩哔哩 iOS Bazel 进化之路

用VSCode基于Bazel打造Apple生态开发环境文章来源地址https://www.toymoban.com/news/detail-853603.html

到了这里,关于Monorepo 解决方案 — 基于 Bazel 的 Xcode 性能优化实践的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • SAP性能监控分析解决方案

            SAP应用的重要性不言而喻,历经30余年的国内发展,已经拥有成百上千的中国用户。         SAP应用对业务至关重要,一旦该应用出现缓慢或性能不佳的情况,将会对企业收入造成重大损失。因此,SAP性能监控和用户体验监测变得尤为重要。         网深科

    2024年02月01日
    浏览(64)
  • Elasticsearch的性能瓶颈与解决方案

    Elasticsearch是一个分布式、实时的搜索和分析引擎,它基于Lucene库构建,具有高性能、高可扩展性和高可用性。在大规模数据处理和实时搜索场景中,Elasticsearch是一个非常重要的工具。然而,随着数据量的增加和查询压力的加大,Elasticsearch可能会遇到性能瓶颈。本文将讨论

    2024年02月20日
    浏览(36)
  • Android开发之性能优化:过渡绘制解决方案

    1. 过渡绘制 屏幕上某一像素点在一帧中被重复绘制多次,就是过渡绘制。 下图中多个卡片跌在一起,但是只有第一个卡片是完全可见的。背后的卡片只有部分可见。但是Android系统在绘制时会将下层的卡片进行绘制,接着再将上层的卡片进行绘制。但其实,下层卡片不可见的

    2024年02月11日
    浏览(37)
  • 【高性能、高并发】页面静态化解决方案-OpenResty

    OpenResty介绍 OpenResty是一个基于 Nginx 与 Lua 的高性能 Web 平台,其内部集成了大量精良的 Lua 库、第三方模块以及大多数的依赖项 用于方便地搭建能够处理超高并发、扩展性极高的动态 Web 应用、Web 服务和动态网关 OpenResty通过汇聚各种设计精良的 Nginx 模块(主要由 OpenResty 团队

    2024年02月13日
    浏览(49)
  • macOS 更新Xcode,UE4编译C++报错variable “LayerNames” set but not used -Wunused-but-set-variable解决方案

    本人在一次苹果macOS系统更新(手贱点了一下AppStore里的全部更新)后,发现虚幻引擎UE4.27的C++项目无法编译通过,报错信息为: 经过翻查社区资料: LayerNames error bricking my Mac projects - Platform Builds - Unreal Engine Forums 外加本人亲自验证,得出如下两种适用于不同用户的解决方案

    2023年04月08日
    浏览(37)
  • 提升Python代理程序性能的终极解决方案:缓存、连接池和并发

    在开发Python代理程序时,优化性能是至关重要的。本文将为你介绍一套终极解决方案,通过缓存、连接池和并发处理等技术,极大地提升Python代理程序的效率和稳定性。 游戏国内地更换虚拟含ip地址数据库地区 1.缓存技术 缓存是 .0-*-+69+6ES2 0一种重要的性能优化技术,通过存

    2024年02月12日
    浏览(35)
  • Redis 分区:构建高性能、高可用的大规模数据存储解决方案

    在 Redis 中,分区是一种将数据分布在多个实例上的技术,用于处理大规模数据和提高系统性能。通过分区,可以将数据均匀地分布在多个节点上,从而减轻单个节点的负载压力,并实现水平扩展。 Redis 分区应用场景 1. 大规模数据存储 在 Redis 中,单个实例的内存有限,无法

    2024年04月14日
    浏览(46)
  • 简单讲讲ES在大数据规模下的性能问题与解决方案(一)

            众所周知,在处理大规模数据量的时候,我们的传统关系型数据库,例如MySQL,Oracle等...它们对于这些大规模数据的处理与计算是非常吃力的,甚至于在内存资源不足的情况下导致在mysql中查询数据失败的情况,甚至由于数据的规模较大,会消耗更多的磁盘空间,得不

    2024年02月04日
    浏览(41)
  • Redis缓存设计与性能优化【并发创建同一个缓存,解决方案:互斥锁】

    开发人员使用“缓存+过期时间”的策略既可以加速数据读写, 又保证数据的定期更新, 这种模式基本能够满足绝大部分需求。 但是有两个问题如果同时出现, 可能就会对应用造成致命的危害: 当前key是一个热点key(例如一个热门的娱乐新闻),并发量非常大。 重建缓存不

    2024年04月09日
    浏览(48)
  • 【虹科干货】Redis Enterprise 自动分层技术:大数据集高性能解决方案

    越来越多的应用程序依赖于庞大的数据集合,而这些应用程序必须快速响应。 借助自动分层,Redis Enterprise 7.2 帮助开发人员轻松 创建超快的应用程序。何乐而不为?   Redis 将数据存储在内存中,因此应用程序能以最快的速度检索和处理数据。 然而,随着 应用程序需要处理

    2024年02月05日
    浏览(43)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包