博客导航
不忘初心,勇往直前!!!^_^
2022-01-14 在你可能在浪费时间的时候,想想那些揪心的日子!(时间是最宝贵的资源)
2022-04-27 不忘初心!
Android系统
搭建Android系统模拟器开发环境
Input子系统
ION内存管理
Treble架构中的HIDL
dma-buf详解
智能指针
ashmem匿名共享内存
C++
benchmark
C/C++
线程池的实现
bazel编译&构建
C++11
C++ Tips of the Week
Linux & 内核
Kernel
巧妙的kfifo
自动驾驶
Fast DDS
我的内存呢?Linux MemAvailable 如何计算
使用Linux开发是常见的问题是:我的内存呢?怎么只剩这么点了?这是怎么回事呢?
消失的内存
通常我们会用free命令(如下)或Node Exporter + Prometheus 来监控系统的内存。
1234# free total used free shared buff/cache availableMem: 6460324 111876 5577136 75188 771312 6073040Swap: 0
上面的输出中,我们很自然的以为free代表可用内存,所以经常会发现这个值特别低,造成“系统的内存用光”的错觉。在比较新的内核里,会有available一项,它才是“可用内存”。
这里有个小知识,free指的是完全没有被用到的内存,而Linux认为内存不用也是浪费,因此会尽量“多”地把内存用来做各种缓存,提高系统的性能。在内存不够用时,它会释放缓存腾出空间给应用程序。因此早期没有available这项指标时,一般会认为 ...
搭建Android系统模拟器开发环境
自从2022年1月份辞去了Android系统的工作从事自动驾驶行业以来, 已经接近1年了, 在这一年间基本没接触过Android系统的源代码了, 但是Android的设计思想还是在的, 特别是在复杂的自动驾驶系统里面, 很多好的设计和架构都是如出一辙, 所以在好学心的驱使下, 还是打算把Android的aosp源代码给下载下来研究研究, 毕竟Android也是在不停演进, 站在巨人的肩膀上也可以有更多的视野
但是有个问题, 光看源代码可能远远不能满足我的需求, 但是手头上已经没有Android的开发设备了(都换成了Apple设备), 于是就开始倒腾模拟器了, 毕竟模拟器环境搭建好之后开发效率还是挺高的, 话不多说行动起来
Android源代码是通过repo管理的, 一个repo仓库管理了N多了git仓, 首先是环境搭建, 我这边是基于一台联想工作站, 12代i7给Android预留了500G硬盘, 32G内存, 安装的ubuntu 1804系统
源代码环境搭建代码管理工具可以参考这个链接来下载repo:
https://source.android.com/docs/setup/dow ...
Linux性能分析60秒
本文翻译自Netflix技术博客:
Linux Performance Analysis in 60,000 Milliseconds | by Netflix Technology Blog | Netflix TechBlog
Frist 60 Seconds:Summary在本文中,Netfix的性能工程师团队会介绍在一上来的60秒内,在命令行中使用一套优化的性能调研,使用Linux系统中现成的工具。在头60内,你可以运行下面的命令来获取到一个High Level的系统资源利用率和正在运行的进程。首先是最容易理解的,查找一些错误信息和性能饱和度,然后才是资源利用率。饱和度是指一个资源已经超出了他本来应该持有的资源数量,可以理解为一个请求队列的长度,或者等待时间的消耗。
12345678910uptimedmesg | tailvmstat 1mpstat -P ALL 1pidstat 1iostat -xz 1free -msar -n DEV 1sar -n TCP,ETCP 1top
上面有一些工具需要使用到sysstat软件包,在ubuntu系统里面可以使用下面的命令去 ...
C++性能测试工具:google benchmark 进阶
本文将会介绍如何使用模板以及参数生成器来批量生成测试用例,简化繁琐的性能测试代码。
测试对象这次测试的对象是标准的vector,我们在Linux GCC上进行测试。为了写代码方便,开启了C++17的支持。
这次的疑问来自于《A Tour of C++》这本书,在第九章给出了一个很有意义的建议:尽量少用reserve方法。
我们都知道reserve会提前分配足够大的内存来容纳元素,这样在push_back时可以减少内存分配和元素移动的次数,从而提高性能。所以习惯上如果我们知道vector中存储元素的大致数量,就会使用reserve提前进行内存分配,这时典型的“空间换时间”。
而书中给出的理由仅仅是说vector的内存分配器性能已经很高,预分配往往是多此一举,收效甚微。事实到底如何呢?性能问题光靠脑补是不能定位的,所以我们用实验结果说话。
使用模板函数生成测试测试用例的设计很简单,我们定义普通vector和reserve过的vector,然后分别对其添加一定数量的元素(逐步从少到多)测试性能。同时vector本身是泛型容器,所以为了测试的全面性我们需要测试两至三种类型参数。
如果针对每一种 ...
C++性能测试工具:google benchmark 入门(2)
上一篇中初步体验了google benchmark的使用,本文将进一步深入了解google benchmark的常用方法。
向测试用例传递参数之前我们的测试用例都只接受一个benchmark::State&类型的参数,如果我们需要给测试用例传递额外的参数呢?
举个例子,加入我们需要实现一个队列,现有ring buffer和linked list两种实现可选,现在我们要测试两种方案在不同情况下的性能表现:
1234567891011121314151617181920212223242526272829303132333435// 必要的数据结构#include "ring.h"#include "linked_ring.h" // ring buffer的测试static void bench_array_ring_insert_int_10(benchmark::State& state){ auto ring = ArrayRing<int>(10); for (auto _: state) ...
C++性能测试工具:google benchmark 入门(1)
如果你正在寻找一款C++性能测试工具,那么此文不容错过。
市面上的benchmark工具或多或少存在一些使用上的不方便,那么是否存在一个使用简便又功能强大的性能测试工具呢?答案是google/benchmark。
google/benchmark是一个由Google开发的基于googletest框架的C++ benchmark工具,它易于安装和使用,并提供了全面的性能测试接口。
下面来介绍google/benchmark的安装并用一个简短的例子介绍它的简单实用。
安装google/benchmarkgoogle/benchmark基于C++11标准和googletest框架,所以安装前需要先做一些准备工作。
首先是g++和cmake
1sudo apt install g++ cmake
确保你的g++版本在5.0以上,否则可能不能很好的支持C++11的某些特性。
然后是googletest框架,你可以选择单独安装,不过这里我选择将其作为benchmark源码树的依赖而不单独安装它,因为benchmark在编译安装时需要googletest,但是在使用时并不需要。
选择一个合适的目录 ...
Tip of the Week 126 ‘make_unique’是新的‘new’
随着代码库的扩展,越来越难以了解你依赖的每件事的细节。需要深入的知识无法扩展:我们必须依靠接口和契约来知道代码是正确的,无论是在写还是在审查代码。在许多情况下,类型系统可以用一种通用的方式来提供这些契约。类型系统契约使用的一致性,通过识别在堆上分配的对象存在潜在风险分配或所有权转移的位置,可以更轻松的编写和审查代码。
虽然在C++中,我们可以通过使用纯值来减少动态内存分配的需求,但是有时我们需要对象的声明周期超过其作用域。在动态分配对象时,C++代码应该优先使用智能指针(最常见的std::unique_ptr)而不是原生指针。这提供了关于分配和所有权转移一致性,并在那些需要更仔细审查代码所有权问题的地方留下了更清晰地视觉提示。满足C++14之后,在外部如何分配及异常安全上的副作用只是小事。
关于此的两个关键工具是absl::make_unique()(C++14的std::make_unique的C++11实现,用于免泄漏动态分配)和absl::WrapUnique()(用于包装拥有指向相应std::unique_ptr类型的原生指针)。他们可以再absl/memory/memory. ...
Tip of the Week 123 absl::optional和std::unique_ptr
如何存储值?此贴士讨论了集中存储值得方法。此处我们使用类成员变量作为示例,但是以下的许多同样也适用于局部变量。
1234567891011#include <memory>#include "third_party/absl/types/optional.h"#include ".../bar.h"class Foo { ... private: Bar val_; absl::optional<Bar> opt_; std::unique_ptr<Bar> ptr_;};
作为一个纯对象这是最简单的方法,val_分别在Foo的构造函数的开头和Foo析构函数的末尾被构造和销毁。如果Bar有一个默认的构造函数,那么它甚至不需要显式初始化。
val_使用起来非常安全,因为它的值不能为null。这小出了一类潜在的错误。
但是bar对象不是很灵活:
val_的生命周期基本与它的父Foo对象的生命周期相关,这有时并不是想要的。如果Bar支持移动或交换操作,那么能够通过这些操作替换val_的 ...
Tip of the Week 116 保留多参数的引用
从绘画到图像,从图像到文本,从文本到声音,一种虚构的指针指示、展示、固定、定位、强加引用系统,试图稳定一个独立空间。——米歇尔·福柯创作的这不是一只烟斗
const引用与指向const的指针const引用用作函数的参数,与指向const的指针相比,它有几个优点:它们不能为null。并且很明显该函数没有取得对象的所有权。但是它们有其他的有事会出现问题的差异:它们更加隐式(即在调用点没有任何内容表明我们正在接受引用),并且它们可以被绑定到临时变量。
类中悬空引用的风险将以下类作为示例:
12345678class Foo { public: explicit Foo(const std::string& content) : content_(content) {} const std::string& content() const { return content_; } private: const std::string& content_;};
它看起来是合理的。但是如果我们从stri ...