摸鱼精选第 24 期

1. Five ways to break Swift Concurrency

Apple 官方文档中说 @MainActor 可以保证方法或属性在主线程被调用。 但作者发现在 Xcode 14.1 中,有些情况下是依然在后台线程跑的,比如

  • self.perform(#selector(self.mainActorFunction))
  • NotificationCenter.default 添加 selector 或者 block
  • 其他一些 OC 方法的 selector 或 block

所以,@MainActor 最好用在你自己的纯 Swift 代码中,不用 selector,不要和其他的并发模式(比如 OperationQueue)混在一起。

2. Effective Shell

作者说是给 shell 用户的教程,不是教你写 shell 脚本。shell 本身能力有限,你要知道 shell 能干什么,不能干什么,想要高级点的可以使用脚本编程语言,比如 Python。

3. C++20 Coroutines and io_uring Part 1

系列文章,还有: C++20 Coroutines and io_uring Part 2 C++20 Coroutines and io_uring Part 3

io_uring 算是这几年 Linux 新增的最实用的功能了,现在大部分服务器都慢慢转向 io_uring

4. Vue3 入门指南与实战案例

入门文章,不一样的是从前端工程化说起,我觉得这是很多 Vuer 们很欠缺的东西,大部分只会 vue-cli 创建项目,再深入就不会了。

5. 百度 APP iOS 端内存优化实践-内存管控方案

大部分场景为了加快启动、响应速度,都会用到内存缓存,但是如果处理不当的时候,内存累积到一定程度会被系统强制要求回收内存,或者导致 OOM 类型的崩溃。

百度 APP 内存管控方案具有如下特点:

  • 针对不同机型制定了相应的内存水位可以更加从容地释放内存。本技术方案结合 Jetsam 机制和百度 APP 线上内存数据,制定了 iPhone 各机型允许使用的内存水位线,给业务和框架更大的空间释放和清理内存。
  • 实时内存监控和精细化页面内存预测,在实时内存监控的基础上,开发了页面级的内存度量方案,可以估算出用户在新开一个页面内存涨幅多少,在未来一段时间内存会不会达到危险水位。
  • 内存管控方案提供主动和被动通知两种方式获取内存水位状态,实现了各业务层根据手机内存情况实时降级,时效性更强,跟之前服务端降全量降级方案相比,更加灵活,性能更好。

6. 淘宝拍立淘 iOS 相册架构设计小结

要做好一个相册框架其实也不是件容易的事,有几个问题需要仔细考虑:

  1. 相册变更的刷新处理
  2. 缩略图缓存、大图预览
  3. iOS 14 新增的 "Limited Photo Library Access" 模式
  4. iOS 15.3 的 App 隐私报告,读取照片的记录会记录下来
  5. iCloud 图片读取
  6. 多线程处理

7. React 中的重新渲染

React 重新渲染,指的是在类函数中,会重新执行 render 函数,类似 Flutter 中的 build 函数,函数组件中,会重新执行这个函数。

React 组件在组件的状态 state 或者组件的属性 props 改变的时候,会重新渲染,条件简单,但是实际上稍不注意,会引起灾难性的重新渲染。

8. 如何魔改 Retrofit

其实就是 AOP 的一个案例,拦截数据请求。

9. 线程和协程,有什么区别,为什么协程可以创建很多?

协程是基于线程实现的,但是两者概念上有很多不一样。

协程有以下优点:

  • 无需线程上下文切换的开销
  • 无需原子操作锁定及同步的开销
  • 方便切换控制流,简化编程模型

10. 《FFmpeg 原理》

做音视频的一定要多研究 FFmpeg。

本书《FFmpeg 原理》主要讲解 FFmpeg 原理性的知识,前面几章主要讲解一些音视频开发的基础知识,例如原始数据 YUV 跟 RGB,封装格式 FLV 跟 MP4 ,压缩编码的基本概念,还有封装格式分析。后面的章节主要讲解如何搭建 FFmpeg 各种调试环境,同时提供 FFmpeg API 函数的使用示例,最重要的是 分析 ffmpeg.c 跟 ffplay.c 的源码逻辑。

11. Writing an OS in Rust

使用 Rust 写一个小型的操作系统,有中文翻译版。 目前已完成部分:

  • A Minimal Rust Kernel
  • VGA Text Mode
  • CPU Exceptions
  • Double Faults
  • Hardware Interrupts
  • Paging Implementation
  • Heap Allocation

12. Inside boost::unordered_flat_map

目前 boost::unordered_flat_map 是最快的 hashmap 了,但是他们做了啥技巧能这么快呢?一些缓存友好的设计,以及 simd

13. Book Review: Embracing Modern C++ Safely

《Embracing Modern C++ Safely》 的书评。

想看的可以去找原书,原书的简介如下,机翻的:

本书总结了 C++社区多年来应用 C++11 和 C++14 功能的经验,将帮助您做出有效而安全的设计决策,这些决策反映了在大规模、多样化的软件开发环境中现实世界中经济的工程权衡。这本书使用从真实的代码库中派生的示例来客观地说明每一个发现,并阐明关键问题。作者确定了每个语言特性的合理用例、隐藏的陷阱和缺点。

这本书讲的不错,列一段代码:

Logger& getLogger() {
  // Even if two threads call getLogger() simultaneously,
  // local will be constructed only once.
  static Logger local("log.txt");
  return local;
}

struct FileManager {
  FileManager()
  {
    getLogger() << "Starting up file manager…";
    // …
  }

  ~FileManager()
  {
    getLogger() << "Shutting down file manager…";
    // …
  }
};

FileManager& getFileManager() {
  // Global fileManager, initialized on the first call
  // to getFileManager().
  static FileManager fileManager;
  return fileManager;
}

这两个是很常规的代码,但组合到一起,就有了问题,析构!如果 Logger 先于 FileManager 析构,FileManager 的析构用到了已经析构的 Logger,崩溃

这种通常是在程序退出的时候莫名其妙多个 core。如何合理的解决这个问题?加锁?

14. kmem_guard_t

iOS 16 / macOS 13 支持的新特性,走读一波 c api。其实在摸鱼精选 23 期的第 10 条已经有 Apple 官方对kalloc_type的解读了。

15. C++ 最佳实践

又一个最佳实践,稍微看看吧,英文原文在