使用真实 Elasticsearch 进行高级集成测试
作者:来自 Elastic Piotr Przybyl

掌握高级 Elasticsearch 集成测试:更快、更智能、更优化。
在上一篇关于集成测试的文章中,我们介绍了如何通过改变数据初始化策略来缩短依赖于真实 Elasticsearch 的集成测试的执行时间。在本期中,我们将进一步缩短测试套件的持续时间,这次我们将通过将高级技术应用于运行 Elasticsearch 的 Docker 容器和 Elasticsearch 本身。
请注意,下面描述的技术通常可以精挑细选:你可以选择最适合你特定情况的技术。
这里有“龙”:权衡取舍
在我们深入探讨各种性能优化方法之前,必须明白一个道理:并非所有优化都应该无条件应用。尽管优化通常能带来提升,但它们也可能让整体设置变得更难理解,尤其是对于不熟悉的人来说。换句话说,在接下来的章节中,我们不会修改测试本身,而是重新设计其周围的 “基础架构代码”。这些改动可能会让代码对经验不足的团队成员来说更加晦涩。文中介绍的技术并非高深莫测,但在使用时仍需谨慎,并且有一定经验会更好。
快照
当我们停止演示代码时,我们仍在使用每个测试的数据初始化 Elasticsearch。这种方法有一些优势,特别是如果我们的数据集在测试用例之间有所不同,例如,我们有时会索引略有不同的文档。但是,如果我们所有的测试用例都可以依赖相同的数据集,我们可以使用快照和恢复方法。
了解快照和恢复在 Elasticsearch 中的工作方式很有帮助,官方文档对此进行了解释。
在我们的方法中,我们不是通过 CLI 或 DevOps 方法处理这个问题,而是将其集成到测试周围的设置代码中。这确保了在开发人员机器以及 CI/CD 中顺利执行测试。
这个想法很简单:我们不是删除索引并在每次测试之前从头开始重新创建它们,而是:
- 在容器的本地文件系统中创建快照(如果它尚不存在,因为这在以后会变得必要)。
- 在每次测试之前恢复快照。
准备快照位置
需要注意的一件重要事情 —— 这使得 Elasticsearch 与许多关系数据库不同 —— 在发送创建快照的请求之前,我们首先需要注册一个可以存储快照的位置,即所谓的存储库。有许多可用的存储选项(这对于云部署非常方便);在我们的例子中,将它们保存在容器内的本地目录中就足够了。
注意:
此处使用的 /tmp/... 位置仅适用于易变集成测试,切勿在生产环境中使用。在生产环境中,请始终将快照存储在安全可靠的位置以进行备份。
为了避免将备份存储在不安全的位置,我们首先将其添加到我们的测试中:
static final String REPO_LOCATION = "/tmp/bad_backup_location";
接下来,我们配置 ElasticsearchContainer 以确保它可以使用此位置作为备份位置:
static ElasticsearchContainer elasticsearch =new ElasticsearchContainer(ELASTICSEARCH_IMAGE)// other instructions.withEnv("path.repo", REPO_LOCATION);
更改设置
现在我们准备将以下逻辑附加到我们的 @BeforeAll 方法中:
if (!snapshotExists()) {setupDataInContainer();createSnapshotInContainer();
}
我们的 @BeforeEach 方法应该以以下内容开头:
restoreSnapshot();
可以通过验证 REPO_LOCATION 目录是否存在并包含一些文件来检查快照是否存在:
static boolean snapshotExists() throws IOException, InterruptedException {ExecResult execResult = elasticsearch.execInContainer("sh", "-c", "[ -d \"" + REPO_LOCATION + "\" ] && [ \"$(ls -A " + REPO_LOCATION + ")\" ]");return execResult.getExitCode() == 0;
}
setupDataInContainer() 方法略有变化:它不再在 @BeforeEach 中调用(我们在需要时按需执行它),并且可以删除 DELETE books 请求(因为不再需要它)。
要创建快照,我们首先需要注册一个快照位置,然后在那里存储任意数量的快照(尽管我们只保留一个,因为测试不需要更多):
static void createSnapshotInContainer() throws IOException, InterruptedException {// Register REPO_LOCATION for backupsExecResult result = elasticsearch.execInContainer("curl", "https://localhost:9200/_snapshot/init_backup", "-u", "elastic:changeme","--cacert", "/usr/share/elasticsearch/config/certs/http_ca.crt","-H", "Content-Type: application/json","-X", "PUT","-d", """{"type":"fs","settings":{"location":"%s"}}""".formatted(REPO_LOCATION));assert result.getExitCode() == 0 && result.getStdout().contains("\"acknowledged\":true");// Create the snapshot and wait for completionresult = elasticsearch.execInContainer("curl", "https://localhost:9200/_snapshot/init_backup/snapshot_1?wait_for_completion=true", "-u", "elastic:changeme","--cacert", "/usr/share/elasticsearch/config/certs/http_ca.crt","-H", "Content-Type: application/json","-X", "PUT","-d", """{"indices": ["books"]}""");assert result.getExitCode() == 0;
}
一旦创建快照,我们可以在每次测试之前恢复它,如下所示:
static void restoreSnapshot() {Container.ExecResult execResult;try {execResult = elasticsearch.execInContainer("/bin/sh", "-c", """curl --cacert /usr/share/elasticsearch/config/certs/http_ca.crt -s -u elastic:changeme -X DELETE "https://localhost:9200/books" \&& \curl --cacert /usr/share/elasticsearch/config/certs/http_ca.crt -s -u elastic:changeme -X POST https://localhost:9200/_snapshot/init_backup/snapshot_1/_restore?wait_for_completion=true""");} catch (Exception e) {throw new RuntimeException(e);}if (execResult.getExitCode() != 0) {throw new RuntimeException("Error when restoring backup: [%s] [%s]".formatted(execResult.getStdout(), execResult.getStderr()));}
}
请注意以下几点:
- 在恢复索引之前,索引不能存在,因此我们必须先将其删除。
- 如果你需要删除多个索引,则可以在单个 curl 调用中执行此操作,例如 “https://localhost:9200/indexA,indexB”。
- 要在容器中链接多个命令,你无需将它们包装在单独的 execInContainer 调用中;运行简单的脚本可以提高可读性(并减少一些网络往返)。
在示例项目中,此技术将我的构建时间缩短至 26 秒。虽然乍一看这似乎不是一个显着的收益,但该方法是一种通用技术,可以在切换到 _bulk 摄取(在上一篇文章中讨论)之前甚至代替它应用。换句话说,你可以以任何方式在 @BeforeAll 中为测试准备数据,然后对其进行快照以在 @BeforeEach 中使用。如果你想最大限度地提高效率,甚至可以使用 elasticsearch.copyFileFromContainer(...) 将快照复制回测试机器,使其作为一种缓存形式,仅在你需要更新数据集(例如,测试新功能)时才会清除。有关完整示例,请查看标签 snapshots。
将数据保存在 RAM 中
有时,我们的测试用例明显包含大量数据,这可能会对性能产生负面影响,尤其是在底层存储速度较慢的情况下。如果你的测试需要读取和写入大量数据,而 SSD 甚至硬盘速度非常慢,你可以指示容器将数据保存在 RAM 中 - 前提是你有足够的可用内存。
这本质上是一行代码,需要在容器定义中添加 .withTmpFs(Map.of("/usr/share/elasticsearch/data", "rw"))。容器设置将如下所示:
static ElasticsearchContainer elasticsearch =new ElasticsearchContainer(ELASTICSEARCH_IMAGE)// other instructions.withTmpFs(Map.of("/usr/share/elasticsearch/data", "rw"));
存储速度越慢,性能提升就越显著,因为 Elasticsearch 现在将写入和读取 RAM 中的临时文件系统。
注意:
顾名思义,这是一个临时文件系统,也就是说它不是持久性的。因此,此解决方案仅适用于测试。请勿在生产中使用它,因为它可能会导致数据丢失。
要评估此解决方案可以在多大程度上提高硬件性能, 你可以尝试标签 tmpfs。
更多工作,相同时间
产品代码库的大小在活跃开发阶段增长最快。然后,当它进入维护阶段(如果适用)时,通常只涉及错误修复。但是,测试库的大小会不断增长,因为功能和错误都需要通过测试来覆盖,以防止回归。理想情况下,错误修复应始终伴随着测试,以防止错误再次出现。这意味着即使开发不是特别活跃,测试的数量也会不断增加。本节中描述的方法提供了有关如何在不显着增加测试套件持续时间的情况下管理不断增长的测试库的提示,前提是有足够的资源来实现并行化。
为简单起见,我们假设示例中的测试用例数量增加了一倍(而不是编写额外的测试,我们将复制现有的测试用例来进行此演示)。
在最简单的方法中,我们可以向 BookSearcherIntTest 类添加三个 @Test 方法。然后,我们可以以一种有点非正统的方式使用 Java 的一个分析器:Java Flight Recorder 来观察 CPU 和内存消耗。由于我们已将其添加到 POM 中,因此在运行测试后,我们可以在主目录中打开 recording-1.jfr。结果在 Environment -> Processes 中可能如下所示:

如你所见,在一个类中运行六个测试使所需时间增加了一倍。此外,上面的 CPU 使用率图表中的主要颜色是……根本没有颜色,因为 CPU 利用率在高峰时刻几乎达不到 20%。当你为使用时间付费时(无论是向云提供商付费还是以你自己的挂钟时间来获得有意义的反馈),未充分利用 CPU 是一种浪费。
你使用的 CPU 很可能有多个核心。这里的优化是将工作负载分成两部分,这应该大约将持续时间减半。为了实现这一点,我们将新添加的测试移到另一个名为 BookSearcherAnotherIntTest 的类中,并指示 Maven 使用 -DforkCount=2 运行两个分支进行测试。完整命令变为:
./mvnw test '-Dtest=*IntTest*' -DforkCount=2

在这里,CPU 的利用率更高。
不应将重点放在确切的数字上来解释此示例。相反,重要的是不仅适用于 Java 的总体趋势:
- 检查你的 CPU 在测试期间是否得到正确利用。
- 如果没有,请尝试尽可能多地并行化你的测试(尽管其他资源有时可能会限制你)。
- 请记住,不同的环境可能需要不同的并行化因素(例如,Maven 中的 -DforkCount=N)。最好避免在构建脚本中硬编码这些因素,而是根据项目和环境对其进行调整:
- 如果只运行一个测试类,则可以跳过开发人员机器(developer machines)的这一步骤。
- 对于功能较弱的 CI 环境,较低的数字可能就足够了。
- 对于功能更强大的 CI 设置,较高的数字可能效果很好。
对于 Java,重要的是避免使用一个大类,而是尽可能将测试分成较小的类。不同的并行化技术和参数适用于其他技术堆栈,但总体目标仍然是充分利用你的硬件资源。
为了进一步完善,请避免在测试类中重复设置代码。将测试本身与基础架构/设置代码分开。例如,应将配置元素(如镜像版本声明)放在一个地方。在 Java 版 Testcontainers 中,我们可以使用(或稍微重新利用)继承来确保在测试之前加载(并执行)包含基础架构代码的类。结构如下所示:
class CommonTestBase {// Containers' declarations, startup, and data handling code here
}class BookSearcherIntTest extends CommonTestBase {// Integration tests, ideally for one service
}class AnotherServiceIntTest extends CommonTestBase {// More integration tests, ideally for another service
}
如需完整的演示,请再次参考 GitHub 上的示例项目。
重用 - 仅启动一次
本文中介绍的最后一种技术对于开发人员机器(eveloper machines)特别有用。它可能不适用于传统的 CI(例如,内部托管的 Jenkins),并且对于临时 CI 环境(如基于云的 CI,其中构建机器是一次性使用的,每次构建后都会退役)通常是不必要的。此技术依赖于 Testcontainers 的预览功能,称为重用。
通常,测试套件完成后会自动清理容器。这种默认行为非常方便,尤其是在长期运行的 CI 中,因为它可以确保无论测试结果如何都不会剩余容器。但是,在某些情况下,我们可以让容器在测试之间保持运行,以便后续测试不会浪费时间再次启动它。这种方法对于在较长时间内(有时是几天)开发功能或修复错误(其中重复运行相同的测试(类))的开发人员特别有益。
如何启用重用
启用重用是一个两步过程:
1. 在声明容器时将其标记为可重用:
static ElasticsearchContainer elasticsearch =new ElasticsearchContainer(ELASTICSEARCH_IMAGE)// other instructions.withReuse(true);
2. 选择在合适的环境中启用重用功能(例如,在你的开发机器上)。在开发人员工作站上执行此操作的最简单、最持久的方法是确保 $HOME 目录中的配置文件具有正确的内容。在 ~/.testcontainers.properties 中,包含以下行:
testcontainers.reuse.enable=true
就这样!首次使用时,测试不会更快,因为容器仍需要启动。但是,在初始测试之后:
- 运行 docker ps 将显示容器仍在运行(这现在是一项功能,而不是错误)。
- 后续测试将更快。
注意:
一旦启用重用,手动停止容器就成为你的责任。
利用快照或初始化数据实现重用
重用功能与仅将初始化数据文件复制到容器一次或使用快照等技术结合使用效果特别好。启用重用后,无需为后续测试重新创建快照,从而节省更多时间。所有优化部分都开始落实到位。
重复使用分叉容器
虽然重复使用在许多情况下效果很好,但在第二次运行期间将重复使用与多个分叉相结合时会出现问题。这可能会导致与容器或 Elasticsearch 处于不正确状态相关的错误或乱码输出。如果你希望同时使用这两项改进(例如,在提交 PR 之前在功能强大的工作站上运行许多集成测试),则需要进行额外的调整。
问题
问题可能表现为以下错误:
co.elastic.clients.elasticsearch._types.ElasticsearchException: [es/esql.query] failed: [illegal_index_shard_state_exception] CurrentState[RECOVERING] operations only allowed when shard state is one of [POST_RECOVERY, STARTED]
发生这种情况的原因在于 Testcontainers 如何识别可重复使用的容器。
当两个分支都启动且没有 Elasticsearch 容器运行时,每个分支都会初始化自己的容器。 但是,重新启动后,每个分支都会查找可重复使用的容器并找到一个。 由于所有容器看起来与 Testcontainers 相同,因此两个分支可能会选择同一个容器。 这会导致竞争条件,其中多个分支尝试使用同一个 Elasticsearch 实例。 例如,一个分支可能正在恢复快照,而另一个分支正在尝试执行相同操作,从而导致上述错误。
解决方案
为了解决这个问题,我们需要引入容器之间的差异,并确保分支根据这些差异确定性地选择容器。
步骤 1:更新 pom.xml
修改 pom.xml 中的 Surefire 配置以包含以下内容:
<environmentVariables><fork>fork_${surefire.forkNumber}</fork>
</environmentVariables>
这会为每个 fork 添加一个唯一标识符 (fork_${surefire.forkNumber}) 作为环境变量。
第 2 步:修改容器声明
调整代码中的 Elasticsearch 容器声明,以包含基于 fork 标识符的标签:
static ElasticsearchContainer elasticsearch =new ElasticsearchContainer(ELASTICSEARCH_IMAGE)// other settings.withLabel("fork", System.getenv().getOrDefault("fork", "fork_1"));
效果
这些更改确保每个分支都会创建并使用自己的容器。由于标签独特,容器略有不同,允许测试容器将它们确定性地分配给特定分支。
这种方法消除了竞争条件,因为没有两个分支会尝试重复使用同一个容器。重要的是,容器内的 Elasticsearch 功能保持不变,并且可以在分支之间动态分配测试而不会影响结果。
它真的值得吗?
正如本文开头所警告的那样,这里介绍的改进应谨慎应用,因为它们会使我们的测试设置代码变得不那么直观。有什么好处?
我们以在我的计算机上大约 25 秒的三个集成测试开始本文。在应用所有改进并将实际测试数量增加一倍至六个之后,我笔记本电脑上的执行时间下降到 8 秒。测试数量增加了一倍;构建时间缩短了三分之二。由你来决定它是否适合你的情况。;-)
它不止于此
这个关于使用真实 Elasticsearch 进行测试的迷你系列到此结束。在第一部分中,我们讨论了何时模拟 Elasticsearch 索引是有意义的,以及何时进行集成测试是一个更好的主意。在第二部分中,我们解决了导致集成测试变慢的最常见错误。第三部分更加努力,使集成测试运行得更快,只需几秒钟而不是几分钟。
还有更多方法可以优化你的体验并降低使用 Elasticsearch 进行系统集成测试相关的成本。不要犹豫,探索这些可能性并尝试你的技术堆栈。
如果你的案例涉及上述任何技术,或者你有任何疑问,请随时通过我们的讨论论坛或社区 Slack 频道与我们联系。
想要获得 Elastic 认证?了解下一次 Elasticsearch 工程师培训何时开始!
Elasticsearch 包含新功能,可帮助你为你的用例构建最佳搜索解决方案。深入了解我们的示例笔记本以了解更多信息,开始免费云试用,或立即在你的本地机器上试用 Elastic。
原文:Advanced integration tests with real Elasticsearch - Elasticsearch Labs
相关文章:
使用真实 Elasticsearch 进行高级集成测试
作者:来自 Elastic Piotr Przybyl 掌握高级 Elasticsearch 集成测试:更快、更智能、更优化。 在上一篇关于集成测试的文章中,我们介绍了如何通过改变数据初始化策略来缩短依赖于真实 Elasticsearch 的集成测试的执行时间。在本期中࿰…...
【R语言】函数
一、函数格式 如下所示: hello:函数名;function:定义的R对象是函数而不是其它变量;():函数的输入参数,可以为空,也可以包含参数;{}:函数体,如果…...
Vue 3 30天精进之旅:Day 12 - 异步操作
在现代前端开发中,异步操作是一个非常常见的需求,例如从后端API获取数据、进行文件上传等任务。Vue 3 结合组合式API和Vuex可以方便地处理这些异步操作。今天我们将重点学习如何在Vue应用中进行异步操作,包括以下几个主题: 异步操…...
VSCode插件Live Server
简介:插件Live Server能够实现当我们在VSCode编辑器里修改 HTML、CSS 或者 JavaScript 文件时,它都能自动实时地刷新浏览器页面,让我们实时看到代码变化的效果。再也不用手动刷新浏览器了,节省了大量的开发过程耗时! 1…...
50. 正点原子官方系统镜像烧写实验
一、Windows下使用OTG烧写系统 1、在Windos使用NXP提供的mfgtool来向开发烧写系统。需要用先将开发板的USB_OTG接口连接到电脑上。 Mfgtool工具是向板子先下载一个Linux系统,然后通过这个系统来完成烧写工作。 切记!使用OTG烧写的时候要先把SD卡拔出来&…...
在C#中,什么是多态如何实现
在C#中,什么是多态?如何实现? C#中的多态性 多态性是面向对象编程的一个核心概念,他允许对象以多种形式表现.在C#中,多态主要通过虚方法,抽象方法和接口来实现. 多态性的存在使得同一个行为可以有多个不同的表达形式 即同一个接口可以使用不同的实例来执行不同的操作 虚方…...
搜索引擎友好:设计快速收录的网站架构
本文来自:百万收录网 原文链接:https://www.baiwanshoulu.com/14.html 为了设计一个搜索引擎友好的网站架构,以实现快速收录,可以从以下几个方面入手: 一、清晰的目录结构与层级 合理划分内容:目录结构应…...
扩散模型(三)
相关阅读: 扩散模型(一) 扩散模型(二) Latent Variable Space 潜在扩散模型(LDM;龙巴赫、布拉特曼等人,2022 年)在潜在空间而非像素空间中运行扩散过程,这…...
it基础使用--5---git远程仓库
it基础使用–5—git远程仓库 1. 按顺序看 -git基础使用–1–版本控制的基本概念 -git基础使用–2–gti的基本概念 -git基础使用–3—安装和基本使用 -git基础使用–4—git分支和使用 2. 什么是远程仓库 在第一篇文章中,我们已经讲过了远程仓库,每个本…...
Baklib如何改变内容管理平台的未来推动创新与效率提升
内容概要 在信息爆炸的时代,内容管理平台成为了企业和个人不可或缺的工具。它通过高效组织、存储和发布内容,帮助用户有效地管理信息流。随着技术的发展,传统的内容管理平台逐渐暴露出灵活性不足、易用性差等局限性,这促使市场需…...
100.1 AI量化面试题:解释夏普比率(Sharpe Ratio)的计算方法及其在投资组合管理中的应用,并说明其局限性
目录 0. 承前1. 夏普比率的基本概念1.1 定义与计算方法1.2 实际计算示例 2. 在投资组合管理中的应用2.1 投资组合选择2.2 投资组合优化 3. 夏普比率的局限性3.1 统计假设的限制3.2 实践中的问题 4. 改进方案4.1 替代指标4.2 实践建议 5. 回答话术 0. 承前 如果想更加全面清晰地…...
Ubuntu 下 nginx-1.24.0 源码分析 ngx_debug_init();
目录 ngx_debug_init() 函数: NGX_LINUX 的定义: ngx_debug_init() 函数: ngx_debug_init() 函数定义在 src\os\unix 目录下的 ngx_linux_config.h 中 #define ngx_debug_init() 也就是说这个环境下的 main 函数中的 ngx_debug_init() 这…...
基于人脸识别的课堂考勤系统
该项目是一个基于人脸识别的课堂考勤系统,使用Python开发,结合了多种技术实现考勤功能。要开发类似的基于人脸识别的考勤系统,可参考以下步骤: 环境搭建:利用Anaconda创建虚拟环境,指定Python版本为3.8&am…...
开启 AI 学习之旅:从入门到精通
最近 AI 真的超火,不管是工作还是生活里,到处都能看到它的身影。好多小伙伴都跑来问我,到底该怎么学 AI 呢?今天我就把自己学习 AI 的经验和心得分享出来,希望能帮到想踏入 AI 领域的朋友们! 一、学习内容有哪些 (一)编程语言 Python 绝对是首选!它在 AI 领域的生态…...
13 尺寸结构模块(size.rs)
一、size.rs源码 // Copyright 2013 The Servo Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution. // // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or // http://www.apache.org/licenses/LICENSE…...
16.[前端开发]Day16-HTML+CSS阶段练习(网易云音乐五)
完整代码 网易云-main-left-rank(排行榜) <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge"><meta name&q…...
ARM嵌入式学习--第十天(UART)
--UART介绍 UART(Universal Asynchonous Receiver and Transmitter)通用异步接收器,是一种通用串行数据总线,用于异步通信。该总线双向通信,可以实现全双工传输和接收。在嵌入式设计中,UART用来与PC进行通信,包括与监控…...
MoonBit 编译器(留档学习)
MoonBit 编译器 MoonBit 是一个用户友好,构建快,产出质量高的编程语言。 MoonBit | Documentation | Tour | Core This is the source code repository for MoonBit, a programming language that is user-friendly, builds fast, and produces high q…...
【TypeScript】基础:数据类型
文章目录 TypeScript一、简介二、类型声明三、数据类型anyunknownnervervoidobjecttupleenumType一些特殊情况 TypeScript 是JavaScript的超集,代码量比JavaScript复杂、繁多;但是结构更清晰 一、简介 为什么需要TypeScript? JavaScript的…...
Unity游戏(Assault空对地打击)开发(3) 摄像机的控制
详细步骤 打开My Assets或者Package Manager。 选择Unity Registry。 搜索Cinemachine,找到 Cinemachine包,点击 Install按钮进行安装。 关闭窗口,新建一个FreeLook Camera,如下。 接着新建一个对象Pos,拖到Player下面…...
【HarmonyOS之旅】基于ArkTS开发(三) -> 兼容JS的类Web开发(三)
目录 1 -> 生命周期 1.1 -> 应用生命周期 1.2 -> 页面生命周期 2 -> 资源限定与访问 2.1 -> 资源限定词 2.2 -> 资源限定词的命名要求 2.3 -> 限定词与设备状态的匹配规则 2.4 -> 引用JS模块内resources资源 3 -> 多语言支持 3.1 -> 定…...
小程序-基础加强-自定义组件
前言 这次讲自定义组件 1. 准备今天要用到的项目 2. 初步创建并使用自定义组件 这样就成功在home中引入了test组件 在json中引用了这个组件才能用这个组件 现在我们来实现全局引用组件 在app.json这样使用就可以了 3. 自定义组件的样式 发现页面里面的文本和组件里面的文…...
尝试ai生成figma设计
当听到用ai 自动生成figma设计时,不免好奇这个是如何实现的。在查阅了不少资料后,有了一些想法。参考了:在figma上使用脚本自动生成色谱 这篇文章提供的主要思路是:可以通过脚本的方式构建figma设计。如果我们使用ai 生成figma脚本…...
【周易哲学】生辰八字入门讲解(八)
😊你好,我是小航,一个正在变秃、变强的文艺倾年。 🔔本文讲解【周易哲学】生辰八字入门讲解,期待与你一同探索、学习、进步,一起卷起来叭! 目录 一、六亲女命六亲星六亲宫位相互关系 男命六亲星…...
康德哲学与自组织思想的渊源:从《判断力批判》到系统论的桥梁
康德哲学与自组织思想的渊源:从《判断力批判》到系统论的桥梁 第一节:康德哲学中的自然目的论与自组织思想 核心内容: 康德哲学中的自然目的论和反思判断力概念,为现代系统论中的自组织思想提供了哲学基础,预见了复…...
解决whisper 本地运行时GPU 利用率不高的问题
我在windows 环境下本地运行whisper 模型,使用的是nivdia RTX4070 显卡,结果发现GPU 的利用率只有2% 。使用 import torch print(torch.cuda.is_available()) 返回TRUE。表示我的cuda 是可用的。 最后在github 的下列网页上找到了问题 极低的 GPU 利…...
【自开发工具介绍】SQLSERVER的ImpDp和ExpDp工具02
工具运行前的环境准备 1、登录用户管理员权限确认 工具使用的登录用户(-u后面的用户),必须具有管理员的权限,因为需要读取系统表 例:Export.bat -s 10.48.111.12 -d db1 -u test -p test -schema dbo 2、Powershell的安全策略确认…...
java异常处理——try catch finally
单个异常处理 1.当try里的代码发生了catch里指定类型的异常之后,才会执行catch里的代码,程序正常执行到结尾 2.如果try里的代码发生了非catch指定类型的异常,则会强制停止程序,报错 3.finally修饰的代码一定会执行,除…...
【人工智能】使用Python和Hugging Face构建情感分析应用:从模型训练到Web部署
《Python OpenCV从菜鸟到高手》带你进入图像处理与计算机视觉的大门! 解锁Python编程的无限可能:《奇妙的Python》带你漫游代码世界 情感分析是自然语言处理(NLP)中的重要任务,它通过分析文本来判断情绪或观点的倾向性。近年来,预训练语言模型如BERT、GPT等在情感分析任…...
DeepSeek-R1:通过强化学习激励大型语言模型(LLMs)的推理能力
摘要 我们推出了第一代推理模型:DeepSeek-R1-Zero和DeepSeek-R1。DeepSeek-R1-Zero是一个未经监督微调(SFT)作为初步步骤,而是通过大规模强化学习(RL)训练的模型,展现出卓越的推理能力。通过强…...
