UNIAPP之IOS离线打包

最新iOS平台SDK下载:https://nativesupport.dcloud.net.cn/AppDocs/download/ios 下载SDK解压找到SDK点击打开此文件“HBuilder-Hello.xcodeproj” 打开xcode开发工具后,先点击运行按钮运行项目,如果没有下载模拟器进行下载 下载模拟器 申请 Appkey:https://nativesupport.dcloud.net.cn/AppDocs/usesdk/appkey 填写appkey 填写描述文件 填写版本号 导入资源 配置应用信息 设置图标 打包

STM32C8T6+面板板+3只LED点亮流水灯

文章目录 一、实验题目二、建立工程文件1.自己建立工程2.使用网上模板 三、点亮LED灯1.代码实现2.编译3.仿真波形图4.烧录5.电路连接6.运行结果 一、实验题目 以 STM32最小系统核心板(STM32F103C8T6)+面板板+3只红绿蓝LED 搭建电路,使用GPIOB、GPIOC、GPIOD这3个端口控制LED灯,轮流闪烁,间隔时长1秒。 1)写出程序设计思路,包括GPIOx端口的各寄存器地址和详细参数; 2)分别用汇编语言,C语言编程实现。 二、建立工程文件 建立工程文件可以我们自己来一步一步按照自己的需要进行建立,也可以在网上找到合适的其他人建立好的工程模板,这样可以大大提高效率,本文就从这两方面给大家介绍。 1.自己建立工程 首先新建一个light工程,工程的建立方法同之前文章的方法,这里不过多介绍。本实验要求我们用STM32C8T6芯片,所以在建立工程前选择芯片要选择相对应的。 建立好的工程如图所示。 接下来我们要添加启动代码,启动代码在网络上有,需要者需要自己进行下载。启动代码就是一段与硬件相关的汇编代码,ST公司对于不同容量的芯片提供了不同的三个启动文件,分别是: startup_stm32f10x_ld.s,startup_stm32f10x_md.s,startup_stm32f10x_hd.s 依次对应: 小容量:FLASH≤32K 中容量:64K≤FLASH≤128K 大容量:256K≤FLASH 我们按照需求选择需要的启动文件,因为我们的芯片选择是STMC8T6,所以我们的Flash容量大小是128K对应中容量,所以我们选择startup_stm32f10x_md.s并将该文件下载保存到工程文件目录下。 接下来在工程中加入启动文件如图所示: 打开该.s文件可以看到对这个文件的描述,这个属于开发者设计的描述内容,我们只需要知道需要添加他才可以进行初始化、调用等操作就行,具体文件内容不用过多了解。 接下来我们在工程文件夹右键点击Manage Project Items,可以看到此时只有一个source group组,我们添加一个组用来存放sys.c,delay.c和usart.c文件,组的名字自己确定一个好记的名字就行。 同样我们可以再新建一个组用来存放我们的.c文件,当然也可以不新建,就放在已有的组source group里就可以,看个人习惯。 接下来我们需要修改全局宏定义,点击魔术棒图标,在C++处修改Define。 在output处勾选生成hex文件。 这样我们的工程就建立完毕。 2.使用网上模板 合理利用互联网资源能使我们工作的效率大大提高,上面介绍了手动建立工程,但网上已经有相关的资源,省去了我们每次建立工程的麻烦,这里我个人使用的是洋桃电子,感兴趣的可以去官网去下载。 如图所示,我们只需直接将模板文件夹内建立好的工程即可,打开后左侧可以看到已经建立好相关的组和文件,当然启动文件也在内。 三、点亮LED灯 1.代码实现 根据题目要求,我们首先要初始化LED灯的接口并配置时钟。选择LED_Init 三个目标端口的模式为推挽输出,默认输出1,这样就完成了初始化端口。 led.c: #include "led.h" void LED_Init(void){ //LED灯的接口初始化 GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE); //开启时钟 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; //选择端口号(0~15或all) GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //选择IO接口工作方式,这里是推挽输出模式 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //设置IO接口速度(2/10/50MHz) GPIO_Init(GPIOA, &GPIO_InitStructure); GPIO_ResetBits(GPIOA,GPIO_Pin_0);//初始值是低电平 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE); GPIO_InitStructure.GPIO_Pin =GPIO_Pin_0; //选择端口号(0~15或all) GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //选择IO接口工作方式 GPIO_InitStructure.

epoll 或者 kqueue 的原理是什么?

作者:张彦飞 链接:https://www.zhihu.com/question/20122137/answer/2134896876 刚回答完一个 epoll,又刷到一个,那我就再来回答一遍吧。 仔细看了一下问题,题主的主要困惑是就是没有看过内核源码,不清楚 epoll 内部究竟是咋工作的。其实我之前和题主一样,也是这个困惑。由于实在是好奇心太强,所以我就抽空撸起袖子,把 epoll 的源码给扒了一遍。 我把我分析 epoll 的过程都放在我的这本电子书里了,《理解了实现再谈网络性能》。需要的同学戳这里下载,传送门:《理解了实现再谈网络性能》 在介绍 epoll 的实现之前。我想先聊聊传统的同步阻塞 IO。 深入理解高性能网络开发路上的绊脚石 - 同步阻塞网络 IO - 知乎 这种网络 IO 模型在对网络性能要求不高的地方现在用的也还是挺多的,我把这个整体流程画了一个图。 这种网络IO模型的问题是每次一个进程专门为了等一个 socket 上的数据就得被从 CPU 上拿下来。然后再换上另一个进程。等到数据 ready 了,睡眠的进程又会被唤醒。总共两次进程上下文切换开销,根据之前的测试来看,每一次切换大约是 3-5 us(微秒)左右。 如果是网络 IO 密集型的应用的话,CPU 就不停地做进程切换这种无用功。 所以多路IO复用,包括 epoll 就是为了解决上述问题而生的。当然 epoll 由于要支持海量的连接,为了高效地插入和删除 socket,在2.6 以后的版本里引入了红黑树。 epoll 作为多路复用技术中的代表,和传统的阻塞网络 IO 相比,最大的性能提升就是节约掉了大量的进程上下文切换。 epoll 内部又涉及出了一套复杂的数据结构,包括一棵红黑树和一个就绪链表(以及一个epollwait等待队列)。全部都工作在内核态。 使用 epoll 大体上由三个函数配合而成,分别是 epoll_create 、epollctl 和 epoll_wait,另外内核的网络模块也会参与其中。接下来我就分这四块来讲。这些都是我看过源码后整理出来的,源码版本是 3.10.0。 一、epoll_create 创建 epoll 内核对象 在用户进程调用 epoll_create 时,内核会创建一个 struct eventpoll 的内核对象。当然了这个对象,并不是由一个结构体构成的,而是一组数据结构。它的结构如下。

javascript几种运算符

目录 运算符 分类 算术运算符 赋值运算符 比较运算符 普通比较 绝对比较 逻辑运算符 ! 非:取反 运算符的优先级 三目运算符 运算符 分类 运算符:算术运算符,赋值运算符,比较运算符,逻辑运算符,三目运算符 表达式:算术表示式,赋值表达式,判断表达式,逻辑表达式 算术运算符 + - * / %取余 自增++ 自减-- 数据在进行运算的时候,会尽量转为数字在进行运算(内置帮我们去转的,属于隐式转换)符合Number的规律 + :一旦遇到字符串表示拼接 将另一边数据也转为字符串 console.log(10 + 10); console.log(10 + "10"); //"10" + "10" =>"1010" console.log(10 + 20 + "100"); //30 + "100" => "30" + "100" => "30100" console.log(true + 100); // 1 + 100 =>101 console.log(false + null); // 0 + 0 => 0 console.

输出每一类的准确率 pytorch

输出每一类的准确率 # prepare to count predictions for each class correct_pred = {classname: 0 for classname in classes} total_pred = {classname: 0 for classname in classes} # again no gradients needed with torch.no_grad(): for data in testloader: images, labels = data outputs = net(images) _, predictions = torch.max(outputs, 1) # collect the correct predictions for each class for label, prediction in zip(labels, predictions): if label == prediction: correct_pred[classes[label]] += 1 total_pred[classes[label]] += 1 # print accuracy for each class for classname, correct_count in correct_pred.

pytorch 指定参数进行权重衰减

def add_weight_decay(net, l2_value, skip_list=()): decay, no_decay = [], [] for name, param in net.named_parameters(): if not param.requires_grad: continue # frozen weights if len(param.shape) == 1 or name.endswith(".bias") or name in skip_list: no_decay.append(param) else: decay.append(param) return [{'params': no_decay, 'weight_decay': 0.}, {'params': decay, 'weight_decay': l2_value}] params = add_weight_decay(net, 2e-5) sgd = torch.optim.SGD(params, lr=0.05) pytorch官方解释

js怎样通过class获取多个下拉框选择的value

将多个select标签赋上class同一个属性值 <select name="sel" class="sel"> <option value="1" >1</option> <option value="2" selected>2</option> <option value="3">3</option> </select> <select name="sel" class="sel"> <option value="4" >4</option> <option value="6" selected>6</option> <option value="5">5</option> </select> <select name="sel" class="sel"> <option value="7" >7</option> <option value="8" selected>8</option> <option value="9">9</option> </select> 通过点击事件 <input type="button" value="获取" onclick="getSelectValue()" /> 编写点击事件方法 <script language="javascript"> function getSelectValue(){ var se =document.getElementsByName("sel"); for(var j=0;j<se.length;j++){ var option=se[j].getElementsByTagName("option"); for(var i=0;i<option.length;i++){ if(option[i].selected==true) { console.log(option[i].value); } } } } </script> 再查看控制台的打印信息 好了,就是这样了,赶紧试试吧

公开密钥密码体制(C语言实现RSA加密算法)

公开密钥密码体制: 公开密钥密码体制的产生主要是因为两个方面的原因,一是由于常规密钥密码体制的密钥分配问题,另一种是由于对和数字签名的需求。 传统的加密方法是加密、解密使用同样的密钥,由发送者和接收者分别保存,在加密和解密时使用,采用这种方法的主要问题是密钥的生成、注入、存储、管理、分发等很复杂,特别是随着用户的增加,密钥的需求量成倍增加。在网络通信中,大量密钥的分配是一个难以解决的问题。 1976年美国斯坦福大学的两名学者迪菲和赫尔曼提出了公开密钥密码体制的概念。所谓的公开密钥密码体制就是使用不同的加密密钥与解密密钥,是一种“由已知加密密钥推导出解密密钥在计算上是不可行的”密码体制。 在公开密钥密码体制中,公开密钥PK是公开信息,而秘密密钥SK是需要保密的。加密算法E和解密算法D也都是公开的。虽然秘密密钥SK是由公开密钥PK决定的,但却不能根据PK计算出SK。 该技术采用"非对称式加密方法,也就是两个不同的密钥来对信息加密和解密。 举个例子吧,单看概念属实看不懂 首先我有两把钥匙,公钥和私钥。我可以把我的公钥给任何一个想给我写信的人,他们写完信之后用我的公钥加密,发给我,然后我用自己的私钥解密。这里要强调的是,只要我的的私钥不泄露,这封信就是安全的,即使落在别人手里,也无法解密。 加密解密原理: 对称加密:又称共享密钥加密,使用同一个密钥对数据进行加密解密。非对称加密:加密解密使用不同密钥,用公钥加密,私钥解密。 RSA公钥加密体制 RSA公共密码密钥体制是一种使用不同的加密密钥与解密密钥,“由已知加密密钥推导出解密密钥在计算上是不可行的”密码体制 。 在公开密钥密码体制中,加密密钥(即公开密钥)PK是公开信息,而解密密钥(即秘密密钥)SK是需要保密的。加密算法E和解密算法D也都是公开的。虽然解密密钥SK是由公开密钥PK决定的,但却不能根据PK计算出SK 。 正是基于这种理论,1978年出现了著名的RSA算法,它通常是先生成一对RSA密钥,其中之一是保密密钥,由用户保存;另一个为公开密钥,可对外公开,甚至可在网络服务器中注册。为提高保密强度,RSA密钥至少为500位长,一般推荐使用1024位。这就使加密的计算量很大。为减少计算量,在传送信息时,常采用传统加密方法与公开密钥加密方法相结合的方式,即信息采用改进的DES或IDEA对话密钥加密,然后使用RSA密钥加密对话密钥和信息摘要。对方收到信息后,用不同的密钥解密并可核对信息摘要。 分析RSA加密原理 RSA算法的过程 RSA算法用到的数学知识特别多,所以在中间介绍这个算法生成私钥和公钥的过程中会穿插一些数学知识。生成步骤如下: 寻找两个不相同的质数 随意选择两个大的质数p和q,p不等于q,计算N=p*q; 什么是质数?我想可能会有一部分人已经忘记了,定义如下: 除了1和该数自身外,无法被其他自然数整除的数(也可定义为只有1该数本身两个正因数]的数)。 比如2,3,5,7这些都是质数,9就不是了,因为3*3=9了 根据欧拉函数获取r r = φ(N) = φ§φ(q) = (p-1)(q-1)。 这里的数学概念就是什么是欧拉函数了,什么是欧拉函数呢? 欧拉函数的定义: 欧拉函数 φ(n)是小于或等于n的正整数中与n互质的数的数目。 互质的定义: 如果两个或两个以上的整数的最大公约数是 1,则称它们为互质 例如:φ(8) = 4,因为1,3,5,7均和8互质。 推导欧拉函数: (1)如果n = 1, φ(1) = 1;(小于等于1的正整数中唯一和1互质的数就是1本身); (2)如果n为质数,φ(n) = n - 1;因为质数和每一个比它小的数字都互质。比如5,比它小的正整数1,2,3,4都和他互质; (3) 如果n是a的k次幂,则 φ(n) = φ(a^k) = a^k - a^(k-1) = (a-1)a^(k-1); (4) 若m,n互质,则φ(mn) = φ(m)φ(n) 证明:设A, B, C是跟m, n, mn互质的数的集,据中国剩余定理(经常看数学典故的童鞋应该了解,剩余定理又叫韩信点兵,也叫孙子定理),A*B和C可建立双射一一对应)的关系。(或者也可以从初等代数角度给出欧拉函数积性的简单证明) 因此的φ(n)值使用算术基本定理便知。(来自维基百科) 选择一个小于r并与r互质的整数e

某银行开发岗面试

某银行 面试时间: 系统开发岗位:2021.10.13 15:00-15:30中间件管理岗位:15:40-16:20 面试形式:多面试官单独面试 总体感受:中间件开发岗位设计中级工程师的技术,总体感觉良好,感觉能拿offer 系统开发岗 系统开发岗几乎没有问任何技术问题,以开放性的问题为主。总体感觉一般,但是面试官态度良好。 自我介绍 说一下里最满意的一个项目经历 着重体现:分析解决问题能力、沟通协调能力 这个问题被问过多次,但是一直没好的答案。我觉得一个好好的 有一定难度自己是主导成功落地的项目 被选项目 Ant切Mavne: 需求:使用ANT进行构建,无法使用远程仓库,插件也很少。本地包无法托管在git难点:项目一个有30万行的代码,有第三方包、部门包、自研包总计270个。需要全部翻译为pom文件,工作量巨大。解决: 分析了maven仓库的查询和详情接口,做了批量查询功能设计6个上下游部门,推动其Jar上公共仓库成功在三级部门推广 项目性能优化:一二级缓存+门面模式 需求:系统产品搜索和加购物车较慢,需要优化难点:产品展示和加购物车逻辑复杂,设计大量的产品表、部件表、价格表、权限表等解决: 考虑在部分缺失缓存的逻辑添加基础数据缓存缓存的key生成规则不统一,难以监控使用情况。和一级缓存api不同,开发混乱。 使用CacheProxy做门面模式,统一二级缓存的接口,key统一生成的规则,统一缓存时间排查代码,在DAO根据业务逻辑,添加一二级缓存。不考虑一致性通过缓存key,反查缓存时间,部分适当加长引入主动更新机制MQ,主动刷新如黑名单等缓存,解决失效问题添加规范日志,便于后期排查(找到了一次雪崩) 主动写日报专项跟踪,并且借助领导的力量 人民医院医生叫号: 需求:门诊叫好轮训数据库叫号表,性能压力大难点:小需求,不过巧妙解决,使用MQ主动推动 平时如何学习新知识 技术上主要在工作学习,终身学习。想办法在工作中使用 工作知识可能偏窄,倾向沟通、项目经验等学习 怎么做sql优化 通过命令找出SQL:重点关注最慢的、调用次数最多的优化 执行计划(关注索引、全表扫描、扫描函数) 多数据源是否有用到?怎么做数据同步 怎么对接客户,拿到清晰的需求 面对“说不清”的需求:使用原型法、写好需求说明书,相对的敏捷面对“说太多”的需求:并且确认功能的优先级,确保功能满足要求对于变更,要评审,记录 中间件开发岗 自我介绍项目中接触过那些MQ,使用场景项目中Redis的使用场景Redis为什么会比较快 基于内存实现高效的数据结构:String、List、Hash、Set等都有优化 惰性释放、压缩类表、头尾节点、跳跃表等一种数据类型,底层可能是多种的数据结构进行支撑 合适的线程模型 如果华为的中间件团队要招聘你,你会去吗? 但是不知道面试的的是中间件团队,所以回答了不去 传递: 1.认真对待自己的职业规划,中间件团队可能偏底层开发 2.不惧怕挑战,觉得可以胜任 SQL优化 Sql的索引机制 怎么看待领导分配的任务 抓住领导任务的重点,尽可能当面沟通定期汇报工作,遇到困难及时反馈,上升完美任务和deadline之前学会平衡保姆型领导和撒手不管型领导 怎么看待加班 不惧怕加班,对工作有责任感。服从公司安排 长期加班反思自己的工作节奏 更加聚焦于自己工作产出的效率和质量、带来生产力的提升 福利和薪酬待遇等

nginx指定目录安装

很简单的 1.先下载到本地 下载地址:http://nginx.org/en/download.html 比如我要下载的是1.18.0版本,点击下载: 2.远程服务器上 打开你的远程服务器链接工具,连接目标服务器。 进入指定安装目录,比如我要把nginx安装在根目录/cxy/domains文件夹下面,就把下载好的nginx-1.18.0.tar.gz拖到这个目录下。 在命令行中进行解压: cd /cxy/domains tar -zxvf nginx-1.18.0.tar.gz 目录下会多一个nginx-1.18.0文件夹: cd nginx-1.18.0 这个文件夹里还是源码,不是我们能使用的。 3.接下来是重点 nginx默认安装目录是/usr/local/nginx。而现在需要把这个默认路径改掉: 已经在nginx-1.18.0文件夹里面了哦: ./configure --prefix=/cxy/domains/nginx 这里要注意最后一定要加上’/nginx’,否则nginx编译后的文件会散落在/cxy/domains文件夹下面,我想这绝对不是你想要的(反正我踩坑了)。 看到其他文章里面还要下载pcre、zlib什么的,不知道是不是因为我们服务器上已经有了,反正我不用装也把nginx装好了。 看到其他文章还要设置sbin等等文件目录,其实没必要了,感觉一般也不需要吧,把prefix设置好后,其他如sbin等文件目录会基于这个prefix的相对路径生成。 然后编译吧: make && make install test -d 然后/cxy/domains/nginx文件夹里面就会出现常见到的conf、sbin等文件夹了。 4.验证一下是不是可以用了呢 启动一下: ./nginx -s reload 然后访问http://这台服务器ip:80,看到如下页面就可以了呢。 参考文章:https://www.jb51.net/article/152144.htm

回流( reflow )与重绘( repaint )

文章目录 1、了解浏览器的渲染机制2、回流3、重绘4、避免方法 1、了解浏览器的渲染机制 (1)浏览器采用流式布局模型。 (2)首先浏览器会将 HTML 解析成 DOM,把 CSS 解析成 CSSOM,把 CSSOM 与 DOM 结合产生 render tree。 (3)有 render tree 之后,我们知道了节点样式,然后浏览器会计算节点的位置,然后把节点绘制到页面上。 2、回流 当 render tree 中的一部分(或全部)因为元素的规模尺寸,布局,隐藏等改变而需要重新构建, 这就称为回流( reflow )。每个页面至少需要一次回流,就是在页面第一次加载的时候。 回流的产生: 1.页面第一次渲染 在页面发生首次渲染的时候,所有组件都要进行首次布局,这是开销最大的一次回流。2.浏览器窗口尺寸改变3.元素位置和尺寸发生改变的时候4.新增和删除可见元素5.内容发生改变(文字数量或图片大小等等)6.元素字体大小变化7.激活CSS伪类(例如::hover)8.设置style属性9.查询某些属性或调用某些方法。比如说:offsetTop、offsetLeft、 offsetWidth、offsetHeight、scrollTop、scrollLeft、scrollWidth、scrollHeight、clientTop、clientLeft、clientWidth、clientHeight 3、重绘 在回流的时候,浏览器会使渲染树中受到影响的部分失效,并重新构造这部分渲染树,完成回流后,浏览器会重新绘制受影响的部分到屏幕中,该过程成为重绘。 重绘的产生: 1.background 改变2.visibility 改变 总结:回流一定会引起重绘,重绘不一定会引起回流。 回流会导致页面重排,影响性能 4、避免方法 直接改变className,如果动态改变样式,则使用cssText(没有优化的浏览器可以考虑);让要操作的元素进行’离线处理’,处理完后一起更新; a、使用 DocumentFragment 进行缓存操作,引发一次回流和重绘; b、使用 display:none 技术,只引发两次回流和重绘; c、使用 cloneNode(true or false) 和 replaceChild 技术,引发一次回流和重绘;不要经常访问会引起浏览器 flush 队列的属性,如果确实要访问,就利用缓存;让元素脱离动画流,减少回流的 Render tree 的规模;

mysql批量删除表

mysql批量删除表 查询构建所有的删除语句 SELECT CONCAT('drop table ',table_name,';') FROM information_schema.TABLES WHERE table_name LIKE 'fine_%'; 复制查出来的删除sql语句,并批量执行 drop table QRTZ_BLOB_TRIGGERS; drop table QRTZ_CALENDARS; drop table QRTZ_CRON_TRIGGERS; drop table QRTZ_FIRED_TRIGGERS; drop table QRTZ_JOB_DETAILS; drop table QRTZ_LOCKS; drop table QRTZ_PAUSED_TRIGGER_GRPS; drop table QRTZ_SCHEDULER_STATE; drop table QRTZ_SIMPLE_TRIGGERS; drop table QRTZ_SIMPROP_TRIGGERS; drop table QRTZ_TRIGGERS; 删除完成!

jvm和底层操作系统交互简介

菠萝科技备注,文中一些概念相关扩展: 并发研究之CPU缓存一致性协议(MESI) - 枫飘雪落 - 博客园 图解|什么是缺页错误Page Fault_架构师小秘圈-CSDN博客 操作系统:进程和程序关系类比/ java中线程是哪种实现_ice-wee的专栏-CSDN博客 java: synchornized底层的实现原理monitor,它的底层实现又是什么_ice-wee的专栏-CSDN博客 Linux与JVM的内存关系分析_ice-wee的专栏-CSDN博客 以下是正文 肉眼看计算机是由 CPU 、内存、显示器这些硬件设备组成,但大部分人从事的是软件开发工作。计算机底层原理就是连通硬件和软件的桥梁,理解计算机底层原理才能在程序设计这条路上越走越快,越走越轻松。从操作系统层面去理解高级编程语言的执行过程,会发现好多软件设计都是同一种套路,很多语言特性都依赖于底层机制,今天为你一一揭秘。 结合 CPU 理解一行 Java 代码是怎么执行的 根据冯·诺依曼思想,计算机采用二进制作为数制基础,必须包含:运算器、控制器、存储设备,以及输入输出设备,如下图所示。 enter image description here 我们先来分析 CPU 的工作原理,现代 CPU 芯片中大都集成了,控制单元,运算单元,存储单元。控制单元是 CPU 的控制中心, CPU 需要通过它才知道下一步做什么,也就是执行什么指令,控制单元又包含:指令寄存器(IR ),指令译码器( ID )和操作控制器( OC )。 当程序被加载进内存后,指令就在内存中了,这个时候说的内存是独立于 CPU 外的主存设备,也就是 PC 机中的内存条,指令指针寄存器IP 指向内存中下一条待执行指令的地址,控制单元根据 IP寄存器的指向,将主存中的指令装载到指令寄存器。 这个指令寄存器也是一个存储设备,不过他集成在 CPU 内部,指令从主存到达 CPU 后只是一串 010101 的二进制串,还需要通过译码器解码,分析出操作码是什么,操作数在哪,之后就是具体的运算单元进行算术运算(加减乘除),逻辑运算(比较,位移)。而 CPU 指令执行过程大致为:取址(去主存获取指令放到寄存器),译码(从主存获取操作数放入高速缓存 L1 ),执行(运算)。 enter image description here 这里解释下上图中 CPU 内部集成的存储单元 SRAM ,正好和主存中的 DRAM 对应, RAM 是随机访问内存,就是给一个地址就能访问到数据,而磁盘这种存储媒介必须顺序访问,而 RAM 又分为动态和静态两种,静态 RAM 由于集成度较低,一般容量小,速度快,而动态 RAM 集成度较高,主要通过给电容充电和放电实现,速度没有静态 RAM 快,所以一般将动态 RAM 做为主存,而静态 RAM 作为 CPU 和主存之间的高速缓存 (cache),用来屏蔽 CPU 和主存速度上的差异,也就是我们经常看到的 L1 , L2 缓存。每一级别缓存速度变低,容量变大。

IDEA2021配置mapper映射文件标签提示

问题描述 最近新安装了IDEA2021版本,在编写MyBatis的的映射文件的时候标签没有提示写起来很不方便。 解决方案: 在mapper文件中添加dtd约束: 1、首先下载dtd约束文件,也可以从jar包中解压出来 http://mybatis.org/dtd/mybatis-3-config.dtd http://mybatis.org/dtd/mybatis-3-mapper.dtd 下载完以后存放到一个目录下,最好不要是中文目录。 2、在IDEA中指定dtd File–>Settings–>Languages&Frameworks–>Schemas andDTDs 然后按照URL + 本地路径的方式配置一下。具体的URL可以打开dtd文件查看

结构体,联合体,枚举详解

结构体,联合体,枚举详解 目录 结构体联合体枚举常量 1.结构体 在C语言中,系统已经提供了一些数据类型,比如float,int,double,char等,但是我们有时会需要更复杂的类型来描述一个数据。假如我想描述一个学生,我需要知道他的学号,姓名,性别,那么我就需要三个类型来分别保存他的信息,到时候需要信息时还得分别查找,显然这是不方便的。因此有了结构体,我们可以根据自己所需来定义数据类型。 简言之,结构体是由不同的类型数据组成的组合型数据结构。 结构体类型的声明以及定义 struct 结构体名 { 成员列表; }结构体变量名; 这就是结构体声明的一个基本形式,写个结构体给大家看看。 struct students { char name [20]; int xuehao[20]; char xinbie[5]; }a,b,c; struct students 为结构体名,这相当于,我们熟知的int ,char,float,就是类型的意思。 { }括号里面的是成员列表,需要注意的是这是结构体声明,我们不可以在里面赋值,这从逻辑上就是错误的,我们想要赋值,只能给变量赋值,怎么能给类型赋值呢。 然后是,a,b,c 这是结构体变量名,我们可以对它们进行赋值。 还要提一嘴的是一种特殊的定义,就是不加结构体名。 struct { char a[20]; int b; }w,q; 这样定义会导致一种情况,就是无法再继续定义其他结构体变量,就是说有且仅有w,q两个变量。 结构体的初始化和引用 结构体的初始化有两种方式,一种是再定义结构体时进行初始化,一种是建立结构体变量,在去初始化。 struct students { char name [20]; int xuehao[20]; char xinbie[5]; }a={"张三",12345667,"男"}; int main() { struct students b={"李四",233244,"男"}; return 0; } 这两种方式都可以,唯一的区别在于,a是全局变量,b是临时变量。 结构体的引用也有两种方式一种是直接引用,另一种是通过指针来引用。 struct students { char name [20]; int xuehao[20]; char xinbie[5]; }a={"

.NET Core 之 七 EF Core(五)

一、EF Core执行非查询原生sql语句 为什么要写原生sql语句 执行非查询sql语句 内插值语法:$"我是{name},我的年龄是{age}" 多行@ ctx.Database.ExecateSqlInterpolatedAsync($"inster into...") 有sql注入漏洞吗? 没有 sql注入最好的解决方案是参数化sql处理 1、字符串内插值的方式不会有sql注入攻击漏洞; 2、字符串内插如果赋值给string变量,就是字符串拼接;字符串内插值如果赋值给FormattableString类型变量,编译器就会构造FormattableString对象,属性Formar和GetArguments()方法 3、ExecuteSqlInterPolatedAsync()的参数FormattableString类型,因此ExecutSqlInterPolatedAsync会进行参数化sql处理 4、除了ExecuteSqlInterPolated(),ExecuteSqlInterPolatedAsync()还有ExecuteSqlRaw(),ExecuSqlRawAsync()也可以执行原生sql语句,但需要开发人员自己处理查询参数,用不好容易造成sql注入风险,以前旧版本用,新版本推荐用内插值方法。 二、执行实体相关查询原生sql语句 如果要执行的原生sql是一个查询语句,并且查询结果也能对应一个实体,就可以调用对应实体的DbSet的FormSqlInterPolated()方法来执行一个查询sql语句,同样使用字符串内插来传递参数 SQL select newid() 可用作随机排序 like时需要参数传入"%中%",不能把%直接放入字符串中 SQL 子查询中不能使用order By 把只能用原生sql语句写的逻辑用FormSqlInterPolated()去执行,然后把分页,分组,二次过滤,排序,Include等其他逻辑尽可能仍然使用EFCore的标准操作去实现 局限性 1、sql查询必须返回实体类型对应数据库表的所有列; 2、结果集中的列名必须与属性映射的列名称匹配; 3、只能单表查询,不能使join语句进行关联查询,但是可以在查询后面使用Include()来进行关联数据的获取; 三、EFCore执行任意原生sql查询语句 什么时候需要ADO.NET 不推荐使用视图,存储过程 执行任意sql ADO.NET 演示,操作太复杂不推荐 Dapper框架 演示,1、建对应DTO对象 2、Query方法 总结 四、EFCore如何知道实体数据变了 演示,SaveChanges时奇怪的地方,与数据库不一致的才会执行修改 快照更改跟踪,概念 实体的状态:已添加(Added),未改变(Unchanged), 已修改(Modified),已删除(Deleted),已分离/未跟踪(Datached) Savechanges的操作 EntityEntry 1、使用DbContext的Entry()方法来获得实体在EFCore中的跟踪信息对象EntityEntry,EntityEntry类的State属性代表实体的状态,通过DebugView.LongView属性可以看到实体的变化信息 2、代码演示 总结:DbContext会根据跟踪的实体的状态,在SaveChanges()的时候根据实体状态的不同,生成update,delete,inster等sql语句,来把内存中实体的变化更新到数据库中。这就是SaveChanges的原理 五、EFCore优化之AsNoTracking 如果查询出来的对象不会被修改,删除等吗,那么查询时可以用AsNoTracking(),就能降低内存占用;不需要跟踪状态,不需要快照 代码演示 六、EFCore实体状态跟踪的妙用(不推荐使用) 修改和删除只执行一句sql语句,不用执行查询sql,可以性能优化,但代码可读性不强,难维护,提升微乎其微,弊大于利,不推荐使用; 七、EFCor数据的批量删除、更新、插入 SQLBulkCopy 可以一次性把很多数据插入到数据库中 演示,EFCore批量修改、删除、插如实体n条sql会执行 为什么不用sql实现 a、原生sql语句需要把表名、列名等硬编码到sql语句中,不符合模型驱动,分层隔离等思想,程序员直接面对数据库表,无法利用EFCore强类型的特性,如果模型发生改变,必须手动变更sql语句; b、无法利用EFCore强大的sql翻译机制来屏蔽不同底层数据库的差异 c、EFCore官方迟迟未支持的原因 与EFCore实体状态跟踪冲突,会导致状态混乱 我的开源实现 Zack.EFCore.Batch 包 批量删除、更新、插入 使用方法,官方文档

SpringBoot——单元测试1——业务逻辑层单元测试

引入Spring-test-starter即可引入 Junit+Mockito+assertJ 业务逻辑层的单元测试 分析业务逻辑层的职责: 被controller层进行调用后; 1.校验数据 2.执行业务逻辑 - 调用其他原子服务的接口 - 组装数据 - 执行对应的操作 3.执行数据库操作 举个例子:创建订单createOrder() public class OrderService { public Boolean createOrder(CreateOrderRequest req) { //校验参数 checkOrderRequestParamter(req); //获得当前用户具体信息:如用户名,用户手机号等信息 //如果是微服务,则需要调用http接口或者是调用对应dubbo服务 UserMsg userMsg = userFacade.getUser(req.getUserId); fillOrderUserMsg(req,userMsg); //获取对应商品信息 List<GoodMsg> goods = GoodsFacade.getGoods(req.getItemsSkuSn()); //对商品信息的有效性进行校验,并填充到req中 checkAndFillGoodsMsg(goods,req); //计算订单商品金额等信息 calculatedAmount(req); /**还有些业务逻辑**/ //落库 orderMapper.createOrder(req); } } servcie层单元测试的目的: 测试中间的业务逻辑是否正确的执行,没有过度执行也没有遗漏业务逻辑;主要是对方法中的业务逻辑进行测试 而不是需要订单真正的落库,那是mapper单元测试需要测试的内容,需要界定你单元测试的范围;也不需要去看对应商品服务接口返回的数据是否有误;单元测试的局限性: 一般单元测试都是由开发在本地进行测试自己的代码,而像一些请求接口并不能去调用,类似于上述例子中:需要获取用户信息或者商品信息,由于是微服务开发,我们不一定能在本地直接去调用对应的接口;那么这个应该如何测试呢? 有两种方法,也是在总览中提到的: 一种是桩代码:也就是在单元测试的时候,将对应的接口调用替换成一段测试专门使用的创建对应的参数进行返回,但不过这样做事有坏处的,如果在发布的时候,忘记将其改回来就会产生问题;所以更推荐的方法是第二种 二:Mock对象;使用上述的工具Mockito;对调用的其他的微服务接口进行模拟对象;其执行原理大致是:动态生成一个被模拟对象相同类型的对象,注入到ioc容器中将其替换,然后我们在书写调用执行对应方法时的业务逻辑; 上述已经论述了为什么使用Mockito的原因与其作用了;那么为什么使用断言呢? 问题: 如何判断单元测试是否执行成功呢? 将结果进行输出System.out.println();由人工去判断是否得到自己想要的结果;那么随着业务系统规模的增大,单元测试越来越多,我们使用maven插件mvn:test一键自动化执行所有的单元测试,在一个一个去进行比较单元测试是否成功是一件很花费时间的事情; 解决:使用断言 断言的作用:比较方法得出的结果与我们预期的结果是否一致,减少用人眼去校对的过程;也就是assertJ的作用; 但具体的对应的方法,本文就不涉及了; 那么业务逻辑层的单元测试还有什么需要注意的? 注意单元测试的覆盖率;由于业务逻辑层的代码相较于其他层是较多的(不同的公司具有不同的规范,业务的复杂度也是不一样的,划分的层次也是不一样的);更需要注重测试的用例是否覆盖了大部分的代码,每一种业务场景是否都有覆盖 最后在给出一个Service层单元测试的例子吧:(基于SpringBoot) import static org.mockito.BDDMockito.given; import static org.

关于PLEX 不能硬解4K hdr 强制转码播放的问题

PLEX客户端更新最新版后,硬解能力有提升流畅一点了,仍然有部分4K hdr 视频不能硬解, 5600X cpu 占用60%+3060TI占用10%+仍然不能流畅, 在的 关掉后能流畅硬解码了,CPU占用10%+3060ti占用30%+,但是颜色暗淡,HDR不能正确解码,上官网一搜,到这个页面: HDR to SDR Tone Mapping | Plex Support 才发现win 下驱动层都还没支持到硬解HDR,intel 能靠opencl硬解部分 ,剩下的都只能软解了。。。。或者是plex布置在linux、docker、nas才能硬解,看来只能升级CPU 了。。。

Java8下Collectors.toMap方法当key重复时报错信息错误

现象: 在Java 8下,使用Collectors.toMap聚合流数据,如果key重复时,会报错如下: 明明是key重复,并且错误信息前缀是Duplicate key,后边却是value1。 分析: 查看Collectors.toMap源码如下 toMap最终是调用了Map.merge方法,传入的mergeFunction是throwingMerger直接抛出异常,日志信息使用的是第一个参数u。传入的mapSupplier是HashMap对象(HashMap::new)。所以最终会调用到HashMap.merge。 而在HashMap.merge中,对于mergeFunction的应用如下: 在HashMap.merge的语义中,mergeFunction用于合并value,比如对于key的计数,可以使用map.merge(key, 1, Integer::sum)。若不存在则置1,存在则+1。这里的入参是oldValue和newValue。 所以最终传递给throwingMerger的两个参数就不是k-v了。所以报错的所谓Duplicate key其实是oldValue。 解决: 保证toMap的key不重复调用重载方法,主动指定当key重复时,需要做的合并操作。 高版本JDK的修复措施 这个问题在后续版本中得到修复,比如在JDK 11中的处理。 https://bugs.java.com/bugdatabase/view_bug.do?bug_id=8178142 https://bugs.openjdk.java.net/browse/JDK-8040892l 参考资料: https://stackoverflow.com/questions/32312876/ignore-duplicates-when-producing-map-using-streams https://stackoverflow.com/questions/57311435/java-8-collectors-tomap-duplicate-key