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

浏览器的数据六种存储方法比较 :LocalStorage vs. IndexedDB vs. Cookies vs. OPFS vs. WASM-SQLite

在构建该 Web 应用程序,并且希望将数据存储在用户浏览器中。也许您只需要存储一些小标志,或者甚至需要一个成熟的数据库。

我们构建的 Web 应用程序类型发生了显着变化。在网络发展的早期,我们提供静态 html 文件。然后我们提供动态渲染的 html,后来我们构建在客户端上运行大部分逻辑的单页应用程序。在未来几年中,您可能希望构建所谓的本地优先应用程序,仅在客户端上处理大而复杂的数据操作,甚至可以在离线状态下工作,这使您有机会构建零延迟的用户交互。

在网络的早期, cookie是存储小型键值分配的唯一选择。但是 JavaScript 和浏览器已经发生了显着的发展,并且添加了更好的存储 API,这为更大、更复杂的数据操作铺平了道路。

在本文中,我们将深入探讨可用于在浏览器中存储和查询数据的各种技术。我们将探索传统方法,如Cookies 、 localStorage 、 WebSQL 、 IndexedDB和较新的解决方案,如通过 WebAssembly 的OPFSSQLite 。我们比较功能和限制,并通过性能测试来揭示使用各种方法在 Web 应用程序中写入和读取数据的速度。

现代浏览器中可用的存储API​

首先,让我们简要概述不同的API,它们的意图用例和历史:

什么是Cookies​

Cookies是netscape在1994年首次引入的。Cookie存储主要用于会话管理、个性化和跟踪的小块键值数据。Cookie可以有几个安全设置,如生存时间或domain属性,以便在几个子域之间共享Cookie。

Cookie值不仅存储在客户端,而且还随每个http请求发送到服务器。这意味着我们不能在cookie中存储太多数据,但与其他方法相比,cookie访问性能仍然很有趣。特别是因为cookie是Web的重要基础功能,许多性能优化已经完成,即使在这些天仍然有进展,如chromium的共享内存版本控制或异步CookieStore API。

什么是LocalStorage​

localStorage API最初是在2009年作为WebStorage规范的一部分提出的。LocalStorage提供了一个简单的API来在Web浏览器中存储键值对。它有方法setItemgetItemremoveItemclear,这是你从键值存储中所需要的。LocalStorage仅适合存储需要跨会话持久化的少量数据,并且受到5 MB存储上限的限制。存储复杂数据只能通过将其转换为字符串来实现,例如使用JSON.stringify()。API不是异步的,这意味着如果完全阻止你的JavaScript进程,而做的事情。因此,在其上运行繁重的操作可能会阻止您的UI呈现。

还有SessionStorage API。关键的区别在于localStorage数据无限期地保持,直到显式清除,而sessionStorage数据在浏览器选项卡或窗口关闭时被清除。

什么是IndexedDB​

IndexedDB于2015年首次作为“索引数据库API”引入。

IndexedDB是一个用于存储大量结构化JSON数据的低级API。虽然API有点难以使用,但IndexedDB可以利用索引和异步操作。它缺乏对复杂查询的支持,只允许覆盖索引,这使得它更像是其他库的基础层,而不是一个完全成熟的数据库。

2018年,IndexedDB 2.0版本发布。这增加了一些重大改进。最值得注意的是getAll()方法,它在获取大量JSON文档时显着提高了性能。

IndexedDB3.0版本正在运行中,其中包含许多改进。最重要的是,添加了基于Promise的调用,使现代JS功能(如async/await)更加有用。

什么是OPFS​

Origin Private File System(OPFS)是一个相对较新的API,它允许Web应用程序直接在浏览器中存储大型文件。它是为数据密集型应用程序而设计的,这些应用程序希望在模拟文件系统中写入和读取二进制数据。

OPFS可以在两种模式下使用:

  • 或者在主线程上异步
  • 或者在WebWorker中使用createSyncAccessHandle()方法进行更快的异步访问。

由于只能处理二进制数据,因此OPFS被用作库开发人员的基本文件系统。在构建“普通”应用程序时,您不太可能直接在代码中使用OPFS,因为它太复杂了。这只对存储像图像这样的普通文件有意义,而不是有效地存储和查询JSON数据。我已经为RxDB构建了一个基于OPFS的存储,并使用了适当的索引和查询,这花了我几个月的时间。

什么是WASM SQLite​

WebAssembly(Wasm)是一种二进制格式,允许在Web上执行高性能代码。Wasm在2017年被添加到主要浏览器中,这为在浏览器中运行什么打开了广泛的机会。您可以将原生库编译为WebAssembly,并只需进行一些调整即可在客户端上运行它们。WASM代码可以被发送到浏览器应用程序,并且通常比JavaScript运行得更快,但仍然比原生代码慢10%左右。

许多人开始使用编译的SQLite作为浏览器内部的数据库,这就是为什么将此设置与本机API进行比较是有意义的。

SQLite编译后的字节码大小约为938.9 kB,用户必须在第一次加载页面时下载并解析。WASM无法直接访问浏览器中的任何持久存储API。相反,它需要数据从WASM流到主线程,然后可以放入浏览器API之一。这是通过所谓的VFS(虚拟文件系统)适配器来完成的,这些适配器处理从SQLite到其他任何东西的数据访问。

什么是WebSQL​

WebSQL是2009年推出的一种Web API,允许浏览器使用SQL数据库进行客户端存储,基于SQLite。这个想法是给开发人员一种在客户端使用SQL存储和查询数据的方法,类似于服务器端数据库。WebSQL近年来已经从浏览器中删除,原因有很多:

  • WebSQL尚未标准化,并且基于SQLite源代码形式的单个特定实现的API很难成为标准。
  • WebSQL要求浏览器使用特定版本的SQLite(版本3.6.19),这意味着无论何时SQLite有任何更新或错误修复,都不可能在不破坏Web的情况下将其添加到WebSQL。
  • 像Firefox这样的主流浏览器从来不支持WebSQL。

因此,在下文中,我们将忽略WebSQL,即使可以通过设置特定的浏览器标志或使用旧版本的chromium来运行测试。


功能比较​

现在您已经了解了API的基本概念,让我们比较一些特定的功能,这些功能对于使用RxDB和基于浏览器的存储的人来说非常重要。

存储复杂的JSON文档​

当您在Web应用程序中存储数据时,通常您希望存储复杂的JSON文档,而不仅仅是存储在服务器端数据库中的integersstrings等“正常”值。

  • 只有IndexedDB可以原生地处理JSON对象。
  • 使用SQLite WASM,您可以将JSON存储在3.38.0(2022-02-22)版以来的text列中,甚至可以对其运行深度查询并使用单个属性作为索引。

其他API只能存储字符串或二进制数据。当然,您可以使用JSON.stringify()将任何JSON对象转换为字符串,但在API中没有JSON支持会使运行查询时变得复杂,并且多次运行JSON.stringify()会导致性能问题。

多选项卡支持​

与Electron或React-Native相比,构建Web应用程序的一个很大区别是,用户将同时在多个浏览器选项卡中打开和关闭应用程序。因此,您不仅有一个JavaScript进程在运行,而且有许多进程可以存在,并且可能必须在彼此之间共享状态更改,以免向用户显示过时的数据。

如果你的用户的肌肉记忆在使用你的网站时把左手放在F5键上,那么你做错了!

并非所有的存储API都支持在选项卡之间自动共享写入事件。

只有localstorage可以通过API本身和storage-event在选项卡之间自动共享写事件,storage-event可用于观察更改。

// localStorage can observe changes with the storage event.
// This feature is missing in IndexedDB and others
addEventListener("storage", (event) => {});

Chrome有实验性的IndexedDB观察者API,但提案存储库已经存档。

要解决此问题,有两种解决方案:

  • 第一个选项是使用BroadcastChannel API它可以在浏览器选项卡之间发送消息。因此,每当您对存储执行写入操作时,您也会向其他选项卡发送通知,以告知它们这些更改。这是RxDB也使用的最常见的解决方法。请注意,WebLocks API其可用于在浏览器选项卡之间具有互斥。
  • 另一种解决方案是使用SharedWorker,并在worker内部执行所有写入操作。然后,所有浏览器选项卡都可以订阅来自单个SharedWorker的消息,并了解更改。

索引支持​

数据库和将数据存储在普通文件中的最大区别在于,数据库以允许在索引上运行操作的格式写入数据,以促进快速性能查询。在我们的技术列表中,只有IndexedDB和WASM SQLite支持开箱即用的索引。从理论上讲,你可以在任何存储(如localstorage或OPFS)上构建索引,但你可能不想自己这样做。

例如,在IndexedDB中,我们可以通过给定的索引范围获取大量文档:

// find all products with a price between 10 and 50
const keyRange = IDBKeyRange.bound(10, 50);
const transaction = db.transaction('products', 'readonly');
const objectStore = transaction.objectStore('products');
const index = objectStore.index('priceIndex');
const request = index.getAll(keyRange);
const result = await new Promise((res, rej) => {request.onsuccess = (event) => res(event.target.result);request.onerror = (event) => rej(event);
});

请注意,IndexedDB的限制是不能对布尔值建立索引。只能索引字符串和数字。为了解决这个问题,你必须在存储数据时将布尔值转换为数字并向后转换。

WebWorker支持​

当运行繁重的数据操作时,您可能希望将处理从JavaScript主线程移开。这确保了我们的应用程序保持快速响应,同时处理可以在后台并行运行。在浏览器中,您可以使用WebWorker、SharedWorker或ServiceWorkerAPI来完成此操作。在RxDB中,您可以使用WebWorker或SharedWorker插件将您的存储移动到worker中。

该用例最常见的API是生成一个WebWorker,并在第二个JavaScript进程上执行大部分工作。worker从一个单独的JavaScript文件(或base64字符串)派生,并通过使用postMessage()发送数据与主线程通信。

不幸的是,由于设计和安全限制,LocalStorage和Cookie不能在WebWorker或SharedWorker中使用。WebWorkers在与主浏览器线程不同的全局上下文中运行,因此不能做可能影响主线程的事情。他们无法直接访问某些Web API,如DOM、localStorage或Cookie。

其他一切都可以从WebWorker内部使用。带有createSyncAccessHandle方法的OPFS的快速版本只能在WebWorker中使用,而不能在主线程上使用。这是因为返回的AccessHandle的所有操作都不是JavaScript,因此会阻塞JavaScript进程,所以您确实希望在主线程上执行此操作并阻塞所有操作。


存储大小限制​

  • Cookie仅限于RFC-6265中的4 KB数据。由于存储的cookie随每个HTTP请求发送到服务器,因此此限制是合理的。您可以在这里测试您的浏览器cookie限制。请注意,您不应该填写完整的4 KBcookie,因为您的Web服务器不会接受太长的标题,并拒绝使用HTTP ERROR 431 - Request header fields too large的请求。一旦你达到了这一点,你甚至不能提供更新的JavaScript给你的用户来清理cookie,你将锁定该用户,直到cookie得到手动清理。

  • LocalStorage的存储大小限制因浏览器而异,但通常每个源的范围为4 MB至10 MB。您可以在这里测试您的localStorage大小限制。

    • Chrome/Chromium/Edge:每个域5 MB
    • Firefox:每个域名10 MB
    • Safari:每个域4-5 MB(不同版本略有不同)
  • IndexedDB没有像localStorage那样的固定大小限制。IndexedDB的最大存储大小取决于浏览器实现。上限通常基于用户设备上的可用磁盘空间。在铬浏览器中,它可以使用高达80%的总磁盘空间。您可以通过调用await navigator.storage.estimate()获得关于存储大小限制的估计。通常,您可以存储千兆字节的数据,可以在这里尝试。

  • OPFS具有与IndexedDB相同的存储大小限制。其限制取决于可用的磁盘空间。这也可以在这里测试。


性能比较​

现在我们已经回顾了每种存储方法的特性,让我们深入到性能比较,重点是初始化时间,读/写延迟和批量操作。

请注意,我们只运行简单的测试,对于您应用程序中的特定用例,结果可能会有所不同。此外,我们只比较性能在谷歌Chrome(版本128.0.6613.137)。Firefox和Safari具有相似但不相等的性能模式。你可以在你自己的机器上从这个github仓库运行测试。在所有的测试中,我们都将网络节流,使其表现得像德国的平均互联网速度。(下载:135,900 kbit/s,上传:28,400 kbit/s,延迟:125 ms)。此外,所有测试都存储一个“平均”JSON对象,根据存储情况,可能需要对该对象进行字符串化。我们也只测试通过id存储文档的性能,因为一些技术(cookie,OPFS和localstorage)不支持索引范围操作,所以比较这些技术的性能没有意义。

初始化时间​

在存储任何数据之前,许多API都需要一个设置过程,例如创建数据库,生成WebAssembly进程或下载其他内容。为了确保应用快速启动,初始化时间非常重要。

localStorage和Cookie的API没有任何设置过程,可以直接使用。IndexedDB需要打开一个数据库和其中的存储。WASM SQLite需要下载一个WASM文件并处理它。OPFS需要下载并启动一个worker文件并初始化虚拟文件系统目录。

以下是从存储第一位数据所需的时间测量:

技术时间毫秒
IndexedDB46
OPFS主线程23
OPFS WebWorker的使用26.8
WASM SQLite(内存)504
WASM SQLiteIndexedDB535

在这里我们可以注意到几件事:

  • 使用单个存储打开新的IndexedDB数据库需要花费惊人的时间
  • 从主线程向WebWorker OPFS发送数据的延迟开销大约为4毫秒。在这里,我们只发送最少的数据来初始化OPFS文件处理程序。当处理更多的数据时,如果延迟增加,那将是有趣的。
  • 下载和解析WASM SQLite并创建一个表大约需要半秒钟。使用IndexedDBVFS持久存储数据还额外增加了31毫秒。使用启用的缓存和已经准备好的表来访问页面要快一些,需要420毫秒(内存)。

小写入延迟​

接下来让我们测试小写入的延迟。当您进行许多相互独立的小数据更改时,这一点很重要。就像你从WebSocket中传输数据,或者持久化伪随机发生的事件,比如鼠标移动。

技术时间毫秒
Cookies0.058
LocalStorage本地存储0.017
IndexedDB0.17
OPFS主线程1.46
OPFS WebWorker的使用1.54
WASM SQLite(内存)0.17
WASM SQLiteIndexedDB3.17

在这里我们可以注意到几件事:

  • LocalStorage具有最低的写入延迟,每次写入仅为0.017毫秒。
  • IndexedDB的写入速度比localStorage慢10倍。
  • 将数据发送到WASM SQLite进程并让其通过IndexedDB持久化是很慢的,每次写入超过3毫秒。

OPFS操作将JSON数据写入每个文件的一个文档大约需要1.5毫秒。我们可以看到,首先将数据发送到Webworker有点慢,这是由于在两端序列化和重新序列化数据的开销。如果我们不在每个文档上创建OPFS文件,而是将所有内容附加到单个文件中,则性能模式会发生显著变化。然后,来自createSyncAccessHandle()的更快的文件句柄每次写入只需要大约1毫秒。但这需要以某种方式记住每个文档存储在哪个位置。因此,在我们的测试中,我们将继续使用每个文档一个文件。

小读取延迟​

现在我们已经存储了一些文档,让我们测量一下读取单个文档所需的时间。

技术时间毫秒
Cookies0.132
LocalStorage本地存储0.0052
IndexedDB0.1
OPFS主线程1.28
OPFS WebWorker的使用1.41
WASM SQLite(内存)0.45
WASM SQLiteIndexedDB2.93

在这里我们可以注意到几件事:

  • LocalStorage读取速度非常快,每次读取仅为0.0052毫秒。
  • 其他技术执行读取的速度与其写入延迟相似。

大批量写入​

下一步,让我们一次对200个文档进行一些大批量操作。

技术时间毫秒
Cookies20.6
LocalStorage本地存储5.79
IndexedDB13.41
OPFS主线程280
OPFS WebWorker的使用104
WASM SQLite(内存)19.1
WASM SQLiteIndexedDB37.12

在这里我们可以注意到几件事:

  • 将数据发送到WebWorker并通过更快的OPFS API运行它的速度大约是原来的两倍。
  • 与单次写入延迟相比,WASM SQLite在批量操作上的性能更好。这是因为如果一次性完成而不是每个文档一次,则将数据发送到WASM并向后发送会更快。

大批量读取​

现在让我们在批量请求中读取100个文档。

技术时间毫秒
Cookies6.34
LocalStorage本地存储0.39
IndexedDB4.99
OPFS主线程54.79
OPFS WebWorker的使用25.61
WASM SQLite(内存)3.59
WASM SQLiteIndexedDB5.84 (35ms无缓存)

在这里我们可以注意到几件事:

  • 在OPFS webworker中阅读许多文件的速度大约是较慢的主线程模式的两倍。
  • WASM SQLite速度惊人。进一步的检查表明,WASM SQLite进程将文档保存在内存中缓存,这改善了我们在对同一数据进行写入后直接读取时的延迟。当浏览器选项卡在写入和读取之间重新加载时,查找这100个文档大约需要35毫秒。

性能结论​

  • LocalStorage确实很快,但请记住它有一些缺点:
    • 它会阻塞主JavaScript进程,因此不应用于大批量操作。
    • 只有键值赋值是可能的,当你需要对数据进行基于索引的范围查询时,你不能有效地使用它。
  • 与直接在主线程中使用OPFS相比,在WebWorker中使用createSyncAccessHandle()方法时,OPFS要快得多。
  • SQLite WASM可以很快,但你必须首先下载完整的二进制文件并启动它,这大约需要半秒钟。如果您的应用程序启动一次并使用很长一段时间,这可能根本不相关。但是对于在许多浏览器标签中打开和关闭多次的网络应用程序来说,这可能是一个问题。

可能改进​

有多种可能的改进和性能改进来加速操作。

  • 对于 IndexedDB,我在这里列出了性能技巧的列表。例如,您可以在多个数据库和网络工作者之间进行分片或使用自定义索引策略。
  • OPFS 在每个文档写入一个文件时速度很慢。但您不必这样做,您可以像普通数据库一样将所有内容存储在单个文件中。这极大地提高了性能,就像使用 RxDB OPFS RxStorage所做的那样。
  • 您可以混合使用这些技术来同时针对多个场景进行优化。例如,在 RxDB 中,有localstorage 元优化器,它将初始元数据存储在 localstorage 中,并将“普通”文档存储在 IndexedDB 内。这缩短了初始启动时间,同时仍然以高效查询的方式存储文档。
  • RxDB中有内存映射存储插件,可以将数据直接映射到内存。将此与共享工作程序结合使用可以显着改善页面加载和查询时间。
  • 在存储数据之前对其进行压缩可能会提高某些存储的性能。
  • 通过分片在多个 WebWorker 之间分割工作可以利用用户设备的全部容量来提高性能。

在这里,您可以看到各种RxDB存储实现的性能比较,这可以更好地了解真实的性能:

RxStorage performance - browser

未来改进​

你正在2024年阅读这篇文章,但网络并没有停滞不前。有一个很好的机会,浏览器得到增强,以允许更快,更好的数据操作。

  • 目前还没有办法从WebAssembly进程内部直接访问持久存储。如果将来发生变化,在浏览器中运行SQLite(或类似的数据库)可能是最好的选择。
  • 在主线程和WebWorker之间发送数据很慢,但将来可能会得到改进。有一个很好的文章关于为什么postMessage()是缓慢的。
  • IndexedDB最近支持存储桶(仅限Chrome),这可能会提高性能

相关文章:

浏览器的数据六种存储方法比较 :LocalStorage vs. IndexedDB vs. Cookies vs. OPFS vs. WASM-SQLite

在构建该 Web 应用程序,并且希望将数据存储在用户浏览器中。也许您只需要存储一些小标志,或者甚至需要一个成熟的数据库。 我们构建的 Web 应用程序类型发生了显着变化。在网络发展的早期,我们提供静态 html 文件。然后我们提供动态渲染的 h…...

Rust个人认为将抢占C和C++市场,逐渐成为主流的开发语言

本人使用C开发8年、C#开发15年、中间使用JAVA开发过项目、后期在学习过程中发现了Rust语言说它是最安全的语言,能够解决C、C的痛点、于是抽出一部分时间网上买书,看网上资料进行学习,这一学习起来发现和其它语言比较起来,在编码的…...

electron-updater软件自动检测更新 +无服务器本地测试

大家好,我是小黄。 今天分享一下如何0基础实现electron自动检测更新功能。 一. 安装 electron-updater 实现自动更新 安装依赖 electron-updater npm install electron-updater 二. 修改package.josn "publish": {"provider": "generi…...

Flink在Linux系统上的安装与入门

一、Flink的引入 这几年大数据的飞速发展,出现了很多热门的开源社区,其中著名的有Hadoop、Storm,以及后来的Spark,他们都有着各自专注的应用场景。Spark 掀开了内存计算的先河,也以内存为赌注,赢得了内存计…...

鸿蒙面试---都用过哪些装饰器

必答的 State装饰器:组件内状态 State装饰的变量,或称为状态变量,一旦变量拥有了状态属性,就可以触发其直接绑定UI组件的刷新。当状态改变时,UI会发生对应的渲染改变。Prop装饰器:父子单向同步Prop装饰的变…...

微信小游戏/抖音小游戏SDK接入踩坑记录

文章目录 前言问题记录1、用是否存在 wx 这个 API 来判断是微小平台还是抖小平台不生效2、微小支付的参数如何获取?3、iOS 平台不支持虚拟支付怎么办?微小 iOS 端支付时序图:抖小 iOS 端支付:4、展示广告时多次回调 onClose5、在使用单例时 this 引起的 bug6、使用 fetch 或…...

uniapp配置全局消息提醒

1.H5使用根标签插入dom的方式实现。 2.app端使用plus.nativeObj.View的方式绘制实现 H5端app端 H5端 创建组件orderAlert.vue <template><div class"view"><div class"content" v-if"visible"><div class"message&q…...

Docker学习

&#x1f389;Docker 简介和安装 Docker 是什么 Docker 是一个应用打包、分发、部署的工具 你也可以把它理解为一个轻量的虚拟机&#xff0c;它只虚拟你软件需要的运行环境&#xff0c;多余的一点都不要&#xff0c; 而普通虚拟机则是一个完整而庞大的系统&#xff0c;包含各…...

【Electron学习笔记(三)】Electron的主进程和渲染进程

Electron的主进程和渲染进程 Electron的主进程和渲染进程前言正文1、主进程2、渲染进程3、Preload 脚本3.1 在项目目录下创建 preload.js 文件3.2 在 main.js 文件下创建路径变量并将 preload.js 定义为桥梁3.3 在 preload.js 文件下使用 electron 提供的contextBridge 模块3.4…...

人工智能的微积分基础

目录 ​编辑 引言 微积分的基本概念 1. 导数 2. 积分 3. 微分方程 微积分在人工智能中的应用 1. 机器学习中的优化 2. 反向传播算法 3. 概率与统计 4. 控制理论 5. 自然语言处理中的梯度 6. 计算机视觉中的积分 7. 优化算法中的微积分 8. 微分几何在深度学习中的…...

关于BeanUtils.copyProperties是否能正常复制字段【详细版】

话不多说&#xff01;先总结&#xff1a; 1、字段相同&#xff0c;类型不同&#xff08;不复制&#xff0c;也不报错&#xff09; 2、子类父类 (1)子类传给父类&#xff08;可以正常复制&#xff09; (2)父类传给子类&#xff08;可以正常复制&#xff09; 3、子类父类&#x…...

oracle将select作为字段查询

在Oracle中&#xff0c;如果你想将一个SELECT语句作为字段的值&#xff0c;你可以使用子查询或者使用WITH子句&#xff08;也称为公用表表达式CTE&#xff09;。以下是两种方法的示例&#xff1a; 方法1&#xff1a;使用子查询 语法如下&#xff1a; SELECTcolumn1,(SELECT …...

FFmpeg 简介与编译

1. ffmpeg 简介&#xff1a; FFmpeg是一套可以用来记录、转换数字音频、视频&#xff0c;并能将其转化为流的开源计算机程序。采用LGPL或GPL许可证。它提供了录制、转换以及流化音视频的完整解决方案。它包含了非常先进的音频/视频编解码库libavcodec&#xff0c;为了保证高可移…...

qt QLinearGradient详解

1、概述 QLinearGradient是Qt框架中QGradient的一个子类&#xff0c;用于创建线性渐变效果。线性渐变是一种颜色沿着一条直线平滑过渡到另一种颜色的效果。QLinearGradient允许你定义渐变的起点和终点&#xff0c;以及在这些点之间的颜色变化。你可以使用它来为图形、背景、边…...

点击A组件跳转到B页面的tab的某一列

1、使用vuex存储点击的数据&#xff1b; 点击A组件里面的button按钮&#xff1a; <div><button click"banli(first)">已办理</button><button click"banli(second)">未办理</button><button click"banli(third)&quo…...

图像小波去噪与总变分去噪详解与Python实现

目录 图像小波去噪与总变分去噪详解与实现1. 基础概念1.1 噪声类型及去噪问题定义1.2 小波去噪算法基础1.3 总变分去噪算法基础2. 小波去噪算法2.1 理论介绍2.2 Python实现及代码详解2.3 案例分析3. 总变分去噪算法3.1 理论介绍3.2 Python实现及代码详解3.3 案例分析4. 两种算法…...

mvn-mac操作小记

1.安装brew 如果报错&#xff0c;Warning: /opt/homebrew/bin is not in your PATH. vim ~/.zshrc&#xff0c;最后一行追加 export PATH“/opt/homebrew/bin:$PATH” source ~/.zshrc 2.安装brew install maven mvn -version查看路径 Maven home: /opt/homebrew/Cellar/mav…...

【娱乐项目】基于批处理脚本与JavaScript渲染视频列表的Web页面

Demo介绍 一个简单的视频播放器应用&#xff0c;其中包含了视频列表和一个视频播放区域。用户可以通过点击视频列表中的项来选择并播放相应的视频&#xff0c;播放器会自动播放每个视频并在播放完毕后切换到下一个视频。本项目旨在通过自动化脚本和动态网页渲染&#xff0c;帮助…...

Faster R-CNN (目标检测)

Faster R-CNN (Faster Region-based Convolutional Neural Networks) Faster R-CNN 是一种高效的目标检测模型&#xff0c;它是在 R-CNN 系列&#xff08;包括 R-CNN 和 Fast R-CNN&#xff09;的基础上发展而来的&#xff0c;能够实现对图像中多个对象的检测。Faster R-CNN 引…...

Diffusion中的Unet (DIMP)

针对UNet2DConditionModel模型 查看Unet的源码&#xff0c;得知Unet的down,mid,up blocks的类型分别是&#xff1a; down_block_types: Tuple[str] ("CrossAttnDownBlock2D","CrossAttnDownBlock2D","CrossAttnDownBlock2D","DownBlock2…...

docker服务容器化

docker服务容器化 1 引言2 多个容器间网络联通2.1 单独创建关联2.2 创建时关联 3 服务搭建3.1 镜像清单3.2 容器创建 4 联合实战4.2 flink_sql之kafka到starrocks4.2 flink_sql之mysql到starrocks 5 文献借鉴 1 引言 ​ 利用docker可以很效率地搭建服务&#xff0c;本文在win1…...

Flink 从入门到实战

Flink中的批和流 批处理的特点是有界、持久、大量&#xff0c;非常适合需要访问全部记录才能完成的计算工作&#xff0c;一般用于离线统计。 流处理的特点是无界、实时, 无需针对整个数据集执行操作&#xff0c;而是对通过系统 传输的每个数据项执行操作&#xff0c;一般用于实…...

ffmpeg安装(windows)

ffmpeg安装-windows 前言ffmpeg安装路径安装说明 前言 ffmpeg的安装也是开箱即用的,并没有小码哥说的那么难 ffmpeg安装路径 这就下载好了! 安装说明 将上面的bin目录加入到环境变量,然后在cmd中测试一下: C:\Users\12114\Desktop\test\TaskmgrPlayer\x64\Debug>ffmpe…...

深度解析:Android APP集成与拉起微信小程序开发全攻略

目录 一、背景以及功能介绍 二、Android开发示例 2.1 下载 SDK 2.2 调用接口 2.3 获取小程序原始Id 2.4 报错提示&#xff1a;bad_param 2.4.1 错误日志 2.4.2 解决方案 相关推荐 一、背景以及功能介绍 需求&#xff1a;产品经理需要APP跳转到公司的小程序(最好指定页…...

DeSTSeg: Segmentation Guided Denoising Student-Teacher for Anomaly Detection

DeSTSeg: Segmentation Guided Denoising Student-Teacher for Anomaly Detection 清华、苹果 个人感觉 Introduction 很自然的让读者理解作者问题的提出&#xff0c;也有例子直接证明了这个问题的存在&#xff0c;值得借鉴&#xff01;&#xff01; Related work写的也很不…...

Xilinx Blockset Gateway In 和Gateway out模块使用及参数配置

目录 一、Gateway InSimulink数据到System Generator数据的转换Gateway BlocksBlock Parameters&#xff08;模块参数&#xff09;Basic选项卡参数Implementation选项卡参数 二、Gateway OutGateway BlocksBlock Parameters&#xff08;模块参数&#xff09;Basic选项卡参数Imp…...

set up RAGFlow on your Mac

个人思考&#xff1a;这些仅仅是工具&#xff0c;和人的思维实际还是有很大差距。 可能是我认知片面&#xff0c;你需要投喂大量的内容给它&#xff0c;它自己其实并不会思考&#xff0c;只是从它的认知里告诉它他知道的东西。举个不太巧当的例子&#xff0c;和以往的方式恰恰相…...

SSM搭建(1)——配置MyBatis

目录 一、框架概述 1.什么是JDBC&#xff1f; 2.JDBC基本流程 3.JDBC的缺点 二、MyBatis的入门程序 1. 创建数据库和表结构 2. MyBatis入门流程总结 3. MyBatis的入门步骤 &#xff08;1&#xff09; 创建maven的项目&#xff0c;创建Java工程即可。 &…...

SickOs: 1.1靶场学习小记

学习环境 kali攻击机&#xff1a;Get Kali | Kali Linux vulnhub靶场&#xff1a;https://download.vulnhub.com/sickos/sick0s1.1.7z 靶场描述&#xff1a; 这次夺旗赛清晰地模拟了在安全环境下如何对网络实施黑客策略从而入侵网络的过程。这个虚拟机与我在进攻性安全认证专…...

Flume 监控配置和实践

要解释 Flume 的监控机制&#xff0c;需要了解 Flume 是如何设计其监控架构的&#xff0c;以及如何将性能指标暴露给用户或集成工具。下面我将详细分解 Flume 的监控机制&#xff0c;从基础架构、实现原理到源码解析&#xff0c;并提供非专业人也能理解的通俗解释。 Flume 的监…...

二分法算法

提示&#xff1a;文章 文章目录 前言一、背景二、二分法2.2 最坏情况下冒泡排序的比较次数 三、大算法之一&#xff1a;分治法总结 前言 前期疑问&#xff1a; 本文目标&#xff1a; 二分法 一、背景 问题来源是一个题目&#xff0c;在A[N]字符串数组中匹配长度为M的字符串&…...

3.27浮点数计算

-127就是说&#xff0c;有8位的数来表示指数&#xff0c;然后给他减去127就是这八位劈半&#xff0c;一半表示负数的指数&#xff0c;一半表示整数的指数&#xff1b;对于移码来说&#xff0c;最高位为1时表示为正&#xff0c;为0时表示为负 对阶是要小阶向大阶对齐&#xff0c…...

存储过程与自然语言处理逻辑的不同与结合

在现代软件开发中&#xff0c;存储过程与自然语言处理&#xff08;NLP&#xff09;逻辑都发挥着重要作用。存储过程是一种在数据库内部运行的预编译程序&#xff0c;通常用于处理与数据相关的任务&#xff0c;例如插入、更新、删除数据以及复杂的查询操作。而自然语言处理&…...

数据集搜集器(百科)008

对数据集搜集器&#xff08;百科&#xff09;007进行一下改进&#xff1a; 错误处理&#xff1a;增加更多的错误处理&#xff0c;比如网络请求超时、解析错误等。 用户界面&#xff1a;增加一些提示信息&#xff0c;让用户更清楚当前的操作状态。 多线程处理&#xff1a;确保多…...

用Pycharm安装manim

由于版本和工具的差异&#xff0c;manim的安装方式不尽相同。本文用Pycharm来安装manim. 一、准备工作&#xff1a;安装相应版本的python、pycharm和ffmpeg. 此处提供一种安装ffmpeg的方式 下载地址&#xff1a;FFmpeg 下载后&#xff0c;解压到指定目录。 配置环境变量&am…...

HTB:Love[WriteUP]

目录 连接至HTB服务器并启动靶机 信息收集 使用rustscan对靶机TCP端口进行开放扫描 使用nmap对靶机开放端口进行脚本、服务扫描 使用浏览器访问靶机443端口 尝试利用该功能访问靶机自身80端口 使用ffuf对靶机80端口进行路径FUZZ 漏洞利用 使用searchsploit搜索靶机80端…...

程序设计 26种设计模式,如何分类?

1. 创建型模式 (Creational Patterns) 这些模式关注如何实例化对象。它们通过各种方式封装对象的创建过程&#xff0c;从而提供灵活性和可扩展性。 单例模式 (Singleton)&#xff1a;确保某个类只有一个实例&#xff0c;并提供全局访问点。工厂方法模式 (Factory Method)&…...

Oracle对比表与表之间的结构

自己首先想到的就是,navicat有提供结构同步 但是有些时候情况不一样,比如我遇到的是连接不同,而且是互相同步,以最多的列的那个表为样 没有说一个固定的源 那么还可以通过导出表结构去另一个库中执行看是否报错,以此来判断结构的不同 但是我感觉有点儿麻烦 最后想到通过sql语…...

MySQL 查询 执行顺序

MySQL查询的执行顺序大致如下&#xff1a; FROM子句&#xff1a;确定要查询的表。 ON&#xff1a;对JOIN语句中的表进行关联条件指定。 JOIN&#xff1a;如果有的话&#xff0c;对表进行关联。 WHERE&#xff1a;对记录进行过滤。 GROUP BY&#xff1a;根据指定的列分组记录…...

Scala习题

姓名&#xff0c;语文&#xff0c;数学&#xff0c;英语 张伟&#xff0c;87&#xff0c;92&#xff0c;88 李娜&#xff0c;90&#xff0c;85&#xff0c;95 王强&#xff0c;78&#xff0c;90&#xff0c;82 赵敏&#xff0c;92&#xff0c;88&#xff0c;91 孙涛&#xff0c…...

VSCode 使用教程:项目使用配置、使用哪些插件、Live Server使用问题及解决方案(你想要的,都在这里)

VSCode的配置&#xff1a; Ⅰ、VSCode 可能需要的项目配置&#xff1a;1、项目颜色主题的切换&#xff1a;其一、点击设置 -> 选择主题 -> 选择颜色主题&#xff1a;其二、通过上下键操作&#xff0c;选择想要的主题&#xff1a; 2、项目文件图标主题的切换&#xff1a;其…...

RPA:电商订单处理自动化

哈喽&#xff0c;大家好&#xff0c;我是若木&#xff0c;最近闲暇时间较多&#xff0c;于是便跟着教程做了一个及RPA&#xff0c;谈到这个&#xff0c;可能很多人并不是很了解&#xff0c;但是实际上&#xff0c;这玩意却遍布文末生活的边边角角。话不多说&#xff0c;我直接上…...

分布式协同 - 分布式锁一二事儿

文章目录 导图Pre概述概述1. 分布式互斥和临界资源的协调2. 分布式锁的基本原理3. 分布式锁的实现方式a. 基于数据库实现的分布式锁b. 基于Redis实现的分布式锁c. 基于Zookeeper实现的分布式锁 4. 高并发场景下的分布式锁优化a. 分段锁&#xff08;Sharded Locks&#xff09;b.…...

React Native学习笔记(三)

一 组件简介 1.1 简介 RN中的核心组件&#xff0c;是对原生组件的封装 原生组件&#xff1a;Android或ios内的组件核心组件&#xff1a;RN中常用的&#xff0c;来自react-native的组件 原生组件 在 Android 开发中是使用 Kotlin 或 Java 来编写视图&#xff1b;在 iOS 开发…...

什么是B+Tree?

BTree是B-Tree的一种变体&#xff0c;它在数据库索引和文件系统中被广泛使用&#xff0c;因为它优化了磁盘I/O操作&#xff0c;并且对于范围查询非常高效。 以下是BTree的详细全面解释&#xff1a; 基本概念 节点&#xff08;Node&#xff09;&#xff1a;BTree由节点组成&…...

LeetCode 热题100(十一)【二分查找】(2)

11.4搜索旋转排序数组&#xff08;中等&#xff09; 题目描述&#xff1a;leetcode链接 33. 搜索旋转排序数组 整数数组 nums 按升序排列&#xff0c;数组中的值 互不相同 。 在传递给函数之前&#xff0c;nums 在预先未知的某个下标 k&#xff08;0 < k < nums.length&…...

《Python基础》之OS模块

目录 前言 各种文件操作方法 1、os.path.exists() 2、os.path.join() 3、os.path.abspath(__file__) 4、os.path.dirname() 5、os.path.isfile() 6、os.path.isdir() 7、os.mkdir() 8、os.remove() 9、os.rmdir() 前言 本文主要介绍使用os模块中的功能操作文件或者文…...

esp32触发相机

esp32触发相机&#xff0c;测试成功上升沿触发 串口发送命令 up 20000 1 20000 触发 #include <Arduino.h>const int outputPin 12; // 输出引脚 String inputCommand ""; // 串口输入缓冲区// 解析命令参数&#xff0c;例如 "up 10 5" 解析为…...

AWS EC2设置用户名密码登录

使用AWS EC2 设置用户名密码登录 步骤 1: 访问控制台 登录到AWS管理控制台。导航至 EC2 Dashboard。在左侧导航栏中选择 Instances。选择需要配置的实例。使用 EC2 Instance Connect 访问实例控制台。 步骤 2: 切换到 root 用户 打开终端或命令行工具&#xff0c;通过SSH连…...

Mac配置和启动 Tomcat

Tomcat 配置与启动&#xff1a; 配置 Tomcat&#xff1a; homebrew install tomcat 启动 Tomcat&#xff1a; 如果cd ~/tomcat/bin文件夹存在startup.sh文件&#xff0c;可以直接在终端运行&#xff1a;./startup.sh 如果~/bin目录下&#xff0c;只有catalina文件。则在终端运行…...