今天面试阿里后端开发,

● 面试官提问:谈谈你对 const 理解

● 我这样回答的: const 仅仅表示变量不能修改,太简答了,我早就知道了。

● 面试官回复:你觉得 这样能面过 P7 ,百万年薪岗位吗。

痛定思痛,今天,聊聊比较重要性能优化的思路:

● 编译期优化

● 从 cpu 角度理解 编译期优化

一. 在项目中带来什么收益,why

1.1 编译期计算

● 所有比较在编译期完成,零运行时开销。

● 例如 if constexpr std::is_same_v (先别走看,不同特性,有着同样原理)

● 更多阅读 CppCon 2014

CppCon 2014: Walter E. Brown "Modern Template Metaprogramming: A Compendium, Part I

1.2 为什么能带来这样收益,第一性原理或者核心实现原理 是什么?

std::is_same_v 是 C++17 引入的编译期类型比较工具,

用于判断两个类型是否严格相同。

if T and U name the same type (taking into account const/volatile qualifications),

provides the member constant value equal to true. Otherwise value is false.

● 具备内部实现先不考虑

● is_same_v 是 is_same<T, U>::value 的简写:

template <typename T, typename U>

inline constexpr bool is_same_v = is_same<T, U>::value;

其底层基于模板元编程中的偏特化机制实现:

与 typeid 的对比

特性 std::is_same_v typeid

比较阶段 编译期 运行时

多态类型 静态类型 动态类型(可能派发到派生类)

性能影响 零开销 RTTI 开销

适用场景 模板元编程、静态检查 运行时类型识别、调试

typeid 运算符

// expre_typeid_Operator.cpp

// compile with: /GR /EHsc

include

include

class Base {

public:

virtual void vvfunc() {}

};

class Derived : public Base {};

using namespace std;

//typeid 运算符允许在运行时确定对象的类型。

int main() {

Derived* pd = new Derived;

Base* pb = pd;

cout << typeid( pb ).name() << endl; //prints "class Base *"

cout << typeid( *pb ).name() << endl; //prints "class Derived"

cout << typeid( pd ).name() << endl; //prints "class Derived *"

cout << typeid( *pd ).name() << endl; //prints "class Derived"

delete pd;

}

if constexpr

● 在普通代码中用 if constexpr 基本没有实际用途。

● if constexpr 是 C++17 引入的编译期条件判断语句。

它在编译时判断条件,如果条件为假,则不会对分支内的代码进行实例化

与模板的关系 在模板中,if constexpr 可以根据模板参数的类型或值,在编译期选择不同的代码路径

● 核心原理:编译时分支决策 编译时条件求值

if constexpr 的条件必须是编译时常量表达式(如 std::is_same_v<T, int>)。编译器在模板实例化或代码生成阶段直接计算条件值,而非运行时

● 分支代码选择性编译

○ 条件为 true:仅编译 if 分支的代码,else 分支(若有)被完全丢弃,不进行语法检查。

○ 条件为 false:仅编译 else 分支,if 分支代码被丢弃

特性 if constexpr 普通 if

条件求值时机 编译时 运行时

分支代码处理 仅编译匹配分支,丢弃其余 编译所有分支,运行时选择执行

语法检查范围 仅检查匹配分支 检查所有分支的语法合法性

适用场景 模板元编程、类型分发 运行时条件判断

无效代码安全性 丢弃分支可包含无效代码 所有分支必须语法合法

1.3 预计多大收益:CPU的分支预测是如何影响程序运行

● 性能优化利器之constexpr

● 消除分支预测失败开销

● 原理:传统 if 在运行时进行分支预测,失败时需清空流水线(约 10~20 周期开销)2。

● if constexpr 优势:在编译时丢弃未匹配分支,生成无分支跳转的代码,彻底避免预测失败17。

● 案例:在 LLVM 编译器中,模板元编程改用 if constexpr 后,解析器的吞吐量提升 12%~15%(测试数据基于 SPEC CPU 2017)

● 实际性能测试对比

测试场景 传统 if

/ SFINAE if constexpr 提升幅度

类型分发(百万次调用) 42 ms 29 ms 31%

JSON 解析(大文件) 78 MB/s 吞吐量 92 MB/s 吞吐量 18%

网络协议处理(小包) 4.2 μs/包 3.5 μs/包 17%

二、举例说明

把字符串变成整数

该函数利用模板和 if constexpr,实现了“根据目标类型自动选择合适的字符串转数值函数”。

只有支持的类型(int、long、long long、double)会被实例化

include

include

include <type_traits>

using namespace std;

template

T str_to_num(const std::string& s)

{

if constexpr (is_same_v<T, int>) {

return std::stoi(s);//如果转换成功的话,stoi函数将会把转换后的得到数字以int类型返回

} else if constexpr (is_same_v<T, long>) {

return std::stol(s);

} else if constexpr (is_same_v<T, long long>) {

return std::stoll(s); //long long stoll

} else if constexpr (is_same_v<T, double>) {

return std::stod(s);

}

}

//g++ 3_if.cpp -std=c++17

int main() {

std::string s4 = "3.14159";

double d = str_to_num(s4);

std::cout << "double: " << d << std::endl;

return 0;

}

2.2 序列化 不存在的字段对应类构造

案例:从谷歌事故报告看技术透明度:我们差的不是SRE,是承认问题的勇气 。配置一个空策略导致解析 null 这几张

业务人员:清楚 什么字段 对应什么类型。

template

bool JSONDecoder::decode_json(const char *name, T& val, JSONObj *obj, bool mandatory)

{

JSONObjIter iter = obj->find_first(name);

if (iter.end()) {

if (mandatory) {

std::string s = "missing mandatory field " + std::string(name);

throw err(s);

}

if constexpr (std::is_default_constructible_v) {

val = T();

}

// 如果条件为 true,那么 {} 里面的代码 val = T(); 就会被编译。

return false;

}

保证了代码的健壮性:

它确保了即使 JSON 中缺少了某个可选字段,

你的变量也能被初始化为一个合理、确定的"空"状态,

而不是未定义的值。

在大型分布式系统如 Ceph、GlusterFS、分布式 KV 引擎(如 RocksDB)开发过程中,我们常常需要根据类型 T 的特性(是否可构造、可拷贝、可移动)来决定容器行为、初始化策略、内存对齐方式甚至 IO 缓冲区创建方式。

std::is_default_constructible 是 C++ 类型萃取(Type Traits)体系的一部分,它提供了一种在编译期判断类型是否支持默认构造的机制

template< class T >

inline constexpr bool is_default_constructible_v = is_default_constructible::value;

三、CPU眼里的C/C++

使用到工具

https://godbolt.org/

● 或者 gdb

3.1 编译期计算 什么含义

● const 与 constexpr 同样效果效果

int main() {

const int val = 1 + 2; //明确一数值

return 0;

}

上述代码汇编结果如下:

main:

push rbp

mov rbp, rsp

mov DWORD PTR [rbp-4], 3

mov eax, 0

pop rbp

ret

从上述汇编结果可以看出,在编译阶段就将val赋值成3,也就是说在编译阶段完成了求值操作

相反 普通的函数 求值过程将会延后至运行时候

constexpr int val = 1 + 2;//性能优化利器之constexpr

3.2 if constexpr 和 if 区别

三个 if 判断,最后编译代码后只有 1 个

基础回顾:c++代码生成的汇编代码

步骤 命令 等价命令 输出文件

预处理 cpp gcc -E .i, .ii

编译 cc1, cc1plus gcc -S .s

汇编 as gcc -c .o, .obj

链接 ld gcc 可执行文件

1 GCC编译C/C++的四个过程

gcc 是 GUN Compiler Collection的缩写。

预处理(pre-processing),E:插入头文件,替换宏,展开宏

gcc -E main.c -o main.i

编译(Compiling)S:编译成汇编

gcc -S main.i –o main.s

汇编(Assembling) c:编译成目标文件

gcc –c main.s –o main.o

链接 (Linking):链接到库中,变成可执行文件

gcc main.o –o main

./main

也可以一次性完成:

gcc main.c –o main

g++ test.cpp -o test

objdump -d tes

最动人的作品,为自己而写,刚刚好打动别人

我在寻找一位积极上进的小伙伴,

一起参与神奇早起 30 天改变人生计划,发展个人事业,不妨 试试

1️⃣关注公众号:后端开发成长指南(回复面经获取)获取过去我全部面试录音和大厂面试复盘攻略

2️⃣ 感兴趣的读者可以通过公众号获取老王的联系方式。

加入我的技术交流群Offer 来碗里 (回复“面经”获取),一起抱团取暖

----------------我是黄金分割线-----------------------------

抬头看天:走暗路、耕瘦田、进窄门、见微光,

● 我要通过技术拿到百万年薪P7职务,别人投入时间完成任务,别人采取措施解决问题了,不要不贪别人功劳,

● 但是不要给自己这样假设:别人完成就等着自己完成了,大家一个集团,一个公司,分工不同,不,这个懒惰表现,这个逃避问题表现,

● 别人不这么假设,至少kpi上不会写成自己的,至少晋升不是你,裁员淘汰是,你的整个公司ceo,整个部门总裁,整个领导不帮助一下的,他们不这么想 ,你什么没做,战略是别人10年一点带你研究的多难,项目拆分别人10年完成多少问题,项目实现10年安排组织一点点完成多少bug,多少代码,是不要给自己这样假设:你等了看了观察10年什么做 ,0 贡献,

● 但是不要给自己这样假设,别人全部市场,别人全部市场,别人占据全部客户,一切重要无比,你太差,太才,思考不行,沟通不行,认知不行,去tmd,给别人丢脸。这个方面我无法控制,在这方面经历任何问题应该的。

● 我控制 的事情是 我必须亲自了解行业遇到难题,了解有什么需求,行业解决方案,我可以从三万英尺看问题,像周围人学习,像免费公开英文资料学习,从模仿开始。然后免费公开。我要通过技术拿到百万年薪P7职务,我必须糊涂混沌中走出来

● 目标:拿百万年 想进入一线大厂,但在C++学习和应用上存在瓶颈,渴望跨越最后一道坎。

● 现状:缺乏实战,渴望提升动手能力公司的项目不会重构,没有重新设计的机会,导致难以深入理解需求。

● 成为优秀完成任务,成为团队、公司都认可的核心骨干。优秀地完成任务= 高效能 + 高质量 + 可持续 + 可度量

低头走路:

● 一次专注做好一个小事。

● 不扫一屋 何以扫天下,让自己早睡,早起,锻炼身体,刷牙保持个人卫生,多喝水 ,表达清楚 基本事情做好。

● 我控制 的事情是 我通过写自己代码拿到百万收益。代码就是杠杆,我必须创造可以运行在2c2g云主机小而美产品出来(服务普通人),而不是运行构建至少10台64cpu 300g内存物理机大而全项目(领航者,超越其他产品,出货全球N1,这个还是有停留有限斗争游戏,为top 10人企业服务)我必须糊涂混沌中走出来

阿里P7,竟问这么简单的题目?的更多相关文章

  1. 面阿里P7,竟问这么简单的题目?

    关于作者:程序猿石头(ID: tangleithu),来自十八县贫困农村(查看我的逆袭之路),BAT某厂P7,是前大疆(无人机)技术主管,曾经也在创业公司待过,有着丰富的经验. 本文首发于微信公众号, ...

  2. 阿里P7岗位面试,面试官问我:为什么HashMap底层树化标准的元素个数是8

    前言 先声明一下,本文有点标题党了,像我这样的菜鸡何德何能去面试阿里的P7岗啊,不过,这确实是阿里p7级岗位的面试题,当然,参加面试的人不是我,而是我部门的一个大佬.他把自己的面试经验分享给了我,也让 ...

  3. 转头条:阿里p7架构师:三年经验应该具备什么样的技能?

    问:工作中,有时候实现一个功能,会去看有没有现成的轮子可用.对于重复造轮子与改造轮子有什么看法? 答:一定会的,其实这也是一个提高技术能力的方法,比如今天想做个日期转换的功能,JDK8有日期的新特性就 ...

  4. 跟着阿里p7一起学java高并发 - 第18天:玩转java线程池,这一篇就够了

    java中的线程池,这一篇就够了 java高并发系列第18篇文章. 本文主要内容 什么是线程池 线程池实现原理 线程池中常见的各种队列 自定义线程创建的工厂 常见的饱和策略 自定义饱和策略 线程池中两 ...

  5. 阿里P7终于讲完了JDK+Spring+mybatis+Dubbo+SpringMvc+Netty源码

    前言 这里普及一下,每个公司都有职别定级系统,阿里也是,技术岗以 P 定级,一般校招 P5, 社招 P6 起.其实阅读源码也是有很多诀窍的,这里分享几点心得: 首先要会用.你要知道这个库是干什么的,掌 ...

  6. grep查询文本:问一个简单shell问题,将grep的输出赋值给一个变量

    问一个简单shell问题,将grep的输出赋值给一个变量 用grep命令得到的输出赋值给一个变量不成功. grep命令如下: 代码: $ grep -c '^abc' file.txt 输出为22,表 ...

  7. 阿里云api调用做简单的cmdb

    阿里云api调用做简单的cmdb 1 步骤 事实上就是调用阿里api.获取可用区,比方cn-hangzhou啊等等.然后在每一个区调用api 取ecs的状态信息,最好写到一个excel里面去.方便排序 ...

  8. 跟着阿里p7一起学java高并发 - 第19天:JUC中的Executor框架详解1,全面掌握java并发核心技术

    这是java高并发系列第19篇文章. 本文主要内容 介绍Executor框架相关内容 介绍Executor 介绍ExecutorService 介绍线程池ThreadPoolExecutor及案例 介 ...

  9. 分享一套主流框架源码资料,征服阿里 P7 面试必备!

    2019年已经过完一半了, 我在这里为大家准备了一份资料,征服阿里 P7 面试必备! 希望这些资料可以帮助到大家,从一个码农进阶为一个优秀的程序员,也可以帮大家提升系统实战能力. 这些资料包括: 讲解 ...

  10. 身边好几个技术一般的程序员都面上了,阿里P7门槛降低?

    经常在网上的论坛里看到讨论程序员的级别,尤其在跳槽类的信息里可以看到对标阿里P7,百度T6,腾讯3.1等字眼,似乎大厂的级别俨然可以成为业内的通用货币,类似于高考分数一样,哪一档就对应着什么样的待遇. ...

随机推荐

  1. linux 查看jdk安装路径

    [root@iz2ze9ufq5ehrayz6j88saz bin]# java -version java version "1.8.0_191" Java(TM) SE Run ...

  2. 如何避免VMware平台ESXi主机CPU使用率的“坑”?

    https://mp.weixin.qq.com/s?__biz=MjM5NTk0MTM1Mw==&mid=2650636818&idx=1&sn=c43f3a3146092f ...

  3. StringBuilder的介绍、构造方法及成员方法

    1.StringBuilder的介绍 1.StringBuilder是字符串缓冲区,可以认为是一种容器,能装任何类型的数据,但被装入的数据都会变为字符串 如图 无论是什么类型的数据,被装入字符串缓冲区 ...

  4. Scanner的进阶使用——数字的输入

    1.用Scanner输入数字(整数和小数) 1.定义一个整数变量 2.建立扫描器 3.使用if 4.建立电脑接收数据 5.设置else(那么)语法 6.关闭Scanner

  5. Docker Commonds

    脑子不够用,记录下自己所学所用的命令,备忘...不断补充. 最最基本的命令 查看 docker 信息 docker info 查看 docker 版本及相关信息 docker version 仅查看 ...

  6. Service Reliability Management: A Comprehensive Overview

    Service Reliability Management: A Comprehensive Overview Service reliability management is a critica ...

  7. Win10在WSL上使用Vivado对ZCU 102 PYNQ进行ILA调试

    ZCU 102上有两个USB接口(接口信号均为micro-A),其中靠近角落的接口为jtag端口,另外一个是uart端口 vivado自带的硬件管理器通过jtag端口连接到开发板.启动开发板,连接开发 ...

  8. MySQL 查询树结构、循环查询、查看函数、视图、存储过程

    MySQL经常会用到查询树结构数据,这里专门收集整了一篇. 构建函数 构建树查询函数:查询父级节点函数 -- 在mysql中完成节点下的所有节点或节点上的所有父节点的查询 -- 根据传入id查询所有父 ...

  9. 使用Python和SymPy推导斯特林公式

    引言 斯特林公式(Stirling's Approximation)是一种用来近似计算阶乘的数学公式.它是数学分析中非常重要的近似公式之一,尤其在概率论.统计学.物理学等领域中广泛应用.本文将使用 P ...

  10. [设计模式/Java] 设计模式之门面模式(外观模式)【20】

    概述 : 门面模式 := 外观模式 := Facade Pattern 产生背景 软件开发过程中,我们经常会遇到复杂系统,其中包含多个子系统和接口.在这种情况下,为了简化客户端的调用过程,提高代码的可 ...