• [新手课堂] 说说你对守护线程的理解
    守护线程:为所有非守护线程提供服务的线程,任何一个守护线程都是在整个JVM中所有非守护线程的保姆。守护线程类似于整个进程的一个小兵,它的生死无关重要,但是它却依赖整个进行而运行,如果其他线程结束了,没有要执行的了,程序就结束了,守护线程立马就中断了。注意:由于守护线程的终止是自身无法控制的,因此不要把IO、File等重要操作逻辑分配给它,因为它不靠谱。
  • [新手课堂] 进程间的通信方式有哪些?
    管道:管道是一种半双工的通信方式,数据只能单向流动,而且只能在具有亲缘关系的进程间使用。进程的亲缘关系通常是指父子进程关系。命名管道FIFO:未命名的管道只能在两个相关的进程之间通信,通过命名管道FIFO,不相关的进程也能交换数据。消息队列:消息队列是消息的链表,具有特定的格式,存放在内存中并由消息队列标识符标识。消息队列允许一个或多个进程向它写入与读取消息。管道和命名管道的通信数据都是先进先出原则,消息队列可以实现消息的随机查询,消息不一定要以先进先出的次序读取,也可以按消息的类型读取,比FIFO更有优势。共享内存:共享内存是允许一个或多个进程共享的一块内存区域。信号量:信号量是一个计数器,可以用来控制多个进程对共享资源的访问。通常作为一种锁机制,防止某进程正在访问共享资源时,其他进程也访问该资源。
  • [问题求助] 【Context】stream只能用于当前Context下吗
        1. 目前做C++应用层开发,遇到一个问题,寻求专家帮助;    2. 文档对于Context的描述如下:        Context作为一个容器,管理了所有对象(包括Stream、Event、设备内存等)的生命周期。不同Context的Stream、不同Context的Event是完全隔离的,无法建立同步等待关系。    3. 问题:        我查看了公共库Atlasutils以及sample示例中的源码,发现DVPP运行类只会实例化一次,同时会创建一个stream(不创建context);假如我起两个线程,创建两个context容器,那DVPP源码内部的stream会跑到哪个线程下呢?        我尝试了在线程起来的时候,直接创建context以及stream,运行没有问题,但这个stream是如何传到dvpp内部我没有搞清楚,请专家解答一下,谢谢。        新问题:不同Context之间的数据能够互相拷贝吗?一个Context可以创建几个stream?
  • [新手课堂] JVM原理学习总结
    这篇总结主要是基于我之前JVM系列文章而形成的的。主要是把重要的知识点用自己的话说了一遍,可能会有一些错误,还望见谅和指点。谢谢#更多详细内容可以查看我的专栏文章:深入理解JVM虚拟机https://blog.csdn.net/column/details/21960.htmlJVM介绍和源码首先JVM是一个虚拟机,当你安装了jre,它就包含了jvm环境。JVM有自己的内存结构,字节码执行引擎,因此class字节码才能在jvm上运行,除了Java以外,Scala,groovy等语言也可以编译成字节码而后在jvm中运行。JVM是用c开发的。JVM内存模型内存模型老生常谈了,主要就是线程共享的堆区,方法区,本地方法栈。还有线程私有的虚拟机栈和程序计数器。堆区存放所有对象,每个对象有一个地址,Java类jvm初始化时加载到方法区,而后会在堆区中生成一个Class对象,来负责这个类所有实例的实例化。栈区存放的是栈帧结构,栈帧是一段内存空间,包括参数列表,返回地址,局部变量表等,局部变量表由一堆slot组成,slot的大小固定,根据变量的数据类型决定需要用到几个slot。方法区存放类的元数据,将原来的字面量转换成引用,当然,方法区也提供常量池,常量池存放-128到127的数字类型的包装类。字符串常量池则会存放使用intern的字符串变量。JVM OOM和内存泄漏这里指的是oom和内存泄漏这类错误。oom一般分为三种,堆区内存溢出,栈区内存溢出以及方法区内存溢出。堆内存溢出主要原因是创建了太多对象,比如一个集合类死循环添加一个数,此时设置jvm参数使堆内存最大值为10m,一会就会报oom异常。栈内存溢出主要与栈空间和线程有关,因为栈是线程私有的,如果创建太多线程,内存值超过栈空间上限,也会报oom。方法区内存溢出主要是由于动态加载类的数量太多,或者是不断创建一个动态代理,用不了多久方法区内存也会溢出,会报oom,这里在1.7之前会报permgem oom,1.8则会报meta space oom,这是因为1.8中删除了堆中的永久代,转而使用元数据区。内存泄漏一般是因为对象被引用无法回收,比如一个集合中存着很多对象,可能你在外部代码把对象的引用置空了,但是由于对象还被集合给引用着,所以无法被回收,导致内存泄漏。测试也很简单,就在集合里添加对象,添加完以后把引用置空,循环操作,一会就会出现oom异常,原因是内存泄漏太多了,导致没有空间分配新的对象。常见调试工具命令行工具有jstack jstat jmap 等,jstack可以跟踪线程的调用堆栈,以便追踪错误原因。jstat可以检查jvm的内存使用情况,gc情况以及线程状态等。jmap用于把堆栈快照转储到文件系统,然后可以用其他工具去排查。visualvm是一款很不错的gui调试工具,可以远程登录主机以便访问其jvm的状态并进行监控。class文件结构class文件结构比较复杂,首先jvm定义了一个class文件的规则,并且让jvm按照这个规则去验证与读取。开头是一串魔数,然后接下来会有各种不同长度的数据,通过class的规则去读取这些数据,jvm就可以识别其内容,最后将其加载到方法区。JVM的类加载机制jvm的类加载顺序是bootstrap类加载器,extclassloader加载器,最后是appclassloader用户加载器,分别加载的是jdk/bin ,jdk/ext以及用户定义的类目录下的类(一般通过ide指定),一般核心类都由bootstrap和ext加载器来加载,appclassloader用于加载自己写的类。双亲委派模型,加载一个类时,首先获取当前类加载器,先找到最高层的类加载器bootstrap让他尝试加载,他如果加载不了再让ext加载器去加载,如果他也加载不了再让appclassloader去加载。这样的话,确保一个类型只会被加载一次,并且以高层类加载器为准,防止某些类与核心类重复,产生错误。defineclass findclass和loadclass类加载classloader中有两个方法loadclass和findclass,loadclass遵从双亲委派模型,先调用父类加载的loadclass,如果父类和自己都无法加载该类,则会去调用findclass方法,而findclass默认实现为空,如果要自定义类加载方式,则可以重写findclass方法。常见使用defineclass的情况是从网络或者文件读取字节码,然后通过defineclass将其定义成一个类,并且返回一个Class对象,说明此时类已经加载到方法区了。当然1.8以前实现方法区的是永久代,1.8以后则是元空间了。JVM虚拟机字节码执行引擎jvm通过字节码执行引擎来执行class代码,他是一个栈式执行引擎。这部分内容比较高深,在这里就不献丑了。编译期优化和运行期优化编译期优化主要有几种1 泛型的擦除,使得泛型在编译时变成了实际类型,也叫伪泛型。2 自动拆箱装箱,foreach循环自动变成迭代器实现的for循环。3 条件编译,比如if(true)直接可得。运行期优化主要有几种1 JIT即时编译Java既是编译语言也是解释语言,因为需要编译代码生成字节码,而后通过解释器解释执行。但是,有些代码由于经常被使用而成为热点代码,每次都编译太过费时费力,干脆直接把他编译成本地代码,这种方式叫做JIT即时编译处理,所以这部分代码可以直接在本地运行而不需要通过jvm的执行引擎。2 公共表达式擦除,就是一个式子在后面如果没有被修改,在后面调用时就会被直接替换成数值。3 数组边界擦除,方法内联,比较偏,意义不大。4 逃逸分析,用于分析一个对象的作用范围,如果只局限在方法中被访问,则说明不会逃逸出方法,这样的话他就是线程安全的,不需要进行并发加锁。1JVM的垃圾回收1 GC算法:停止复制,存活对象少时适用,缺点是需要两倍空间。标记清除,存活对象多时适用,但是容易产生随便。标记整理,存活对象少时适用,需要移动对象较多。2 GC分区,一般GC发生在堆区,堆区可分为年轻代,老年代,以前有永久代,现在没有了。年轻代分为eden和survior,新对象分配在eden,当年轻代满时触发minor gc,存活对象移至survivor区,然后两个区互换,等待下一场gc,当对象存活的阈值达到设定值时进入老年代,大对象也会直接进入老年代。老年代空间较大,当老年代空间不足以存放年轻代过来的对象时,开始进行full gc。同时整理年轻代和老年代。一般年轻代使用停止复制,老年代使用标记清除。3 垃圾收集器serial串行parallel并行它们都有年轻代与老年代的不同实现。然后是scanvage收集器,注重吞吐量,可以自己设置,不过不注重延迟。cms垃圾收集器,注重延迟的缩短和控制,并且收集线程和系统线程可以并发。cms收集步骤主要是,初次标记gc root,然后停顿进行并发标记,而后处理改变后的标记,最后停顿进行并发清除。g1收集器和cms的收集方式类似,但是g1将堆内存划分成了大小相同的小块区域,并且将垃圾集中到一个区域,存活对象集中到另一个区域,然后进行收集,防止产生碎片,同时使分配方式更灵活,它还支持根据对象变化预测停顿时间,从而更好地帮用户解决延迟等问题。
  • [技术干货] Linux查看系统信息的常用命令
    使用命令查看Linux系统版本、内核版本、CPU型号、硬盘空间、内存信息、网络信息。1、查看系统版本:lsb_release -a2、查看内核版本:uname -a3、查看cpu型号:cat /proc/cpuinfo4、查看硬盘空间情况:df -h5、查看内存信息:free -m 6、查看网络信息:ifconfig常用的查看linux环境信息的命令设进程号为pid,端口号为port。1.CPU占用率命令:top -p pid,%CPU一项,单位为百分比。2.物理内存使用量命令:top -p pid,RES一项,单位为KB。3.虚拟内存使用量命令:top -p pid,VIRT一项,单位为KB。4.进程队列长度命令:top,load average一项,三个值分别代表最近1分钟、5分钟、15分钟进程队列的平均长度。5.打开的socket及其状态命令:netstat -an | grep port,第四列代表源IP,第五列代表目的IP,第六列代表状态(如LISTEN、ESTABLISHED、TIME_WAIT等)。替代命令:ss,需要安装几个内核模块,在连接较多时性能比netstat好很多。安装内核模块命令:insmod /lib/modules/2.6.18-164.el5/kernel/net/ipv4/inet_diag.koinsmod /lib/modules/2.6.18-164.el5/kernel/net/ipv4/tcp_diag.koinsmod /lib/modules/2.6.18-1.2.0.0-xen/kernel/net/ipv4/inet_diag.koinsmod /lib/modules/2.6.18-1.2.0.0-xen/kernel/net/ipv4/tcp_diag.ko6. I/O使用率命令:iostat -x,%util一项,单位为百分比。7.磁盘读写速率命令:iostate -k,kB_read/s表示磁盘每秒读出多少KB数据,kB_wrtn/s表示磁盘每秒写入多少KB数据。8.最近使用的系统调用及其耗费时间命令:strace -f -tt -T -p pid,第一项代表系统调用名称,最后一项代表该调用耗费的时间,单位为秒。9.打开的文件描述符数量命令:ls /proc/pid/fd | wc -l。10.进程地址空间命令:pmap -d pid。11.环境变量命令:cat /proc/pid/environ。12.进程各模块的内存使用情况命令:cat /proc/pid/smaps。13.进程状态信息命令:cat /proc/pid/status,State代表进程状态(运行、睡眠、僵尸等),SleepAVG代表进程睡眠时间的比例,Tgid代表线程组号,PPid代表父进程号,FDSize代表文件描述符的最大个数,VmSize代表进程虚拟地址空间的大小,VLck代表进程锁住的物理内存的大小,锁住的物理内存无法交换到磁盘,VmRSS代表进程正在使用的物理内存的大小,VmData代表进程数据段的大小,VmStk代表进程在用户态的栈的大小,VmExe代表进程拥有的可执行虚拟内存的大小,代码段,不包括使用的库,VmLib代表映射到进程地址空间的库的大小,以上单位均为KB,SigQ代表待处理信号的数量,SigBlk代表被阻塞的信号,SigIgn代表被忽略的信号,SigCgt代表被捕获的信号。14.进程的线程数量命令:ls /proc/pid/task | wc -l。15.启动该进程的命令行命令:cat /proc/pid/cmdline。16.列出当前系统打开了哪些文件以及分别由哪个进程打开命令:sudo lsof -n17.使程序主动生成core dump文件命令:gdb -p pid -batch -ex "generate-core-file"
  • [优秀实践] swap分区过小导致系统异常案例总结
    1. 问题现象在某数据库测试的时候发现执行linux基础命令报错:-bash: fork: Cannot allocate memory重启后,问题不再出现。与此同时,客户也反馈测试过程中会经常出现数据库进程少了的现象。 2. 问题分析网上碰到的问题都是说是由于进程数满了,这个可能性不大,因为系统的进程最大数已经设置成32768了,已经很大了。由于出现问题后,无法执行命令查看系统状态。首先想到的办法是查看message日志。通过BMC登录后,收集到message日志查看后发现有crash的现象:从日志上可以看出,系统内存不够用了,所以kill了数据库进程,这也能够解释得了客户发现的数据库进程变少的现象了。从这个日志往上看,发现了另外一个关键信息:可以看出swap空间已经被用光了,出发了OOM,导致了系统出现了异常。对比这次测试跟之前的测试,数据库使用的内存大小都是一样的,发现这次开辟的SWAP空间较小。之前的SWAP分区有150G,而这次才开了4G,在内存紧张的情况下,很容易就出现了OOM。3. 解决方法由于客户不愿意修改数据库内存,认为当前的数据库内存配置是最优的,所以我们动态调整了SWAP分区大小。创建空文件# dd if=/dev/zero of=/home/swap bs=1G count=200挂载到swap空间mkswap /home/swap加载swap空间/sbin/swapon /home/swap以上命令重启后会失效,如果想让修改永久生效则需要修改配置:设置开机自动挂载,修改/etc/fstab/home/swap                       swap                    swap    defaults        0 0 按照这个方式修改后,再也没有出现过此问题了。
  • [优秀实践] 裸盘IO优化案例分享
    1 问题背景同一型号SSD裸盘性能测试,4k随机读写测试(单jobs、iodepth为32),TaiShan200服务器性能不符合预期,需要进行调优。 2 原因分析执行测试命令,分析TaiShan系统表现,发现fio线程cpu占用较低,对fio进程绑核后性能表现等没有变化;将fio测试进程增加到4个,使用4个cpu测试,iops提升很小,cpu占用率更低,说明cpu没到瓶颈。iostat分析,TaiShan的await保持在58,也就是IO请求从下发到完成的耗时较长,由于是裸盘测试不经过文件系统,所以可能与cpu的超频、驱动实现有关。分析热点函数,发现TaiShan的tick_nohz_idle_enter,tick_nohz_idle_exit两个函数cpu占用较高,尝试给系统启动命令加上nohz=off,加上后此两个热点函数消失,但是性能只有小幅提升。在iBMC排查raid配置,发现TaiShan的测试盘一个盘自己组了raid0,为排除影响将磁盘raid模式调整为jbod直通模式,性能没有提升。测试前erase硬盘除去脏数据可能导致的不同程度写放大影响,性能还是没有提升。更换TaiShan测试盘,排除硬件本身差异,性能没有提升。TaiShan使用华为高性能SAS SSD盘测试,4k随机读写iops比当前使用的测试盘高几倍,cpu占用很高,确认主要瓶颈不在cpu。Blktrace工具分析IO请求具体的耗时占比,发现D2C占比高达99%,确认耗时主要在驱动和硬件。D2C表示IO请求被driver提交给硬件,经过HBA、电缆(光纤、网线等)、交换机(SAN或网络)、最后到达存储设备,设备完成IO请求之后再把结果发回这段路径的耗时。lsscsi发现TaiShan服务器有expander芯片。通过raid卡管理工具确认,测试盘接在expander背板,expander背板与raid卡相接,也就是IO请求先下发到raid卡,raid卡发送到expander芯片,expander芯片再发送到硬盘,理论上expander芯片会带来性能损耗。家里实验室验证硬盘背板带expander芯片和不带expander芯片场景下4k随机读写性能,的确有较大差距。3 解决方案调整TaiShan硬盘方面硬件配置,选用不带expander芯片的硬盘背板型号。4 总结裸盘IO由于不经过文件系统,io路径短,如果硬盘性能低不能使cpu达到瓶颈,则在其他硬件配置一致的情况下不同cpu测试性能是持平的;如果硬盘属于高性能硬盘,cpu占用极高,则需通过添加测试进程数,增加使用的cpu个数以达到硬盘瓶颈。需要注意的是,裸盘测试需要确保对比机器的硬盘接入方式是相同的,比如都是cpu直出、都是raid卡直通、都接在expander硬盘背板上;确保raid配置是相同的,比如都是raid1或者都是jbod模式
  • [优秀实践] 虚拟化场景IO性能优化案例分享
    1 问题背景虚拟机(8C16G)裸盘(预分配80G)fio 4k随机写测试(4jobs,iodepth为32)TaiShan 200服务器性能不符合预期,需要进行调优。 2 原因分析执行测试命令,观察TaiShan服务器表现:物理机上,发现kvm进程cpu占用较高,进一步分析发现TaiShan上kvm线程200+;虚拟机上,TaiShan cpu0占用率很高,其中软中断占比高的不合理。怀疑是虚拟机实现方式的问题,发现TaiShan虚拟机测试磁盘类型为virtio-scsi-device(可以使用virtio-block-device,block设备比scsi设备IO路径稍微短些),且当前测试使用的qemu版本较低,可能还不支持armv8新特性。修改TaiShan虚拟机启动参数,将测试盘类型调整为virtio-block-device,性能有小幅提升,物理机上kvm线程数从200+降低到80以内,虚拟机上cpu0的软中断也较低到合理范围,但系统占用又变得很高,说明kvm线程和软中断高是磁盘类型导致,此时是cpu瓶颈。无法给TaiShan虚拟机指定cpu asimd特性,显示参数错误。将虚拟机vcpu一对一绑核,关闭irqbalance,给fio测试程序绑核,几乎没有性能提升。开启大页内存,没有性能提升。分析fio系统调用,发现clock_gettime系统调用耗时有时达到2ms,耗时很高,此客户机操作系统为3,更换为centos7.7,fio系统调用看不到clock_gettime函数,但是性能没有提升。使用原生0.0版本测试,性能有一定提升;进一步重新编译qemu,加上对native aio的支持,性能提升较大。此时,虚拟机上仍然是cpu0 占用特别高,物理机上观测一个vcpu线程cpu占用特别高,qemu主线程cpu占用不高。尝试给磁盘配置iothread卸载qemu主线程压力、对磁盘添加write-cache=on和ioeventfd =on等属性、排查TaiShan物理机上对应SSD的性能表现,没有性能提升。将物理机上SSD的调度策略由默认的cfq调整为noop,性能有一定提升。使用7开始对virtio-blk支持的新特性multiqueues磁盘多队列,性能有较大提升,虚拟机上单个cpu占用特别高的问题解决了。进一步优化,将TaiShan iommu模式配置为passthrough,性能有进一步提升。3 解决方案使用新版qemu如0.0或更高版本,guest os版本也尽量高点使用virtio-blk磁盘多队列特性虚拟机异步io模式配置为native若虚拟化场景无需使用磁盘、网卡直通或SRIOV特性,则可关闭SMMU。4 总结虚拟化场景IO测试,IO路径较长,且不同类型磁盘IO路径也不同。首先需要确认磁盘bus类型(scsi、ide、virtio),保证使用的磁盘文件的协议(nfs、iscsi、本地挂载)是一致的,保证磁盘文件在对应物理机上创建的规则是一样的(预分配、缓存特性等)。如果判断是单核瓶颈,可以尝试使用磁盘多队列特性(针对virtio-blk设备,对qemu、geust操作系统版本有要求);如果是qemu主线程占用高,可以考虑开启iothread分担压力(可能影响动态迁移特性,需调研);设置磁盘异步调用为native会有性能提升,不过也有一定的使用限制(不能用于sparse images,否则在文件系统元数据需要更新时会导致qemu threads阻塞),需了解使用需求。实际测试中,瓶颈分析需要结合虚拟机和物理机两者的系统表现,因为虚拟机的cpu、io等占用信息不一定是真实的(存在vcpu等kvm线程本身被调度和阻塞的问题等)。
  • [技术干货] web场景-Varnish调优
    1.1 Varnish简介Varnish是一款高性能的反向代理缓存服务器,通过缓存静态资源,在基于Web的业务场景可提升站点10+倍的性能,目前仍是CDN(Content Delivery Network)的一个重要实现方案。1.2 Varnish物理机调优1.2.1 Varnish配置参数调优目的:通过调优Varnish的配置文件,可以有效的提高服务器的性能。方法:配置varnish的配置文件/usr/local/varnish/config/default.vcl中的default,vcl_recv,vcl_backend_response,vcl_pipe,vcl_pass,vcl_hash,vcl_hit,vcl_miss,vcl_deliver模块。配置项说明default配置通信IP及端口vcl_recv用于接收和处理请求;当请求到达varnish,通过判断请求的数据来决定如何处理请求vcl_backend_response获得后端主机的响应后调用vcl_pipe用于将请求直接传递至后端主机,并将后端响应原封不动返回给客户端vcl_pass用于将请求直接传递给后端主机,但后端主机的响应并不缓存,而是直接返回给客户端vcl_hash在vcl_recv调用后为请求创建一个hash值时,调用。此hash值将作为varnish中hash表的keyvcl_hit在缓存中找到请求的内容后自动调用vcl_miss在缓存中没有找到请求的内容后自动调用。用于判断是否需要从后端服务器获取内容vcl_deliver将在缓存中找到的请求的内容发送给客户端前调用1.2.2 Varnish亲和性配置目的:对varnish进程进行绑核并启动。方法:以物理机1P场景为例,使用numactl设置CPU与内存的亲和性。numactl -C 0-2,4-10,12-18,20-26,28-34,36-42,44-47 --membind=0,1 /usr/local/varnish/sbin/varnishd -P /tmp/varnish.pid -a :12345 -T 127.0.0.1:6082 -s malloc,100GB -f /usr/local/varnish/config/default.vcl -t 600 -p thread_pool_max=5000 -p thread_pools=10 -p thread_pool_destroy_delay=3 -p timeout_idle=75 -p thread_pool_min=700参数名称参数说明-C进程绑定的CPU core--membind分配进程的内存,其中0,1表示分配的内存在node0和node1上-PVarnish进程pid文件存放路径-a表示Varnish对httpd的监听地址及端口-T设定 varnish 的 telnet 管理地址及其端口-s指定 varnish 缓存存放的方式,常用的方式有:“-s file,<dir_or_file>,<size>”。-f指定 varnish 的配置文件位置-t指定默认的TTL值-p thread_pool_max每个线程池创建的最大线程数-p thread_pools设置线程池个数-p thread_pool_destroy_delay摧毁线程的延迟时间,也就是摧毁之前需要犹豫一下,这个犹豫的时间-p timeout_idle设置保持链接的空闲时长-p thread_pool_min每个线程池创建的最小线程数 
  • [技术干货] web场景-squid调优
    1.1 Squid简介Squid是一个高性能的代理缓存服务器,通过缓存和重用经常请求的网页,减少了带宽并缩短了响应时间。1.2 Squid物理机调优1.2.1 Squid亲和性调优目的:通过调优Squid的配置文件,可以有效的提高服务器的性能。方法:对squid进程进行绑核并启动。在/usr/local/squid/etc/squid.conf中配置cpu_affinity_map参数:workers 43cpu_affinity_mapprocess_numbers=1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38, 39,40,41,42,43,44,45,46,47,48cores=1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37, 38,39,40,41,42,43,44,45,46,47,48Squid启动参数说明参数说明Workers启动的进程数cpu_affinity_map process_numbers进程与CPU的对应关系,如上配置,表示squid的启动的1-48个进程分别对应着1-48号CPU步骤2   一路CPU上启动一个Squid实例。             /usr/local/squid/sbin/squid -s                如需启动两个Squid实例,需新建配置文件squid_2.conf,执行如下命令启动第二个实例:        /usr/local/squid/sbin/squid -f /usr/local/squid/etc/squid_2.conf
  • [技术干货] 异步编程
    什么时候用异步编程在前端编程中(甚至后端有时也是这样),我们在处理一些简短、快速的操作时,例如计算 1 + 1 的结果,往往在主线程中就可以完成。主线程作为一个线程,不能够同时接受多方面的请求。所以,当一个事件没有结束时,界面将无法处理其他请求。现在有一个按钮,如果我们设置它的 onclick 事件为一个死循环,那么当这个按钮按下,整个网页将失去响应。为了避免这种情况的发生,我们常常用子线程来完成一些可能消耗时间足够长以至于被用户察觉的事情,比如读取一个大文件或者发出一个网络请求。因为子线程独立于主线程,所以即使出现阻塞也不会影响主线程的运行。但是子线程有一个局限:一旦发射了以后就会与主线程失去同步,我们无法确定它的结束,如果结束之后需要处理一些事情,比如处理来自服务器的信息,我们是无法将它合并到主线程中去的。为了解决这个问题,JavaScript 中的异步操作函数往往通过回调函数来实现异步任务的结果处理。回调函数回调函数就是一个函数,它是在我们启动一个异步任务的时候就告诉它:等你完成了这个任务之后要干什么。这样一来主线程几乎不用关心异步任务的状态了,他自己会善始善终。实例function print() {    document.getElementById("demo").innerHTML="RUNOOB!";}setTimeout(print, 3000);尝试一下 »这段程序中的 setTimeout 就是一个消耗时间较长(3 秒)的过程,它的第一个参数是个回调函数,第二个参数是毫秒数,这个函数执行之后会产生一个子线程,子线程会等待 3 秒,然后执行回调函数 "print",在命令行输出 "RUNOOB!"。当然,JavaScript 语法十分友好,我们不必单独定义一个函数 print ,我们常常将上面的程序写成:实例setTimeout(function () {    document.getElementById("demo").innerHTML="RUNOOB!";}, 3000);尝试一下 »注意:既然 setTimeout 会在子线程中等待 3 秒,在 setTimeout 函数执行之后主线程并没有停止,所以:实例setTimeout(function () {    document.getElementById("demo1").innerHTML="RUNOOB-1!";}, 3000);document.getElementById("demo2").innerHTML="RUNOOB-2!";console.log("2");尝试一下 »这段程序的执行结果是:RUNOOB-1!RUNOOB-2!异步 AJAX除了 setTimeout 函数以外,异步回调广泛应用于 AJAX 编程。有关于 AJAX 详细请参见:https://www.runoob.com/ajax/ajax-tutorial.htmlXMLHttpRequest 常常用于请求来自远程服务器上的 XML 或 JSON 数据。一个标准的 XMLHttpRequest 对象往往包含多个回调:实例var xhr = new XMLHttpRequest(); xhr.onload = function () {    // 输出接收到的文字数据    document.getElementById("demo").innerHTML=xhr.responseText;} xhr.onerror = function () {    document.getElementById("demo").innerHTML="请求出错";} // 发送异步 GET 请求xhr.open("GET", "https://www.runoob.com/try/ajax/ajax_info.txt", true);xhr.send();尝试一下 »XMLHttpRequest 的 onload 和 onerror 属性都是函数,分别在它请求成功和请求失败时被调用。如果你使用完整的 jQuery 库,也可以更加优雅的使用异步 AJAX:实例$.get("https://www.runoob.com/try/ajax/demo_test.php",function(data,status){    alert("数据: " + data + "\n状态: " + status);});尝试一下 »
  • [问题求助] 【CANN】【数据传输】host侧传数据到device侧memcpy失败,返回507899
    【功能模块】【操作步骤&问题现象】1、关联帖子 https://bbs.huaweicloud.com/forum/forum.php?mod=viewthread&tid=1695832、现在我这边有一个多线程服务,线程E和线程F,线程E用来检测文字,线程F用来识别文字,用python队列通信。存在问题,线程E跑完,线程F在接受到任务后开始从host侧读数据到device侧,出现了错误,返回507899。我已经通过get_context()确定了两个线程的context不同。【截图信息】【日志信息】(可选,上传日志内容或者附件)
  • [问题求助] 【摄像机 SDC】在创建文件和写入文件中利用代码未能成功创建文件和写入文件
    【功能模块】【操作步骤&问题现象】一、已操作出现的问题及现象   我在YOLOv3的代码中利用C的库函数(文件操作函数fopen、fprintf等) (未用咱们的SDC 服务化接口-open,read等,因为open返回的句柄不支持多线程并发访问,所以没用),用C的文件操作函数在SDC中 的/home/sftp_admin/home/admin/的路径下生成日志文件,测试了两种情况:           一是,将文件创建和写入文件操作写在了YUV处理线程的电瓶车进入电梯的报警程序中,当打开调试窗口按钮后,电瓶车出入梯视频开始播放,检测算法是运行的,有目标检测框,和 区域框(如前述视频中所示,报警框是左上角小框,区域框是窗口下方大框,目标检测框就是电瓶车检测框)当电瓶车进入对应区域后,要报警时,因为要将报警信息写入文件了,这个时候,算法就失效了(没有任何框,区域框和目标检测框都没有了,注:区域框在YUV处理线程中代码设置的是一直存在的),最后当电瓶车离开电梯后,那么此时检测程序又正常运行了,又有区域框和目标检测框了,最后后台看了一下  日志文件未生成,我认为  就是   报警日志文件生成程序因为没有执行,阻塞了检测算法,导致算法停掉了,所以后来当不报警时,检测算法又能用了,如视频1gl-对比.mp4,   二是,我在主线程(main函数开头)用代码想直接生成.txt文件,写入文件内容,(iClient的算法商城的调试窗口中的)在区域框就未显示,我也认为算法停掉了,因为日志也没生成,如视频2.mp4;原未加日志文件生成程序的检测视频如1_gl1.mp4;   视频详见压缩包.     注:1.工程代码是在Rpm中,已安装在SDC中(通过SDC的web界面安装)            2. 本测试过程是在SDC上已安装Rpm包的前提下,打开iClient的算法商城的调试窗口按钮,进行目标检测  二、求教        请问一下,在SDC中/usr/下的哪个路径下的文件夹下有读写权限和可以数据掉电不丢失?【截图信息】【日志信息】(可选,上传日志内容或者附件)
  • [问题求助] 【atlas200dk】【日志】我运行的进程的日志怎么配置让他打印到atlas200的日志系统里面,这个文件在哪里找
    例如我进程打印了syslog的一些日志,我怎么让他写入到atlas200的日志系统里,然后这个文件在哪里找出来查看打印的日志
  • [运维管理] 巡检后发现dentry内存的告警需要怎么排查时那个进程导致的?
    【操作步骤&问题现象】执行slabtop -o 2>/dev/null | grep "dentry" | awk '{print $(NF-1)}'命令,检查Dentry内存超过10GB(排查频繁操作大量文件的进程,找出问题根因,解决dentry占用内存问题),怎么排查是那个进程导致的?
总条数:756 到第
上滑加载中