1.?商业商业?ҵ?ʼ?Դ??
2.EasyLogger源码学习笔记(1)
3.EasyLogger源码学习笔记(3)
4.Mobx源码阅读笔记——3. proxy 还是defineProperty,劫持对象行为的笔记笔记两个方案
5.mmdetection源码笔记(一):train.py解读
6.EasyLogger源码学习笔记(5)
??ҵ?ʼ?Դ??
在闲暇之余,阅读JDK源码能加深对自己开发环境的源码源码理解,同时也大有裨益。商业商业本文为您介绍阿里巴巴发布的笔记笔记版JDK源码剖析,以展示其内部设计的源码源码崩坏三源码精妙之处。通过阅读,商业商业您将发现与自身知识的笔记笔记差距远超想象。这份详尽的源码源码笔记对源码内容进行了精细划分,方便学习。商业商业以下是笔记笔记其章节概览:
多线程基础 Atomic类 Lock与Condition 同步工具类 并发容器 线程池与Future ForkJoinPool CompletableFuture请注意,由于笔记内容丰富,源码源码篇幅较长,商业商业本文仅展示部分章节概览。笔记笔记如有需要,源码源码可点击下方链接获取完整版资料。
EasyLogger源码学习笔记(1)
在编程中,预处理器通过宏定义执行特定的逻辑。使用`#ifdef`和`#else`可以实现条件编译。当`#ifdef _XXXX`中的标识符_XXXX被`#define`命令定义时,编译器将执行`#ifdef`后的程序段1,否则执行`#else`后的程序段2。`#ifndef _XXXX`则表示如果标识符未被定义,则执行程序段1,反之执行程序段2。
ANSI C宏提供了多种实用信息,如`__DATE__`返回当前日期,`__TIME__`返回当前时间,`__FILE__`包含当前文件名,`__LINE__`包含当前行号。`__STDC__`常量用于判断程序是否遵循ANSI C标准。`__FUNCTION__`宏在预编译时返回所在函数的名称。
宏参数的茅台溯源码改版了吗处理可以通过`#`将参数变为字符串,使用`##`将两个宏参数连接起来。`__VA_ARGS__`是一个可变参数宏,需配合`define`使用,将宏左侧的`..`内容原样复制到右侧。
`#if defined`和`#if !defined`在功能上相似,都用于判断宏是否定义。`#error`指令在编译时生成错误消息并停止编译,用于警告开发者。
`extern`关键字用于引用其他文件中的函数或全局变量。例如`extern ElogErrCode elog_port_init(void);`声明了一个名为`elog_port_init`的外部函数,调用时需要指明返回值类型和参数。
在多线程编程中,使用`sched_param`结构来管理线程调度参数。`sem_t`表示信号量,用于实现互斥和同步。`pthread_attr_setschedpolicy(&thread_attr, SCHED_RR);`设置进程调度策略为实时轮转调度。
`SCHED_OTHER`默认分时调度策略,`SCHED_FIFO`采用先进先出策略,而`SCHED_RR`是`SCHED_FIFO`的增强版,提供实时轮转功能。使用`sched_get_priority_max(int policy);`和`sched_get_priority_min(int policy);`函数可以获取线程可设置的最高和最低优先级,其中策略参数即上述三种调度策略的宏定义。
`pthread_attr_setschedparam(&thread_attr, &thread_sched_param);`用于设置线程的优先级。通过这些函数,开发者可以精细地控制线程调度,提高程序性能。
EasyLogger源码学习笔记(3)
在EasyLogger源码学习中,枚举变量的使用十分直观。定义枚举类型后,可以直接在代码中操作,提升可读性和代码清晰度。
va_list是悬赏任务平台源码Spring一个字符指针,用于在可变参数表中导航和取值。首先,你需要定义一个va_list类型的变量ap,然后通过va_start函数初始化,ap指向变参表的第一个参数,后续的参数获取通过va_arg完成,它会根据指定类型从ap中提取并返回值,同时更新ap的位置。使用完毕后,记得调用va_end来释放ap,以确保程序的健壮性。
对于字符串处理,vsnprintf提供了格式化输出功能,它能在指定长度内限制输出,避免溢出。例如,snprintf函数可以格式化字符串并存储在给定的缓冲区中,确保字符数不超过预设的大小。
在查找字符串时,strstr函数用于在haystack中查找needle首次出现的位置,但不包括结束符。在函数定义中,诸如va_start(args, format)这样的语句用于处理可变参数。
在elog_output函数中,tag_sapce的初始化出现疑问,原因在于需要保证标签对齐,通过memset函数在前面填充空格。这里,用'ELOG_FILTER_TAG_MAX_LEN / 2 - tag_len'的长度来确保足够的空间,而不是'ELOG_FILTER_TAG_MAX_LEN + 1',因为这样可以避免不必要的填充。
在elog_find_tag函数中,源码4k效果返回值的问题在于它实际返回了日志的tag及其后续信息,而不是仅限于tag本身。因此,需要检查并修正这个逻辑,以确保返回正确的内容。
Mobx源码阅读笔记——3. proxy 还是defineProperty,劫持对象行为的两个方案
这篇文章将深入分析 MobX 的 observableObject 数据类型的源码,同时探讨使用 Proxy 和 Object.defineProperty 这两种实现方案来劫持对象行为的策略。通过分析,我们能够理解 MobX 在创建 observableObject 时是如何同时采用这两种方案,并在创建时决定使用哪一种。
首先,回顾 observableArray 的实现方式,通过 Proxy 代理数组的行为,转发给 ObservableArrayAdministration 来实现响应式修改的逻辑。同样,我们已经讨论过 observableValue 的实现,通过一个特殊的类 ObservableValue 直接使用其方法,无需代理。
对于 observableObject 的实现机制,其特点在于同时采用了上述两种方案,并且在创建时决定使用哪一种。让我们回到文章中提到的工厂方法,其中根据 options.proxy 的值来决定使用哪一种方案。
在 options.proxy 为 false 的情况下,使用第一条路径来实现 observableObject。这通过直接返回 extendObservable 的结果,其中 extendObservable 是一个工具函数,用于向已存在的目标对象添加 observable 属性。属性映射中的所有键值对都会导致目标上生成新的 observable 属性,并且属性映射中的任意 getters 会被转化为计算属性。
这里首先根据 options 参数选择特定的夏邑好的源码出售 decorator,这个过程与之前在第一篇文章中通过 options 参数选择特定的 enhancer 类似。实际上,这里的 decorator 起到了类似的作用,甚至在创建 decorator 这个过程本身也需要通过 enhancer 参数。
至于 decorator 和 enhancer 之间的耦合机制,文章中详细解释了 createDecoratorForEnhancer 和 createPropDecorator 函数,通过这些函数我们能够了解到它们是如何将 decorator 和 enhancer 联系起来的。
接下来,文章深入分析了 decorator 的作用机制,包括它如何决定是否立即执行,以及在不立即执行时如何将创建 prop 的相关信息保存下来。通过 initializeInstance 函数,我们了解了如何解决 # 问题,这涉及到如何正确处理那些在创建时未被立即执行的 prop。
最终,通过为 target 对象创建 ObservableObjectAdministration 管理对象,并通过 $mobx 和 target 属性将它们关联起来,我们完成了 observableObject 的创建。如果传入的 properties 不为空,则使用 extendObservableObjectWithProperties 来初始化。这里的代码逻辑相对简单,主要遍历 properties 中的所有键并调用对应的 decorator。
文章还指出,虽然在第一条路径中,使用 Object.defineProperty 重写了 prop 的 getter 和 setter,但在 MobX 4 及以下版本中,使用 Proxy 来实现 observableObject 的逻辑更为常见。Proxy 特性在 ES6 引入后,提供了更强大的能力来劫持对象的行为,不仅限于 getter 和 setter,还包括对象的其他行为。
最后,文章总结了使用 Proxy 方案的优点,包括能够更全面地劫持对象的行为,而不仅仅是属性的 getter 和 setter。Proxy 方案在实现双向绑定时,能够提供更灵活和强大的功能。同时,文章也提到了两种方案的局限性,尤其是在处理对象属性的可观察性方面,Proxy 方案在某些情况下可能更具优势。
mmdetection源码笔记(一):train.py解读
本文深入探讨mmdetection源码中的train.py文件,旨在为初学者提供详细解读,以便更好地理解模型训练过程。
train.py文件主要包括两个核心函数:parse_args()和main()。其中,parse_args()负责解析命令行参数,从创建解析对象到实际解析,实现获取命令行输入的各个参数。
main()函数为程序的主入口,执行一系列操作,包括配置文件、工作目录和日志的初始化处理。紧接着,通过调用build_detector()创建模型,build_dataset()注册数据集,最终执行模型训练的train_detector()函数。这三个关键函数的具体实现细节暂不展开讨论。
了解配置文件对掌握mmdetection至关重要。配置文件通常包含模型结构、训练配置和测试配置等信息,执行train.py时,主要依赖配置文件中的参数进行模型训练。
以博主的实际操作为例,通过命令行执行训练过程,主要参数为配置文件路径。配置文件加载到模型中后,根据配置文件指示的数据集路径,调用build_dataset()加载数据集模型,最后执行train_detector()进行训练。
接下来,我们深入分析train.py中的关键代码段。在第行,传入了cfg.model, train_cfg=cfg.train_cfg, test_cfg=cfg.test_cfg,其中cfg代表配置文件,它是一个字典,包含多个字段,每个字段的值可能是另一个字典。此行代码将配置文件中名为model、train_cfg和test_cfg的字段值传入build_detector()函数,用于模型创建。
对于model、train_cfg和test_cfg的具体源代码,配置文件通常为faster_rcnn_r_fpn_1x.py。这些配置文件详细地规定了模型结构、训练策略和测试配置,为模型训练提供了全面指导。
综上所述,train.py文件是mmdetection模型训练的核心,通过命令行参数解析、配置文件加载、模型创建、数据集注册和模型训练等关键步骤,实现对检测模型的高效训练。深入理解这些过程有助于进一步掌握mmdetection的使用与优化。
EasyLogger源码学习笔记(5)
在EasyLogger源码的学习中,我们了解到日志对象使用了互斥锁以确保同一时刻只有一个线程能进行操作,保证了日志管理的安全性与高效性。
对于异步输出,EasyLogger通过信号量实现了优化。当需要等待执行时,某个线程会被阻塞,以减少CPU的占用。这一特性允许用户单独设置异步输出的日志等级,提高系统的灵活性与可控性。
在文件输出时,使用了信号量集合,其中仅包含一个信号量。这一设计确保了同时只有一个线程能向文件中写入日志,避免了多线程并发写入导致的文件混乱。
日志输出的多样选择体现了EasyLogger的灵活性,无论是输出到文件还是串口,都可以根据需要配置是否采用异步输出,以适应不同的应用场景与性能需求。
此外,sem_post函数用于解锁由semby指定的信号量,执行对特定信号量的解锁操作。而semop函数则用于执行一组预先定义的信号量操作,适用于对多个信号量进行原子性操作。
在信号量集合仅包含一个信号量的情况下,使用sem_post函数进行操作可能直接替代使用semop函数。这一设计简化了信号量管理,提高了代码的可读性和效率。
Postgresql学习笔记0: 源码安装、gdb调试与VSCode智能提示设置
本文详细介绍如何使用源码安装PostgreSQL并进行gdb调试,以及如何在VSCode中设置智能提示。
首先,安装依赖、克隆仓库并指定编译安装目录。在configure中,开启额外选项以支持gdb调试。
配置环境变量,将安装目录的四个文件夹添加到环境中。初始化数据库,新建数据库目录并完成初始化。
启动数据库,通过psql连接数据库并查看登录信息。初始化后,自动创建名为postgres的数据库和安装时的用户。
启用gdb调试,进入pg_ctl所在的目录,执行特定命令,若成功将显示调试信息。单步调试pg_ctl,发现主程序启动位置。
注意,主程序启动由exec执行sh后启动,但可通过获取pid后attach的方式进行调试。使用pg_ctl启动后,发现有多个进程,包括响应客户端请求的后端进程。
使用gdb调试指定进程,结果显示进程在系统调用epoll_wait中,此时没有源码调试文件。使用backtrace追踪调用栈信息,可以观察到后端进程等待客户端网络活动的正常运行状态。
继续调试SocketBackend,接受客户端链接,可在此处设置断点。使用ctrl c暂停进程,然后在psql连接客户端一侧使用\l命令,后端进程继续执行,成功进入PostgreSQL业务代码,并附带源码调试信息。
VSCode智能提示设置中,发现直接打开项目文件夹时,代码提示和补全功能受限。通过查阅得知,智能跳转通常需要一个编译数据库(compile_commands.json)。这个文件包含编译器在编译项目时使用的命令,允许代码分析工具理解代码编译过程,提供准确的智能感知。
使用bear拦截编译命令,安装bear并使用Ubuntu的apt进行安装。通过特定命令捕获编译命令,生成compile_commands.json文件。注意,在执行make命令前,需先执行make clean以清除之前的编译结果,确保bear能正确捕获编译命令。
设置VSCode时,导入生成的compile_commands.json文件,之后重启VSCode,发现C文件已具备智能提示和跳转功能。
参考资料包括postgresql.org官方文档、知乎专栏以及CSDN博客文章,本文在Zhihu平台上使用VSCode完成创作并发布。