首页 文章 精选 留言 我的

精选列表

搜索[优化],共10000篇文章
优秀的个人博客,低调大师

Android官方开发文档Training系列课程中文版:布局性能优化之ListView的优化

原文地址:http://android.xsoftlab.net/training/improving-layouts/smooth-scrolling.html 想要让ListView滑动流畅的关键所在是减轻主线程的负担。要确保任何的磁盘访问、网络访问、或者SQL访问都是在单独的线程中执行的。如果要测试APP的状态,可以开启StrictMode。 使用后台线程 使用工作线程可以使UI线程将所有的注意力都集中在UI的绘制上。在很多情况下,使用AsyncTask所提供的功能就可以在工作线程中处理耗时任务。AsyncTask会自动的将execute()发起的请求排队,并依次执行。这意味着你不要自己创建线程池。 在下面的示例代码中,AsyncTask被用来加载一张图像,并在加载结束后自动的将其渲染到UI上。它还在图像加载时展示了一个旋转的进度条。 // Using an AsyncTask to load the slow images in a background thread new AsyncTask<ViewHolder, Void, Bitmap>() { private ViewHolder v; @Override protected Bitmap doInBackground(ViewHolder... params) { v = params[0]; return mFakeImageLoader.getImage(); } @Override protected void onPostExecute(Bitmap result) { super.onPostExecute(result); if (v.position == position) { // If this item hasn't been recycled already, hide the // progress and set and show the image v.progress.setVisibility(View.GONE); v.icon.setVisibility(View.VISIBLE); v.icon.setImageBitmap(result); } } }.execute(holder); 从Android 3.0开始,AsyncTask提供了一项新特性:可以将任务运行在多核处理器上。你可以使用executeOnExecutor()方法发起执行请求,这样多个请求就可以同时进行,同时进行的任务数量取决于CPU的核心数量。 使用View Holder持有View对象 在滑动ListView时,代码可能会频繁的调用findViewById(),这会降低性能。就算是Adapter将已经加载过的View返回,但是在复用时还是需要去查询这些View来更新它们。杜绝重复使用findViewById()的方法就是使用”View Holder”设计模式。 ViewHolder对象将每个View组件存储于布局容器的tag属性内,所以你可以快速访问它们而不需要每次都去查询。首先,你需要创建一个类来持有已加载的View: static class ViewHolder { TextView text; TextView timestamp; ImageView icon; ProgressBar progress; int position; } 然后对ViewHolder的成员属性赋值,然后将其存放在布局容器内: ViewHolder holder = new ViewHolder(); holder.icon = (ImageView) convertView.findViewById(R.id.listitem_image); holder.text = (TextView) convertView.findViewById(R.id.listitem_text); holder.timestamp = (TextView) convertView.findViewById(R.id.listitem_timestamp); holder.progress = (ProgressBar) convertView.findViewById(R.id.progress_spinner); convertView.setTag(holder); 那么现在就可以很方便的对这些View组件进行访问,而不再需要对它们单独进行查询,如此便可以节省出宝贵的CPU资源。

优秀的个人博客,低调大师

优化技术专题-系统服务优化系列-这绝对是你的知识盲点,NUMA的为什么存在

NUMA的产生背景 在NUMA架构出现前,CPU欢快的朝着频率越来越高的方向发展(纵向发展)。受到物理极限的挑战,又转为核数越来越多的方向发展(横向发展)。在一开始,内存控制器还在北桥中,所有CPU对内存的访问都要通过北桥来完成。此时所有CPU访问内存都是“一致的”,如下图所示: 这样的架构称为UMA(Uniform Memory Access),直译为“统一内存访问”,这样的架构对软件层面来说非常容易,总线模型保证所有的内存访问是一致的,即每个处理器核心共享相同的内存地址空间。但随着CPU核心数的增加,这样的架构难免遇到问题,比如对总线的带宽带来挑战、访问同一块内存的冲突问题。为了解决这些问题,有人搞出了NUMA。 注意:北桥芯片(North Bridge)是主板芯片组中起主导作用的最重要的组成部分,也称为主桥(Host Bridge)。 一般来说, 芯片组的名称就是以北桥芯片的名称来命名的,例如:英特尔845E芯片组的北桥芯片是82845E,875P芯片组的北桥芯片是82875P等等。 NUMA构架细节 通过“NUMA的产生背景”,让我们了解到了之前内存访问架构原则,与此相对的就是NUMA,NUMA 全称 Non-Uniform Memory Access,译为“非一致性内存访问”。这种构架下,不同的内存器件和CPU核心从属不同的Node,每个 Node 都有自己的集成内存控制器(IMC,Integrated Memory Controller)。 在 Node 内部,架构类似SMP,使用IMC Bus进行不同核心间的通信;不同的 Node间通过QPI(Quick Path Interconnect)进行通信,如下图所示: 一般来说,一个内存插槽对应一个Node。需要注意的一个特点是,QPI的延迟要高于IMC Bus,也就是说CPU访问内存有了远近(remote/local)之别,而且实验分析来看,这个差别非常明显。 在Linux中,对于NUMA有以下几个需要注意的地方: 默认情况下,内核不会将内存页面从一个 NUMA Node 迁移到另外一个 NUMA Node; 但是有现成的工具可以实现将冷页面迁移到远程(Remote)的节点:NUMA Balancing; 关于不同 NUMA Node 上内存页面迁移的规则,社区中有依然有不少争论。 NUMA详细分析 非一致性内存架构(Non-uniform Memory Architecture)是为了解决传统的对称多处理(Symmetric Multi-processor)系统中的可扩展性问题而诞生的。在对称多处理系统中,处理器共享北桥中的内存控制器来达到共同访问外部内存和IO的目的,也就是说所有的处理器对内存和I/O的访问方式和开销都是相同的。在这种系统中,随着更多的处理器被添加到SMP系统中,总线的竞争将会越来越大,系统的性能也必将随之大打折扣。SMP系统的示意图如下: 本地节点: 对于某个节点中的所有CPU,此节点称为本地节点;(速度最快) 邻居节点: 与本地节点相邻的节点称为邻居节点;(速度次之) 远端节点: 非本地节点或邻居节点的节点,称为远端节点。(速度最差) 超立方体可以作为一种有效的拓扑来描述NUMA系统,它将系统中的节点数限制在2^C内,C是每个节点拥有的邻居节点数,如下图所示 开销总结 以C=3为例,则对于节点1而言,2,3,5则为邻居节点,4,6,7,8为远端节点,显然访问开销的关系为 本地节点<邻居节点<远端节点。 NUMA案例分析 AMD Hyper-Transport 早期的SMP(对称多处理器系统) 只拥有一个位于北桥中的内存控制器,而如今更先进的做法是将内存控制器整合到CPU中去,这样每个CPU都拥有自己的内存控制器,不会相互之间产生竞争。 最先采用这种做法的一批处理器就是AMD在2003年推出的AMD Opteron系列处理器,其结构如下图所示: 每个CPU中都整合了一个内存控制器(IMC),并且CPU之间采用了一种Hyper-Transport的技术建立连接,这种连接可以使得CPU通过其他CPU来访问外部内存,当然访问开销要比访问本地内存更大。 操作系统的支持 为了支持NUMA架构,OS的设计必须将内存分布的特点考虑进去。 举一个简单的例子,假如一个进程运行在一个给定的处理器中,那么为这个进程所分配的物理内存就应该是该处理器的本地内存,而不是外部内存。 OS还要注意避免将一个进程从一个节点给迁移到另一个节点。在一个普通的多处理系统中,OS就应该已经尝试不去在处理器之间迁移进程,因为这意味着一个处理器的cache中的相关内容都将被丢失。如果在某种情况下必须进行迁移,那么OS可以随意选择一个空闲的处理器。 但是在NUMA系统中,可选择的新处理器将要受到一些限制,最重要的一点就是新处理器访问内存的开销不能比先前的处理器大,也就是说应该尽可能选择本地节点中的处理器。 当找不到符合条件的处理器,OS才能选择其他类型的处理器。 在这种较糟的情况下有两种选择: 如果进程只是暂时性的被迁移出去,可以再将其迁移回更加合适的处理器; 如果不是暂时性的,那么可以将该进程的内存拷贝到新处理器的内存中,这样就可以通过访问拷贝的内存来消除访问外部内存的开销,显然这是一种空间换时间的做法。 NUMA Node 操作 NUMA Node 分配 有两个NUMA Node,每个节点管理16GB内存。 NUMA Node 绑定 Node 和 Node 之间进行通信的代价是不等的,同样是 Remote 节点,其代价可能不一样,这个信息在 node distances 中以一个矩阵的方式展现。 我们可以将一个进程绑定在某个 CPU 或 NUMA Node 的内存上执行,如上图所示。 NUMA 状态

资源下载

更多资源
Mario

Mario

马里奥是站在游戏界顶峰的超人气多面角色。马里奥靠吃蘑菇成长,特征是大鼻子、头戴帽子、身穿背带裤,还留着胡子。与他的双胞胎兄弟路易基一起,长年担任任天堂的招牌角色。

Nacos

Nacos

Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service 的首字母简称,一个易于构建 AI Agent 应用的动态服务发现、配置管理和AI智能体管理平台。Nacos 致力于帮助您发现、配置和管理微服务及AI智能体应用。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据、流量管理。Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。

Rocky Linux

Rocky Linux

Rocky Linux(中文名:洛基)是由Gregory Kurtzer于2020年12月发起的企业级Linux发行版,作为CentOS稳定版停止维护后与RHEL(Red Hat Enterprise Linux)完全兼容的开源替代方案,由社区拥有并管理,支持x86_64、aarch64等架构。其通过重新编译RHEL源代码提供长期稳定性,采用模块化包装和SELinux安全架构,默认包含GNOME桌面环境及XFS文件系统,支持十年生命周期更新。

Sublime Text

Sublime Text

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。

用户登录
用户注册