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

bazel远程缓存(Remote Cache)

原理

您可以将服务器设置为构建输出(即这些操作输出)的远程缓存。这些输出由输出文件名列表及其内容的哈希值组成。借助远程缓存,您可以重复使用其他用户的 build 中的构建输出,而不是在本地构建每个新输出。

增量构建极大的提升了本地研发的构建效率,但有些场合它的效果不是很好,例如 CI 环境通常采用“干净”的容器,此时没有上一次的构建数据,只能全量构建。

即使是本地研发,如果从远端同步代码时修改了全局参数,也会导致增量构建失效。

缓存 (Remote Cache) 与远程执行 (Remote Execution) 可以很好的解决这个问题。

前面聊到,Action 满足封闭性,即相同的 Action 信息一定产生相同的结果。因此可以建立 Action 到 ActionResult 的映射。为了便于索引,Bazel 把 Action 信息通过 sha256 哈希算法压缩成摘要 (Digest),把 Digest 到 ActionResult 的映射存储在云端,就可以实现 Action 的跨构建共享。

Action 共享示意图

这里的 Storage 是完全基于内容寻址的,即“一个 Digest 唯一对应一个 ActionResult”,内容寻址的好处是不容易污染存储空间,因为修改任何一行代码会计算出不同的 Digest,不用担心污染别人的 ActionResult。内容寻址的存储引擎,被称为Content Addressable Storage(CAS),如果没有特别强调,本文后续使用简称 CAS 来表述。

CAS 里存放的任何文件,无论是 Action 的 Meta 信息还是编译产物二进制,都被称为 Blob。

为保证 CAS 的存储空间被有效利用,通常会使用 LRU 算法管理 CAS 里存储的 Blob,当存储空间写满时,最久没被访问的 Blob 就会被自动淘汰,这样就保证了空间里的 Blob 是最活跃的。

部署

部署&运行

前面讲了Bazel的基本本地使用和原理,但是我们知道,Bazel最重要的是支持缓存和分布式(远程执行),那么这一节主要就是讲如何让bazel使用缓存。

要能够缓存Bazel每个action的输出,我们就要一个server来实现remote cache,用于存储action的输出。这些输出实际上是一堆文件输出对应的hash值。总体来说,我们需要满足三个前提:

  • 设置一个server作为cache backend

  • 配置Bazel build去使用cache

  • Bazel版本要在0.10.0以上

Cache本身会存储两种数据:

  • action cache,或者说实际上是一个acton->action result的map映射表

  • 一个可寻址(addressable)的输出文件存储系统

https://docs.bazel.build/versions/master/remote-caching.html 中对Bazel Remote Cache的使用和工作有更详细的介绍,就不重复了。这里直接讲到底怎么设置一个Bazel Remote Cache Server. 在上面这个链接中提到了三种方式:

  • NGINX的WebDAV模块

  • 开源的bazel-remote

  • Google Cloud Storage

这里我们直接选择第二种:开源的bazel-remote,以便可能的定制及更好理解内部实现。

buchgr/bazel-remote

这里我们不用去重新编译运行,直接下载对应的docker镜像并运行即可

$docker pull buchgr/bazel-remote-cache

bazel-remote支持grpc和http的接口调用,但注意docker内部应用的http接口应该是8080而不是9090(官方文档有误)。

创建一个目录cache, 然后启动docker容器如下

path=`pwd`;docker run -v $path/cache:/data -p 9090:8080 -p 9092:9092 buchgr/bazel-remote-cache

备注:

  • 需要提前创建cache目录或者失败后对目录加777权限,并用-u指定当前用户的uid和gid,否则会报mkdir /data/cas.v2:permission denied。即docker run -u $uid:$gid -v xxx

  • 建议用--max_size限制缓存目录的大小。一般在命令最后加上 --maz_size=50

我们可以看到一堆输出:

2020/10/13 16:12:20 bazel-remote built with go1.14.5 from git commit cc9030667416ab63d89b9fbf543f0243292009b4.
2020/10/13 16:12:20 Initial RLIMIT_NOFILE cur: 1048576 max: 1048576
2020/10/13 16:12:20 Setting RLIMIT_NOFILE cur: 1048576 max: 1048576
2020/10/13 16:12:21 Migrating files (if any) to new directory structure: /data/ac
2020/10/13 16:12:21 Migrating files (if any) to new directory structure: /data/cas
2020/10/13 16:12:21 Loading existing files in /data.
2020/10/13 16:12:23 Sorting cache files by atime.
2020/10/13 16:12:23 Building LRU index.
2020/10/13 16:12:23 Finished loading disk cache files.
2020/10/13 16:12:23 Loaded 0 existing disk cache items.
2020/10/13 16:12:23 Starting HTTP server on address :8080
2020/10/13 16:12:23 HTTP AC validation: enabled
2020/10/13 16:12:23 Starting HTTP server for profiling on address :6060
2020/10/13 16:12:23 Starting gRPC server on address :9092
2020/10/13 16:12:23 gRPC AC dependency checks: enabled
2020/10/13 16:12:23 experimental gRPC remote asset API: disabled
然后可以通过其/status接口来查看是否正常启动
$curl http://localhost:9090/status
{"CurrSize": 0,"MaxSize": 5368709120,"NumFiles": 0,"ServerTime": 1602605641,"GitCommit": "cc9030667416ab63d89b9fbf543f0243292009b4"
}

另外我们也可以查看cache目录下是否生成了对应文件:

​这时就可以在运行bazel build的时候指定remote cache server的地址:

$bazel build //src/main:app --remote_cache=http://localhost:9090
INFO: Invocation ID: a9a389d2-1e9f-4878-b65b-586e7b70fa35
INFO: Analyzed target //src/main:app (0 packages loaded, 0 targets configured).
INFO: Found 1 target...
Target //src/main:app up-to-date:bazel-bin/src/main/app_deploy.jarbazel-bin/src/main/app_unsigned.apkbazel-bin/src/main/app.apk
INFO: Elapsed time: 3.271s, Critical Path: 3.02s
INFO: 12 processes: 9 darwin-sandbox, 3 worker.
INFO: Build completed successfully, 13 total actions

备注:

为了避免本地缓存对远程缓存的影响,在执行构建前清理本地缓存。运行以下命令可删除输出文件,并可选择停止服务器。:

bazel clean

检查缓存命中率

在 Bazel 运行的标准输出结果中,查看列出进程的 INFO 行,该进程大致对应于 Bazel 操作。运行操作所在的行详细信息。查找 remote 标签,该标签表示远程执行的操作、linux-sandbox 在本地沙盒内执行的操作,以及用于其他执行策略的其他值。操作来自远程缓存的操作会显示为 remote cache hit。

例如:

INFO: 11 processes: 6 remote cache hit, 3 internal, 2 remote.

在此示例中,有 6 次远程缓存命中,有 2 项操作没有缓存命中,且远程执行了这些命中。这 3 个内部部分可以忽略。 它通常是微小的内部操作,例如创建符号链接。此摘要不包含本地缓存命中。如果获得 0 个进程(或低于预期的数字),请运行 bazel clean,后跟构建/测试命令。

在docker一侧,我们可以看到输出

​可以看到cache主要是通过http put/get,并使用hash作为key来进行对应结果的查找。

我们重复几次bazel build后可以看到耗时很短,只有不到0.3秒:

INFO: Analyzed target //src/main:app (0 packages loaded, 0 targets configured).
INFO: Found 1 target...
Target //src/main:app up-to-date:bazel-bin/src/main/app_deploy.jarbazel-bin/src/main/app_unsigned.apkbazel-bin/src/main/app.apk
INFO: Elapsed time: 0.286s, Critical Path: 0.03s
INFO: 0 processes.
INFO: Build completed successfully, 1 total action

这显然是cache的作用,我们也可以在BUILD文件中禁止cache。这实际上是对rule的tags设置(我们在以后再讲如何定义rule),我们在这里可以尝试对java_library这个rule添加tag,禁止cache。修改src/main/java/com/example/bazel/util/BUILD中的java_library属性如下:

这样bazel就不会对该BUILD的结果进行缓存,读者可以自行尝试对比,这里就不过多展示实验结果。

排查缓存命中问题

如果您没有获得预期的缓存命中率,请执行以下操作:

确保重新运行相同的构建/测试命令会生成缓存命中

1.运行您希望填充缓存的构建和/或测试。首次在特定堆栈上运行新 build 时,应该不会有任何远程缓存命中。在远程执行过程中,操作结果会存储在缓存中,后续运行结果应该会提取这些结果。

2.运行 bazel clean。此命令会清理您的本地缓存,这样一来,您便可以调查远程缓存命中,而结果不会被本地缓存命中遮盖。

3.(在同一机器上)运行调查的 build 和测试。

4.请查看 INFO 行,了解缓存命中率。如果您看到除 remote cache hit 和 internal 以外的任何进程,则表明您的缓存已正确填充和访问。在这种情况下,请跳到下一部分。

5.可能的差异来源是 build 中非封闭的内容,导致操作在两次运行中接收不同的操作键。如需找到这些操作,请执行以下操作:

a.重新运行相关 build 或测试以获取执行日志:

bazel clean
bazel --optional-flags build //your:target --execution_log_binary_file=/tmp/exec1.log

b. 在两次运行之间比较执行日志。确保两个日志文件中的操作完全相同。 通过差异,您可以了解两次运行之间的变化。请更新您的 build 以消除这些差异。

如果您能够解决缓存问题,并且现在重复运行会生成所有缓存命中,请跳到下一部分。

如果您的操作 ID 相同,但没有任何缓存命中,则表示配置中有某项内容阻止了缓存。继续完成此部分,检查是否存在常见问题。

如果您不需要区分执行日志,则可以改用直观易懂的 --execution_log_json_file 标志。它包含执行时间,并且不能保证顺序,因此无法用于稳定差异比较。

6.检查执行日志中的所有操作是否均将 cacheable 设置为 true。如果指定操作的执行日志中未显示 cacheable,则表示相应规则在 BUILD 文件的定义中可能有 no-cache 标记。查看执行日志中直观易懂的 progress_message 字段,以帮助确定操作的来源。

7.如果操作相同且为 cacheable 但没有缓存命中,则您的命令行中可能包含针对 build 停用缓存查询的 --noremote_accept_cached。 如果难以确定实际命令行,请使用 Build Event Protocol 中的规范命令行,如下所示: a.将 --build_event_text_file=/tmp/bep.txt 添加到 Bazel 命令中,以获取日志的文本版本。 b. 打开日志的文本版本,然后使用 command_line_label: "canonical" 搜索 structured_command_line 消息。 展开之后会列出所有选项。 c.搜索 remote_accept_cached 并检查其是否已设置为 false。 d. 如果 remote_accept_cached 为 false,请确定它位于 false 的位置:在命令行中或在 bazelrc 文件中。

确保可以跨机器进行缓存

在同一台计算机上按预期执行缓存命中后,在其他机器上运行相同的构建/测试。如果您怀疑缓存未在机器间运行,请执行以下操作:

1.对构建稍作修改,以避免命中现有缓存。

2.在第一台机器上运行构建:

bazel clean
bazel ... build ... --execution_log_binary_file=/tmp/exec1.log

3.在第二台机器上运行 build,确保包含第 1 步中所做的修改:

bazel clean
bazel ... build ... --execution_log_binary_file=/tmp/exec1.log
4.比较两次运行的执行日志。如果日志不相同,请调查构建配置是否存在差异,以及主机环境中是否存在泄露到任一 build 中的属性。

比较执行日志

执行日志包含构建期间执行的所有操作的记录。每个操作都有一个 SpawnExec 元素,其中包含操作键中的所有信息。因此,如果日志相同,则操作缓存键也相同。

如需比较两个未按预期共享缓存命中的构建的日志,请执行以下操作:

1.从每个 build 中获取执行日志,并将其存储为 /tmp/exec1.log 和 /tmp/exec2.log。

2. 下载 Bazel 源代码,然后使用以下命令导航到 Bazel 文件夹。您需要使用源代码来使用 execlog 解析器解析执行日志。

git clone https://github.com/bazelbuild/bazel.git
cd bazel

3.使用执行日志解析器将日志转换为文本。以下调用还会对第二个日志中的操作进行排序,以匹配第一个日志中的操作顺序,以方便比较。

bazel build src/tools/execlog:parser
bazel-bin/src/tools/execlog/parser \--log_path=/tmp/exec1.log \--log_path=/tmp/exec2.log \--output_path=/tmp/exec1.log.txt \--output_path=/tmp/exec2.log.txt

4.使用您最喜欢的文本,差异为 /tmp/exec1.log.txt 和 /tmp/exec2.log.txt。

实际上,remote caching只是最基本的一个结果缓存机制,部署和使用都很简单,这里也只是对此进行快捷说明。小团队完全可以用这种方式来部分提升效率。而远程执行(Remote Execution)往往集成了缓存功能,因此在实际大型团队部署中一般不会专门对Remote Cache创建server。我们在下一节来介绍Remote Execution.

本文属于如下文章中的子章节

bazel学习系列章节汇总_m0_74043383的博客-CSDN博客

相关文章:

bazel远程缓存(Remote Cache)

原理 您可以将服务器设置为构建输出(即这些操作输出)的远程缓存。这些输出由输出文件名列表及其内容的哈希值组成。借助远程缓存,您可以重复使用其他用户的 build 中的构建输出,而不是在本地构建每个新输出。 增量构建极大的提升…...

算法竞赛入门经典习题2-6 排列(permutation)

排列&#xff08;permutation&#xff09;——算法竞赛入门经典_还记得樱花正开~的博客-CSDN博客 上面的代码很厉害&#xff0c;学习...我的代码水平就比较差了... #include <cstdio> #include <set>int main(){for(int i 123; i < 329; i){std::set<int&…...

队列的链表实现 题目(难度1/10)

C数据结构与算法 目录 队列介绍 队列这种容器&#xff0c;就像大家排队上公交车一样。 第一个来到的人排在最前面&#xff1b; 最后来的排在最后面&#xff1b; 第一个先上车&#xff08;离开队列&#xff09;&#xff1b; 队列的接口 队列是有如下接口的容器&#xff1…...

SpringMVC常用的三种获取请求参数的方式

在Spring MVC中&#xff0c;可以使用多种方式来获取请求参数。下面我将介绍常用的几种方式&#xff0c;并提供相关的示例代码。 1. 使用RequestParam注解获取请求参数 RequestParam注解用于从请求中获取指定名称的参数值&#xff0c;并将其绑定到方法参数上。如果请求中没有找…...

2023开学礼新疆理工学院图书馆藏八一新书《乡村振兴战略下传统村落文化旅游设计》许少辉新财经理工

2023开学礼新疆理工学院图书馆藏八一新书《乡村振兴战略下传统村落文化旅游设计》许少辉新财经理工...

数据结构----结构--线性结构--字符串

数据结构----结构–线性结构–字符串 一.字符串的定义方式 第一种&#xff1a; char* str1"Hello"第二种&#xff1a; char str2[]"Hello";区别 1.所在区域不同 //str1在常量区//str2在这里的写法是在栈区2.元素是否可改 //str1中的元素不可改//st…...

数据工厂-生成接口通用用例

章节目录&#xff1a; 一、背景介绍二、前置准备三、设计思路四、代码具体实现五、执行效果六、其他说明七、结束语 一、背景介绍 有哪些用例是可以通用且固定的&#xff1f; 针对之前提到的接口用例设计思路&#xff0c;拆分为三个切入点&#xff1a; 举个例子&#xff1a; {…...

N 字形变换

N 字形变换 题目: 将一个给定字符串 s 根据给定的行数 numRows &#xff0c;以从上往下、从左到右进行 Z 字形排列。比如输入字符串为 "PAYPALISHIRING" 行数为 3 时&#xff0c;排列如下&#xff1a;P A H N A P L S I I G Y I R 之后&#xff0c;你的输…...

STM32+RTThread配置以太网无法ping通,无法获取动态ip的问题

记录一个非常蠢的问题&#xff0c;今天在移植rtthread的以太网驱动的时候出现无法获取动态ip的问题&#xff0c;问题如下&#xff1a; 设置为动态ip时不管是连接路由器还是电脑主机都无法ping通&#xff0c;也无法获取dns地址。 设置为静态ip时无法ping通主机。 使用wireshark…...

python编写MQTT订阅程序

Download | Eclipse Mosquitto 1、下载&#xff1a; https://mosquitto.org/files/binary/win64/mosquitto-2.0.17-install-windows-x64.exe 2、安装&#xff1a; 3、conf配置 1)使用notepad打开“C:\Program Files\mosquitto\mosquitto.conf”另存为c:\myapp\msquitto\mo…...

mysql 中 cast 函数用法

在 MySQL 中&#xff0c;CAST() 函数用于将一个表达式转换为指定的数据类型。它可以用于多种场景&#xff0c;例如将字符串转换为数字&#xff0c;或者将日期时间转换为特定格式。 以下是 CAST() 函数的基本语法&#xff1a; CAST(expression AS datatype) 其中&#xff0c…...

MongoDB 的简介

MongoDB 趋势 对于 MongoDB 的认识 Q&A QA什么是 MongoDB&#xff1f; 一个以 JSON 为数据模型的文档数据库一个以 JSON 为数据模型的文档数据库文档来自于“JSON Document”&#xff0c;并非我们一般理解的 PDF&#xff0c;WORD谁开发 MongDB&#xff1f; 上市公司 MongoD…...

是否在业务中使用大语言模型?

ChatGPT取得了巨大的成功&#xff0c;在短短一个月内就获得了1亿用户&#xff0c;并激发了企业和专业人士对如何在他们的组织中利用这一工具的兴趣和好奇心。 但LLM究竟是什么&#xff0c;它们如何使你的企业受益?它只是一种炒作&#xff0c;还是会长期存在? 在这篇文章中我…...

37. 交换字符(第三期模拟笔试)

题目&#xff1a; 给定一个01串&#xff08;仅由字符0和字符1构成的字符串&#xff09;。每次操作可以交换两个相邻的字符。 例如&#xff1a;对于字符串"001110"来说&#xff0c; 可以交换第二个字符0和第三个字符1&#xff0c;交换之后的字符串变成了"0101…...

git 查看当前分支最近一次提交的commit SHA

获取当前分支最近一次commit SHA &#xff08;长度为40个16进制数字的字符&#xff09;命令如下&#xff1a; git rev-parse HEAD 获取简写&#xff08;短&#xff09; commit SHA git rev-parse --short HEAD...

LuatOS 开发指南

NDK 开发 官方教程 官方例程 API 下载软件 下载官方NDK例程压缩包到本地&#xff0c;并解压。可以看到目录如下&#xff1a; doc: 文档教程 env: 编译环境 example: NDK示例 platform: 需要编译的平台&#xff08;air72x/air8xx&#xff09; tools: 其他辅助软件 VSCode 使…...

maven推包The environment variable JAVA_HOME is not correctly set

解决办法&#xff1a; 打开idea查看jdk安装位置 1.在/etc下面创建&#xff08;如果存在就是更新&#xff09;launchd.conf。里面添加一行&#xff1a; setenv JAVA_HOME /Library/Java/JavaVirtualMachines/jdk1.8.0_351.jdk/Contents/Home #JAVA_HOME后面是我的java安装路径…...

Python VScode 配置

在上一章节中我们已经安装了 Python 的环境&#xff0c;本章节我们将介绍 Python VScode 的配置。 准备工作&#xff1a; 安装 VS Code安装 VS Code Python 扩展安装 Python 3 安装 VS Code VSCode&#xff08;全称&#xff1a;Visual Studio Code&#xff09;是一款由微软…...

【vue2第九章】组件化开发和根组件以及style上的scoped作用

组件化开发和根组件 什么是组件化开发&#xff1f; 一个页面可以拆分为多个组件&#xff0c;每个组件有自己的样式&#xff0c;结构&#xff0c;行为&#xff0c;组件化开发的好处就是&#xff0c;便于维护&#xff0c;利于重复利用&#xff0c;提升开发的效率。 便于维护&…...

从零开始的Hadoop学习(五)| HDFS概述、shell操作、API操作

1. HDFS 概述 1.1 HDFS 产出背景及定义 1&#xff09;HDFS 产生背景 随着数据量越来越大&#xff0c;在一个操作系统存不下所有的数据&#xff0c;那么就分配到更多的操作系统管理的磁盘中&#xff0c;但是不方便管理和维护&#xff0c;迫切 需要一种系统来管理多台机器上的…...

【spark】序列化和反序列化,transient关键字的使用

序列化 Spark是基于JVM运行的进行&#xff0c;其序列化必然遵守Java的序列化规则。 序列化就是指将一个对象转化为二进制的byte流&#xff08;注意&#xff0c;不是bit流&#xff09;&#xff0c;然后以文件的方式进行保存或通过网络传输&#xff0c;等待被反序列化读取出来。…...

2.4 Vector<T> 动态数组(随机访问迭代器)

C自学精简教程 目录(必读) 该 Vector 版本特点 这里的版本主要是使用模板实现、支持随机访问迭代器&#xff0c;支持std::sort等所有STL算法。(本文对随机迭代器的支持参考了 复旦大学 大一公共基础课C语言的一次作业) 随机访问迭代器的实现主要是继承std::iterator<std:…...

Ubuntu下运行QEMU模拟riscv64跑Debian

1.安装QEMU 下载地址&#xff1a; https://www.qemu.org/download/ 建议选择稳定版本&#xff0c;下载后解压&#xff0c;然后make wget https://download.qemu.org/qemu-8.0.3.tar.xz tar xjvf qemu-8.0.3.tar.xz cd qemu-8.0.3 ./configure --enable-kvm --enable-virtfs …...

移动基站ip的工作原理

原理介绍 Basic Principle 先说一下概念&#xff0c;大家在不使用 WIFI 网络的时候&#xff0c;使用手机通过运营商提供的网络进行上网的时候&#xff0c;目前都是在用户端使用私有IP&#xff0c;然后对外做 NAT 转换&#xff0c;这样的情况就导致大家统一使用一些 IP 段进行访…...

Kubernetes技术--使用kubeadm搭建高可用的K8s集群(贴近实际环境)

1.高可用k8s集群架构(多master) 2.安装硬件要求 一台或多台机器,操作系统 CentOS7.x-86_x64 硬件配置:2GB或更多RAM,2个CPU或更多CPU,硬盘30GB或更多 注: 这里属于教学环境,所以使用三台虚拟机模拟实现。 3.部署规划 4.部署前准备 (1).关闭防火墙 systemctl stop fi…...

【Linux】文件

Linux 文件 什么叫文件C语言视角下文件的操作文件的打开与关闭文件的写操作文件的读操作 & cat命令模拟实现 文件操作的系统接口open & closewriteread 文件描述符进程与文件的关系重定向问题Linux下一切皆文件的认识文件缓冲区缓冲区的刷新策略 stuout & stderr 什…...

Android OTA 相关工具(六) 使用 lpmake 打包生成 super.img

我在 《Android 动态分区详解(二) 核心模块和相关工具介绍》 介绍过 lpmake 工具&#xff0c;这款工具用于将多个分区镜像打包生成一个 Android 专用的动态分区镜像&#xff0c;一般称为 super.img。Android 编译时&#xff0c;系统会自动调用 lpmake 并传入相关参数来生成 sup…...

信创环境 Phytium S2500 虚拟机最大内存规格测试

在 ARM 架构中,"IPA" 通常指的是 "Instruction Set Architecture"(指令集架构),arm环境的虚拟机支持的最大内存规格与母机上内存多少无关,由arm本身的ipa size决定,ipa size 可以理解为虚拟机的物理地址空间,kernel5.4.32中ipa默认是44bits(16T si…...

新建工程——第一个S32DS工程

之前的"测试开发板"章节 测试开发板——第一个AutoSAR程序,使用了一个 demo 工程,不管是裸机程序还是 AutoSAR 程序,那都是别人已经创建好的工程。本节来介绍如何来创建自己的工程,本节介绍如何创建一个 S32DS 的工程,点亮开发板上的 LED 我们从官方提供的例程…...

基于Open3D的点云处理16-特征点匹配

点云配准 将点云数据统一到一个世界坐标系的过程称之为点云配准或者点云拼接。&#xff08;registration/align&#xff09; 点云配准的过程其实就是找到同名点对&#xff1b;即找到在点云中处在真实世界同一位置的点。 常见的点云配准算法: ICP、Color ICP、Trimed-ICP 算法…...

旅游网站怎么用dw做/网络营销方式

算法设计之五大常用算法设计方法总结 来源 http://blog.csdn.net/zolalad/article/details/11393915 一、【分治法】 在计算机科学中&#xff0c;分治法是一种很重要的算法。字面上的解释是“分而治之”&#xff0c;就是把一个复杂的问题分成两个或更多的相同或相似的子问题&am…...

律师做网站推广有用吗/收录网站排名

题目链接&#xff1a;http://codeforces.com/gym/101778/problem/B Codeforces上的一篇题解&#xff1a;http://codeforces.com/blog/entry/58982 题意&#xff1a;给出n和a&#xff0c;让找一个n个数的正整数集合使得这个集合中的元素累加和的平均值等于a&#xff0c;基于此求…...

百度手机网站优化指南/营销网

企业老板还在为处理有机废气烦恼吗&#xff1f;您应该了解一下活性炭吸附法工业有机废气是指工业生产过程中排出的含挥发性有机物的气态污染物&#xff0c;这些废气如果得不到有效处理会对工作人员和周围环境造成严重的危害。因此治理有机废气&#xff0c;让废气排放达到环保标…...

做自营网站还是amazon/外贸网站建设公司

好了&#xff0c;就不多说了&#xff0c;事实上只要你有了足够的能力&#xff0c;能开始想老板所想的事&#xff0c;这时候你会发现&#xff0c;你也可以做老板了。 据我所知&#xff0c;很多程序员都是越过架构师这道坎&#xff0c;有了整体的架构布局思维&#xff0c;就开始…...

购物网站前台功能模块分析/独立站seo推广

移动开发领域与PC 开发得区别&#xff0c;总结为&#xff1a;3低&#xff0c; 3高&#xff0c;3有限。开发移动程序是应该时刻记住这9个限制。 3低低处理能力低分辨率低速的数据传输能力3高传输数据高成本高延迟高不可靠地数据连接3有限有限的RAM有限的永久存储能力有限的电池使…...

商洛免费做网站/网站定制开发

一 算法简述 设置X为累加和表达式的正数和&#xff0c;设置Y为累加和表达式的负数和&#xff0c;则满足 X - Y 10 X Y 44(2 3 ... 9) 推导可得X 27&#xff0c;即只需从这8个连续数找到累加和为27的这些数&#xff0c;比如X可以是2 3 5 8 9或2 3 4 5 6 7等…...