• 关于

    内存位置是什么

    的搜索结果

问题

我的配置CPU双核两G内存宽带5M为什么网站还是卡卡的

红色鲨鱼 2019-12-01 22:01:42 6253 浏览量 回答数 10

回答

C标准库中的函数原型是void memcpy(void str1, const void *str2, size_t n);参考地址:地址的2.14.4 章节为什么一定要转换为(char *)?文档说的很清楚了Copies n characters from str2 to str1. If str1 and str2 overlap the behavior is undefined.Returns the argument str1.函数的返回值是void,但是这个函数操作之后,新的string的值应该是str1,也就是说,从str2所指的内存地址的起始位置开始拷贝n个字节到目标str1所指的内存地址的起始位置中,本质上是改变了str1指向的值.所以,如果不是char *,你如何改变str1的值?

a123456678 2019-12-02 02:41:26 0 浏览量 回答数 0

回答

ps变量的使用有问题吧,在二重循环里用ps取结果集,但在三重循环里又用ps插入数据,而且每次三重循环在创建新ps前都没有close。回复 @nubo:你用的什么工具?发现问题了,是没有创建新的ps和close掉的原因。谢谢了!很多靠眼睛难找的bug,用工具监测下很容易就发现了。尝试每次少取点儿,正则的确很占内存,尤其在正则不是那么高效的情况下回复 @布谷鸟:这个位置应该是MD5加密的原字符串过长需要较多内存造成的,但异常根本原因还是其他地方占用了绝大部分内存。是不是字符串的编码出问题了,报错位置的类这是干嘛的?atsun.nio.cs.ext.GBK.newEncoder(GBK.java:36)为什么内存会不断增长呢?我每次匹配完了,不是正则所占内存会被回收吗? 、目测下来,很有可能是数据库连接过大消耗完了内存! 曾经我的项目也出现过此问题!加入开源的proxool就ok了! 建议楼主项目加入缓存! 是在不行,用eclipse提供的堆栈跟踪tool看看!因为我每次事务下来都关闭了结果集、PreparedStatement和数据库连接,而且我每次取连接是用的连接池。不知道是不是因为连接过多的原因? 引用来自“Beyond-Bit”的答案 、目测下来,很有可能是数据库连接过大消耗完了内存! 曾经我的项目也出现过此问题!加入开源的proxool就ok了! 建议楼主项目加入缓存! 是在不行,用eclipse提供的堆栈跟踪tool看看!全局只采用一个连接的方法已经测试过了,问题是同样的。因为就数据情况而言这段代码始终都不会报SQL异常,所以没有写finally,前期的代码中已经排除掉SQL插入的异常了,现在每次关闭连接是没有问题的。visualvm 你可以用 Java自带的工具visualvm查看一下内存使用情况 看看具体是哪里出了问题   很明显是拼接string啊,用stringbuilder 同意楼上string,非常明显了,string类型,还是循环

爱吃鱼的程序员 2020-06-22 19:29:59 0 浏览量 回答数 0

阿里云爆款特惠专场,精选爆款产品低至0.95折!

爆款ECS云服务器8.1元/月起,云数据库低至1.5折,限时抢购!

回答

不晓得你看的什么书,我不大明白这个地址值和数据值的定义一个左值可能是一个函数或者对象。 一个右值可能是一个对象、临时对象或者临时对象的子对象、或者不是对象的值 具体可以参阅标准3.10小节,讲的就是左值与右值至于5所在的内存位置,对于这种整数来说,对于编译器来讲一般都是使用立即数直接赋值,5并没有临时存在于什么地方,就像是把5放在a所在的栈上的位置,那么这句话就是 a = 5;如果是字符串,有可能存储在其他位置比如代码段,然后拷贝过来,这样就是 str = "123143";

杨冬芳 2019-12-02 02:27:36 0 浏览量 回答数 0

问题

第一次用云主机上手真难,还没有思路呢

7dayz 2019-12-01 20:57:57 8306 浏览量 回答数 6

回答

流读取了就没了。######回复 @打哭你 :流对应的是数据,数据放在内存中,有的是部分放在内存中。read 一次标记一次当前位置(mark position),第二次read就从标记位置继续读(从内存中copy)数据。 所以这就是为什么读了一次第二次是空了。 怎么让它不为空呢?只要inputstream 中的pos 变成0就可以重写读取当前内存中的数据,但很遗憾,没找到有修改pos 的api。######好像是这样的.....这是为什么呢?百度也搜索不到相关内容###### 把拦截器去掉能接收到吗?    为什么不用@RequestParam ? ######json请求.....没用br.read()这个操作就可以接收到...######我的用json数据作为请求数据。接收的时候用@RequestParam Map<String ,Object > map   直接接收######嗯嗯....用@RequestBody好像流读取....读一次就没有了....貌似这样...######既然你用了spring MVC要做数据处理,就利用它的 HttpMessageConverter吧,不要写那种拦截器了。######  有一种方式做验证就是通过Aop,对controller的方法做切面。 在切面里面可以拿到方法的参数, @Around(" **** ") public Object doBasicProfiling(ProceedingJoinPoint pjp) throws Throwable ProceedingJoinPoint pjp Object[] args = pjp.getArgs(); 通过 HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest(); HttpServletResponse response = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getResponse(); 可以拿到当前线程使用的request和response再进行校验和处理即可

爱吃鱼的程序员 2020-06-02 12:00:47 0 浏览量 回答数 0

回答

流读取了就没了。######回复 @打哭你 :流对应的是数据,数据放在内存中,有的是部分放在内存中。read 一次标记一次当前位置(mark position),第二次read就从标记位置继续读(从内存中copy)数据。 所以这就是为什么读了一次第二次是空了。 怎么让它不为空呢?只要inputstream 中的pos 变成0就可以重写读取当前内存中的数据,但很遗憾,没找到有修改pos 的api。######好像是这样的.....这是为什么呢?百度也搜索不到相关内容###### 把拦截器去掉能接收到吗?    为什么不用@RequestParam ? ######json请求.....没用br.read()这个操作就可以接收到...######我的用json数据作为请求数据。接收的时候用@RequestParam Map<String ,Object > map   直接接收######嗯嗯....用@RequestBody好像流读取....读一次就没有了....貌似这样...######既然你用了spring MVC要做数据处理,就利用它的 HttpMessageConverter吧,不要写那种拦截器了。######  有一种方式做验证就是通过Aop,对controller的方法做切面。 在切面里面可以拿到方法的参数, @Around(" **** ") public Object doBasicProfiling(ProceedingJoinPoint pjp) throws Throwable ProceedingJoinPoint pjp Object[] args = pjp.getArgs(); 通过 HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest(); HttpServletResponse response = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getResponse(); 可以拿到当前线程使用的request和response再进行校验和处理即可

爱吃鱼的程序员 2020-05-29 17:55:32 0 浏览量 回答数 0

回答

流读取了就没了。######回复 @打哭你 :流对应的是数据,数据放在内存中,有的是部分放在内存中。read 一次标记一次当前位置(mark position),第二次read就从标记位置继续读(从内存中copy)数据。 所以这就是为什么读了一次第二次是空了。 怎么让它不为空呢?只要inputstream 中的pos 变成0就可以重写读取当前内存中的数据,但很遗憾,没找到有修改pos 的api。######好像是这样的.....这是为什么呢?百度也搜索不到相关内容###### 把拦截器去掉能接收到吗?    为什么不用@RequestParam ? ######json请求.....没用br.read()这个操作就可以接收到...######我的用json数据作为请求数据。接收的时候用@RequestParam Map<String ,Object > map   直接接收######嗯嗯....用@RequestBody好像流读取....读一次就没有了....貌似这样...######既然你用了spring MVC要做数据处理,就利用它的 HttpMessageConverter吧,不要写那种拦截器了。######  有一种方式做验证就是通过Aop,对controller的方法做切面。 在切面里面可以拿到方法的参数, @Around(" **** ") public Object doBasicProfiling(ProceedingJoinPoint pjp) throws Throwable ProceedingJoinPoint pjp Object[] args = pjp.getArgs(); 通过 HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest(); HttpServletResponse response = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getResponse(); 可以拿到当前线程使用的request和response再进行校验和处理即可

优选2 2020-06-05 13:11:19 0 浏览量 回答数 0

回答

如果评论不多,放在一起的设计很合适,楼上说得很好。但是如果评论多了,问题就来了。最重要的有两基本出发点: 1. 硬盘太慢; 2. 只要数据在内存里,就没问题。1.find数据特别大了之后,在磁盘上读好多数据,因为Memory Mapped File都会放在内存里,可是我们只需要里面的一小部分,最主要的问题是可能OS会把别的数据换页到硬盘上。单就列出文章列表来说,内存就没有被有效地利用。2.insert在磁盘文件上,如果一个document一直长啊长,好多次,这不是一个好事。因为 如果新加入数据后,比如加了一个新评论,document变大了,原来的地方放不下了,就要找新的地方,以前的空洞会被重新利用。但是问题是,document位置变了,所有跟它有关的索引都要变。如果你还有个数组上的索引,比如发表评论的用户名,那更新的索引就跟这个数组长度成线性关系。综上,评论特别多的时候,会影响性能。总结,schema设计要考虑1.数据规模,经常访问的数据只要在内存里,对访问来说没什么问题。上面第一条find里提到的内存利用不充分,其实不是大问题。因为热门文章的评论总有不少人看,放内存里也不错。如果document一直长呀长,MongoDB会自动地在分配磁盘空间时多分配一些。2.与Access Pattern相适应。写评论相对看文章看评论,太小了,Twitter的数据是平均发tweet 5K/s, 读timeline 300K/s. 60倍呀!只要读请求在内存里能满足就好了。用MongoDB就可以不用另搞caching了。不是访问真得特别大,写特别多这样极端的情况,都好说。真得到了那一天,MongoDB的sharding就派上用场了。3.开发方便 产品的成本不仅仅是机器硬件、网络的成本,更重要的是程序员的开发成本,工资都那么高……所以,写着快捷方便,不容易出错也是很重要的一点,对不?这也就解释了为什么MongoDB文档模型的灵活性广受好评了。话说回来了,我觉得绝大多数这类应用的评论都不会过百吧……这时候单文档就发挥出优势了,几百评论都没问题的,题主的问题就不是问题了。希望题主的应用能突破这个数……

蛮大人123 2019-12-02 01:46:52 0 浏览量 回答数 0

回答

在内存中两个数组的内存分配应该是这样的:'?' '?' '?' 'h' 'e' 'l' 'l' 'o' 'w' 'o' 'r' 'l' 'd' '0' (数组b没有初始化所以内容是不确定的)strcpy不知道这个字符数组a有多长,只知道一段字符串遇到'0'就算结束,于是把a全部复制到b了:'h' 'e' 'l' 'l' 'o' 'w' 'o' 'r' 'l' 'd' '0' 'l' 'd' '0'c语言有个观点(哲学?):程序员知道自己正在做什么。于是c中有些地方就没有做安全性检查了。然而后来发现,许多程序员并不清楚自己在做什么,于是就有了strcpy_s。补充下,两个数组的位置是由编译器决定的。比如我用gcc编译的结果是,a、b数组都为helloworld。

杨冬芳 2019-12-02 02:27:33 0 浏览量 回答数 0

回答

 nestedexceptionisjava.lang. NoClassDefFoundError:com.ibm.ws.wstx.handler.WSATGenerator 根据提示信息,应该是少了ibmws依赖的jar包。 回复 @皮皮蟹:我把有关的包儿加到classpath中还是有这个问题,没起作用啊。。。。 @内存不足google下就有了,,,com.ibm.jaxws.thinclient.xxxx.jar那到底是什么包儿呢?!Maven项目?回复 @内存不足:你把引用的jar换个位置,如果都报不同的,说明jar没找到,这种classNotFound也可能是jar冲突呢。。。回复 @rebelman:在,估计是我的classpath的问题,我的classpath写成class_path了,下载我没办法改,我生产环境白天不让动。。。回复 @内存不足:确认jar在lib目录下面吗?Ant

爱吃鱼的程序员 2020-06-14 18:52:40 0 浏览量 回答数 0

回答

1.使用key值前缀来作命名空间虽然说Redis支持多个数据库(默认32个,可以配置更多),但是除了默认的0号库以外,其它的都需要通过一个额外请求才能使用。所以用前缀作为命名空间可能会更明智一点。另外,在使用前缀作为命名空间区隔不同key的时候,最好在程序中使用全局配置来实现,直接在代码里写前缀的做法要严格避免,这样可维护性实在太差了。2.创建一个类似 ”registry” 的key用于标记key使用情况为了更好的管理你的key值的使用,比如哪一类key值是属于哪个业务的,你通常会在内部wiki或者什么地方创建一个文档,通过查询这个文档,我们能够知道Redis中的key都是什么作用。与之结合,一个推荐的做法是,在Redis里面保存一个registry值,这个值的名字可以类似于 key_registry 这样的,这个key对应的value就是你文档的位置,这样我们在使用Redis的时候,就能通过直接查询这个值获取到当前Redis的使用情况了。3.注意垃圾回收Redis是一个提供持久化功能的内存数据库,如果你不指定上面值的过期时间,并且也不进行定期的清理工作,那么你的Redis内存占用会越来越大,当有一天它超过了系统可用内存,那么swap上场,离性能陡降的时间就不远了。所以在Redis中保存数据时,一定要预先考虑好数据的生命周期,这有很多方法可以实现。比如你可以采用Redis自带的过期时间为你的数据设定过期时间。但是自动过期有一个问题,很有可能导致你还有大量内存可用时,就让key过期去释放内存,或者是内存已经不足了key还没有过期。如果你想更精准的控制你的数据过期,你可以用一个ZSET来维护你的数据更新程度,你可以用时间戳作为score值,每次更新操作时更新一下score,这样你就得到了一个按更新时间排序序列串,你可以轻松地找到最老的数据,并且从最老的数据开始进行删除,一直删除到你的空间足够为止。4.设计好你的Sharding机制Redis目前并不支持Sharding,但是当你的数据量超过单机内存时,你不得不考虑Sharding的事(注意:Slave不是用来做Sharding操作的,只是数据的一个备份和读写分离而已)。所以你可能需要考虑好数据量大了后的分片问题,比如你可以在只有一台机器的时候就在程序上设定一致性hash机制,虽然刚开始所有数据都hash到一台机器,但是当你机器越加越多的时候,你就只需要迁移少量的数据就能完成了。5.不要有个锤子看哪都是钉子当你使用Redis构建你的服务的时候,一定要记住,你只是找了一个合适的工具来实现你需要的功能。而不是说你在用Redis构建一个服务,这是很不同的,你把Redis当作你很多工具中的一个,只在合适使用的时候再使用它,在不合适的时候选择其它的方法。

落地花开啦 2019-12-02 01:48:56 0 浏览量 回答数 0

回答

一。zval、引用计数、变量分离、写时拷贝我们一步步来理解1、php语言特性PHP是脚本语言,所谓脚本语言,就是说PHP并不是独立运行的,要运行PHP代码需要PHP解析器,用户编写的PHP代码最终都会被PHP解析器解析执行PHP的执行是通过Zend engine(ZE, Zend引擎),ZE是用C编写的用户编写的PHP代码最终都会被翻译成PHP的虚拟机ZE的虚拟指令(OPCODES)来执行也就说最终会被翻译成一条条的指令既然这样,有什么结果和你预想的不一样,查看php源码是最直接最有效的 2、php变量的存储结构在PHP中,所有的变量都是用一个结构zval结构来保存的,在Zend/zend.h中可以看到zval的定义:zval结构包括:① value —— 值,是真正保存数据的关键部分,定义为一个联合体(union)② type —— 用来储存变量的类型 ③ is_ref —— 下面介绍④ refcount —— 下面介绍 声明一个变量$addr="北京";PHP内部都是使用zval来表示变量的,那对于上面的脚本,ZE是如何把addr和内部的zval结构联系起来的呢?变量都是有名字的(本例中变量名为addr)而zval中并没有相应的字段来体现变量名。PHP内部肯定有一个机制,来实现变量名到zval的映射在PHP中,所有的变量都会存储在一个数组中(确切的说是hash table)当你创建一个变量的时候,PHP会为这个变量分配一个zval,填入相应的信息,然后将这个变量的名字和指向这个zval的指针填入一个数组中。当你获取这个变量的时候,PHP会通过查找这个数组,取得对应的zval 注意:数组和对象这类复合类型在生成zval时,会为每个单元生成一个zval3、我们经常说每个变量都有一个内存地址,那这个zval和变量的内存地址,这俩有什么关系吗?定义一个变量会开辟一块内存,这块内存好比一个盒子,盒子里放了zval,zval里保存了变量的相关信息,需要开辟多大的内存,是由zval所占空间大小决定的zval是内存对象,垃圾回收的时候会把zval和内存地址(盒子)分别释放掉 4、引用计数、变量分离、写时拷贝zval中的refcount和is_ref还没有介绍,我们知道PHP是一个长时间运行的服务器端脚本。那么对于它来说,效率和资源占用率是一个很重要的衡量标准,也就是说,PHP必须尽量减少内存占用率。考虑下面这段代码:第一行代码创建了一个字符串变量,申请了一个大小为9字节的内存,保存了字符串“laruence”和一个NULL(0)的结尾第二行定义了一个新的字符串变量,并将变量var的值“复制”给这个新的变量第三行unset了变量var 这样的代码是很常见的,如果PHP对于每一个变量赋值都重新分配内存,copy数据的话,那么上面的这段代码就要申请18个字节的内存空间,为了申请新的内存,还需要cpu执行某些计算,这当然会加重cpu的负载而我们也很容易看出来,上面的代码其实根本没有必要申请两份空间,当第三句执行后,$var被释放了,我们刚才的设想(申请18个字节内存空间)突然变的很滑稽,这次复制显得好多余。如果早知道$var不用了,直接让$var_dup用$var的内存不就行了,还复制干嘛?如果你觉得9个字节没什么,那设想下如果$var是个10M的文件内容,或者20M,是不是我们的计算机资源消耗的有点冤枉呢?呵呵,PHP的开发者也看出来了: 刚才说了,PHP中的变量是用一个存储在symbol_table中的符号名,对应一个zval来实现的,比如对于上面的第一行代码,会在symbol_table中存储一个值“var”,对应的有一个指针指向一个zval结构,变量值“laruence”保存在这个zval中,所以不难想象,对于上面的代码来说,我们完全可以让“var”和“var_dup”对应的指针都指向同一个zval就可以了(额,鸟哥一会说hash table,一会说symbol_table,暂且理解为symbol_table是hash table的子集) PHP也是这样做的,这个时候就需要介绍一下zval结构中的refcount字段了refcount,引用计数,记录了当前的zval被引用的次数(这里的引用并不是真正的 & ,而是有几个变量指向它)比如对于代码:第一行,创建了一个整形变量,变量值是1。 此时保存整形1的这个zval的refcount为1第二行,创建了一个新的整形变量(通过赋值的方式),变量也指向刚才创建的zval,并将这个zval的refcount加1,此时这个zval的refcount为2所以,这个时候(通过值传递的方式赋值给别的变量),并没有产生新的zval,两个变量指向同一zval,通过一个计数器来共用zval及内存地址,以达到节省内存空间的目的当一个变量被第一次创建的时候,它对应的zval结构的refcount的值会被初始化为1,因为只有这一个变量在用它。但是当你把这个变量赋值给别的变量时,refcount属性便会加1变成2,因为现在有两个变量在用这个zval结构了 PHP提供了一个函数可以帮助我们了解这个过程debug_zval_dump输出:long(1) refcount(2)long(1) refcount(3)如果你奇怪 ,var的refcount应该是1啊?我们知道,对于简单变量,PHP是以传值的形式传参数的。也就是说,当执行debug_zval_dump($var)的时候,$var会以传值的方式传递给debug_zval_dump,也就是会导致var的refcount加1,所以只要能看到,当变量赋值给一个变量以后,能导致zval的refcount加1这个结果即可现在我们回头看上面的代码, 当执行了最后一行unset($var)以后,会发生什么呢?unset($var)的时候,它删除符号表里的$var的信息,准备清理它对应的zval及内存空间,这时它发现$var对应的zval结构的refcount值是2,也就是说,还有另外一个变量在一起用着这个zval,所以unset只需把这个zval的refcount减去1就行了上代码:输出:string(8) "laruence" refcount(2) 但是,对于下面的代码呢?很明显在这段代码执行以后,$var_dup的值应该还是“laruence”,那么这又是怎么实现的呢?这就是PHP的copy on write机制(简称COW):PHP在修改一个变量以前,会首先查看这个变量的refcount,如果refcount大于1,PHP就会执行一个分离的过程(在Zend引擎中,分离是破坏一个引用对的过程)对于上面的代码,当执行到第三行的时候,PHP发现$var想要改变,并且它指向的zval的refcount大于1,那么PHP就会复制一个新的zval出来,改变其值,将改变的变量指向新的zval(哪个变量指向新复制的zval其实已经无所谓了),并将原zval的refcount减1,并修改symbol_table里该变量的指针,使得$var和$var_dup分离(Separation)。这个机制就是所谓的copy on write(写时复制,这里的写包括普通变量的修改及数组对象里的增加、删除单元操作)如果了解了is_ref之后,上面说的并不严谨 上代码测试:输出:long(1) refcount(2)string(8) "laruence" refcount(2) 现在我们知道,当使用变量复制的时候 ,PHP内部并不是真正的复制,而是采用指向相同的zval结构来节约开销。那么,对于PHP中的引用,又是如何实现呢?这段代码结束以后,$var也会被间接的修改为1,这个过程称作(change on write:写时改变)那么ZE是怎么知道,这次的复制不需要Separation呢?这个时候就要用到zval中的is_ref字段了:对于上面的代码,当第二行执行以后,$var所代表的zval的refcount变为2,并且设置is_ref为1到第三行的时候,PHP先检查var_ref对应的zval的is_ref字段(is_ref 表示该zval是否被&引用,仅表示真或假,就像开关的开与关一样,zval的初始化情况下为0,即非引用),如果为1,则不分离,直接更改(否则需要执行刚刚提到的zval分离),更改共享的zval实际上也间接更改了$var的值,因为引擎想所有的引用变量都看到这一改变php源码做了这样一个判断,大体逻辑示意如下:如果这个zval中的if_ref为1(即被引用),或者该zval引用计数小于2任何一种方式:都不会进行分离 尽管已经存在写时复制和写时改变,但仍然还存在一些不能通过is_ref和refcount来解决的问题对于如下的代码,又会怎样呢?这里$var、$var_dup、$var_ref三个变量将共用一个zval结构(其实这是不可能的,一个zval不可能既被&,又被指向),有两个属于change-on-write组合($var和$var_ref),有两个属于copy-on-write组合($var和$var_dup),那is_ref和refcount该怎样工作,才能正确的处理好这段复杂的关系呢?答案是不可能!在这种情况下,变量的值必须分离成两份完全独立的存在当执行第二行代码的时候,和前面讲过的一样,$var_dup 和 $var 指向相同的zval, refcount为2当执行第三行的时候,PHP发现要操作的zval的refcount大于1,则PHP会执行Separation(也就是说php将一个zval的is_ref从0设为1 之前,当然此时refcount还没有增加,会看该zval的refcount,如果refcount>1,则会分离), 将$var_dup分离出去,并将$var和$var_ref做change on write关联。也就是,refcount=2, is_ref=1;所以内存会给变量var_dup 分配出一个新的zval,类型与值同 $var和$var_ref指向的zval一样,是新分配出来的,尽管他们拥有同样的值,但是必须通过两个zval来实现。试想一下,如果三者指向同一个zval的话,改边 $var_dup 的值,那么 $var和$var_ref 也会受到影响,这样就乱套了图解:下面的这段代码在内核中同样会产生歧义,所以需要强制复制!也就是说一个zval不会既被引用,又被指向,必须分离 基于这样的分析,我们就可以让debug_zval_dump出refcount为1的结果来:输出:string(8) "laruence" refcount(1) 为什么结果是refcount(1)呢debug_zval_dump()中参数是引用的话,refcount永远为1这两段代码在执行的时候是这样的逻辑:PHP先看变量指向的zval是否被引用,如果是引用,则不再产生新的zval甭管哪个变量引用了它,比如有个变量$a被引用了,$b=&$a,就算自己引用自己$a=&$a,$a所指向的zval都不会被复制,改变其中一个变量的值,另一个值也被改变(写时改变)如果is_ref为0且refcount大于1,改变其中一个变量时,复制新的zval(写时复制) 还有一个知识点需要了解下,就是PHP数组复制的机制复制一个数组,就是把一个数组赋值给一个变量便可。会把数组指针位置一同复制。这里面有两种情况:① 指针位置合法,这时直接复制,无影响② 原数组指针位置非法时(移出界),“新”数组指针会初始化(这里的新为什么要加引号?请看下文),而老的数组指针位置不变,还是false先看例子: 结果:!结果:出现这种情况好像不对?$arr2 难道不是新数组?新数组的数组指针应该重置了啊这里注意了:$arr2 = $arr1 ,在俩变量都没发生写操作时,他们其实引用的是同一个内存地址。在其中一个变量发生写操作后,内存地址会复制一份,发生改变的变量会去引用它,并把数组指针初始化。所以 $arr1 会去引用复制的内存地址,并将指针初始化二。.foreach循环时调用current等函数!结果: 56按照之前说的,foreach先赋值,再移动指针,再执行循环体,第一次结果为2可以理解为什么三次都是2呢?咋就这么2呢?因为current函数是按引用传递的函数 在zval笔记中说了,一个zval不能既被引用,又被指向所以,变量分离,重新拷贝一份数组专门用于current函数 当然,如果数组zval的is_ref为1,则不会拷贝数组了或者:结果:current是引用传参

杨冬芳 2019-12-02 02:26:33 0 浏览量 回答数 0

回答

栈内存一般而言由系统的约束和配置决定,一般来说默认的在1-8M每进程不等。linux和macosx一般可以用ulimit命令调节,但一般仍会受到操作系统的“硬限制”而不能想调多大调多大。 关于系统栈: 系统栈的目的,在于跟踪和追溯函数调用的历史。这里的函数尤其指每个函数都有功能上的意义,即打印出系统栈就能表示出程序有意义的功能分块。使用栈内存做算法,不是不好,不过和系统栈的惯例用法毕竟稍微有一点偏差。层级很深,但每个层级都很类似(单独提取出来,无甚分析价值)的深层搜索,无论是为了防止炸栈,还是为了保持调用栈的简洁可分析,都应当自己建立用户栈。关于栈内存: 栈内存整批进、整批退,不存在碎片和管理问题,性能优于堆内存。但相应的代价就是: 其一,比较少,寸土寸金;其二,函数结束(退栈)之后,栈顶退回函数执行前的位置,则函数中所有局部变量所在的栈内存落在栈外自然销毁。(重要)因此函数内的局部变量,只应当表示函数内部执行到了什么状态,绝对不能用作实质性的数据区域。例如:应当用局部变量表示缓冲区的下标、指针,但缓冲区本身绝对不应该开在栈上。数据区域要么从堆上分配获得指针,要么通过参数传递得到指针。事实上这里用全局变量也不是唯一的选择(至少全局变量在语义上还是不太好看)。也可以使用malloc()来做,获取按需分配内存的灵活性,不必事前规定一个“足够大的范围”: int n, i;int a, p;scanf("%d", &n);a = malloc(sizeof(int) * n);p = a;for (i=0; i{ scanf("%d", p++); }题外话——“局部变量所在的栈内存区域自然销毁”这件事,坑死多少C程序员。这里不详细展开,但请一定小心不要撞这个常识性的错误,即:不要把任何局部变量的地址用return返回给调用者。

a123456678 2019-12-02 02:39:20 0 浏览量 回答数 0

回答

一、前言 缓存可以说是性能优化中简单高效的一种优化方式了。一个优秀的缓存策略可以缩短网页请求资源的距离,减少延迟,并且由于缓存文件可以重复利用,还可以减少带宽,降低网络负荷。 对于一个数据请求来说,可以分为发起网络请求、后端处理、浏览器响应三个步骤。浏览器缓存可以帮助我们在第一和第三步骤中优化性能。比如说直接使用缓存而不发起请求,或者发起了请求但后端存储的数据和前端一致,那么就没有必要再将数据回传回来,这样就减少了响应数据。 接下来的内容中我们将通过缓存位置、缓存策略以及实际场景应用缓存策略来探讨浏览器缓存机制。 二、缓存位置 从缓存位置上来说分为四种,并且各自有优先级,当依次查找缓存且都没有命中的时候,才会去请求网络。 Service WorkerMemory CacheDisk Cache Push Cache Service Worker Service Worker 是运行在浏览器背后的独立线程,一般可以用来实现缓存功能。使用 Service Worker的话,传输协议必须为 HTTPS。因为 Service Worker 中涉及到请求拦截,所以必须使用 HTTPS 协议来保障安全。Service Worker 的缓存与浏览器其他内建的缓存机制不同,它可以让我们自由控制缓存哪些文件、如何匹配缓存、如何读取缓存,并且缓存是持续性的。 Service Worker 实现缓存功能一般分为三个步骤:首先需要先注册 Service Worker,然后监听到 install 事件以后就可以缓存需要的文件,那么在下次用户访问的时候就可以通过拦截请求的方式查询是否存在缓存,存在缓存的话就可以直接读取缓存文件,否则就去请求数据。. 当 Service Worker 没有命中缓存的时候,我们需要去调用 fetch 函数获取数据。也就是说,如果我们没有在 Service Worker 命中缓存的话,会根据缓存查找优先级去查找数据。但是不管我们是从 Memory Cache 中还是从网络请求中获取的数据,浏览器都会显示我们是从 Service Worker 中获取的内容。 Memory Cache Memory Cache 也就是内存中的缓存,主要包含的是当前中页面中已经抓取到的资源,例如页面上已经下载的样式、脚本、图片等。读取内存中的数据肯定比磁盘快,内存缓存虽然读取高效,可是缓存持续性很短,会随着进程的释放而释放。 一旦我们关闭 Tab 页面,内存中的缓存也就被释放了。 那么既然内存缓存这么高效,我们是不是能让数据都存放在内存中呢? 这是不可能的。计算机中的内存一定比硬盘容量小得多,操作系统需要精打细算内存的使用,所以能让我们使用的内存必然不多。 当我们访问过页面以后,再次刷新页面,可以发现很多数据都来自于内存缓存 内存缓存中有一块重要的缓存资源是preloader相关指令(例如 )下载的资源。总所周知preloader的相关指令已经是页面优化的常见手段之一,它可以一边解析js/css文件,一边网络请求下一个资源。 需要注意的事情是,内存缓存在缓存资源时并不关心返回资源的HTTP缓存头Cache-Control是什么值,同时资源的匹配也并非仅仅是对URL做匹配,还可能会对Content-Type,CORS等其他特征做校验。 Disk Cache Disk Cache 也就是存储在硬盘中的缓存,读取速度慢点,但是什么都能存储到磁盘中,比之 Memory Cache 胜在容量和存储时效性上。 在所有浏览器缓存中,Disk Cache 覆盖面基本是最大的。它会根据 HTTP Herder 中的字段判断哪些资源需要缓存,哪些资源可以不请求直接使用,哪些资源已经过期需要重新请求。并且即使在跨站点的情况下,相同地址的资源一旦被硬盘缓存下来,就不会再次去请求数据。绝大部分的缓存都来自 Disk Cache,关于 HTTP 的协议头中的缓存字段,我们会在下文进行详细介绍。 浏览器会把哪些文件丢进内存中?哪些丢进硬盘中? 关于这点,网上说法不一,不过以下观点比较靠得住: 对于大文件来说,大概率是不存储在内存中的,反之优先 当前系统内存使用率高的话,文件优先存储进硬盘 Push Cache Push Cache(推送缓存)是 HTTP/2 中的内容,当以上三种缓存都没有命中时,它才会被使用。它只在会话(Session)中存在,一旦会话结束就被释放,并且缓存时间也很短暂,在Chrome浏览器中只有5分钟左右,同时它也并非严格执行HTTP头中的缓存指令。 Push Cache 在国内能够查到的资料很少,也是因为 HTTP/2 在国内不够普及。这里推荐阅读Jake Archibald的 HTTP/2 push is tougher than I thought 这篇文章,文章中的几个结论: - 所有的资源都能被推送,并且能够被缓存,但是 Edge 和 Safari 浏览器支持相对比较差 - 可以推送 no-cache 和 no-store 的资源 - 一旦连接被关闭,Push Cache 就被释放 - 多个页面可以使用同一个HTTP/2的连接,也就可以使用同一个Push Cache。这主要还是依赖浏览器的实现而定,出于对性能的考虑,有的浏览器会对相同域名但不同的tab标签使用同一个HTTP连接。 - Push Cache 中的缓存只能被使用一次 - 浏览器可以拒绝接受已经存在的资源推送 - 你可以给其他域名推送资源 如果以上四种缓存都没有命中的话,那么只能发起请求来获取资源了。 那么为了性能上的考虑,大部分的接口都应该选择好缓存策略,通常浏览器缓存策略分为两种:强缓存和协商缓存,并且缓存策略都是通过设置 HTTP Header 来实现的。 作者:浪里行舟 链接:https://www.jianshu.com/p/54cc04190252 来源:简书 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

九旬 2020-05-24 11:47:06 0 浏览量 回答数 0

问题

为什么空间升级后速度变慢了?

wation 2019-12-01 21:47:09 5299 浏览量 回答数 1

问题

全国性的站点,是杭州节点好还是青岛的好?

lizhichao11 2019-12-01 21:04:44 7949 浏览量 回答数 9

回答

首先,还是先解释一下如何使用数据库,按照上面的方法就可以连接数据库了。这里要解释两件事情。  1.执行sql语句返回的reCount是什么?  这个recount不是我们执行sql的时候查出的内容,而是,明白了吧,就是这样,喵~~~  2.cur是什么?  这里的cur指的是游标。游标是映射在结果集中一行数据上的位置实体,有了游标,用户就可以访问结果集中的任意一行数据了,将游标放置到某行后,即可对该行数据进行操作。然而这些都是mysql内部的事情了,我们只需要知道要写上这么两句话,在执行sql语句前实例化一个游标对象,并在执行完sql语句提交后,关掉这个游标就好了。  批量插入数据    对就是这么简单,参数换成列表,方法换成executemany,搞定!需要注意的是那个占位符类似物:%s,要记得list里有几个元素就写几个。  cur.lastrowid和conn.insert_id():    cursor.lastrowid:最后一条记录的主键ID    conn.insert_id():最新插入记录的主键ID    网上说:结果一般情况下是一样的,最后一条记录肯定就是刚刚插入的记录。但如果是并发插入就不一样了。自己起了多线程,也并没有发现什么。。。如果有小伙伴知道,欢迎指教~~~上面两个方法需要注意的是一定要在conn.commit()之前执行。否则只会返回0。这两个方法也只能返回本次conn连接中插入数据的信息,放在select之后是不好用的哦!使用mysql数据库——删、改 删   改  删除操作和修改操作与插入操作唯一的不同就是——sql不同。。。还要怎么简单!!!使用mysql数据库——查  在python的MySQLdb模块中,有三个查找方法,fetchone,fetchmany和fetchall。常用的只有fetchall。需要注意的是,fetch的结果默认返回tuple。((item1,item2,...),(item1,item2,...)),第一层是行,第二层是列(也就是一行中的每一项)。当然可以修改返回值的格式。下面介绍~~~  fetchone    jiang~就是上面这样,这个时候好像就知道游标是怎么一回事儿了吧?  fetchmany    为什么说fetchone,fetchonemany并没有什么用呢?我们看上面的方法,其实都是执行了一样的sql,也就是说,我们其实是将所有的数据读到了内存中,再从中选取我们需要的,但是这一步我们在写sql的时候就可以做到了,读到内存里占用了大量的内存空间,绝对得不偿失~~~  fetchall    在最后补上修改返回结果格式为dict的方法。这就是mysql的基本操作啦~~~

xuning715 2019-12-02 01:09:57 0 浏览量 回答数 0

回答

使用mysql数据库——增  插入一条数据    首先,还是先解释一下如何使用数据库,按照上面的方法就可以连接数据库了。这里要解释两件事情。  1.执行sql语句返回的reCount是什么?  这个recount不是我们执行sql的时候查出的内容,而是,明白了吧,就是这样,喵~~~  2.cur是什么?  这里的cur指的是游标。游标是映射在结果集中一行数据上的位置实体,有了游标,用户就可以访问结果集中的任意一行数据了,将游标放置到某行后,即可对该行数据进行操作。然而这些都是mysql内部的事情了,我们只需要知道要写上这么两句话,在执行sql语句前实例化一个游标对象,并在执行完sql语句提交后,关掉这个游标就好了。  批量插入数据    对就是这么简单,参数换成列表,方法换成executemany,搞定!需要注意的是那个占位符类似物:%s,要记得list里有几个元素就写几个。  cur.lastrowid和conn.insert_id():    cursor.lastrowid:最后一条记录的主键ID    conn.insert_id():最新插入记录的主键ID    网上说:结果一般情况下是一样的,最后一条记录肯定就是刚刚插入的记录。但如果是并发插入就不一样了。自己起了多线程,也并没有发现什么。。。如果有小伙伴知道,欢迎指教~~~上面两个方法需要注意的是一定要在conn.commit()之前执行。否则只会返回0。这两个方法也只能返回本次conn连接中插入数据的信息,放在select之后是不好用的哦!使用mysql数据库——删、改 删   改  删除操作和修改操作与插入操作唯一的不同就是——sql不同。。。还要怎么简单!!!使用mysql数据库——查  在python的MySQLdb模块中,有三个查找方法,fetchone,fetchmany和fetchall。常用的只有fetchall。需要注意的是,fetch的结果默认返回tuple。((item1,item2,...),(item1,item2,...)),第一层是行,第二层是列(也就是一行中的每一项)。当然可以修改返回值的格式。下面介绍~~~  fetchone    jiang~就是上面这样,这个时候好像就知道游标是怎么一回事儿了吧?  fetchmany    为什么说fetchone,fetchonemany并没有什么用呢?我们看上面的方法,其实都是执行了一样的sql,也就是说,我们其实是将所有的数据读到了内存中,再从中选取我们需要的,但是这一步我们在写sql的时候就可以做到了,读到内存里占用了大量的内存空间,绝对得不偿失~~~  fetchall    在最后补上修改返回结果格式为dict的方法。这就是mysql的基本操作啦~~~

xuning715 2019-12-02 01:10:43 0 浏览量 回答数 0

回答

先补充一下概念:Java 内存模型中的可见性、原子性和有序性。可见性:  可见性是一种复杂的属性,因为可见性中的错误总是会违背我们的直觉。通常,我们无法确保执行读操作的线程能适时地看到其他线程写入的值,有时甚至是根本不可能的事情。为了确保多个线程之间对内存写入操作的可见性,必须使用同步机制。  可见性,是指线程之间的可见性,一个线程修改的状态对另一个线程是可见的。也就是一个线程修改的结果。另一个线程马上就能看到。比如:用volatile修饰的变量,就会具有可见性。volatile修饰的变量不允许线程内部缓存和重排序,即直接修改内存。所以对其他线程是可见的。但是这里需要注意一个问题,volatile只能让被他修饰内容具有可见性,但不能保证它具有原子性。比如 volatile int a = 0;之后有一个操作 a++;这个变量a具有可见性,但是a++ 依然是一个非原子操作,也就是这个操作同样存在线程安全问题。  在 Java 中 volatile、synchronized 和 final 实现可见性。原子性:  原子是世界上的最小单位,具有不可分割性。比如 a=0;(a非long和double类型) 这个操作是不可分割的,那么我们说这个操作时原子操作。再比如:a++; 这个操作实际是a = a + 1;是可分割的,所以他不是一个原子操作。非原子操作都会存在线程安全问题,需要我们使用同步技术(sychronized)来让它变成一个原子操作。一个操作是原子操作,那么我们称它具有原子性。java的concurrent包下提供了一些原子类,我们可以通过阅读API来了解这些原子类的用法。比如:AtomicInteger、AtomicLong、AtomicReference等。  在 Java 中 synchronized 和在 lock、unlock 中操作保证原子性。有序性:  Java 语言提供了 volatile 和 synchronized 两个关键字来保证线程之间操作的有序性,volatile 是因为其本身包含“禁止指令重排序”的语义,synchronized 是由“一个变量在同一个时刻只允许一条线程对其进行 lock 操作”这条规则获得的,此规则决定了持有同一个对象锁的两个同步块只能串行执行。下面内容摘录自《Java Concurrency in Practice》:  下面一段代码在多线程环境下,将存在问题。复制代码+ View code1 /** 2 * @author zhengbinMac 3 */ 4 public class NoVisibility { 5 private static boolean ready; 6 private static int number; 7 private static class ReaderThread extends Thread { 8 @Override 9 public void run() {10 while(!ready) {11 Thread.yield();12 }13 System.out.println(number);14 }15 }16 public static void main(String[] args) {17 new ReaderThread().start();18 number = 42;19 ready = true;20 }21 }复制代码  NoVisibility可能会持续循环下去,因为读线程可能永远都看不到ready的值。甚至NoVisibility可能会输出0,因为读线程可能看到了写入ready的值,但却没有看到之后写入number的值,这种现象被称为“重排序”。只要在某个线程中无法检测到重排序情况(即使在其他线程中可以明显地看到该线程中的重排序),那么就无法确保线程中的操作将按照程序中指定的顺序来执行。当主线程首先写入number,然后在没有同步的情况下写入ready,那么读线程看到的顺序可能与写入的顺序完全相反。  在没有同步的情况下,编译器、处理器以及运行时等都可能对操作的执行顺序进行一些意想不到的调整。在缺乏足够同步的多线程程序中,要想对内存操作的执行春旭进行判断,无法得到正确的结论。  这个看上去像是一个失败的设计,但却能使JVM充分地利用现代多核处理器的强大性能。例如,在缺少同步的情况下,Java内存模型允许编译器对操作顺序进行重排序,并将数值缓存在寄存器中。此外,它还允许CPU对操作顺序进行重排序,并将数值缓存在处理器特定的缓存中。二、Volatile原理  Java语言提供了一种稍弱的同步机制,即volatile变量,用来确保将变量的更新操作通知到其他线程。当把变量声明为volatile类型后,编译器与运行时都会注意到这个变量是共享的,因此不会将该变量上的操作与其他内存操作一起重排序。volatile变量不会被缓存在寄存器或者对其他处理器不可见的地方,因此在读取volatile类型的变量时总会返回最新写入的值。  在访问volatile变量时不会执行加锁操作,因此也就不会使执行线程阻塞,因此volatile变量是一种比sychronized关键字更轻量级的同步机制。  当对非 volatile 变量进行读写的时候,每个线程先从内存拷贝变量到CPU缓存中。如果计算机有多个CPU,每个线程可能在不同的CPU上被处理,这意味着每个线程可以拷贝到不同的 CPU cache 中。  而声明变量是 volatile 的,JVM 保证了每次读变量都从内存中读,跳过 CPU cache 这一步。当一个变量定义为 volatile 之后,将具备两种特性:  1.保证此变量对所有的线程的可见性,这里的“可见性”,如本文开头所述,当一个线程修改了这个变量的值,volatile 保证了新值能立即同步到主内存,以及每次使用前立即从主内存刷新。但普通变量做不到这点,普通变量的值在线程间传递均需要通过主内存(详见:Java内存模型)来完成。  2.禁止指令重排序优化。有volatile修饰的变量,赋值后多执行了一个“load addl $0x0, (%esp)”操作,这个操作相当于一个内存屏障(指令重排序时不能把后面的指令重排序到内存屏障之前的位置),只有一个CPU访问内存时,并不需要内存屏障;(什么是指令重排序:是指CPU采用了允许将多条指令不按程序规定的顺序分开发送给各相应电路单元处理)。volatile 性能:  volatile 的读性能消耗与普通变量几乎相同,但是写操作稍慢,因为它需要在本地代码中插入许多内存屏障指令来保证处理器不发生乱序执行。

wangccsy 2019-12-02 01:48:10 0 浏览量 回答数 0

回答

Re请问服务器卡该升级带宽吗?请看图 你这也没有一个显示带宽的位置,还有你这服务器用的是多少的带宽?最好到服务器里面看看服务器的CPU、内存什么之类的,服务器卡不只是和带宽有关的。

窝头 2019-12-02 01:32:33 0 浏览量 回答数 0

回答

delete []不知道分配的大小。但是,该知识驻留在运行时或操作系统的内存管理器中,这意味着编译器在编译期间不可用。而sizeof()不是一个真正的功能,它实际上是评价由编译器的常数,这是一件好事它不能用于动态分配数组,其大小在编译期间是不知道做。 另外,请考虑以下示例: int *arr = new int[256]; int *p = &arr[100]; printf("Size: %d\n", sizeof(p)); 编译器将如何知道其大小p?问题的根源在于C和C ++中的数组不是一流的对象。它们会衰减为指针,编译器或程序本身无法知道指针是否指向分配的内存块的开头new,或单个对象或块中间的某个位置。由分配的内存new。 原因之一是C和C ++将内存管理留给了程序员和操作系统,这也是为什么它们没有垃圾回收的原因。实施new和delete不是C ++标准的一部分,因为C ++,就是要在各种不同的平台,它可以以非常不同的方式管理他们的记忆中。如果您正在为运行在最新Intel CPU上的Windows框编写文字处理器,则可以让C ++跟踪所有分配的数组及其大小,但是当编写在Windows XP上运行的嵌入式系统时,这可能是完全不可行的。 DSP。

保持可爱mmm 2020-02-10 16:04:59 0 浏览量 回答数 0

回答

HashSet如何检查重复 两个对象的 hashCode() 相同,则 equals() 也一定为 true,对吗? hashCode和equals方法的关系 面试官可能会问你:“你重写过 hashcode 和 equals 么,为什么重写equals时必须重写hashCode方法?” hashCode()介绍 hashCode() 的作用是获取哈希码,也称为散列码;它实际上是返回一个int整数。这个哈希码的作用是确定该对象在哈希表中的索引位置。hashCode() 定义在JDK的Object.java中,这就意味着Java中的任何类都包含有hashCode()函数。 散列表存储的是键值对(key-value),它的特点是:能根据“键”快速的检索出对应的“值”。这其中就利用到了散列码!(可以快速找到所需要的对象) 为什么要有 hashCode 我们以“HashSet 如何检查重复”为例子来说明为什么要有 hashCode: 当你把对象加入 HashSet 时,HashSet 会先计算对象的 hashcode 值来判断对象加入的位置,同时也会与其他已经加入的对象的 hashcode 值作比较,如果没有相符的hashcode,HashSet会假设对象没有重复出现。但是如果发现有相同 hashcode 值的对象,这时会调用 equals()方法来检查 hashcode 相等的对象是否真的相同。如果两者相同,HashSet 就不会让其加入操作成功。如果不同的话,就会重新散列到其他位置。(摘自我的Java启蒙书《Head first java》第二版)。这样我们就大大减少了 equals 的次数,相应就大大提高了执行速度。 hashCode()与equals()的相关规定 如果两个对象相等,则hashcode一定也是相同的 两个对象相等,对两个对象分别调用equals方法都返回true 两个对象有相同的hashcode值,它们也不一定是相等的 因此,equals 方法被覆盖过,则 hashCode 方法也必须被覆盖 hashCode() 的默认行为是对堆上的对象产生独特值。如果没有重写 hashCode(),则该 class 的两个对象无论如何都不会相等(即使这两个对象指向相同的数据) 对象的相等与指向他们的引用相等,两者有什么不同? 对象的相等 比的是内存中存放的内容是否相等而 引用相等 比较的是他们指向的内存地址是否相等。

剑曼红尘 2020-03-27 16:08:02 0 浏览量 回答数 0

回答

String是Java中一个比较基础的类,每一个开发人员都会经常接触到。而且,String也是面试中经常会考的知识点。String有很多方法,有些方法比较常用,有些方法不太常用。今天要介绍的subString就是一个比较常用的方法,而且围绕subString也有很多面试题。 substring(int beginIndex, int endIndex)方法在不同版本的JDK中的实现是不同的。了解他们的区别可以帮助你更好的使用他。为简单起见,后文中用substring()代表substring(int beginIndex, int endIndex)方法。 substring() 的作用 substring(int beginIndex, int endIndex)方法截取字符串并返回其[beginIndex,endIndex-1]范围内的内容。 String x = "abcdef"; x = x.substring(1,3); System.out.println(x); 输出内容: bc 调用substring()时发生了什么? 你可能知道,因为x是不可变的,当使用x.substring(1,3)对x赋值的时候,它会指向一个全新的字符串: 然而,这个图不是完全正确的表示堆中发生的事情。因为在jdk6 和 jdk7中调用substring时发生的事情并不一样。 JDK 6中的substring String是通过字符数组实现的。在jdk 6 中,String类包含三个成员变量:char value[], int offset,int count。他们分别用来存储真正的字符数组,数组的第一个位置索引以及字符串中包含的字符个数。 当调用substring方法的时候,会创建一个新的string对象,但是这个string的值仍然指向堆中的同一个字符数组。这两个对象中只有count和offset 的值是不同的。 下面是证明上说观点的Java源码中的关键代码: //JDK 6 String(int offset, int count, char value[]) { this.value = value; this.offset = offset; this.count = count; } public String substring(int beginIndex, int endIndex) { //check boundary return new String(offset + beginIndex, endIndex - beginIndex, value); } JDK 6中的substring导致的问题 如果你有一个很长很长的字符串,但是当你使用substring进行切割的时候你只需要很短的一段。这可能导致性能问题,因为你需要的只是一小段字符序列,但是你却引用了整个字符串(因为这个非常长的字符数组一直在被引用,所以无法被回收,就可能导致内存泄露)。在JDK 6中,一般用以下方式来解决该问题,原理其实就是生成一个新的字符串并引用他。 x = x.substring(x, y) + "" 关于JDK 6中subString的使用不当会导致内存系列已经被官方记录在Java Bug Database中: 内存泄露:在计算机科学中,内存泄漏指由于疏忽或错误造成程序未能释放已经不再使用的内存。 内存泄漏并非指内存在物理上的消失,而是应用程序分配某段内存后,由于设计错误,导致在释放该段内存之前就失去了对该段内存的控制,从而造成了内存的浪费。 JDK 7 中的substring 上面提到的问题,在jdk 7中得到解决。在jdk 7 中,substring方法会在堆内存中创建一个新的数组。 Java源码中关于这部分的主要代码如下: //JDK 7 public String(char value[], int offset, int count) { //check boundary this.value = Arrays.copyOfRange(value, offset, offset + count); } public String substring(int beginIndex, int endIndex) { //check boundary int subLen = endIndex - beginIndex; return new String(value, beginIndex, subLen); } 以上是JDK 7中的subString方法,其使用new String创建了一个新字符串,避免对老字符串的引用。从而解决了内存泄露问题。 所以,如果你的生产环境中使用的JDK版本小于1.7,当你使用String的subString方法时一定要注意,避免内存泄露。

montos 2020-06-01 21:28:15 0 浏览量 回答数 0

回答

就ISO C标准(语言的正式定义)而言,访问其边界之外的数组具有“ 未定义的行为 ”。其字面意思是: 在使用非便携式或错误程序构造或错误数据时的行为,对此国际标准不施加任何要求 一个非规范性的注释扩展了这一点: 可能的不确定行为范围从完全忽略具有无法预测结果的情况到在翻译或程序执行过程中以环境特征记录的方式表现(带有或不带有诊断消息)到终止翻译或执行(带有发布)诊断消息)。 这就是理论。现实是什么? 在“最佳”情况下,您将访问一些内存,这些内存要么是当前正在运行的程序所拥有的(这可能导致您的程序行为不当),要么不是当前正在运行的程序所拥有的(这可能会导致您的程序崩溃,例如细分错误)。或者,您可以尝试写入程序拥有的内存,但是将其标记为只读;这也可能导致程序崩溃。 假设您的程序在一个试图保护彼此并发运行的进程彼此之间的操作系统下运行。如果您的代码在“裸机”上运行,比如说它是OS内核或嵌入式系统的一部分,则没有这种保护;您行为不当的代码就是应该提供这种保护的内容。在这种情况下,损坏的可能性会更大,包括在某些情况下对硬件(或附近的东西或人)的物理损坏。 即使在受保护的OS环境中,保护也不总是100%。例如,存在一些操作系统错误,这些错误使无特权的程序可以获取根(管理)访问权限。即使具有普通用户特权,出现故障的程序也可能消耗过多的资源(CPU,内存,磁盘),从而可能使整个系统瘫痪。许多恶意软件(病毒等)利用缓冲区溢出来获得对系统的未授权访问。 (一个历史示例:我听说过,在一些带有核心内存的旧系统中,在紧密循环中重复访问单个内存位置可能确实导致该内存块融化。其他可能性包括破坏CRT显示器和移动读取的内容。 /写入磁盘驱动器磁头,使其具有驱动器柜的谐波频率,从而使其滑过桌子并掉落在地板上。) 而且总是有天网需要担心。 底线是:如果您可以编写一个程序来故意做一些不好的事情,那么从理论上讲,一个有缺陷的程序至少有可能偶然地做同样的事情。 在实践中,这是非常不可能的,你与MacOS X系统上运行错误的程序会做什么比暴跌更加严重。但是,不可能完全防止错误的代码做真正的坏事。 问题来源于stack overflow

保持可爱mmm 2020-01-16 15:55:44 0 浏览量 回答数 0

问题

超出范围访问数组有多危险?

保持可爱mmm 2020-01-16 15:55:32 0 浏览量 回答数 1

回答

开发者您好, 对于一些高级程序语言的,它的元素类型没有严格的要求,它有一个标准的叫法叫做泛型,它就是说任何一个单元类型都可以放进去。 对于数组,它底层的硬件实现,有一个叫内存管理器的东西,每当你申请数组的话,计算机实际上是在内存中,给你开辟了(申请了)一段连续的地址,每一个地址都可以直接通过内存管理器进行访问。这张图里示意的地方就是它相应的内存地址。直接访问方面,它访问第一个元素和访问中间某个元素,时间复杂度都是一样的。也就是常数时间称为O(1)。从这里可以总结出它可以进行随机地访问任何的一个元素,访问速度非常快,这也是它的特性之一。 对于JS,假如有一个数组含有ABCEFG,我们想把元素D插入到数组中输出ABCDEFG。这个时候需要把EFG往下挪一个位置,而这样的操作导致了时间复杂度不再是常数级了,而是O(n)的时间复杂度。在最坏的情况甚至需要挪动整个数组;最好的情况下插入到最后面就变成了O(1);平均情况下需要移动一半的元素位置。同理可得,进行删除操作的时候一样。平均时间复杂度O(n)。 由此可见,如果对数组进行大量的增删操作,它会涉及到非常多的array copy,这样它的时间复杂度不是特别高效的。其实这个问题不仅仅存在于JS,Java也是如此,举个例子,ensure capacity 所进行的操作其实相对暴力,它会先查找整个数组的实际长度,如果长度够的话就什么都不做;如果长度不够的话,那么它会直接new一个新的数组出来,新的数组长度是当前长度乘以2,把老数组的值拷贝到新数组上面去。 针对您说的,是否在工作中动态扩展阵列或其他一些性能提升算法?我觉得您可以参考工业上那些已经千锤百炼的老代码,他们的做法,从两点触发:空间换时间、升维。 祝您在喜欢的技术道路上越走越好

罗思雨 2020-02-12 14:50:33 0 浏览量 回答数 0

回答

聚簇索引:将数据存储与索引放到了一块,找到索引也就找到了数据 非聚簇索引:将数据存储于索引分开结构,索引结构的叶子节点指向了数据的对应行,myisam通过key_buffer把索引先缓存到内存中,当需要访问数据时(通过索引访问数据),在内存中直接搜索索引,然后通过索引找到磁盘相应数据,这也就是为什么索引不在key buffer命中时,速度慢的原因 澄清一个概念:innodb中,在聚簇索引之上创建的索引称之为辅助索引,辅助索引访问数据总是需要二次查找,非聚簇索引都是辅助索引,像复合索引、前缀索引、唯一索引,辅助索引叶子节点存储的不再是行的物理位置,而是主键值

剑曼红尘 2020-03-31 10:56:02 0 浏览量 回答数 0

回答

试试看heapdump,既然线上一直都会爆满,那么在本地压测,用heapdmp间隔5分钟输出一批内存日志,然后在chrome的dev tool里面做compare,就能看到一直只增不减的对象是什么了,再定位到代码的具体位置。互联数据不知道是不是这样描述,互相学习! 答案来源于网络

养狐狸的猫 2019-12-02 02:15:56 0 浏览量 回答数 0

问题

关于“建立数据库连接时出错”的解决方法

原不周 2019-12-01 20:58:11 13238 浏览量 回答数 5
阿里云大学 云服务器ECS com域名 网站域名whois查询 开发者平台 小程序定制 小程序开发 国内短信套餐包 开发者技术与产品 云数据库 图像识别 开发者问答 阿里云建站 阿里云备案 云市场 万网 阿里云帮助文档 免费套餐 开发者工具 企业信息查询 小程序开发制作 视频内容分析 企业网站制作 视频集锦 代理记账服务 2020阿里巴巴研发效能峰会 企业建站模板 云效成长地图 高端建站