自定义博客皮肤VIP专享

*博客头图:

格式为PNG、JPG,宽度*高度大于1920*100像素,不超过2MB,主视觉建议放在右侧,请参照线上博客头图

请上传大于1920*100像素的图片!

博客底图:

图片格式为PNG、JPG,不超过1MB,可上下左右平铺至整个背景

栏目图:

图片格式为PNG、JPG,图片宽度*高度为300*38像素,不超过0.5MB

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+
  • 博客(793)
  • 收藏
  • 关注

原创 LeetCode 3444.使数组包含目标值倍数的最小增量

题目想要让target中每个数都能在nums中找到一个倍数,比如target中有两个数3、5,那么需要nums中有一个数是3、5的最小公倍数的倍数,即15的倍数,如果target中的数是5、10,那么需要nums中有一个数是10的倍数,因此我们可以先计算出target中所有非空子集的最小公倍数,然后用暴力法dp,我们可以遍历nums中的所有数字,当前数字可以进行增加操作,也可以不进行增加操作,如果不对当前数字进行增加操作,就相当于nums中少了一个数字,问题变成了规模更小的同样问题;

2025-02-09 21:58:49 290

原创 LeetCode 3443.K次修改后的最大曼哈顿距离

题目要计算移动过程中,距离原点最大的曼哈顿距离,我们可以对移动过程中的每一位置进行查看,看当前位置经过最多k次修改后的最大曼哈顿距离,然后找出所有位置中经过修改后的距离最大值即可。将 s[1] 从 ‘S’ 改为 ‘N’ ,将 s[4] 从 ‘E’ 改为 ‘W’。将 s[2] 从 ‘S’ 改为 ‘N’ ,字符串 s 变为 “NWNE”。如果字符串s的长度为n,此方法时间复杂度为O(n),空间复杂度为O(1)。s 仅由 ‘N’、‘S’、‘E’ 和 ‘W’。‘S’:向南移动 1 个单位。

2025-02-06 00:43:23 193

原创 LeetCode 3442.奇偶频次间的最大差值 I

先遍历一遍字符串s,统计每个字母的出现次数,然后找出出现次数中,最大的奇数和最小的偶数,相减即可。字符 ‘a’ 出现 奇数次 ,次数为 5;字符 ‘b’ 出现 偶数次 ,次数为 2。字符 ‘a’ 出现 奇数次 ,次数为 3;字符 ‘c’ 出现 偶数次 ,次数为 2。返回 最大 差值,计算方法是出现 奇数次 字符的次数 减去 出现 偶数次 字符的次数。如果n是字符串s的长度,则此方法时间复杂度为O(n),空间复杂度为O(1)。s 至少由一个出现奇数次的字符和一个出现偶数次的字符组成。

2025-02-05 22:10:45 230

原创 PHP7内核剖析 学习笔记 第六章 函数

编译时,如果函数指定了返回值类型,则也为返回值创建一个zend_arg_info结构,该结构与参数的zend_arg_info结构保存在一起,即zend_op_array->arg_info数组中,返回值的zend_arg_info结构的保存位置为zend_op_array->arg_info[-1],即zend_op_array->arg_info指向的是参数开始的位置,而返回值的zend_arg_info结构在参数开始位置的前一位置。

2025-01-26 16:22:30 1190

原创 PHP7内核剖析 学习笔记 第五章 PHP的编译与执行(2)

5.4PHP的执行ZendVM执行器由指令处理handler与调度器组成:指令处理handler是每条opcode定义的具体处理过程,根据操作数的不同类型,每种opcode可定义25个handler,执行时,由执行器调用相应的handler完成指令的处理;调度器负责控制指令的执行,以及执行器的上下文切换,由调度器发起handler的执行。5.4.1handler的定义所有opcode的处理handler定义在Zend/zend_vm_def.h中,定义时不需要为每一条opcode定义25个handler

2025-01-19 00:55:32 632

原创 PHP7内核剖析 学习笔记 第五章 PHP的编译与执行(1)

PHP的编译与执行是两个相对独立的阶段,编译的流程为词法分析、语法分析、抽象语法树的生成,执行阶段则是根据编译阶段输出的产物(即opline指令)进行执行。5.1 语言的编译与执行计算机只认识机器语言,无法理解人类定义的编程语言,因此需要将编程语言翻译为机器语言,这个翻译过程称为编译。根据编译的时机不同,编程语言可分为编译型、解释型。编译型语言在程序运行前提前编译为计算机可执行的二进制文件,在执行时直接执行机器指令,这种类型语言的典型代表就是C、C++、Golang;解释型语言是程序在运行时由解释器边

2025-01-10 23:05:01 1212

原创 PHP7内核剖析 学习笔记 第四章 内存管理(2)

所有线程的tsrm_tls_entry结构保存在tsrm_tls_table数组中,该数组是一个全局变量,操作这个变量时需要加锁。然后根据线程id从tsrm_tls_table数组中获取tsrm_tls_entry,这里需要对取到的tsrm_tls_entry遍历,比较线程id,以找到该线程的tsrm_tls_entry,如果没有找到则表示线程还未分配tsrm_tls_entry,进入第2步进行分配,如果找到了则表示已经分配了tsrm_tls_entry,进入第3步返回storage中对应的资源。

2024-12-28 15:57:02 981

原创 PHP7内核剖析 学习笔记 第四章 内存管理(1)

PHP中的变量不需要手动释放,内核实现了变量的内存管理,包括内存的分配与回收。4.1 变量的自动GC机制C/C++语言中,如果想在堆上分配变量,需要手动进行内存的分配与释放,变量的内存管理是一件非常烦琐的事情,稍有不慎就可能导致不可预知的错误。现代高级语言普遍提供了变量的自动GC机制,由语言自己进行管理,这使得开发者不需要再去关心变量的分配与释放,PHP也实现了这种机制,PHP中可直接通过$声明一个变量,使用完也不需要手动销毁,内核自己清楚什么时间该进行释放。我们先自己思考下如何实现自动GC,最简单的

2024-12-24 21:45:15 946

原创 PHP7内核剖析 学习笔记 第三章 数据类型

type_info实际是将v结构的4个成员组合到了一起,v中的成员各站一个字节,总共4个字节,type_info也是4个字节,每个字节对应v的一个成员,可直接通过type_info位移获取v成员的值。如果发现中间映射表中要设置的位置已经被之前插入的元素占用了(值不等于初始化的-1),那么会把已经存在的值保存到新插入的Bucket中(实际是将Bucket的zval成员的u2.next指针指向已经存在的Bucket),然后将中间映射表中的值更新为新Bucket的存储位置,即每次都会把冲突的元素插到开头。

2024-12-14 18:36:56 1074

原创 PHP7内核剖析 学习笔记 第二章 SAPI

其中Cli和Fpm是完整实现的应用程序,它们有定义自己的main函数,方便我们从入口开始逐步分析PHP的处理,尤其是单进程的Cli,非常方便调试,本书后面章节基本都是以Cli模式为例的。fpm_init()中主要的处理就是上面介绍的几个init过程,完成这些初始化操作后就是最关键的fpm_run()操作了,此环节将fork子进程,启动进程管理器,执行后master进程将不会返回main()函数,之后各worker进程会返回,也就是说main()函数中调用fpm_run()之后的操作均是worker进程的。

2024-12-08 21:01:08 958

原创 PHP7内核剖析 学习笔记 第一章 PHP基础架构

这个版本被命名为PHP2,已经有了今日PHP的一些雏形,类似Perl的变量命名方式(Perl也用$声明标量变量,标量变量可以存储单一的值,如整数、浮点数、字符串,此外Perl中还有用@声明的数组变量和%声明的散列变量)、表单处理功能、嵌入到HTML中执行的能力。在编译阶段,PHP脚本将经历从PHP源代码到抽象语法树再到opline指令的转化过程,最终生成的opline指令就是Zend引擎可识别的执行指令,这些指令接着被执行器执行,这就是PHP代码解释执行的过程,本书介绍的大部分内容都是关于这两个阶段的。

2024-12-04 21:35:06 658

原创 Redis设计与实现 学习笔记 第二十四章 监视器

例如,客户端c10086向服务器发送MONITOR命令,那么这个客户端的REDIS_MONITOR标志会被打开,且这个客户端本身会被添加到monitors链表的表尾。服务器在每次处理命令请求前,都会调用replicationFeedMonitors函数,由这个函数将被处理的命令请求的相关信息发送给各个监视器。1.客户端可通过执行MONITOR命令,将客户端转换成监视器,接收并打印服务器处理的每个命令请求的相关信息。4.每次处理命令请求时,服务器都会遍历monitors链表,将相关信息发送给监视器。

2024-11-30 00:43:42 184

原创 Redis设计与实现 学习笔记 第二十三章 慢查询日志

每次执行命令的之前和之后,程序都会记录微秒格式的当前UNIX时间戳,这两个时间戳之间的差就是服务器执行命令所耗费的时长,服务器会将这个时长作为参数之一传送给slowlogPushEntryIfNeeded函数,此函数会检查是否需要为这次执行的命令创建慢查询日志。服务器使用先进先出方式保存多条慢查询日志,当服务器存储的慢查询日志数量等于slowlog-max-len选项的值时,服务器在添加一条新的慢查询日志前,会先将最旧的一条慢查询日志删除。

2024-11-30 00:27:15 656

原创 Redis设计与实现 学习笔记 第二十二章 二进制位数组

2.查表法的效果还受到CPU缓存的限制,对于固定大小的CPU缓存来说,创建的表越大,CPU缓存能保存的内容相比整个表格的比例就越少,查表时出现缓存不命中(cache miss)的情况就越多,缓存的换入和换出操作就会越频繁,最终影响查表法的实际效率。由于以上两个原因,我们可以得出结论,查表法是一种比遍历算法更好的统计办法,但受限于查表法带来的内存压力,以及缓存不命中可能带来的影响,我们只能考虑创建键长为8或16位的表,而这两种表带来的效率提升,对于处理非常长的位数组来说仍然远远不够。

2024-11-28 22:35:29 640

原创 Redis设计与实现 学习笔记 第二十一章 排序

SORT命令为每个被排序的键都创建一个与键长度相同的数组,数组的每个项都是一个redisSortObject结构,根据SORT命令使用的选项不同,程序使用redisSortObject结构的方式也不同。8.当SORT命令使用了GET选项时,命令会根据排序结果集中的元素,以及GET选项给定的模式,查找并返回其他键的值,而不是返回被排序的元素。但通过使用GET选项,我们可以让SORT命令对键进行排序后,根据被排序的元素,以及GET选项指定的模式,查找并返回某些键的值。

2024-11-24 23:40:39 733

原创 Redis设计与实现 学习笔记 第二十章 Lua脚本

主服务器清空repl_scriptcache_dict字典,可以强制自己向所有从服务器传播脚本,从而确保新的从服务器不会出现脚本未找到错误。repl_scriptcache_dict字典的键是一个个Lua脚本的SHA1校验和,而字典的值则全部都是NULL,当一个校验和出现在repl_scriptcache_dict字典时,说明这个校验和对应的Lua脚本已经传播给了所有从服务器,主服务器可以直接向从服务器传播包含这个SHA1校验和的EVALSHA命令,而不必担心从服务器会出现脚本未找到错误。

2024-11-23 17:20:29 1462

原创 Redis设计与实现 学习笔记 第十九章 事务

所有对数据库进行修改的命令,如SET、LPUSH(将一个或多个值插入到列表头部)、SADD、ZREM(移除有序集合中的一个或多个成员,不存在的成员将被忽略)、DEL、FLUSHDB(清空数据库中的所有key)等,在执行后都会调用multi.c/touchWatchKey函数对watched_keys字典进行检查,查看是否有客户端正在监视刚刚被命令修改过的数据库键,如果有,那么touchWatchKey函数会将监视被修改键的客户端的REDIS_DIRTY_CAS标识打开,表示该客户端的事务安全性已经被破坏。

2024-11-18 22:44:33 631

原创 Redis设计与实现 学习笔记 第十八章 发布与订阅

因为服务器状态中的pubsub_patterns链表记录了所有模式的订阅关系,所以为了将消息发送给所有与channel频道相匹配的模式的订阅者,PUBLISH命令要做的就是遍历整个pubsub_patterns链表,查找那些与channel频道相匹配的模式,并将消息发送给订阅了这些模式的客户端。通过执行SUBSCRIBE命令,客户端可订阅一个或多个频道,从而成为这些频道的订阅者(subscriber):每当有其他客户端向被订阅的频道发送消息(message)时,频道的所有订阅者都会收到这条消息。

2024-11-17 13:40:56 1002

原创 Redis设计与实现 学习笔记 第十七章 集群

2.PING消息:集群里的每个节点默认每隔一秒就会从已知节点列表中随机选出五个节点,然后对这五个节点中最长时间没有发送过PING消息的节点发送PING消息,以此来检测被选中的节点是否在线。另外,一个节点也可以通过向集群广播自己的PONG消息来让集群中的其他节点刷新关于这个节点的认识,例如当一次故障转移操作成功执行后,新的主节点会向集群广播一条PONG消息,以此来让集群中的其他节点立即知道这个节点已经变成了主节点,并且接管了已下线节点负责的槽。

2024-11-13 22:34:12 1344

原创 Redis设计与实现 学习笔记 第十六章 Sentinel

8.源Sentinel接收到目标Sentinel返回的命令回复后,会检查回复中leader_epoch参数的值和自己的配置纪元是否相同,如果相同,那么源Sentinel继续取出回复中的leader_runid参数,如果leader_runid参数的值和源Sentinel的运行ID一致,那么表示目标Sentinel将源Sentinel设置成了局部领头Sentinel。9.如果有某个Sentinel被半数以上Sentinel设置成了局部领头Sentinel,那么这个Sentinel成为领头Sentinel。

2024-11-07 21:19:36 929

原创 Redis设计与实现 学习笔记 第十五章 复制

如果因为网络故障,主服务器传播给从服务器的写命令在半路丢失,那么当从服务器向主服务器发送REPLCONF ACK命令时,主服务器将发觉从服务器的复制偏移量少于自己的复制偏移量,然后主服务器就会根据从服务器提交的复制偏移量,在复制积压缓冲区里找到从服务器缺少的数据,并将这些数据重新发给从服务器。3.当主服务器的BGSAVE命令执行完毕时,主服务器会将BGSAVE命令生成的RDB文件发送给从服务器,从服务器接收并载入这个RDB文件,将自己的数据库状态更新至主服务器执行BGSAVE命令时的数据库状态。

2024-11-03 16:03:04 769

原创 Redis设计与实现 学习笔记 第十四章 服务器

3.检查服务器设置的AOF重写条件是否满足,如果条件满足,且服务器没有在执行其他持久化操作,那么服务器将开始一次新的BGREWRITEAOF操作(虽然3是在rdb_child_pid和aof_child_pid属性都为-1时进行的检查,但由于1和2的存在,服务器还是会检查一下是否正在进行持久化操作)。命令的参数个数为-3,表示命令接受三个或以上数量的参数;命令的标识为“wm”,表示SET命令是一个写入命令,且在执行这个命令前,服务器应该对内存占用情况进行检查,因为这个命令可能会占用大量内存。

2024-10-31 19:52:29 718

原创 Redis设计与实现 学习笔记 第十三章 客户端

但timeout选项也有例外情况:如果客户端是主服务器(打开了REDIS_MASTER标志)、从服务器(打开了REDIS_SLAVE标志)、正在被BLPOP等命令阻塞(打开了REDIS_BLOCKED标志)、正在执行SUBSCRIBE(订阅某个频道)和PSUBSCRIBE(订阅一个或多个符合给定匹配模式的频道)等订阅命令,那么即使客户端的空转时间超过了timeout选项的值,客户端也不会被服务器关闭。1.在主从服务器进行复制操作时,主服务器会成为从服务器的客户端,而从服务器也会成为主服务器的客户端。

2024-10-27 21:21:29 787

原创 Redis设计与实现 学习笔记 第十二章 事件

3.对文件事件和时间事件的处理都是同步、有序、原子地执行的,服务器不会中途中断事件处理,也不会对事件进行抢占,因此,不管是文件事件的处理器,还是时间事件的处理器,它们都会尽可能减少程序的阻塞时间,并在有需要时主动让出执行权,从而降低造成事件饥饿的可能性。当回复能发送时,将产生AE_WRITABLE事件,触发命令回复处理器执行,当命令回复处理器将全部回复写入套接字后,将不再监听客户端套接字的AE_WRITABLE事件。正常情况下,服务器几乎是将无序链表退化成一个指针来使用,因此不会影响事件执行的性能。

2024-10-26 20:35:28 777

原创 Redis设计与实现 学习笔记 第十一章 AOF持久化

上面介绍的aof_rewrite函数会进行大量的写入操作,所以调用这个函数的线程将被长时间阻塞,因为Redis使用单个线程来处理命令请求,所以如果服务器直接调用aof_rewrite函数,那么在AOF重写期间,服务器将无法处理客户端发来的命令请求。因为AOF持久化是通过保存被执行的写命令来记录数据库状态的,所以随着时间流逝,AOF文件中的内容会越来越多,文件也会越来越大,如果不加以控制,体积过大的AOF文件可能对Redis服务器或宿主机造成影响,且AOF文件越大,还原所需时间就越多。

2024-10-25 23:17:09 768

原创 Redis设计与实现 学习笔记 第十章 RDB持久化

其中,REDIS_RDB_ENC_LZF常量标志着字符串已被LZF算法压缩过了,程序读入到这个常量时,会根据compressed_len(字符串被压缩后的长度)、origin_len(字符串被压缩前的长度)、compressed_string(被压缩后的字符串)对字符串进行解压。如果TYPE值为REDIS_RDB_TYPE_SET_INTSET,那么value保存的就是一个整数集合对象,RDB文件保存这种对象的方法是:先将整数集合转换为字符串对象,然后将这个字符串对象保存到RDB文件里。

2024-10-23 22:45:48 964

原创 Redis设计与实现 学习笔记 第九章 数据库

例如,对于一些和时间有关的数据,比如日志(log),在某个时间点后,对它们的访问会大大减少,甚至不再访问,如果这类过期数据大量积压在数据库中,用户以为服务器已经自动将它们删除了,但实际上这些键仍存在,且键占用的内存也没有释放,那造成的后果是非常严重的。但定时策略对CPU时间最不友好,在过期键比较多的情况下,删除过期键的行为可能会占用相当一部分CPU时间,在内存不紧张但CPU时间非常紧张的情况下,将CPU时间用在删除和当前任务无关的过期键上,无疑会对服务器的响应时间和吞吐量造成影响。

2024-10-20 21:05:42 858

原创 Redis设计与实现 学习笔记 第八章 对象

注意,linkedlist编码的列表对象在底层的双端链表结构中包含了多个字符串对象,这种嵌套字符串对象的行为在稍后介绍的哈希对象、集合对象、有序集合对象中都会出现,字符串对象是Redis五种类型的对象中唯一会被其他四种类型对象嵌套的对象。通过encoding属性来设定对象使用的编码,而不是为特定类型的对象关联一种固定的编码,极大地提升了Redis的灵活性和效率,因为Redis可以根据不同的场景来为一个对象设置不同的编码,从而优化对象在某一场景下的效率。

2024-10-17 23:20:35 1017

原创 Redis设计与实现 学习笔记 第七章 压缩列表

如果e1至eN都是大小介于250至253字节的节点,big节点的长度大于等于254字节,而small节点的长度小于254字节,那么当我们将small节点从压缩列表中删除后,为了让e1的previous_entry_length属性可以记录big节点的长度,程序将扩展e1的空间,并由此引发之后的连锁更新。2.如果前一节点的长度大于等于254字节,那么previsou_entry_length属性长为5字节:第一字节被设置为0xFE(十进制254),之后四字节则用于保存前一节点的长度。

2024-10-12 23:24:17 1173

原创 Redis设计与实现 学习笔记 第六章 整数集合

虽然contents数组保存的四个值中,只有第一个是真正需要用int64_t来保存的,其他三个值都可以用int16_t来保存,但根据整数集合的升级规则,当向一个底层为int16_t的整数集合添加一个int64_t类型的整数值时,整数集合已有的所有元素都会被转换成int64_t类型。要让一个数组可以同时保存int16_t、int32_t、int64_t三种类型的整数,最简单的做法是直接使用int64_t类型的数组作为整数集合的底层实现,但这样一来保存小整数时比较浪费内存。

2024-10-10 00:01:35 536

原创 Redis设计与实现 学习笔记 第五章 跳跃表

在同一个跳跃表中,各个节点保存的成员对象必须是唯一的,但是多个节点保存的分值却可以是相同的:分值相同的节点将按照成员对象在字典序中的大小来排序,成员对象较小的节点会排在前面(靠近表头的方向),而成员对象较大的节点则会排在后面(靠近表尾的方向)。再举个例子,图5-5用虚线标记了在跳跃表中查找分值为2.0、成员对象为o2的节点时,沿途经历的层:在查找节点的过程中,程序经过了两个跨度为1的节点,因此可以计算出,目标节点在跳跃表中的排位为2。在跳跃表中,节点按各自保存的分值从小到大排列。

2024-10-04 12:16:38 757

原创 Redis设计与实现 学习笔记 第四章 字典

根据BGSAVE命令或BGREWRITEAOF命令是否正在执行,服务器执行扩展操作所需的负载因子并不相同,这是因为在执行这两个命令的过程中,Redis需要创建子进程,而大多数操作系统都采用写时复制(copy-on-write)技术来优化子进程的使用效率,所以在子进程存在期间,服务器会提高执行扩展操作所需的负载因子,从而尽可能避免在子进程存在期间进行哈希表扩展操作,这可以避免不必要的内存写入操作,最大限度节约内存。

2024-10-03 00:26:52 586

原创 Redis设计与实现 学习笔记 第三章 链表

5.多态:链表节点使用void *指针来保存节点值,且可以通过list结构的dup、free、match三个属性为节点值设置类型特定函数,所以链表可用于保存各种不同类型的值。4.带链表长度计数器:程序使用list结构的len属性来对list持有的链表节点进行计数,程序获取链表中节点数量的复杂度为O(1)。2.每个链表节点由一个ListNode结构来表示,每个节点都有一个指向前置节点和后置节点的指针,所以Redis的链表实现是双端链表。3.match函数用于对比链表节点保存的值和另一个输入值是否相等;

2024-10-01 21:49:33 881

原创 Redis设计与实现 学习笔记 第二章 简单动态字符串

与C字符串不同,SDS的空间分配策略完全杜绝了发生缓冲区溢出的可能性:当SDS API需要对SDS进行修改时,API会先检查SDS的空间是否满足修改所需的要求,如果不满足,API会自动将SDS的空间扩展至执行修改所需的大小,然后才执行实际的修改操作,所以使用SDS既不需要手动修改SDS的空间大小,也不会出现前面所说的缓冲区溢出问题。为空字符分配额外的1字节空间、添加空字符到字符串末尾等操作,都是由SDS函数自动完成的,这个空字符对于SDS的使用者来说是完全透明的。

2024-10-01 15:08:59 1131

原创 Redis设计与实现 学习笔记 第一章 引言

本书是基于Redis 2.9——也就是Redis 3.0的开发版来编写的,因为Redis 3.0的更新主要与Redis的多机功能有关,而Redis 3.0的单机功能与Redis 2.6、Redis 2.8的单机功能基本相同,所以本书的内容对于使用Redis 2.6至Redis 3.0的读者来说应该都是有用的。在本书的第四部分中,除了第20章的其中一节涉及多机功能的内容之外,其他章节都没有涉及多机功能的内容,所以第四部分的大部分章节都可以在只阅读了本书第一部分和第二部分的情况下阅读。

2024-09-28 17:36:28 795

原创 Go语言设计与实现 学习笔记 第九章 标准库

作为标准库的JSON提供的接口非常简洁,虽然它的性能一直被开发者所诟病,但作为框架它提供了很好的通用性,通过分析JSON库的实现,我们也可以从中学习到使用反射的各种方法。默认情况下,当我们在序列化和反序列化结构体时,标准库都会认为字段名和JSON中的键具有一一对应的关系,然而Go语言的字段一般都是驼峰命名法,JSON中下划线的命名方式相对比较常见,使用标签特性可以建立键与字段之间的映射关系。我们在这里会简单介绍JSON标准库中的接口和标签,这是它为开发者提供的为数不多的影响编解码过程的接口。

2024-09-26 00:59:00 887 1

原创 Go语言设计与实现 学习笔记 第八章 元编程

熟悉Go语言的开发者一般都非常了解Goroutine和Channel的原理,包括如何设计基于CSP模型(该模型中的并发实体通过消息传递来通信,而不是共享内存)的应用程序,但Go的插件系统是一个很少有人了解的模块,通过插件系统,我们可以在运行时加载动态库实现一些比较有趣的功能。Go语言的代码生成机制会读取包含预编译指令的注释,然后执行注释中的命令读取包中的文件,它们将文件解析成抽象语法树并根据语法树生成新的Go语言代码和文件,生成的代码会在项目的编译期间与其它代码一起编译和运行。

2024-09-23 23:50:27 1188

原创 Go语言设计与实现 学习笔记 第七章 内存管理(2)

扫描对象运行时会使用runtime.gcDrain函数扫描工作缓冲区中的灰色对象,它会根据传入gcDrainFlags的不同选择不同的策略:// 清空垃圾收集器的工作缓冲区func gcDrain(gcw *gcWork, flags gcDrainFlags) { // 获取当前M上运行的Goroutine gp := getg().m.curg // 清空操作是否可被抢占 preemptible := flags&gcDrainUntilPreempt !=

2024-09-22 13:14:41 944 1

原创 Go语言设计与实现 学习笔记 第七章 内存管理(1)

7.1 内存分配器程序中的数据和变量都会被分配到程序所在的虚拟内存中,内存空间包含两个重要区域——栈区(Stack)和堆区(Heap)。函数调用的参数、返回值、局部变量大都会被分配到栈上,这部分内存会由编译器进行管理;不同编程语言使用不同的方法管理堆区的内存,C++等编程语言会由工程师主动申请和释放内存,Go以及Java等编程语言会由工程师和编译器共同管理,堆中的对象由内存分配器分配并由垃圾收集器回收。不同的编程语言会选择不同的方式管理内存,本节会介绍Go语言内存分配器,详细分析内存分配的过程以及其背后

2024-09-17 13:41:43 915 1

原创 Go语言设计与实现 学习笔记 第六章 并发编程(3)

会返回可读或者可写事件(如上,还有异常事件)的个数,应用程序就可以在输入的文件描述符中(实际上,select函数会通过参数返回哪些fd可用,例如通过readfds参数返回可读的fd集合,通过writefds参数返回可写的fd集合)查找哪些可读或可写(或异常),然后执行相应的操作。Go语言的系统监控也起到了很重要的作用,它在内部启动了一个不会中止的循环,在循环的内部会轮询网络、抢占长期运行或处于系统调用的Goroutine、触发垃圾回收,通过这些行为,它能够让系统的运行状态变得更健康。

2024-09-07 17:53:18 1200 1

空空如也

空空如也

TA创建的收藏夹 TA关注的收藏夹

TA关注的人

提示
确定要删除当前文章?
取消 删除