Android build子系统(01)Ninja构建系统解读
说明:本文将解读Ninja构建系统,这是当前Android Framework中广泛使用的构建工具。我们将从Ninja的起源和背景信息开始,逐步解读Ninja的优势和核心原理,并探讨其一般使用场景。然后介绍其在Android Framework中的应用及相关工具:kati、soong、gn等,最后介绍下如何自行构建一个Ninja编译系统,以便于对Ninja有一个完整的了解。
1 Ninja基本内容解读
1.1 什么是Ninja?
Ninja是一个小型的、专注于速度的构建系统,最初由Google的程序员Chris Manson开发,最初用于加速Chrome浏览器的构建过程。Ninja的设计哲学是简化构建过程,通过精确指定输入和输出关系,实现快速增量构建。Ninja的首次使用是在开源的Chromium浏览器项目中,该项目拥有超过30,000个源文件,Ninja能够在不到一秒的时间内开始构建过程,相较于其他构建系统有显著的速度优势。
与Make相比,Ninja舍弃了各种高级功能来实现快速的增量编译。Make具有各种高级功能,比如函数、内置规则,而Ninja则专注于速度。Ninja的构建文件是可读的,但更多场合下,是由其他构建系统的工程文件自动生成的。
Ninja被用于构建Google Chrome、部分Android系统、LLVM等项目。由于CMake支持Ninja后端,CMake可以生成Ninja构建文件,从而利用Ninja的高效构建能力。
总之,Ninja是一个快速、轻量级的构建系统,专注于增量构建,常用于大型项目。
1.2 Ninja的核心原理解读
Ninja的核心原理基于构建文件中定义的规则和依赖关系,通过构建图(依赖图)来确定需要重新构建的目标。Ninja使用简单的文件时间戳比较来实现增量构建,避免了不必要的编译过程。总结下,它的核心原理主要包含以下几个方面:
- 依赖图: Ninja构建过程基于一个明确的依赖图,这个依赖图定义了项目中所有文件的依赖关系。每个节点代表一个文件或一个构建命令,边代表依赖关系。Ninja在构建前会构建这个依赖图,并在构建时只执行那些受影响的节点。
- 构建文件: Ninja使用
.ninja
文件作为输入,这些文件包含了构建规则和目标。这些规则定义了如何从输入文件生成输出文件。.ninja
文件通常由其他工具(如GN或CMake)生成。 - 增量构建: 只有当输入文件发生变化时,Ninja才会重新构建目标。它通过比较文件的时间戳来确定哪些文件需要更新。
- 并行构建: Ninja能够并行执行多个构建任务,以充分利用多核处理器的能力。它会智能地调度任务,以最大化并行度并减少构建时间。
- 避免冗余: Ninja的设计避免了不必要的工作。例如,它不会在构建过程中重新扫描依赖关系,因为这些信息已经在构建文件中明确指定。
- 简洁性: Ninja的构建文件(
.ninja
文件)是简洁的,专注于构建逻辑,不包含条件逻辑或循环。这使得构建文件易于理解和维护。 - 可靠性: Ninja在构建过程中会捕获错误并立即停止,这样可以避免无效的构建尝试。
- 工具链无关性: Ninja本身不关心底层的编译器或工具链,它只负责调度构建任务。这使得Ninja可以与多种编译器和工具链一起使用。
- 跨平台: Ninja可以在Windows、Linux和macOS等多种操作系统上运行,这使得它适用于跨平台项目。
- 性能: Ninja的性能非常出色,尤其是在大型项目中。它能够快速地开始构建过程,并在构建过程中保持高效率。
Ninja的核心原理是提供一个简单、快速、可靠的构建系统,它通过优化构建过程和利用现代硬件的优势来实现这一目标。
1.3 Ninja相比于make的优势
Ninja 和 Make 都是构建系统,用于自动化编译和构建软件项目。Ninja 是在 Make 的基础上发展起来的,它旨在解决 Make 在某些方面的局限性,特别是在大型项目中的性能问题。以下是 Ninja 相比 Make 的一些优势:
- 速度: Ninja 的主要优势是速度快。它在设计时就注重减少磁盘 I/O 和提高构建速度。Ninja 通过预先计算构建依赖关系,并在构建文件中明确指定,从而避免了 Make 在构建过程中重复扫描源代码文件的开销。
- 并行构建: Ninja 能够更有效地利用多核处理器进行并行构建。它默认就会并行执行构建任务,而 Make 需要显式地通过
-j
选项来指定并行构建的作业数。 - 依赖关系: Ninja 的依赖关系更加明确和静态。它不依赖于文件的时间戳来确定是否需要重新构建,而是使用文件内容的哈希值,这减少了在构建过程中的不确定性和不必要的构建。
- 构建文件: Ninja 的构建文件(
.ninja
文件)通常由其他工具(如 GN 或 CMake)生成,这使得构建文件的维护和管理更加一致和简单。而 Makefile 通常需要手工编写,容易出错且难以维护。 - 简洁性: Ninja 的构建文件更加简洁,因为它避免了 Makefile 中常见的复杂逻辑和条件判断。这使得 Ninja 文件更容易理解和修改。
- 可靠性: Ninja 在遇到错误时会立即停止构建,而不是尝试继续执行其他任务。这有助于更快地发现和解决问题。
- 跨平台: Ninja 支持跨平台构建,可以在 Windows、Linux 和 macOS 上运行,而 Make 起源于 Unix 系统,虽然也有跨平台的支持,但在某些平台上可能需要额外的配置。
- 工具链无关性: Ninja 不关心底层的编译器或工具链,它只负责调度构建任务。这使得 Ninja 可以与多种编译器和工具链一起使用,而 Make 可能需要为不同的编译器或工具链编写不同的 Makefile。
- 一致性: Ninja 通过生成的构建文件来执行构建,这使得构建过程更加一致,不受环境变化的影响。而 Makefile 可能会受到当前 shell 环境的影响。
- 性能: Ninja 在大型项目中的性能优势尤为明显,因为它能够更快地启动构建过程,并且在增量构建时更加高效。
总的来说,Ninja 通过优化构建过程和利用现代硬件的优势,提供了一种更快速、更可靠、更易于维护的构建解决方案。
1.4 Ninja的安装
ubuntu上可以直接安装:
$sudo apt install ninja-build
1.5 Ninja的一般使用场景
以下是 Ninja 的一般使用场景:
- 跨平台构建:Ninja 支持在 Windows、Linux 和 macOS 等多种操作系统上运行,适用于跨平台项目构建。
- 大型项目构建:Ninja 特别适合于大型项目,如 Chromium、LLVM 等,这些项目包含成千上万个源文件,Ninja 通过并行编译显著缩短构建时间。
- 与现代构建系统配合:Ninja 常与 CMake 或 Meson 等现代构建系统配合使用,生成高效的构建文件。
- 持续集成/持续部署(CI/CD):在 CI/CD 系统中,Ninja 的快速构建能力有助于缩短反馈循环时间,提高构建和测试的效率。
- 需要快速迭代的场景:在开发过程中,如果需要频繁编译,Ninja 可以提供快速的反馈循环,使得开发者可以更快地进行代码迭代。
- 自定义构建规则:Ninja 允许开发者自定义构建规则,适用于需要特殊构建逻辑的项目。
- 与Android NDK配合:Android NDK 默认使用 Ninja 进行原生库的构建,因此在 Android 原生应用开发中,Ninja 是一个重要的工具。
- Bazel 构建工具:Google 的 Bazel 构建工具虽然有自己的内部构建系统,但也可以配置为使用 Ninja 提高性能。
Ninja 的核心优势在于其构建速度和并行编译能力,这使得它成为许多大型和复杂项目的理想选择。
2 Ninja在Android Framework中的应用
Ninja适用于需要快速构建的大型项目,尤其是在C/C++代码编译方面表现出色。在Android Framework的构建中,Ninja主要用于编译原生代码,同时也支持Java/Kotlin代码的编译。
随着Android系统的不断演进,从Android 7.0(Nougat)开始引入了Soong构建系统,它使用Android.bp
文件来定义构建规则,并生成Ninja文件,然后由Ninja执行实际的编译和链接任务。
2.1 为什么要引入ninja?
实际上在Android 7.0(Nougat)之前,Android系统主要使用Makefile和Android.mk
文件来描述构建过程。这些文件定义了如何编译和链接模块,并通过调用make
命令来执行构建任务。
随着Android系统和应用程序的增长,这种构建方式变得越来越慢,尤其是在大型项目中。为了解决这个问题,Google开始引入新的构建系统来提高编译速度和效率。
2.2 过渡期工具:Kati工具
在从Make过渡到Ninja的过程中,Google开发了Kati工具,用于将Android.mk
文件转换为Ninja可以理解的构建文件。这样,现有的Android.mk
文件可以被重用于新的构建系统,而不需要立即迁移到新的格式。
这里给出一个简单的kati工具使用的流程,便于更好地理解Kati工具:
假设你有一个简单的 Android.mk
文件,它定义了一个模块的编译规则,如下所示:
include $(CLEAR_VARS)
LOCAL_MODULE := my_module
LOCAL_SRC_FILES := my_source.c
include $(BUILD_SHARED_LIBRARY)
这个 Android.mk
文件告诉构建系统如何编译一个共享库 my_module
,它由 my_source.c
源文件构建而来。使用 Kati 转换这个过程如下:
$cd path/to/your/module
$ckati --ninja
这将生成一个 build.ninja
文件,内容类似于:
rule cccommand = gcc -c $cflags -o $out $indescription = COMPILEbuild my_module.o: cc my_source.c
build my_module: link my_module.o
然后,你可以使用 Ninja 来构建这个模块:
$ninja -f build.ninja
2.3 Soong工具构建系统引入
从Android 7.0(Nougat)开始,引入了Soong构建系统,它使用Android.bp
文件来定义构建规则,并生成Ninja构建文件。在Android 8.0(Oreo)中,Google进一步引入了Android.bp
文件和Soong构建系统。Android.bp
文件是一种更简洁、更易于维护的构建脚本格式。Soong是一个新的构建引擎,它使用Android.bp
文件来生成Ninja构建文件。
这里给出一个简单的kati工具使用的流程,便于更好地理解Soong工具:
假设你有一个简单的 Android.bp
文件,它定义了一个 C/C++ 库的构建规则,如下所示:
cc_library_shared {name: "my_library",srcs: ["src/my_library.c"],shared_libs: ["liblog"],export_include_dirs: ["include"],
}
这个 Android.bp
文件告诉构建系统如何编译一个共享库 my_library
,它由 src/my_library.c
源文件构建而来,并包含 liblog
库。
在 Android 构建环境中,通常不需要直接调用 Soong 命令,因为构建脚本会自动化这个过程。这里为了方便理解,使用手动方式触发 Soong 的构建过程,使用以下命令:
source build/envsetup.sh
lunch XXX-target
out/soong/.bootstrap/bin/soong_build --make-mode <target-moudle>
这个命令会执行 Soong,生成 out/soong/build.ninja
文件,然后 Ninja 会使用这个文件来编译项目,使用 Ninja 来构建这个模块:
$ninja -f build.ninja
2.4 GN工具的引入
GN(Generate Ninja)是一个由Google开发的元构建系统,它用于生成Ninja构建文件,这些文件随后由Ninja构建系统使用来编译项目。GN在Android系统中的使用是逐步引入的。
GN在Android系统中的引入最开始主要是为了改善Chromium项目的构建性能。Chromium是Google Chrome浏览器的开源项目,它有着庞大的代码库。GN的设计目标是减少构建时间,尤其是在大型项目中。GN通过并行构建和优化依赖关系来提高构建速度。
从Android 8.0(Oreo)开始,GN的使用更加广泛,并且随着Android版本的更新,GN和Ninja的集成逐渐深入到Android的构建系统中。GN的主要优势如下:
- 速度:GN生成的Ninja文件能够快速执行构建任务,尤其是在大型项目中。
- 可读性:GN的构建文件(
.gn
或BUILD.gn
)比传统的Makefile更容易阅读和维护。 - 跨平台:GN支持跨平台构建,可以在不同的操作系统上使用。
总的来说,GN的引入也是为了提高Android系统和Chromium等大型项目的构建效率。
gn的安装,可以从官网下载代码编译:
$git clone https://gn.googlesource.com/gn
$cd gn
$python build/gen.py
$ninja -C out
然后把二进制文件放到你的路径里即可。
这里给出一个简单的GN工具使用的流程,便于更好地理解GN工具:
假设你有一个简单的 C++ 项目,你需要编写一个 BUILD.gn
文件来告诉 GN 如何构建它。这个文件可能会包含如下内容:
# 定义一个可执行文件目标
executable("my_app") {sources = ["main.cc","utils.cc",]deps = ["//third_party/some_library",]
}
这个 BUILD.gn
文件定义了一个名为 my_app
的可执行文件,它依赖于 main.cc
和 utils.cc
这两个源文件,以及一个名为 some_library
的第三方库。
在 Android 构建环境中,GN 的执行通常是自动的。这里为了方便理解,手动运行 GN,在项目根目录下运行以下命令:
$gn gen out/debug --dotfile=out/debug/gn_graph.dot
这个命令会生成一个名为 out/debug
的输出目录,生成一个 Ninja 构建文件。并创建一个名为 gn_graph.dot
的文件,该文件包含了构建图的 Graphviz 表示,用于可视化构建过程。
然后可以使用 Ninja 来构建这个模块:
$ninja -f build.ninja
2.5 详细解读kati soong gn与Ninja之间的关系
Kati、Soong、GN 和 Ninja 都是构建系统组件。在 Android 系统的编译过程中,这些工具通常按照以下流程工作:
- GN 将BUILD.gn转换为 Ninja 文件。
- Kati 将
Android.mk
转换为 Ninja 文件。 - Soong 解析
Android.bp
文件并生成 Ninja 文件。 - Ninja 读取生成的 Ninja 文件,并执行构建任务。
总的来说,GN Kati Soong相当于cmake的角色,而Ninja相当于make的角色。同时GN 和 Ninja 是现代构建系统的工具,而 Kati 和 Soong 是 Android 在从旧的 Make 构建系统过渡到基于 Ninja 的构建系统过程中引入的组件。
作为一个高效、轻量级的构建工具,在Android Framework的构建过程中发挥着重要作用。了解Ninja的原理和优势,可以帮助开发者更好地优化构建过程,提高开发效率。接下来用一个最简单的例子,我们来熟悉一下Ninja的编译流程。
3 构建一个最简单Ninja编译系统
构建一个最简单的 Ninja 编译系统,你需要以下2个文件:一个 C/C++ 源文件、一个 Ninja 构建文件。以下是一个简单的 "Hello, World!" 程序的例子。
3.1 源代码文件(hello.c
)
// hello.c
#include <stdio.h>int main() {printf("Hello, World!\n");return 0;
}
3.2 Ninja 构建文件(build.ninja
)
# 定义编译器
cflags = -Wall# 定义构建规则
rule cccommand = gcc $cflags -c $in -o $outdescription = Compiling $out# 定义构建目标
build hello.o: cc hello.c
build hello: link hello.ocommand = gcc -o $out $indescription = Linking $out
3.3 运行 Ninja 构建
首先,确保你已经安装了 Ninja。然后,在包含上述两个文件的目录中打开命令行,运行以下命令:
#默认路径
$ninja
这个命令会检查 build.ninja
文件中的指令,编译 hello.c
文件,并将其链接成可执行文件 hello
。构建完成后,你可以运行生成的可执行文件:
$./hello
Hello, World!
相关文章:
Android build子系统(01)Ninja构建系统解读
说明:本文将解读Ninja构建系统,这是当前Android Framework中广泛使用的构建工具。我们将从Ninja的起源和背景信息开始,逐步解读Ninja的优势和核心原理,并探讨其一般使用场景。然后介绍其在Android Framework中的应用及相关工具&am…...
徐老师的吉祥数
题目背景 文件读写 输入文件avoid.in 输出文件avoid.out 限制 1000ms 512MB 题目描述 众所周知, 3这个数字在有些时候不是很吉利,因为它谐音为 “散” 所以徐老师认为只要是 3的整数次幂的数字就不吉利 现在徐老师想知道,在某个范围[l,r] …...
使用html写一个能发起请求的登录界面
目录 head部分 内联样式部分 body部分 login-form类的div myModal类的div id script部分 总的代码 界面与操作演示 <!DOCTYPE html> <html lang"en"> <!DOCTYPE html> 这是文档类型声明,告诉浏览器这是一个 HTML文档。 <…...
五子棋双人对战项目(2)——登录模块
目录 一、数据库模块 1、创建数据库 2、使用MyBatis连接并操作数据库 编写后端数据库代码 二、约定前后端交互接口 三、后端代码编写 文件路径如下: UserAPI: UserMapper: 四、前端代码 登录页面 login.html: 注册页面…...
几种操作系统和几种cpu
常见的操作系统:windows,linux,macOS,统信,deepin,raspberry,andriod,iOS,鸿蒙,等等。 常见的cpu:intel,amd,龙芯&#x…...
[Cocoa]_[初级]_[使用NSNotificationCenter作为目标观察者实现时需要注意的事项]
场景 在开发Cocoa程序时,由于界面是用Objective-C写的。无法使用C的目标观察者[1]类。如果是使用第二种方案2[2],那么也需要增加一个代理类。那么有没有更省事的办法? 说明 开发界面的时候,经常是需要在子界面里传递数据给主界面࿰…...
彩虹易支付最新版源码及安装教程(修复BUG+新增加订单投诉功能)
该源码当前版本为较新的版本,新增了订单投诉功能和一套精美的二次元模板。 此版本为全开源版本,所有文件均未加密。系统默认安装完成后无法直接打开,需要进一步配置。 本站特别针对BUG文件进行了修复,且在PHP7.4环境下表现良好。…...
ping香港服务器超时的原因通常有哪些?
Ping命令用于测试计算机与目标服务器之间的网络连接。当您在尝试使用ping命令检测服务器时遇到超时的情况,通常可能是由以下原因造成的: 1. 网络连接问题: - 本地网络故障:如网线损坏、路由器故障或配置不当。 - ISP(互联网服务提…...
书生大模型实战(从入门到进阶)L3-彩蛋岛-InternLM 1.8B 模型 Android 端侧部署实践
目录 1 环境准备 1.1 安装rust 1.2 安装Android Studio 1.3 设置环境变量 2 转换模型 2.1 安装mlc-llm 2.2 (可选)转换参数 2.3 (可选)生成配置 2.4 (可选)上传到huggingface 2.5 (可选) 测试转换的模型 3 打包运行 3.1 修改配置文件 3.2 运行打包命令 3.3 创建签…...
setState是同步更新还是异步更新
setState是同步更新还是异步更新 先说结论setState为什么设计为异步react18之前为什么不确定是同步还是异步呢react18之后setState有哪些改动 先说结论 React18之前:使用了ReactDOM.render,setState在React调度流程中是异步更新,在原生事件和…...
TCP 流量控制 - 滑动窗口和拥塞控制算法解析
滑动窗口主要管理数据流动的速率,对单个连接较好,拥塞控制则防止网络出现过载,对提高整体的网络通畅较好。下面详细解析两者的原理和作用。 1. TCP 滑动窗口算法 TCP 使用滑动窗口机制来控制数据的发送和接收,以实现流量控制&…...
MongoDB聚合操作及索引底层原理
目录 链接:https://note.youdao.com/ynoteshare/index.html?id=50fdb657a9b06950fa255a82555b44a6&type=note&_time=1727951783296 本节课的内容: 聚合操作: 聚合管道操作: 编辑 $match 进行文档筛选 编辑 将筛选和投影结合使用: 编辑 多条件匹配: …...
C++ | Leetcode C++题解之第454题四数相加II
题目: 题解: class Solution { public:int fourSumCount(vector<int>& A, vector<int>& B, vector<int>& C, vector<int>& D) {unordered_map<int, int> countAB;for (int u: A) {for (int v: B) {count…...
【从零开始实现stm32无刷电机FOC】【实践】【7.2/7 完整代码编写】
目录 stm32cubemx配置芯片选择工程配置stm32基础配置SPI的配置定时器的配置ADC的配置中断优先级的配置生成工程 工程代码编写FOC代码结构搭建电机编码器角度读取PWM产生FOC开环代码编写确定电机正负旋转方向电机旋转速度计算多圈逻辑角度电流采样极对数转子角度确定 闭环控制控…...
谷歌收录查询工具,谷歌收录查询工具的使用指南
谷歌收录查询工具是网站管理员和SEO专业人士用于检查网站是否被谷歌搜索引擎收录及其收录情况的重要辅助手段。以下是一些常用的谷歌收录查询工具及其详细使用指南: 一、Google Search Console(谷歌搜索控制台) 简介: Google Sea…...
vue3 拖拽插件(drag)
前端vue项目中,经常会有弹框拖拽的需求,下面介绍常用方法: 1.如果你使用的是elementPlus插件的el-dialog组件,只需要增加draggable属性即可,代码如下: <el-dialogv-model"showDiloag"width"500&quo…...
数据结构--线性表(顺序结构)
1.线性表的定义和基本操作 1.1线性表以及基本逻辑 1.1.1线性表 (1)n(>0)个数据元素的有限序列,记作(a1,a2,...an),其中ai是线性表中的数据元素,n是表的长度。 (2)…...
面试准备111
Java基础 反射 集合 多线程 Synchronized/volatile 线程池 cas atomic 网络 tcp 三次握手/四次挥手 流量控制 拥塞控制 数据结构 算法 Spring 循环依赖 Mybatis 如何防止sql注入 Mysql 索引 索引分类 索引设计原则 事务 四种隔离级别 MVCC 日志 Binlog…...
Spring 的 IOC 和 AOP 是什么,有哪些优点?解密 Spring两大核心概念:IOC与AOP的魅力所在
在现代Java开发中,Spring框架几乎是不可或缺的存在。它不仅简化了开发过程,还提高了软件的灵活性和可维护性。今天,我们要深入探讨Spring中的两个核心概念:IOC(控制反转)和AOP(面向切面编程&…...
第二百六十四节 JPA教程 - JPA查询日期参数示例
JPA教程 - JPA查询日期参数示例 我们可以在查询中使用日期类型值。 以下代码使用EntityManager创建具有两个参数的查询。 然后它传递两个日期类型值。 em.createQuery("SELECT e " "FROM Professor e " "WHERE e.startDate BETWEEN :start AND :en…...
Spring MVC的运行流程详解
Spring MVC作为一个广泛使用的框架,提供了灵活且强大的MVC架构支持。尤其在业务系统中,Spring MVC能够有效地处理大量并发请求,提供良好的用户体验。本文将详细讲解Spring MVC的运行流程,以电商交易系统为案例,帮助读者…...
判断有向图是否为单连通图的算法
判断有向图是否为单连通图的算法 算法描述伪代码C语言实现解释在图论中,单连通图(singly connected graph)是指对于图中的任意两个顶点 m 和 v,如果存在从 m 到 v 的路径,则该路径是唯一的。为了判断一个有向图是否为单连通图,我们需要确保从任意顶点出发,到任意其他顶点…...
php与python建站的区别有哪些
php与Python建站的区别: 1、语言层面Python的特性比php好,更加规范。 2、Python的性能比php高。 3、有只需要启动服务的时候执行一次的代码,在php里每个请求都会被执行一次,Python不需要。虽然php可以通过缓存缩短这方面的差距…...
模型评估与验证:确保模型在未知数据上的表现----示例:使用K折交叉验证评估分类模型、房价预测问题使用K折交叉验证来评估一个线性回归模型的性能
模型评估与验证是机器学习流程中的关键步骤,它帮助我们了解模型在未见过的数据上的泛化能力。交叉验证(Cross-Validation, CV)是一种常用的技术,通过将数据集划分为多个子集并进行多次训练和测试来估计模型的性能。此外࿰…...
awd基础学习
一、常用防御手段 1、改ssh密码 passwd [user] 2、改数据库密码 进入数据库 mysql -uroot -proot 改密码 update mysql.user set passwordpassword(新密码) where userroot; 查看用户信息密码 select host,user,password from mysql.user; 改配置文件 (否则会宕机…...
C#基于SkiaSharp实现印章管理(10)
向PDF文件插入印章图片比之前实现的向图片文件插入印章麻烦得多。 最初的想法是使用PDF浏览控件在线打开PDF文件,然后在控件中实现鼠标移动时动态显示印章,点击鼠标时向当前PDF页面的鼠标点击位置插入图片。由于是.net 8的Winform项目,选…...
通过栈实现字符串中查找是否有指定字符串的存在
题目示例: 分析 由与没有给出字符串的长度,所以只能通过getline一次性处理,而在输入后恰好能倒序处理字符串,以标点符号为分界点,将数字当成字符放到栈里,遇到下一个标点符号时执行查找操作,…...
MongoDB伪分布式部署(mac M2)
1. 序言 本博客是上一博客的进阶版:mac M2安装单机版 MongoDB 7.x,上一博客可以看做是单机、单节点部署MongoDB本博客将介绍单机、多服务部署MongoDB,实际就是伪分布式部署 2. 副本集(Replica Set)方式部署 2.1 什么是副本集? …...
Golang | Leetcode Golang题解之第454题四数相加II
题目: 题解: func fourSumCount(a, b, c, d []int) (ans int) {countAB : map[int]int{}for _, v : range a {for _, w : range b {countAB[vw]}}for _, v : range c {for _, w : range d {ans countAB[-v-w]}}return }...
[ComfyUI]Flux:超美3D微观山水禅意,经典中文元素AI重现,佛陀楼阁山水画卷
在数字艺术和创意领域,[ComfyUI]Flux以其独特的虚实结合技术,已经成为艺术家和设计师们手中的利器。今天,我们激动地宣布,[ComfyUI]Flux带来了一款超美的3D微观山水禅意作品,经典中文元素通过AI技术重现,包…...
网站 跑马灯图片怎么做/运营怎么做
一. 简介 默认配置下 I.MX6U 工作频率为 396 MHz。但是 I.MX6U 系列标准的工作频率为 528MHz,有些 型号甚至可以工作到 696。本文我们就学习如何配置 I.MX6U 的系统时钟和其他的外设时钟,使其工作频率为 52 8MHz,而其他的外设时钟源都工作…...
响应式网站设计公司/2021百度模拟点击工具
DialogResult drMessageBox.Show("确认删除吗?", "提示", MessageBoxButtons.OKCancel); if (dr DialogResult.OK) { //用户选择确认的操作 MessageBox.Show("您选择的是【确认】"); } else if (dr DialogResult.Cancel) { //用户…...
杭州市建设工程检测协会网站/上海最近三天的新闻
VSCode 很方便 * 支持以目录作为一个 Project 的基准。 * 支持全局 search * 支持自定义 command (Task) 轻量级 Editor,有这些,就很舒心了。 VSCODE支持git、支持多种语言、支持各种插件、支持各种键盘映射,可以模仿成vim、sublime之类的 &a…...
为违法网站做推广进去要几年/神起网络游戏推广平台
今天记录的这两个是链表操作的两个题目 反转链表 反转一个单链表。 示例: 输入: 1->2->3->4->5->NULL 输出: 5->4->3->2->1->NULL 进阶: 你可以迭代或递归地反转链表。你能否用两种方法解决这道题? 思路一:采用头插法逆…...
王健林亏60亿做不成一个网站/百度关键词seo推广
一、Eclipse/JDK/Tomcat设置缓存 1, 设置Eclipse内存使用情况修改eclipse根目录下的eclipse.ini文件-vmargs //虚拟机设置-Xms40m -Xmx256m-XX:PermSize128M //非堆内存设置-XX:MaxPermSize256M2, JVM内存设置打开eclipse window-preferences-Java &…...
专业的建站/四川疫情最新情况
火车采集器(LocoySpider) 是一个供各大主流文章系统,论坛系统等使用的多线程内容采集发布程序。使用火车采集器,你可以瞬间建立一个拥有庞大内容的网站。系统支持远程图片下载,图片批量水印,Flash下载,下载文件地址探测࿰…...