当前位置: 首页 > 科技观察

针对JavaScript的缓存未命中分析

时间:2023-03-20 11:38:52 科技观察

在本文中,我们将讨论数据的创建和访问方式如何影响应用程序性能。简介JavaScript是一种非常高级的语言,在使用JavaScript进行开发时不必过多考虑数据在内存中的存储方式。在本文中,我们将探讨数据如何存储在内存中,以及数据在JavaScript中的分布和访问方式如何影响CPU和内存性能。浪漫三角当计算机需要做一些计算任务时,计算机处理单元(CPU)需要数据进行处理,因此,根据手头的任务,它会向内存发送请求,通过bus,像这样:这就是我们的浪漫三角CPU->Bus->Memory浪漫三角需要第四个元素来保持稳定由于CPU比内存快很多,处理方式从CPU->Bus->Memory->Bus->CPU是大量的计算时间被浪费了,因为在查找内存的同时,CPU处于空闲状态,无法做其他事情。缓存的出现有效的缓解了这个问题。在本文中我们不会详细讨论缓存的技术细节和类型,我们只需要知道缓存可以作为CPU的内部存储空间。当CPU接收到运行命令时,它首先在缓存中搜索目标数据,如果没有找到目标数据,则通过总线发起请求。然后总线获取请求的数据和一部分内存,将其存储在缓存中以供CPU快速调用。这样,CPU就可以高效地处理数据,而不会浪费时间等待内存返回。缓存引用也可能引发新问题基于上述架构,我们在处理大量数据时可能会出现一种称为“缓存未命中”的错误。cachemiss是指在一次计算过程中,CPU发现需要的数据不在cache中,因此需要通过正常通道(即已知的慢速内存)请求这些数据。上图就是一个很好的例子,在数据处理组中,因为计算出来的数据超过了cachelimit数据,导致了cachemiss。但这与我作为JavaScript程序员有什么关系呢?好问题,大多数时候,我们JavaScript开发人员不必关心这个。但是随着越来越多的数据涌入Node.js服务器甚至富客户端,在使用JavaScript遍历大型数据集时很容易遇到缓存未命中的情况。一个经典的例子让我们用一个例子来说明。这是一个名为Boom的类:classBoom{constructor(id){this.id=id;}setPosition(x,y){this.x=x;this.y=y;}}这个类(Boom)只有3个属性:id、x和y。现在,让我们创建一个方法来填充x和y。让我们构建设置:constROWS=1000;constCOLS=1000;constrepeats=100;constarr=newArray(ROWS*COLS).fill(0).map((a,i)=>newBoom(i));现在,我们将在方法中使用此设置:functionlocalAccess(){for(leti=0;i{repeat(farAccess,'NonLocal');},2000);这是最终结果:非局部迭代速度几乎慢了4倍。随着数据量的增加,这种差异会越来越大。发生这种情况是因为CPU由于高速缓存未命中而处于空闲状态。那么你付出的代价是多少?这完全取决于数据的大小。好吧,我发誓我永远不会那样做!一般来说,您可能不会这么想,但在某些情况下,您可能想要使用非线性(如1、2、3、4、5)或非偶然性。Like(for(leti=0;i{repeat(farAccess,'NonLocal')setTimeout(()=>{repeat(()=>farAccess(diffArr),'NonLocalSorted')},2000);},2000);我们运行它,我们得到:我们已经优化了数据以适应更常见的查看方式。有关完整示例,请参阅https://yonatankra.com/performance/memory/liveExamples/objectPool2/index.html