1.内存延迟与带宽分析
2.ISCISC:Index of Stream Condition
3.Android-Native开发系列之利用AAudio播放音频
4.Alluxio 客户端源码分析
5.ARM cpu性能测试总结
6.详解Java Stream的指标分组和聚合
内存延迟与带宽分析
在现代计算机环境中,内存访问效率往往成为性能瓶颈。源码处理器访问内存的标源速度,即延迟,指标以及每秒可以传输的源码数据量,即带宽,标源immutable源码是指标影响应用程序性能的关键因素。这两个因素在各种场景中都至关重要。源码本节将专注于评估内存子系统组件的标源峰值性能。
在x平台上,指标英特尔内存延迟检查器(MLC)是源码一个非常有用的工具,可以在Windows和Linux上免费使用。标源MLC可以通过不同的指标访问模式和负载来测量缓存和内存的延迟和带宽。在基于ARM的源码系统上,虽然没有类似的标源工具,但用户可以从源代码中下载并构建内存延迟和带宽基准测试,例如lmbench 2、bandwidth 4和Stream等。
本节将讨论空闲读取延迟和读取带宽这两个子集指标。空闲读取延迟是指系统处于空闲状态时,从内存系统组件获取数据所需的最小时间。当系统被其他内存消耗大的应用程序加载时,此延迟会增加。MLC通过进行相关加载(也称为指针追踪)来测量空闲延迟。一个测量线程分配一个非常大的缓冲区,并对其进行初始化,以便缓冲区内的每个(字节)缓存行包含指向该缓冲区内另一个非相邻缓存行的指针。通过适当调整缓冲区的大小,我们可以确保几乎所有的加载都命中某个级别的缓存或主存。
以下是一个测试系统的示例,包括英特尔Alderlake主机、Core i7-P CPU和GB DDR4 @ MT/s双通道内存。该处理器有4个性能P(实际上是两个物理核*2个超线程)超线程核心和8个E(高效)核心。每个P核心有KB的L1数据缓存和1.MB的L2缓存。每个E核心有KB的L1数据缓存,而四个E核心组成一个集群,可以访问共享的2MB L2缓存。系统中的所有核心都由MB的L3缓存支持。以下是示例mlc命令:
选项--idle_latency用于测量读取延迟。MLC具有--loaded_latency选项,用于在由其他线程生成的内存流量存在时测量延迟。选项-c0将测量线程固定在逻辑CPU 0上,该CPU位于P核心上。选项-L启用大页以限制我们的测量中的TLB效应。选项-bm告诉MLC使用MB缓冲区,在我们的系统上可以放在L3缓存中。
以下图表显示了L1、L2和L3缓存的读取延迟。左侧的第一个区域对应于L1d缓存,该缓存是每个物理核心私有的。我们可以观察到E核心的延迟为0.9ns,而P核稍高为1.1ns。肉类追溯系统源码此外,我们可以使用此图来确认缓存大小。请注意,当缓冲区大小超过KB时,E核心的延迟开始上升,但是在KB之前P核心的延迟保持不变。这证实了E核心的L1d缓存大小为KB,而P核心的L1d缓存大小为KB。
第二个区域显示L2缓存延迟,E核的延迟几乎是P核的两倍(5.9ns vs. 3.2ns)。对于P核,延迟在我们超过1.MB缓冲区大小后会增加,这是预期的。但我们期望E核的延迟保持不变,直到2MB,但在我们的测量中没有发生这种情况。
第三个区域从2MB到MB对应于L3缓存延迟,对于两种类型的内核都大约为ns。系统中所有内核共享的L3缓存的总大小为MB。有趣的是,我们从MB开始看到一些意想不到的动态变化,而不是MB。这很可能是因为一些访问错过了L3,需要去主内存。
第四个区域对应于内存延迟,图表上只显示了其开始部分。当我们越过MB的边界时,延迟会急剧上升,并在E核心的MB和P核心的MB处开始趋于稳定。使用更大的缓冲区大小为MB时,E核心的访问延迟为ns,P核心为ns。这测量了内存延迟,因为几乎没有加载会命中L3缓存。
使用类似的技术,我们可以测量内存层次结构的各个组件的带宽。为了测量带宽,MLC执行的加载请求不会被任何后续指令使用。这允许MLC生成可能的最大带宽。MLC在每个配置的逻辑处理器上生成一个软件线程。每个线程访问的地址是独立的,线程之间没有数据共享。与延迟实验一样,线程使用的缓冲区大小确定了MLC是在测量L1/L2/L3缓存带宽还是内存带宽。
这里的新选项是-k,它指定了用于测量的CPU编号列表。-Y选项告诉MLC使用AVX2加载,即每次加载字节。MLC使用不同的读写比例来测量带宽,但在下图中,我们只显示了全部读取带宽,免费java项目源码因为它可以让我们对内存带宽的峰值有一个直观的了解。但其他比例也可能很重要。我们在使用Intel MLC测量的系统的组合延迟和带宽数字如图下所示。
核心可以从较低级别的缓存(如L1和L2)中获得比从共享的L3缓存或主内存中更高的带宽。共享缓存(如L3和E核心L2)相当好地扩展,可以同时为多个核心提供请求。例如,单个E核心L2的带宽为GB/s。使用来自同一集群的两个E核心,我测量了GB/s,三个E核心为GB/s,而所有四个E核心可以从共享L2中获得GB/s。对于L3缓存也是如此,单个P核心的带宽为GB/s,而单个E核心只有GB/s。但是当所有核心都被使用时,L3缓存可以维持GB/s的带宽。
我们用纳秒测量延迟,用GB/s测量带宽,因此它们还取决于核心运行的频率。在各种情况下,观察到的数字可能不同。例如,假设仅在系统上以最大睿频运行时,P核心的L1延迟为X,L1带宽为Y。当系统负载满时,我们可能观察到这些指标分别变为1.X和0.Y。为了减轻频率效应,与其使用纳秒,延迟和度量可以使用核心周期来表示,并归一化为一些样本频率,比如3Ghz。
了解计算机的主要特征是评估程序如何利用可用资源的基本方法。通过屋顶线性能模型了解系统的瓶颈在哪里,是CPU运算的瓶颈还是内存读取的瓶颈。如果经常在单个平台上分析性能,最好记住内存层次结构的各个组件的延迟和带宽,这有助于建立对测试系统的心理模型,将有助于进一步的性能分析。
ISCISC:Index of Stream Condition
ISCISC是一种针对河流健康状况的评价工具,它由Ladson(年)主要设计。该方法将河流的健康状况评估分为五个关键领域:水文学特征、形态特征、河岸带状态、水质以及水生生物多样性。每条河流在这些方面与特定的参照点进行对比,每个指标都有相应的评分,最终的总分作为河流综合健康的评价指标。 该评价体系的一大优点是它整合了河流状态的多个关键因素,使得对河流的快递物流查询源码长期评估成为可能。这对于科学的水资源管理和决策制定提供了宝贵依据。然而,它也存在一些局限性,例如,它未能单独反映每个指标的变化情况,这可能影响到评估的精确性。此外,选择参考河段的过程相对主观,可能会影响不同河流评价的公正性。 总的来说,ISCISC作为一种综合性的河流健康评价方法,为我们理解河流生态系统的整体状况提供了框架,但同时需要结合其他更为细致的分析方法以弥补其不足之处。扩展资料
ISC服务器控制。是Intel的服务器管理软件。只适用于使用Intel架构的带有集成管理功能主板的服务器。采用这种技术后,用户在一台普通的客户机上,就可以监测网络上所有使用Intel主板的服务器,监控和判断服务器的工作状态是否正常。一旦服务器内部硬件传感器进行实时监控或第三方硬件中的任何一项出现错误,就会报警提示管理人员。并且,监测端和服务器端之间的网络可以是局域网也可以是广域网,可直接通过网络对服务器进行启动、关闭或重新置位,极大地方便了管理和维护工作。Android-Native开发系列之利用AAudio播放音频
前言 在Android C/C++层实现音频播放/录制功能,大家可能首先想到的是利用opensles。这是经过考验的实现方式,适配广泛。然而,若项目最低版本支持Android 及以上,追求最小延迟与最高性能时,可考虑AAudio。 博主之前使用opensles处理音频,后尝试oboe、aaudio实现,有感而发,特此记录,以供参考。什么是AAudio?
AAudio是Android 8.0引入的一种新型C风格接口的底层音频库,旨在追求性能与低延迟。它专注于原始数据的播放与录制,如播放PCM数据。与opensles不同,AAudio不包含编解码模块。 oboe是对opensles与aaudio的封装,它根据设备判断选择使用aaudio或opensles。例如,在低于Android 8.0的c 计算源码补码设备上,它会使用opensles。配置AAudio开发环境与AAudioStream
AAudioStream是关键概念,它是与AAudio交换音频数据的基础。我们首先创建AAudioStreamBuilder,然后通过它配置AAudioStream。创建AAudioStreamBuilder
AAudioStream的创建采用builder模式,故需先创建对应的builder对象。配置AAudioStream
通过builder的setXXX函数配置AAudioStream。简要概述这些函数,具体详情请参阅源码注释。 注释的回调用于后续使用,暂不展开。创建AAudioStream
调用openStream获取配置的AAudioStream对象。接下来,可利用AAudioStream处理音频数据,通过调用相关getXXX函数,验证配置是否满足预期。操作AAudioStream
AAudioStream的状态转换流程图展示了状态变化的路径。涉及的函数包括请求状态变更的函数,这些函数为异步调用。
AAudioStream处理音频数据有直接读写与回调两种方式,具体选择取决于项目需求。通过callback回调处理数据
回调方式推荐,因其能提供更好的性能。直接读写数据到流方式在大多数情况下的延迟指标表现良好,具体取决于项目需求。 使用callback方式处理数据需设置回调函数dataCallback与errorCallback,分别在AAudio需要数据时与出现错误时触发。注意
回调函数内避免执行耗时任务。errorCallback触发时需在新线程中处理,可直接调用AAudioStream相关的getXXX函数。AAudio使用demo
GitHub上已提供使用demo,欢迎查看并star。补充内容
underrun & overrun
underrun与overrun是音频数据生产和消费节奏不匹配导致的问题,分别指播放时未及时写入数据与录制时未及时读取数据。 AAudio通过动态调整缓冲区大小来降低延迟,避免underrun。Thread safety
AAudio接口并非完全线程安全,使用时需注意。结论
AAudio接口简洁,与opensles相比代码量减少,功能略显不足,如解码与音量控制等。选择取决于实际需求。 已提供GitHub链接,配合文章阅读更易理解。 参考链接:developer.android.com/ndk/guides/...Alluxio 客户端源码分析
Alluxio是一个用于云分析和人工智能的开源数据编排技术,作为分布式文件系统,采用与HDFS相似的主从架构。系统中包含一个或多个Master节点存储集群元数据信息,以及Worker节点管理缓存的数据块。本文将深入分析Alluxio客户端的实现。
创建客户端逻辑在类alluxio.client.file.FileSystem中,简单示例代码如下。
客户端初始化包括调用FileSystem.Context.create创建客户端对象的上下文,在此过程中需要初始化客户端以创建与Master和Worker连接的连接池。若启用了配置alluxio.user.metrics.collection.enabled,将启动后台守护线程定时与Master节点进行心跳传输监控指标信息。同时,客户端初始化时还会创建负责重新初始化的后台线程,定期从Master拉取配置文件的哈希值,若Master节点配置发生变化,则重新初始化客户端,期间阻塞所有请求直到重新初始化完成。
创建具有缓存功能的客户端在客户端初始化后,调用FileSystem.Factory.create进行客户端创建。客户端实现分为BaseFileSystem、MetadataCachingBaseFileSystem和LocalCacheFileSystem三种,其中MetadataCachingBaseFileSystem和LocalCacheFileSystem对BaseFileSystem进行封装,提供元数据和数据缓存功能。BaseFileSystem的调用主要分为三大类:纯元数据操作、读取文件操作和写入文件操作。针对元数据操作,直接调用对应GRPC接口(例如listStatus)。接下来,将介绍客户端如何与Master节点进行通信以及读取和写入的流程。
客户端需要先通过MasterInquireClient接口获取主节点地址,当前有三种实现:PollingMasterInquireClient、SingleMasterInquireClient和ZkMasterInquireClient。其中,PollingMasterInquireClient是针对嵌入式日志模式下选择主节点的实现类,SingleMasterInquireClient用于选择单节点Master节点,ZkMasterInquireClient用于Zookeeper模式下的主节点选择。因为Alluxio中只有主节点启动GRPC服务,其他节点连接客户端会断开,PollingMasterInquireClient会依次轮询所有主节点,直到找到可以连接的节点。之后,客户端记录该主节点,如果无法连接主节点,则重新调用PollingMasterInquireClient过程以连接新的主节点。
数据读取流程始于BaseFileSystem.openFile函数,首先通过getStatus向Master节点获取文件元数据,然后检查文件是否为目录或未写入完成等条件,若出现异常则抛出异常。寻找合适的Worker节点根据getStatus获取的文件信息中包含所有块的信息,通过偏移量计算当前所需读取的块编号,并寻找最接近客户端并持有该块的Worker节点,从该节点读取数据。判断最接近客户端的Worker逻辑位于BlockLocationUtils.nearest,考虑使用domain socket进行短路读取时的Worker节点地址一致性。根据配置项alluxio.worker.data.server.domain.socket.address,判断每个Worker使用的domain socket路径是否一致。如果没有使用域名socket信息寻找到最近的Worker节点,则根据配置项alluxio.user.ufs.block.read.location.policy选择一个Worker节点进行读取。若客户端和数据块在同一节点上,则通过短路读取直接从本地文件系统读取数据,否则通过与Worker节点建立GRPC通信读取文件。
如果无法通过短路读取数据,客户端会回退到使用GRPC连接与选中的Worker节点通信。首先判断是否可以通过domain socket连接Worker节点,优先选择使用domain socket方式。创建基于GRPC的块输入流代码位于BlockInStream.createGrpcBlockInStream。通过GRPC进行连接时,每次读取一个chunk大小并缓存chunk,减少RPC调用次数提高性能,chunk大小由配置alluxio.user.network.reader.chunk.size.bytes决定。
读取数据块完成后或出现异常终止,Worker节点会自动释放针对该块的写入锁。读取异常处理策略是记录失败的Worker节点,尝试从其他Worker节点读取,直到达到重试次数上限或没有可用的Worker节点。
若无法通过本地Worker节点读取数据,则客户端尝试发起异步缓存请求。若启用了配置alluxio.user.file.passive.cache.enabled且存在本地Worker节点,则向本地Worker节点发起异步缓存请求,否则向负责读取该块数据的Worker节点发起请求。
数据写入流程首先向Master节点发送CreateFile请求,Master验证请求合法性并返回新文件的基本信息。根据不同的写入类型,进行不同操作。如果是THROUGH或CACHE_THROUGH等需要直接写入底层文件系统的写入类型,则选择一个Worker节点处理写入到UFS的数据。对于MUST_CACHE、CACHE_THROUGH、ASYNC_THROUGH等需要缓存数据到Worker节点上的写入类型,则打开另一个流负责将每个写入的块缓存到不同的Worker上。写入worker缓存块流程类似于读取流程,若写入的Worker与客户端在同一个主机上,则使用短路写直接将块数据写入Worker本地,无需通过网络发送到Worker上。数据完成写入后,客户端向Master节点发送completeFile请求,表示文件已写入完成。
写入失败时,取消当前流以及所有使用过的输出流,删除所有缓存的块和底层存储中的数据,与读取流程不同,写入失败后不进行重试。
零拷贝实现用于优化写入和读取流程中WriteRequest和ReadResponse消息体积大的问题,通过配置alluxio.user.streaming.zerocopy.enabled开启零拷贝特性。Alluxio通过实现了GRPC的MethodDescriptor.Marshaller和Drainable接口来实现GRPC零拷贝特性。MethodDescriptor.Marshaller负责对消息序列化和反序列化的抽象,用于自定义消息序列化和反序列化行为。Drainable扩展java.io.InputStream,提供将所有内容转移到OutputStream的方法,避免数据拷贝,优化内容直接写入OutputStream的过程。
总结,阅读客户端代码有助于了解Alluxio体系结构,明白读取和写入数据时的数据流向。深入理解Alluxio客户端实现对于后续阅读其他Alluxio代码非常有帮助。
ARM cpu性能测试总结
ARM CPU性能测试总结:
ARM处理器性能的评估通常通过两个关键工具:DMIPS(Dhrystone Million Instructions Per Second)和CoreMark。DMIPS是通过Dhrystone基准测试衡量系统每秒钟执行的Dhrystone指令数量,转化为DMIPS后便于比较。然而,DMIPS只是理论上的性能指标,实际应用性能还需考虑架构、缓存等因素。在Linux上,可通过下载Dhrystone源码并调整Makefile(如使用O3优化,设置HZ值)进行测试,最终结果以DMIPS/MHz表示。
CoreMark则是针对嵌入式应用的性能测试,它关注处理器在执行典型工作负载(如算术、内存操作等)时的迭代次数。CoreMark结果越高,表明处理器性能越好,同时还能提供功耗数据。在GitHub上获取源代码后,通过修改makefile编译并执行,结果以Iterations/Sec(每秒迭代次数)/MHz表示。
另外,Stream测试用于测量内存带宽,对CPU计算能力需求较小,但对内存带宽压力大。Stream测试包含四个基本功能,如Copy、Scale等,通过修改makefile进行多线程测试,结果反映了内存带宽的性能。
详解Java Stream的分组和聚合
通过使用Java Stream和Collectors类,我们可以对分组内的元素进行有意义的操作,如计算和、平均数或最大/最小值,这有助于我们有效地分析数据。此外,我们可以使用Java Stream和Collectors轻松完成复杂字段的聚合,包括加权平均数、几何平均数等。
实现这种功能的关键是利用Collectors.groupingBy方法,与分类函数配合,对分组后的元素执行聚合操作。例如,我们可以在一个由TaxEntry实体组成的集合中,根据城市或省进行分组,并计算税目总数。这展示了如何使用Java Stream高效地处理大量数据。
对于更复杂的聚合问题,例如同时对多个字段进行操作或者计算复合指标,我们可以定义一个封装这些指标的record类。通过使用Collectors.toMap方法,我们可以轻松地将原始数据转换为映射。这种做法有效地处理了多种字段和非原始数据类型(如BigDecimal)的分组和聚合操作。
进一步地,为了计算加权平均数或执行其他形式的复杂计算,我们可以采用分阶段处理的方法。首先使用Collectors.mapping初始化所需的聚合指标,然后通过Collectors.reducing来执行复杂计算,例如计算总和与个数,从而得出平均值。
综上所述,通过Java Stream和Collectors API以及记录集合作品,我们可以高效地解决多字段分组和聚合问题,不仅适用于原始数据类型,还能处理复杂的数据结构和指标需求。这些方法提高了数据处理的效率和灵活性,使得在开发和维护大数据库应用时变得更加轻松。最终,这为开发者提供了一种简化并加快数据分析和处理流程的有效手段。
微型ADCP水文仪器StreamPro微型ADCP技术指标
StreamPro微型ADCP是一款专为水文测量设计的高效仪器,其独特的宽带专利技术能够精确地捕捉流速剖面信息。该设备支持1-个单元的选择,最小单元长度仅为2厘米,最大单元长度可达厘米,为精细测量提供了灵活性。它的最大剖面深度可达2米,若需进一步扩展,可升级至4米深度,适用于多种水文环境。
第一单元的起点范围宽广,从7到厘米,适应了不同深度的测量需求。流速量程覆盖±7.2米/秒,确保了对强烈水流的准确捕捉。在精度方面,StreamPro拥有出色的表现,其测量误差在±1.0%和±0.2厘米/秒之间,确保数据的可靠性。此外,分辨率高达1毫米/秒,使得微小的流速变化也能清晰捕捉。
StreamPro的另一个亮点是其快速的数据输出能力,流速数据以1 Hz的速率实时输出,对于实时监测和分析非常有利。同时,其水跟踪速率高达 Hz,使得水体动态变化的追踪更为及时准确。
星流(Stellar Stream)
探讨星流(Stellar Stream)的识别方法及在星系演化中的作用,星流在天文学中是理解星系演变、确定星系势和研究晕中过密度区子块的关键。
星流的识别有两种方式:首先,通过星群中的过量密度;其次,寻找具有相似位置和速度的星群(利用角动量可缓解对共位置的需求)。识别星流的直接方法是确定星系中恒星的三维位置,然后寻找比周围地区高密度的局部区域。
为了获取三维坐标,我们需要筛选具有标准烛光属性的恒星以确定距离。水平支星是很好的标准烛光,因为它们的绝对亮度非常狭窄。蓝水平支星(BHBs)可以通过蓝色颜色优先选择,尽管会有些与蓝色散星的混杂,后者有主序星的表面重力。然而,BHBs仅存在于非常古老的、金属贫乏的星群中,且此类星群相对较少。红水平支星的识别更困难,因容易与巨星分支星及较暗的主序星混淆。
RR Lyrae星是更好的标准烛光,但识别它们较为困难(通常通过多周期变化研究),且仅出现在中等年龄、相对金属贫乏的群体中。RR Lyrae星是稀有且更少的密度指标,比水平支星更难描绘星群密度。为了确定每个RR Lyrae星的距离,还需要额外观察(光谱或时间序列光度计)。
M巨星非常明亮,但仅存在于金属丰富的星群中,而在银河系晕中罕见。事实上,唯一已被验证的用M巨星追踪的星流是最大的且最明显的过量密度:半人马矮星流。Monoceros环、三角-安德罗梅达云和比斯开过量密度也在此星群中被研究。
K巨星是追踪星群密度的自然选择,因为它们在相似内在亮度的星群中数目更多,并存在于所有古老的星群中。使用K巨星的主要缺点是需要光谱(或特别敏感于K星重力的滤光器;见,例如,Majewski等人,)来区分K巨星与盘中大量相似视亮度的K矮星。此外,绝对亮度依赖于年龄和金属含量,颜色(红巨星分支在CMD上几乎垂直);测量的距离将严重依赖于用于校准它们的模型。