CN114817185A - 一种基于消息驱动的异步日志处理方法 - Google Patents
一种基于消息驱动的异步日志处理方法 Download PDFInfo
- Publication number
- CN114817185A CN114817185A CN202210347868.3A CN202210347868A CN114817185A CN 114817185 A CN114817185 A CN 114817185A CN 202210347868 A CN202210347868 A CN 202210347868A CN 114817185 A CN114817185 A CN 114817185A
- Authority
- CN
- China
- Prior art keywords
- memory block
- log information
- thread
- log
- pointer
- Prior art date
- Legal status (The legal status is an assumption and is not a legal conclusion. Google has not performed a legal analysis and makes no representation as to the accuracy of the status listed.)
- Pending
Links
Images
Classifications
-
- G—PHYSICS
- G06—COMPUTING; CALCULATING OR COUNTING
- G06F—ELECTRIC DIGITAL DATA PROCESSING
- G06F16/00—Information retrieval; Database structures therefor; File system structures therefor
- G06F16/10—File systems; File servers
- G06F16/17—Details of further file system functions
- G06F16/176—Support for shared access to files; File sharing support
- G06F16/1767—Concurrency control, e.g. optimistic or pessimistic approaches
- G06F16/1774—Locking methods, e.g. locking methods for file systems allowing shared and concurrent access to files
-
- G—PHYSICS
- G06—COMPUTING; CALCULATING OR COUNTING
- G06F—ELECTRIC DIGITAL DATA PROCESSING
- G06F16/00—Information retrieval; Database structures therefor; File system structures therefor
- G06F16/10—File systems; File servers
- G06F16/18—File system types
- G06F16/1805—Append-only file systems, e.g. using logs or journals to store data
- G06F16/1815—Journaling file systems
-
- G—PHYSICS
- G06—COMPUTING; CALCULATING OR COUNTING
- G06F—ELECTRIC DIGITAL DATA PROCESSING
- G06F3/00—Input arrangements for transferring data to be processed into a form capable of being handled by the computer; Output arrangements for transferring data from processing unit to output unit, e.g. interface arrangements
- G06F3/06—Digital input from, or digital output to, record carriers, e.g. RAID, emulated record carriers or networked record carriers
- G06F3/0601—Interfaces specially adapted for storage systems
- G06F3/0628—Interfaces specially adapted for storage systems making use of a particular technique
- G06F3/0638—Organizing or formatting or addressing of data
- G06F3/064—Management of blocks
-
- G—PHYSICS
- G06—COMPUTING; CALCULATING OR COUNTING
- G06F—ELECTRIC DIGITAL DATA PROCESSING
- G06F9/00—Arrangements for program control, e.g. control units
- G06F9/06—Arrangements for program control, e.g. control units using stored programs, i.e. using an internal store of processing equipment to receive or retain programs
- G06F9/46—Multiprogramming arrangements
- G06F9/50—Allocation of resources, e.g. of the central processing unit [CPU]
- G06F9/5005—Allocation of resources, e.g. of the central processing unit [CPU] to service a request
- G06F9/5027—Allocation of resources, e.g. of the central processing unit [CPU] to service a request the resource being a machine, e.g. CPUs, Servers, Terminals
-
- G—PHYSICS
- G06—COMPUTING; CALCULATING OR COUNTING
- G06F—ELECTRIC DIGITAL DATA PROCESSING
- G06F9/00—Arrangements for program control, e.g. control units
- G06F9/06—Arrangements for program control, e.g. control units using stored programs, i.e. using an internal store of processing equipment to receive or retain programs
- G06F9/46—Multiprogramming arrangements
- G06F9/52—Program synchronisation; Mutual exclusion, e.g. by means of semaphores
- G06F9/526—Mutual exclusion algorithms
Landscapes
- Engineering & Computer Science (AREA)
- Theoretical Computer Science (AREA)
- Physics & Mathematics (AREA)
- General Engineering & Computer Science (AREA)
- General Physics & Mathematics (AREA)
- Software Systems (AREA)
- Data Mining & Analysis (AREA)
- Databases & Information Systems (AREA)
- Human Computer Interaction (AREA)
- Debugging And Monitoring (AREA)
Abstract
本发明公开了一种基于消息驱动的异步日志处理方法,包括获取多条用户线程的日志信息;对多线程并发的用户线程加第一互斥锁;根据每条用户线程的日志信息,从静态缓冲区选取与日志信息大小匹配的内存块,并对选取的内存块加调用锁,得到已分配内存块;释放调用锁,并将对应的日志信息写入解锁后的已分配内存块;通过调用事件通知调用线程,使得调用线程从静态缓冲区读取多条日志信息,并发送到多条处理线程;每条处理线程通过自定义回调函数控制日志信息的输出格式。本发明采用双缓存机制,能够实现多线程同时读写,有效避免读写线程互相阻塞,提升异步日志处理的效率,保证自动驾驶系统的实时性与可靠性。
Description
技术领域
本发明涉及自动驾驶技术领域,尤其涉及一种基于消息驱动的异步日志处理方法。
背景技术
随着自动驾驶成为未来汽车的主流趋势,不断有各式各样的自动驾驶汽车诞生,自动驾驶汽车的核心为中央计算平台,该平台负责车辆的融合感知、定位、规划等计算任务,对自动驾驶系统的实时性要求极高;而由于实际工程应用中不可避免的需要日志对自动驾驶系统出现的问题进行定位分析,对自动驾驶系统的实时运行状态进行追踪,并且在写日志的过程中存在频繁的I/O操作,会对系统性能产生影响。
现有的日志系统包括同步日志系统和异步日志系统;其中,同步日志系统直接将打印信息向控制台或者日志文件输出,在每一个需要记录信息的地方进行直接打印;在每个需要输出的地方直接进行日志输出,需要同步等待日志刷盘,造成业务线程阻塞,严重影响系统性能。
而异步日志系统只支持输出指定格式的消息内容;在输出字符串时,异步日志系统直接对字符串进行拷贝等相关操作,处理较为简单;并且,异步日志系统采用简单的多生产者与单消费者模型,利用单一缓冲区来提供面向用户线程和系统线程的读写操作。
但是,异步日志系统无法同时支持多个输出源,无论是相应的日志级别或者是日志输出格式,都无法做到定制化处理,必须依赖于固定的格式,导致日志可读性不高;同时,由于字符串拷贝涉及动态分配内存,以及用户态与内核态之间的切换,因此性能消耗较大,导致效率降低;且由于在写日志的过程中将涉及多线程读和写同一块缓冲区,一方面未采取相应办法解决锁粒度的问题,导致锁的粒度增大,另一方面无法保证读和写有效并发进行,导致线程阻塞,降低日志处理的效率。
日志系统在故障定位的应用中至关重要,一般的日志系统设计时对性能要求并不用特别高,但是自动驾驶系统由于实时性和可靠性的要求,同时具有高并发和低延迟的应用场景,加之日志系统设计本身具有一定的复杂性,一般的日志系统在应对自动驾驶场景时可行性不高。
因此,需要一种基于消息驱动的异步日志处理方法,能够有效避免读写线程互相阻塞,实现异步日志的多线程并发读写,提升异步日志处理的效率。
发明内容
针对上述现有技术中存在的问题,本发明提供了一种基于消息驱动的异步日志处理方法,能够有效避免读写线程互相阻塞,实现异步日志的多线程并发读写,提升异步日志处理的效率。所述技术方案如下:
本发明提供了一种基于消息驱动的异步日志处理方法,包括:
获取多条用户线程的日志信息;
对多线程并发操作对应的所述用户线程加第一互斥锁;
根据每条所述用户线程的所述日志信息,从静态缓冲区中选取与所述日志信息大小相匹配的内存块,并对选取的所述内存块加调用锁,得到已分配内存块;其中,所述静态缓冲区包括多个所述内存块,所述内存块为所述静态缓冲区中预先分配的静态内存;
释放所述调用锁,并将对应的所述日志信息写入解锁后的所述已分配内存块;
通过调用事件通知调用线程,使得所述调用线程从所述静态缓冲区读取多条所述日志信息,并发送到多条处理线程;
根据接收到的所述日志信息,每条所述处理线程通过自定义回调函数控制所述日志信息的输出格式;其中,每条所述处理线程分别由对应的处理事件触发。
进一步地,所述日志信息为待输出信息,包括:
系统级的消息和用户级的内容信息。
进一步地,在所述释放所述调用锁,并将对应的所述日志信息写入解锁后的所述已分配内存块之后,所述方法还包括:
判断所述已分配内存块是否可写入;
若所述已分配内存块可写入,则继续将所述日志信息写入所述已分配内存块;其中,正在写入内存块的指针指向对应的所述已分配内存块,所述已分配内存块置为正在写入内存块;
若所述已分配内存块不可写入,则将所述正在写入内存块的指针传递至不可写入内存块的指针,以使得所述不可写入内存块的指针指向所述已分配内存块,并置所述正在写入内存块的指针为空;其中,所述已分配内存块置为不可写入内存块。
进一步地,在所述若所述已分配内存块不可写入,则将所述正在写入内存块的指针传递至不可写入内存块的指针,以使得所述不可写入内存块的指针指向所述已分配内存块,并置所述正在写入内存块的指针为空之后,所述方法还包括:
引入暂存内存块,将所述不可写入内存块的指针传递至所述暂存内存块的指针,以使得所述暂存内存块的指针指向所述已分配内存块;其中,所述已分配内存块置为暂存内存块;
释放所述第一互斥锁,以使得所述用户线程继续写入所述日志信息;
将置为空的所述正在写入内存块的指针重新初始化,并指向所述静态缓冲区中未被使用的所述已分配内存块,用于实现所述用户线程的继续写入。
进一步地,在所述通过调用事件通知调用线程,使得所述调用线程从所述静态缓冲区读取多条所述日志信息,并发送到多条处理线程之前,所述方法还包括:
将所述暂存内存块转化为链表数据进行存储;其中,所述暂存内存块的头结点由第一可读内存块表示;
对所述调用线程与所述处理线程加第二互斥锁,以使得所述第一可读内存块不被修改;
将包含有待输出的所述日志信息的所述内存块置为锁定内存块;其中,所述第一可读内存块的指针传递至所述锁定内存块。
进一步地,所述通过调用事件通知调用线程,使得所述调用线程从所述静态缓冲区读取多条所述日志信息,并发送到多条处理线程包括:
通过所述调用事件通知所述调用线程;
对多个所述锁定内存块设置读锁,并将读锁初始值设置为待读取的所述日志信息的数量;
所述调用线程从对应的所述锁定内存块中读取多条所述日志信息;
将多条所述日志信息一一对应发送到多条所述处理线程。
进一步地,在所述调用线程从对应的所述锁定内存块中读取多条所述日志信息之后,所述方法还包括:
将完成读取后的所述锁定内存块释放,重置为所述静态缓冲区中空闲的所述内存块,用于下一次写入。
进一步地,在所述根据接收到的所述日志信息,每条所述处理线程通过自定义回调函数控制所述日志信息的输出格式之后,所述方法还包括:
将所述第二互斥锁释放。
进一步地,所述日志信息通过TraceDictinary机制实现写入与读取。
进一步地,所述TraceDictinary机制包括:
为所述日志信息中的每一个字符串均分配一个索引编号与一个插入编号;其中,所述索引编号的头指针为第一索引编号,所述插入编号的头指针为第一插入编号,每一个所述索引编号均对应着所述插入编号的所述第一插入编号。
实施本发明,具有如下有益效果:
1、本发明采用双缓存机制,将静态缓冲区预先分配出多个内存块,利用部分已分配内存块进行多线程同时写入的同时,还能够利用静态缓冲区中的其他内存块进行多线程同时读取,有效避免了读写线程互相阻塞,实现异步日志的多线程并发读写,大大提升了异步日志处理的效率,保证自动驾驶系统的实时性与可靠性。
2、本发明支持多输出源输出,并支持各个输出源可配置,通过自定义回调函数能够定制各个输出源,即输出的日志信息的输出格式、输出级别,提高日志信息的可读性,并且能够对输出源完全解耦,具有高可靠性、高扩展性与高灵活性。
3、本发明采用TraceDictinary机制,使得日志读写过程仅需要对字符串的索引编号和插入编号进行操作即可,避免直接操作字符串,降低性能消耗,进一步提升异步日志处理的效率。
附图说明
为了更清楚地说明本发明实施例中的技术方案,下面将对实施例中所使用的附图作简单的介绍。显而易见地,下面描述中的附图仅仅是本发明的一些实施例,对于本领域普通技术人员来讲,在不付出创造性劳动的前提下,还可以根据这些附图获得其它附图。
图1为本发明实施例提供的一种基于消息驱动的异步日志处理方法的逻辑结构图;
图2为本发明实施例提供的已分配内存块的状态确定方法的示意图;
图3为本发明实施例提供的实现用户线程继续写入的方法的逻辑结构图;
图4为本发明实施例提供的避免第一可读内存块在读取过程中被修改的方法的逻辑结构图;
图5为本发明实施例提供的读取锁定内存块中日志信息的过程示意图;
图6为本发明实施例提供的锁定内存块再利用的逻辑结构图;
图7为本发明实施例提供的一种基于消息驱动的日志系统的架构图;
图8为本发明实施例提供的静态缓冲区的原理示意图;
图9为本发明实施例提供的TraceDictinary机制的原理示意图。
具体实施方式
下面将结合本发明实施例中的附图,对本发明实施例中的技术方案进行清楚、完整地描述,显然,所描述的实施例仅仅是本发明的一部分实施例,而不是全部的实施例,因此不能理解为对本发明的限制。基于本发明中的实施例,本领域普通技术人员在没有做出创造性劳动的前提下所获得的所有其他实施例,都属于本发明保护的范围。
需要说明的是,本发明的说明书和权利要求书及附图中的术语“第一”、“第二”等是用于区别类似的对象,而不必用于描述特定的顺序或先后次序。应该理解这样使用的数据在适当情况下可以互换,以便本发明的实施例能够以除了下述图示或下述描述以外的顺序实施。此外,术语“包括”和“具有”以及他们的任何变形,意图在于覆盖不排他的包含,例如,包含了一系列步骤或单元的过程、方法、系统、产品或服务器不必限于清楚地列出的那些步骤或单元,而是可包括没有清楚地列出的或对于这些过程、方法、产品或设备固有的其它步骤或单元。
本实施例针对现有技术中,异步日志系统无法同时支持多个输出源,日志可读性不高;多线程读写时对同一块缓冲区进行操作,无法保证读写有效并发进行;以及字符串拷贝时内存消耗较大,导致整体异步日志系统效率低下的问题,提供了一种基于消息驱动的日志处理方法。
当多条用户线程需要同时写入日志信息时,该基于消息驱动的日志处理方法对这些多线程并发进行的用户线程加第一互斥锁,代表该方法排他性地访问这些用户线程(即多线程并发操作)的对应的缓冲区以便写入写入,根据每条用户线程的日志信息,从静态缓冲区中选取与日志信息大小匹配的空闲内存块,将该空闲内存块加调用锁后,得到已分配内存块,之后快速释放该调用锁,使得相应的日志信息能够写入这一已分配内存块,直至该已分配内存块达到不可写入的状态;而静态缓冲区中不止包括空闲的已分配内存块,还包括已经写入日志信息的不可写入内存块,为了避免在读取过程中不可写入内存块中的日志信息被修改,利用暂存内存块与第一可读内存块进行指针传递,传递至锁定内存块;则对于读取过程,通过调用事件通知调用线程,使得调用线程能够从静态缓冲区的锁定内存块中读取多条日志信息,并通过多条处理事件触发对应的多条处理线程,每条处理线程通过自定义回调函数控制对应的日志信息的输出格式,从而实现多线程输出源的输出以及输出格式的定制,这一过程能够避免多线程读写线程的互相阻塞,实现多线程读写的有效并发进行,显著提升异步日志处理的效率,满足自动驾驶系统对实时性与可靠性的高要求。
下面对本发明实施例的技术方案进行详细介绍,参考说明书附图1、说明书附图7与说明书附图8所示,该方法包括:
S101,获取多条用户线程的日志信息。
具体地,日志信息为需要输出的待输出信息,包括系统级的消息(Systeminformation,以下简称System info)和用户级的内容信息(User information,以下简称User info)。
S103,对多线程并发操作对应的所述用户线程加第一互斥锁。
此处的加第一互斥锁是对用户线程进行的操作,用户线程即为多线程并发操作,则该过程是对多线程并发操作缓冲区进行加第一互斥锁。
在本实施例中,第一互斥锁为HandlerMutex锁,用于将多线程的用户线程锁定,以使得写入时能够选择对应的多线程用户线程进行排他性的访问,标记该用户线程对应的内存区域,避免后续出现访问和写入位置出错。
S105,根据每条所述用户线程的所述日志信息,从静态缓冲区中选取与所述日志信息大小相匹配的内存块,并对选取的所述内存块加调用锁,得到已分配内存块。
其中,需要说明的是,静态缓冲区(buffer)本身已经是预先分配好的静态内存,静态缓冲区中包括多种功能、状态不同的内存块,例如,空闲内存块(idleChunks)、正在写入内存块(chunkBeingWritten)、不可写入内存块(finishedWritingChunks)、暂存内存块(temporaryChunks)、可读内存块与锁定内存块(lockedChunk)等等。
例如,在该步骤中,能够被选取的内存块均为空闲内存块,即此时的已分配内存块还是空闲内存块,块内为空,不包含任何写入的日志信息,处于空闲状态;在后续S107步骤中,释放调用锁时,已分配内存块仍为空闲内存块,而将日志信息已经写入一部分的已分配内存块中内容不为空,则此时的已分配内存块处于正在写入的状态,为正在写入内存块。
则在选取时,根据日志信息的大小,能够确定所需的空闲内存块的大小,从而在众多的空闲内存块中选择与日志信息大小相匹配的内存块;而为了区分这一被选取的内存块,防止后续写入错位,将选取的这一空闲内存块加调用锁(LockMemory),得到加锁后的已分配内存块,完成内存块的分配;那么后续写入时,对应的用户线程能够针对性地访问该已分配内存块,将相应的日志信息写入该已分配内存块。
并且,根据同时需要写入的日志信息的数量,同时进行分配的也可以为多个空闲内存块,对多个空闲内存块同时分别加调用锁;以及后续S107步骤中,也可以根据日志信息的数量(或者用户线程的数量),选择对应数量的预分配内存块进行同时写入日志信息的操作,实现多线程同时写入。
S107,释放所述调用锁,并将对应的所述日志信息写入解锁后的所述已分配内存块。
在S105步骤与S107步骤之间,调用锁的获取与释放是一个迅速完成的过程,而加锁状态下的已分配内存块只是代表该内存块已经被分配,但由于调用锁的存在,此时的已分配内存块为不可写入的状态,则在该步骤中将调用锁释放(ReleaseMemory)后,日志信息才得以写入该已分配内存块。
需要说明的是,S105步骤中可以同时得到多个已分配内存块,则在S105步骤中多个已分配内存块同时进行写入操作,使得多条日志信息分别写入对应的已分配内存块中,实现多线程同时写入。
S109,通过调用事件通知调用线程,使得所述调用线程从所述静态缓冲区读取多条所述日志信息,并发送到多条处理线程。
其中,S109步骤为日志信息读取步骤,主要针对静态缓冲区中已经写完日志信息、并即将输出的内存块,而在众多内存块中,锁定内存块定义为已经不可写入、且被锁定无法再进行更改的内存块,即调用线程(dispatch thread)从静态缓冲区读取是从锁定内存块中读取日志信息;而锁定内存块与正在写入内存块为静态缓冲区中不同的内存块,能够实现用户线程向正在写入内存块写入日志信息与调用线程从锁定内存块读取其他日志信息的同时进行,这种写入与读取分别采用不同内存块的双缓存机制,保证读写线程的有效并发进行,避免线程阻塞,大大提升日志处理的效率。
另外,对于正在写入内存块,当其经过一段时间的写入达到不可写入状态时,会通过一系列指针转化为锁定内存块,以备调用线程从中读取日志信息,实现该日志信息的一轮写入与读取;即已分配内存块不可写入后,就会向调用线程发送调用事件(DispatchEvent)进行事件触发,使得调用线程开始读取日志信息。
S111,根据接收到的所述日志信息,每条所述处理线程通过自定义回调函数控制所述日志信息的输出格式;其中,每条所述处理线程分别由对应的处理事件触发。
现有异步日志系统无法同时支持多个输出源,无论是相应的日志信息的级别或者是日志信息的输出格式,都无法做到定制化处理,必须依赖固定的格式;而在该步骤中,在调用线程读取一条日志信息之后,能够通过对应的处理事件(HandlerEvent)触发一条处理线程(handler thread),处理线程通过回调函数(Callback function,以下简称Callbackfun)来进行日志处理,且每一条处理线程都对应一个输出源(即日志信息),则只需要自定义不同处理线程的回调函数,即可实现对多日志信息输出格式的自定义控制,即能够通过自定义回调函数的方式定制各个输出源的输出格式,输出级别,并对各个输出源完全解耦,使得执行该方法的异步日志系统具有高可靠性、高可扩展性以及高灵活性。
具体地,在本说明书的一个可能的实施方式中,如说明书附图2所示,在所述释放所述调用锁,并将对应的所述日志信息写入解锁后的所述已分配内存块之后,即S107步骤之后,所述方法还包括:
S202,判断所述已分配内存块是否可写入。
S204,若所述已分配内存块可写入,则继续将所述日志信息写入所述已分配内存块;其中,正在写入内存块的指针指向对应的所述已分配内存块,所述已分配内存块置为正在写入内存块。
在该步骤中,正在写入内存块的指针指向该已分配内存块,代表该已分配内存块处于可写入或者说正在被写入的状态,使得日志信息能够持续不断地写入;而在该步骤之后,对正在写入内存块可以选择始终返回执行上述S202步骤,直至判断结果为该正在写入内存块不可写入,则执行后续S206步骤。
S206,若所述已分配内存块不可写入,则将所述正在写入内存块的指针传递至不可写入内存块的指针,以使得所述不可写入内存块的指针指向所述已分配内存块,并置所述正在写入内存块的指针为空;其中,所述已分配内存块置为不可写入内存块。
指针传递至不可写入内存块,代表该已分配内存块当前处于不可写入的状态,能够被置为不可写入内存块,该不可写入内存块处于不可写入的状态,则为了避免用户线程仍旧对该不可写入内存块进行操作,将原本指向该已分配内存块的正在写入内存块的指针置为空,代表目前的静态缓冲区中并不存在处于正在写入状态的内存块,而该不可写入内存块也已不可访问或者不可以进行写入操作。
此外,在S103步骤中对整个多线程并发的用户线程加Handlermutex锁,则在本说明书的一个可能的实施方式中,如说明书附图8所示,不可写入内存块与正在写入内存块的指针均处于加Handlermutex锁状态,虽然正在写入内存块的指针此时为空,但被第一互斥锁锁住,也处于不可写入的状态。
具体地,在经过上述一轮同时写入操作之后,加Handlermutex锁状态下的不可写入内存块与正在写入内存块无法写入,造成资源浪费,则如图3所示,在所述若所述已分配内存块不可写入,则将所述正在写入内存块的指针传递至不可写入内存块的指针,以使得所述不可写入内存块的指针指向所述已分配内存块,并置所述正在写入内存块的指针为空之后,即在S206步骤之后,所述方法还包括:
S301,引入暂存内存块,将所述不可写入内存块的指针传递至所述暂存内存块的指针,以使得所述暂存内存块的指针指向所述已分配内存块;其中,所述已分配内存块置为暂存内存块。
S303,释放所述第一互斥锁,以使得所述用户线程继续写入所述日志信息。
S305,将置为空的所述正在写入内存块的指针重新初始化,并指向所述静态缓冲区中未被使用的所述已分配内存块,用于实现所述用户线程的继续写入。
其中,暂存内存块是一种处于临时存储日志信息状态的内存块,存在时间很短,用于存储多个用户线程已经写好的日志信息,并且随着多个用户线程的数量的增加(或者说多轮用户线程的进行),通过不可写入内存块至暂存内存块的指针传递,更多不可写入内存块转化为暂存内存块,即暂存内存块中的日志信息仍旧是不断更新的,以备后续调用线程读取。
而引入暂存内存块,能够利用其进行一次指针传递,通过暂存内存块指向静态缓冲区,以使得后续调用线程在接收到调用事件后,不会对不可写入内存块再次操作,降低锁粒度。
在S303步骤之后,由于HandlerMutex锁被释放,用户线程得以继续写入日志,此时正在写入内存块的指针为空,代表其如果重新初始化,可以重新用于指向静态缓冲区中另一个未被使用过的空闲内存块,即正在写入内存块的指针能够重新寻找并指向新的空闲内存块,而该空闲内存块为经过S101-S107之后所分配完成并且释放调用锁后的已分配内存块,正在写入内存块的指针指向这一个空闲内存块代表该空闲内存块能够执行下一轮用户线程的写入。
即S301-S305步骤所进行的是在将日志信息通过指针传递到暂存内存块后,对正在写入内存块与不可写入内存块的指针的释放,使得正在写入内存块指针与不可写入内存块的指针能够应用于下一轮用户线程的写入过程;则采用本发明的基于消息驱动的异步日志处理方法,不仅可以实现多线程同时写入,还可以实现内存块的重复利用,实现多轮写入。
此外,需要说明的是,在将置为空的正在写入内存块的指针重新初始化去寻找新的内存块执行写入时,需要对静态缓冲区中是否存在处于可写入状态的内存块进行判断,若存在这样的可写入状态的内存块(即正在写入内存块),则可以直接进行写入操作;若不存在正在写入状态的内存块,则可以进一步判断当前静态缓冲区中是否存在空闲内存块,若存在空闲内存块,则可以按照S105步骤进行分配,得到一个新的空闲的已分配内存块,之后将重新初始化的正在写入内存块的指针指向该已分配内存块,实现在另一个内存块中进行下一轮日志信息的写入操作。
若当前时刻下,静态缓冲区中既不存在正在写入内存块,也不存在空闲内存块,则判断静态缓冲区中是否存在可供回收的不可写入内存块,其中,如果存在一些内存块中已经没有多余的内存区域以供写入、或者存在一些内存块过于老旧、或者一些已经能够被要求刷新的内存块,则可以判断上述的这些内存块可供回收;例如,后续步骤中已经完成全部读取操作的锁定内存块,则属于可供回收的内存块,将其清空释放后,可以作为一个空闲状态的内存块去执行下一次的日志信息写入操作;而若静态缓冲区中的内存块不能回收,那么就选择一个特殊内存块,将日志信息写入,但是在这种情况下,这些日志信息永远也不会输出。
至此,多线程向正在写入内存块写入日志信息,利用不可写入内存块作为中间介质,将指针传递到暂存内存块,则日志信息可以准备被读取了,但是由于暂存内存块中的内容需要频繁地进行更新,不能对处于不断更新状态下的内存块直接进行读取操作,可能导致读取的内容不准确。
具体地,如说明书附图4所示,在所述通过调用事件通知调用线程,使得所述调用线程从所述静态缓存区读取多条所述日志信息,并发送到多条处理线程之前,即在S109步骤之前,所述方法还包括:
S402,将所述暂存内存块转化为链表数据进行存储;其中,所述暂存内存块的头结点由第一可读内存块表示。
即在S301步骤之后,由于暂存内存块频繁地进行更新,将其转化为链表数据进行存储,则更新的日志信息作为链表数据加入到链表中;且以第一可读内存块表示暂存内存块的头结点,能够通过头结点遍历链表,以备读取暂存内存块中的所有日志信息;此时,第一可读内存块(firstReadyChunk)中的日志信息不会再发生改变,该第一可读内存块已经准备好被读取了。
S404,对所述调用线程与所述处理线程加第二互斥锁,以使得所述第一可读内存块不被修改。
S406,将包含有待输出的所述日志信息的所述内存块置为锁定内存块;其中,所述第一可读内存块的指针传递至所述锁定内存块。
而为了避免第一可读内存块在后续调用线程和处理线程进行的同时被修改,利用第二互斥锁锁定调用线程和处理线程,对第一可读内存块和需要输出的锁定内存块进行保护,直至各个调用线程均从锁定内存块中完成读取操作;在本实施例中,第二互斥锁为DispatchMutex,能够有效保护锁定内存块,防止锁定内存块中可读的日志信息在读取过程中被修改,保证日志信息读取的可靠性。
具体地,在DispatchMutex锁定完成后,调用线程即可开始读取操作,如说明书附图5所示,所述通过调用事件通知调用线程,使得所述调用线程从所述静态缓存区读取多条所述日志信息,并发送到多条处理线程包括:
S501,通过所述调用事件通知所述调用线程。
其中,该步骤实际上是在S301步骤引入暂存内存块进行指针传递之前,S206步骤将正在写入内存块的指针置为空之后,调用线程就已经接收调用事件被触发了,只是无法直接从不可写入内存块直接读取,才依次经过上述指针传递到暂存内存块、第一可读内存块与锁定内存块的过程之后,执行后续S503步骤进行读取。
S503,对多个所述锁定内存块设置读锁,并将读锁初始值设置为待读取的所述日志信息的数量。
在该步骤中,读锁初始值的设置是为了支持后续多个处理线程,假设有n个处理线程,则将锁定内存块的读锁初始值设为n,代表读取线程一共读取了n个日志信息,后续S505步骤中就可以有n条处理线程一一对应地分别对n个日志信息进行处理,实现多线程同时读取。
S505,所述调用线程从对应的所述锁定内存块中读取多条所述日志信息。
S507,将多条所述日志信息一一对应发送到多条所述处理线程。
具体地,如说明书附图6所示,在所述调用线程从对应的所述锁定内存块中读取多条所述日志信息之后,即在S505步骤之后,所述方法还包括:
S602,将完成读取后的所述锁定内存块释放,重置为所述静态缓冲区中的所述内存块,用于下一次写入。
也就是说,锁定内存块与正在写入内存块的区分都是代表该内存块所处的状态,而不同内存块所处的状态是可以相互转化的,从而使得已经使用的内存块被清空后能够重新作为空闲内存块被利用,进行下一轮写入,即前述的对不可写入内存块的回收再利用,该回收过程使得静态缓冲区的利用率高,也有利于减少不同线程之间的等待过程,提升整体处理效率。
具体地,在所述根据接收到的所述日志信息,每条所述处理线程通过自定义回调函数控制所述日志信息的输出格式之后,所述方法还包括:
将所述第二互斥锁释放。
在该步骤中,释放DispatchMutex是将所有的DispatchMutex均释放,也就是将第一可读内存块以及锁定内存块所依赖的DispatchMutex释放掉,并且,释放DispatchMutex必须在调用线程发送到处理线程的内存块均执行完读取操作之后进行,以保证日志信息输出的稳定性,提升异步日志处理的效率。
本发明采用双缓存机制,由于写入操作与读取操作所利用的内存块(分别为正在写入内存块和锁定内存块)为静态缓冲区中不同的内存块,同时进行读写时不会导致两种线程互相阻塞,能够大大提升日志处理的效率。
具体地,本发明还引入TraceDictinary机制实现日志信息的写入与读取,以规避对字符串直接进行拷贝操作,降低性能消耗,进一步提升异步日志处理的效率。
如说明书附图9所示,日志信息写入的大多都是字符串,则为日志信息中的每一个字符串均分配一个索引编号(简写为dictID)与一个插入编号(简写为entryID),当写入的或者需要被读取的字符串形成字符串链表时,所分配的多个索引编号也形成索引链表,相应地,多个插入编号之间形成插入链表;则索引编号能够用于查询到该字符串,而插入编号能够查询该字符串在整个链表中的插入位置。
其中,第一索引编号(firstDictID)为指向索引链表的头指针,则通过第一索引编号,能够查询到索引链表中的每一个索引编号;同样地,第一插入编号(firstEntryID)为指向插入链表的头指针,则通过第一插入编号,能够查询到插入链表中的每一个插入编号。
在写入日志信息时,实际上是将对应的索引编号与插入编号分别写入索引链表与插入链表中,先查询到原有索引链表对应的第一索引编号,将新的索引编号插入到第一索引编号前方,而每一个索引编号均对应着插入链表的头指针第一插入编号,将新插入的插入编号添加到对应插入链表的头部,完成索引编号与插入编号的写入;而当需要读取日志信息,做字符串拷贝时,只需要操作对应的索引编号与插入编号即可,而无需直接操作字符串,大大节省性能消耗;而当需要查询字典对应字符串的实际内容时,只需要遍历链表即可,大大提升日志处理的效率。
在本说明书的一个可能的实施方式中,以三线程同时写入与读取为例,参阅说明书附图7,三条用户线程(即User thread1、User thread2和User thread3)需要同时写入内存块,则先将多线程并发操作缓冲区加HandlerMutex锁,再从静态缓冲区中,根据每条用户线程要输出的System info与User info,为每条用户线程分别分配一块大小相匹配的内存块,并调用LockMemory对三块内存块分别加锁,以使得对应的用户线程在后续调用ReleaseMemory对内存块解锁后能够向对应的内存块分别写入日志信息。
由于静态缓冲区为预先分配好的静态内存,参阅说明书附图8,其中不止包括可以写入日志信息的idleChunks与chunkBeingWritten,还包括用于读取日志信息的lockedChunk与firstReadyChunk等等,则为了使一部分内存块被写入的同时,不影响另一些内存块被用于读取,在不同内存块之间进行指针传递;采用双缓存机制,用户线程可以向chunkBeingWritten写入日志信息,利用finishedWritingChunks为中间介质,将指针指向temporaryChunks,并将temporaryChunks转化为链表进行存储,以firstReadyChunk表示该链表的头结点,以备读取。
而当内存块达到不可写入状态之后,参阅图7,向dispatch thread发送DispatchEvent进行事件触发,使得dispatch thread读取User thread1、User thread2和User thread3写入的日志信息,并通过三个处理事件(HandlerEvent1、HandlerEvent2和HandlerEvent3)分别发送到三条处理线程(handler thread1、handler thread2和handlerthread3),在每条处理线程中通过自定义回调函数(Callback fun1、Callback fun2和Callback fun3)的方式实现对日志信息的输出格式的控制。
并且,整个写入与读取过程均采用TraceDictinary机制,参阅说明书附图9,当User thread3要写入日志信息时,查询索引链表的头指针firstDictID,并将DictID3插入DictID2的头部,之后根据DictID2对应的firstEntryID,将EntryID3插入该插入链表的头部;而读取User thread3的日志信息时,只需要操作DictID3即可,大大提升处理效率。
通过上述实施例可知,本发明实施例中的基于消息驱动的异步日志处理方法具有以下有益效果:
1、本发明采用双缓存机制,将静态缓冲区预先分配出多个内存块,利用部分已分配内存块进行多线程同时写入的同时,还能够利用静态缓冲区中的其他内存块进行多线程同时读取,有效避免了读写线程互相阻塞,实现异步日志的多线程并发读写,大大提升了异步日志处理的效率,保证自动驾驶系统的实时性与可靠性。
2、本发明支持多输出源输出,并支持各个输出源可配置,通过自定义回调函数能够定制各个输出源,即输出的日志信息的输出格式、输出级别,提高日志信息的可读性,并且能够对输出源完全解耦,具有高可靠性、高扩展性与高灵活性。
3、本发明采用TraceDictinary机制,使得日志读写过程仅需要对字符串的索引编号和插入编号进行操作即可,避免直接操作字符串,降低性能消耗,进一步提升异步日志处理的效率。
本发明实施例还提供一种存储介质,所述存储介质中存储有至少一条指令或至少一段程序,所述至少一条指令或所述至少一段程序由处理器加载并执行以实现以上所述的基于消息驱动的异步日志处理方法;可选地,该存储介质可以位于计算机网络的多个网络服务器中的至少一个网络服务器;此外,该存储介质可以包括但不限于随机存取存储器(RAM,Random Access Memory)、只读存储器(ROM,Read-Only Memory)、U盘、移动硬盘、磁盘存储器件、闪存器件、其他易失性固态存储器件等各种可以存储程序代码的存储介质。
需要说明的是,上述本发明实施例先后顺序仅仅为了描述,不代表实施例的优劣。且上述对本说明书特定实施例进行了描述。其它实施例在所附权利要求书的范围内。在一些情况下,在权利要求书中记载的动作或步骤可以按照不同于实施例中的顺序来执行并且仍然可以实现期望的结果。另外,在附图中描绘的过程不一定要求示出的特定顺序或者连续顺序才能实现期望的结果。在某些实施方式中,多任务处理和并行处理也是可以的或者可能是有利的。
本说明书中的各个实施例均采用递进的方式描述,各个实施例之间相同相似的部分互相参见即可,每个实施例重点说明的都是与其他实施例的不同之处。尤其,对于装置实施例而言,由于其基本相似于方法实施例,所以描述的比较简单,相关之处参见方法实施例的部分说明即可。
以上所描述的仅为本发明的一些实施例而已,并不用于限制本发明,本行业的技术人员应当了解,本发明还会有各种变化和改进,任何依照本发明所做的修改、等同替换和改进都落入本发明所要求的保护的范围内。
Claims (10)
1.一种基于消息驱动的异步日志处理方法,采用双缓存机制实现,其特征在于,包括:
获取多条用户线程的日志信息;
对多线程并发操作对应的所述用户线程加第一互斥锁;
根据每条所述用户线程的所述日志信息,从静态缓冲区中选取与所述日志信息大小相匹配的内存块,并对选取的所述内存块加调用锁,得到已分配内存块;其中,所述静态缓冲区包括多个所述内存块,所述内存块为所述静态缓冲区中预先分配的静态内存;
释放所述调用锁,并将对应的所述日志信息写入解锁后的所述已分配内存块;
通过调用事件通知调用线程,使得所述调用线程从所述静态缓冲区读取多条所述日志信息,并发送到多条处理线程;
根据接收到的所述日志信息,每条所述处理线程通过自定义回调函数控制所述日志信息的输出格式;其中,每条所述处理线程分别由对应的处理事件触发。
2.根据权利要求1所述的一种基于消息驱动的异步日志处理方法,其特征在于,所述日志信息为待输出信息,包括:
系统级的消息和用户级的内容信息。
3.根据权利要求1所述的一种基于消息驱动的异步日志处理方法,其特征在于,在所述释放所述调用锁,并将对应的所述日志信息写入解锁后的所述已分配内存块之后,所述方法还包括:
判断所述已分配内存块是否可写入;
若所述已分配内存块可写入,则继续将所述日志信息写入所述已分配内存块;其中,正在写入内存块的指针指向对应的所述已分配内存块,所述已分配内存块置为正在写入内存块;
若所述已分配内存块不可写入,则将所述正在写入内存块的指针传递至不可写入内存块的指针,以使得所述不可写入内存块的指针指向所述已分配内存块,并置所述正在写入内存块的指针为空;其中,所述已分配内存块置为不可写入内存块。
4.根据权利要求3所述的一种基于消息驱动的异步日志处理方法,其特征在于,在所述若所述已分配内存块不可写入,则将所述正在写入内存块的指针传递至不可写入内存块的指针,以使得所述不可写入内存块的指针指向所述已分配内存块,并置所述正在写入内存块的指针为空之后,所述方法还包括:
引入暂存内存块,将所述不可写入内存块的指针传递至所述暂存内存块的指针,以使得所述暂存内存块的指针指向所述已分配内存块;其中,所述已分配内存块置为暂存内存块;
释放所述第一互斥锁,以使得所述用户线程继续写入所述日志信息;
将置为空的所述正在写入内存块的指针重新初始化,并指向所述静态缓冲区中未被使用的所述已分配内存块,用于实现所述用户线程的继续写入。
5.根据权利要求4所述的一种基于消息驱动的异步日志处理方法,其特征在于,在所述通过调用事件通知调用线程,使得所述调用线程从所述静态缓冲区读取多条所述日志信息,并发送到多条处理线程之前,所述方法还包括:
将所述暂存内存块转化为链表数据进行存储;其中,所述暂存内存块的头结点由第一可读内存块表示;
对所述调用线程与所述处理线程加第二互斥锁,以使得所述第一可读内存块不被修改;
将包含有待输出的所述日志信息的所述内存块置为锁定内存块;其中,所述第一可读内存块的指针传递至所述锁定内存块。
6.根据权利要求5所述的一种基于消息驱动的异步日志处理方法,其特征在于,所述通过调用事件通知调用线程,使得所述调用线程从所述静态缓冲区读取多条所述日志信息,并发送到多条处理线程包括:
通过所述调用事件通知所述调用线程;
对多个所述锁定内存块设置读锁,并将读锁初始值设置为待读取的所述日志信息的数量;
所述调用线程从对应的所述锁定内存块中读取多条所述日志信息;
将多条所述日志信息一一对应发送到多条所述处理线程。
7.根据权利要求6所述的一种基于消息驱动的异步日志处理方法,其特征在于,在所述调用线程从对应的所述锁定内存块中读取多条所述日志信息之后,所述方法还包括:
将完成读取后的所述锁定内存块释放,重置为所述静态缓冲区中空闲的所述内存块,用于下一次写入。
8.根据权利要求7所述的一种基于消息驱动的异步日志处理方法,其特征在于,在所述根据接收到的所述日志信息,每条所述处理线程通过自定义回调函数控制所述日志信息的输出格式之后,所述方法还包括:
将所述第二互斥锁释放。
9.根据权利要求1所述的一种基于消息驱动的异步日志处理方法,其特征在于,所述日志信息通过TraceDictinary机制实现写入与读取。
10.根据权利要求9所述的一种基于消息驱动的异步日志处理方法,其特征在于,所述TraceDictinary机制包括:
为所述日志信息中的每一个字符串均分配一个索引编号与一个插入编号;其中,所述索引编号的头指针为第一索引编号,所述插入编号的头指针为第一插入编号,每一个所述索引编号均对应着所述插入编号的所述第一插入编号。
Priority Applications (1)
Application Number | Priority Date | Filing Date | Title |
---|---|---|---|
CN202210347868.3A CN114817185A (zh) | 2022-04-01 | 2022-04-01 | 一种基于消息驱动的异步日志处理方法 |
Applications Claiming Priority (1)
Application Number | Priority Date | Filing Date | Title |
---|---|---|---|
CN202210347868.3A CN114817185A (zh) | 2022-04-01 | 2022-04-01 | 一种基于消息驱动的异步日志处理方法 |
Publications (1)
Publication Number | Publication Date |
---|---|
CN114817185A true CN114817185A (zh) | 2022-07-29 |
Family
ID=82533652
Family Applications (1)
Application Number | Title | Priority Date | Filing Date |
---|---|---|---|
CN202210347868.3A Pending CN114817185A (zh) | 2022-04-01 | 2022-04-01 | 一种基于消息驱动的异步日志处理方法 |
Country Status (1)
Country | Link |
---|---|
CN (1) | CN114817185A (zh) |
-
2022
- 2022-04-01 CN CN202210347868.3A patent/CN114817185A/zh active Pending
Similar Documents
Publication | Publication Date | Title |
---|---|---|
US9798595B2 (en) | Transparent user mode scheduling on traditional threading systems | |
US5410700A (en) | Computer system which supports asynchronous commitment of data | |
US7673105B2 (en) | Managing memory pages | |
CN101833475B (zh) | 用于执行指令原子块的方法和装置 | |
US5175849A (en) | Capturing data of a database system | |
US7827536B2 (en) | Critical path profiling of threaded programs | |
CN1908890B (zh) | 用于使用记录板机制处理加载锁定指令的方法和装置 | |
US8108627B2 (en) | Array comparison and swap operations | |
CN110727675B (zh) | 一种链表的处理方法及装置 | |
US11132294B2 (en) | Real-time replicating garbage collection | |
JPS5983249A (ja) | 待ち行列制御方法 | |
CN101788922A (zh) | 基于辅助线程实现事务存储系统的方法和装置 | |
CN109144749B (zh) | 一种使用处理器实现多处理器间通信的方法 | |
CN106104515A (zh) | 利用非易失性存储器的文件系统设计和故障恢复方法 | |
EP1760580A1 (en) | Processing operation information transfer control system and method | |
CN114756355B (zh) | 一种计算机操作系统的进程自动快速恢复的方法和装置 | |
CN116257359A (zh) | 数据处理方法及装置、存储介质及电子设备 | |
CN114817185A (zh) | 一种基于消息驱动的异步日志处理方法 | |
CN111752685A (zh) | 多核架构下的持久性内存事务提交方法 | |
CN111814007B (zh) | 双向链表数据处理方法、装置、设备及机器可读存储介质 | |
CN111352860B (zh) | 一种Linux Bcache中的垃圾回收方法及系统 | |
CN116756380A (zh) | 环形单链表的处理方法和装置 | |
JP4131579B2 (ja) | データ管理システムおよびデータ管理方法 | |
CN117785496A (zh) | 一种微内核操作系统的用户级rcu实现方法 | |
CN116303117A (zh) | 内存回收方法、设备、存储介质和系统 |
Legal Events
Date | Code | Title | Description |
---|---|---|---|
PB01 | Publication | ||
PB01 | Publication | ||
SE01 | Entry into force of request for substantive examination | ||
SE01 | Entry into force of request for substantive examination |