Skip to content
Calvin's Blog

摸鱼精选第 35 期

May 26, 2024 — Reading

一般来说,如果是基础的中后台应用,大多数交互都比较粗糙,通常不需要。如果你的应用类似图形编辑器,大多数交互是颗粒状的(比如说移动形状),那么此时 useMemo 可能会起到很大的帮助。

使用 useMemo 进行优化仅在少数情况下有价值:

这几句是不是很熟悉,就是开头我说的 useMemo 的官方文档的用法中提到的这几项。

在其他情况下,将计算过程包装在 useMemo 中没有任何好处。不过这样做也没有重大危害,所以一些团队选择不考虑具体情况,尽可能多地使用 useMemo,这种做法会降低代码可读性。此外,并不是所有 useMemo 的使用都是有效的:一个“永远是新的”的单一值就足以破坏整个组件的记忆化效果。

本指南详细介绍了鸿蒙运行环境的配置、使用 Taro 开发鸿蒙应用的步骤和注意事项。

其他两篇姊妹文章:

使用 Taro 开发鸿蒙原生应用第一篇——探秘适配鸿蒙 ArkTS 的工作原理 (opens in a new window)

使用 Taro 开发鸿蒙原生应用第二篇 —— 当 Taro 遇到纯血鸿蒙 (opens in a new window)

本文主要介绍了红黑树的经典实现,包括 2-3-4 搜索树和经典红黑树的定义、性质,以及红黑树的插入和删除节点操作。此外,还分析了红黑树的时间复杂度,并给出了相关的参考资料。

重要亮点

本文介绍了鸿蒙系统的开发,包括开发简介、第一个鸿蒙版 Hello World、小试牛刀-度加首页和基础图谱入门。鸿蒙系统是一款面向万物互联的全场景分布式操作系统,支持手机、平板、智能穿戴、智慧屏和车机等多种终端设备。本文还介绍了鸿蒙系统的开发环境搭建、开发套件、第一个鸿蒙应用的创建、项目结构、运行和基础图谱入门。

这篇文章是一份全面的 C++编程避坑指南,它详细总结了在 C++开发中常见的错误和最佳实践。以下是文章的精确凝练总结:

  1. 空指针调用成员函数:静态成员函数可以被空指针调用,而非静态成员函数则会导致程序崩溃。
  2. 字符串处理:使用std::string的查找方法时要注意逻辑严谨性,避免错误的字符串匹配。同时,std::stringstd::wstring之间的转换要确保字符编码一致,避免乱码。
  3. 全局静态对象:虽然提供了良好的封装和线程安全,但可能会增加程序启动时间和资源消耗,建议使用externconstexpr来声明全局常量。
  4. 迭代器删除:在使用 STL 容器时,要注意迭代器失效问题,使用eraseremove组合可以安全地删除元素。
  5. 对象拷贝:避免不必要的对象拷贝,使用引用传递和返回值优化(RVO/NRVO)来提升性能。
  6. std::shared_ptr线程安全shared_ptr的引用计数操作是线程安全的,但修改指向时需注意线程安全问题。
  7. std::map使用:使用operator[]可能插入未定义值的元素,应确保键存在或指定默认值。
  8. sizeofstrlensizeof返回类型或变量的字节大小,strlen返回以 null 结尾的字符串长度,两者使用场景不同。
  9. std::async:可能不是真正的异步,取决于启动策略,确保使用std::launch::async以实现真正的异步执行。
  10. 内存泄漏:在使用智能指针如std::shared_ptr时,确保在异常安全的情况下创建和管理,避免内存泄漏。
  11. constconstexprconst保证变量不可修改,而constexpr用于编译时可计算的常量表达式,提高程序性能。

文章最后鼓励 C++开发者交流经验,以避免这些常见的陷阱,并提供了一些额外的学习资源链接。

这篇文章讨论了 Android 架构中的模块化设计原则,以实现高内聚和低耦合的代码结构。以下是文章的精确凝练总结:

  1. 组件与模块定义:组件是业务相关的文件集合,在 Android 中等同于 Gradle 模块。

  2. 模块化的好处:包括更合理的代码目录、更快的编译速度和更高的开发效率。

  3. 内聚性原则:由共同闭包原则(CCP)、共同复用原则(CRP)和复用发布等同原则(REP)组成,指导如何合理划分模块以追求高内聚。

  4. 耦合性原则:包括无环依赖原则(ADP)、稳定依赖原则(SDP)和稳定抽象原则(SAP),关注模块间的依赖关系。

  5. 模块划分:讨论了基于层级、业务和领域的划分方法,每种方法都有其优势和局限性。

  6. 封装模块:强调模块内部代码应该避免公开,以保持封装性和降低耦合。

  7. 集成模块:app 模块作为集成层,负责连接模块所需的所有“胶水代码”、初始化逻辑、导航代码和公共依赖注入。

  8. 实践建议:推荐学习《整洁架构》一书,以深入理解 Android 架构理念,并应用于实际项目中。

文章强调,模块化设计是每个初阶工程师迈向高阶过程中必须掌握的知识,整洁架构中的设计原则对于构建可维护和可扩展的 Android 应用至关重要。

B 站流媒体技术部直播组开发了自研流媒体协议 BMT(Bili Media Transport),旨在解决直播下行带宽节省和回源带宽成本问题。BMT 协议在兼容性、载荷比和握手简化方面进行了优化,支持多种编解码器和多轨道能力,减少额外开销,提高效率。通过核心库 libbmt 的开发和回源架构设计,BMT 在自建 CDN 回源带宽上取得显著节省效果,并在多音轨直播活动中展现了其优势。未来,BMT 协议将继续迭代,探索在推流端的应用并增加互动玩法,为业务赋能。

文章介绍了如何在鸿蒙系统中开发 Flutter 项目,并解决 Flutter 开发者不熟悉鸿蒙代码的问题。通过使用 pigeon 工具,可以一键生成 ets 代码,实现多端代码复用。文章提供了详细的代码示例和步骤,包括如何指定引用、创建接口协议文件、执行命令生成 Channel 文件,以及鸿蒙端的代码实现。通过这种方式,Flutter 代码可以无损迁移,实现 Android、iOS、鸿蒙的 UI 多端统一。

文章由 360 奇舞团前端开发工程师撰写,探讨了 Rust 与 JavaScript/TypeScript 在 Web 开发中的对比。作者在计划开发一个 SSR 渲染的 Blog 时,面临了选择 JavaScript 还是 Rust 的决策。文章从前端视角出发,寻找 Rust 与 Js/Ts 的语法相似之处,帮助加深对 Rust 语言的理解。同时,文章还讨论了 Rust 中一些有争议的新特性,如 Async,并提供了 Rust 与 JavaScript 在异步编程、类型系统、错误处理、模块系统等方面的详细对比。作者建议前端开发者通过实践和编译错误来学习 Rust,并尝试在 Rust 中实现熟悉的 JavaScript/TypeScript 功能或概念,以此加深两种语言的相似之处和不同之处的认知。

微信客户端团队开源的 WCDB 数据库经过五年发展,推出重大升级。新版 WCDB 不向后兼容旧接口,增加 C++核心逻辑支持,通过桥接方法使 Swift 和 Java 能接入。它完整支持 Java 和 Kotlin ORM,覆盖更多终端平台。WCDB 重写 Winq 提高 SQL 表达能力,强化数据备份和修复方案,引入数据迁移、压缩及自动添加新列功能,并进行 FTS5 优化和支持可中断事务。这些改进让 WCDB 在性能、安全性、灵活性和扩展性方面有显著提升,支持多语言且易于集成,适用于复杂业务场景。

文章讨论了客户端开发中如何通过动态降级系统确保在不同硬件和网络环境下提供流畅的用户体验。服务端已有的降级和熔断机制可以作为客户端设计降级系统的参考。客户端需要处理性能和网速两大类问题,进一步细分为 CPU、内存、电量和网速等方面。通过实时监控这些指标并设定阈值,系统能够计算出性能等级并在必要时通知业务方进行降级处理。

系统设计包括三个主要部分:DynamicLevelManager负责调用监控和决策模块,并通过通知告知业务方;DynamicLevelMonitor监控关键性能指标;DynamicLevelDecision对性能指标进行计算并决定性能级别。文章提供了伪代码示例,阐释了设计思路,并展示了如何在 iOS 系统中实现监控和计算逻辑。

降级处理的示例包括降低网络请求图片尺寸等,目的是减少系统性能消耗,快速恢复到正常运行状态。文章还介绍了如何通过NSNotificationCenter发送性能降级或恢复通知,并根据当前性能等级调整业务处理规则。

整体而言,动态降级系统通过实时监控和智能决策,帮助客户端在面对性能或网络问题时,依然能够提供相对流畅的用户体验,并保证应用内功能的正常使用不受影响。

Ollama 是一个开源框架,允许用户在本地运行大型语言模型,如 Llama 3、Mistral、Gemma 等,同时支持自定义和创建新模型。该框架使用 Go 语言开发,适用于 macOS、Linux 和 Windows 系统。

本文深入探讨了 Java 线程池的实现原理、源码分析,并提供了在业务场景中使用线程池的最佳实践。

线程池简介

Java 线程池的实现原理

源码分析

线程池在业务中的最佳实践

文章强调了在业务开发中合理利用线程池的重要性,并提供了实际代码示例和问题分析,帮助开发者更高效地使用线程池。

文章全面介绍了 Java 虚拟机(JVM)的基础知识,涵盖了 JVM 内存划分、堆内存分配策略、对象创建步骤、引用类型、类加载机制、垃圾回收(GC)及其算法、垃圾收集器配置、性能调优工具和故障排查策略。

JVM 内存划分:包括堆、方法区(元空间)、虚拟机栈、本地方法栈和程序计数器。堆是对象实例存储的共享区域,方法区存储类信息和静态变量,JDK1.8 后改为元空间。

堆内存分配策略:对象优先在 Eden 区分配,大对象直接进入老年代,长期存活的对象也会进入老年代。动态对象年龄判定和空间分配担保是确保 GC 安全进行的机制。

创建对象步骤:类加载检查、分配内存、初始化零值、设置对象头和执行 init 方法。

对象引用:包括强引用、软引用、弱引用和虚引用,影响垃圾回收行为。

JVM 类加载过程:包括加载、验证、准备、解析和初始化五个阶段。双亲委派机制保证了核心类的安全加载。

垃圾回收:介绍了引用计数法和可达性分析法,以及两次标记过程。垃圾回收算法包括复制算法、标记清除、标记整理和分代收集。

垃圾收集器:从 Serial、Parnew 到 CMS、G1、ZGC 等,各有特点,适用于不同的应用场景。

性能调优:使用 jps、jinfo、jstat 等工具监控和调优 JVM 性能。

故障排查:包括硬件故障、内存泄漏、CPU 飙高、死循环等问题的排查方法。

文章适合作为 JVM 入门和日常调优工作的参考。

本文详细介绍了 Netty 框架的核心组件、逻辑架构、IO 模型、Reactor 多线程模型、拆包粘包问题解决方案、自定义协议、WriteAndFlush 操作、内存管理、高性能数据结构和定时器原理。

核心组件

逻辑架构

五种 IO 模型

Reactor 多线程模型

拆包粘包问题

自定义协议

WriteAndFlush

内存管理

数据载体 ByteBuf

内存分配算法

高性能数据结构

零拷贝技术

select、poll、epoll 的区别

文章适合作为 Netty 入门和日常开发的参考资料。

本文主要介绍了 ChatGPT 的工作原理,包括其基本概念、概率来源、模型构建、训练过程、嵌入概念、内部结构、训练方法以及实际应用等方面。作者通过深入浅出的方式,解释了 ChatGPT 如何通过大量的文本数据进行训练,从而能够生成自然流畅的语言文本。同时,作者还探讨了 ChatGPT 在实际应用中可能存在的问题和挑战,并提出了一些未来的研究方向和建议。

重要亮点