1 Libresource: Library of APIs through which application can get system resource information e.g. memory, CPU, stat, networking, security related information. Currently most of such Information is read from /proc and /sys. 2 Benefits: 2.1 Ease of use Currently application (e.g. DB) needs to read this info mostly from /proc and /sys file-systems. In most of the cases complex string parsing is involved which is needed to be done in application code. With the library APIs, application can get the information directly and all the string parsing, if any, will be done by library. 2.2 Stability If the format in which the information is provided in /proc or /sys file-system is changed then the application code is changed to align with those changes. Also if a better way to get information comes in future, like through a syscall or a sysconf, then again application code needs to be changed to get the benefit of it. Library will take care of such changes and the application will never have to change the code. 2.3 Virtualization In cases where DB is running in a virtualized environment using cgroup or namespaces, reading from /proc and /sys file-systems might not give correct information as these are not cgroup aware. Library API will take care of this e.g. if a process is running in a cgroup then library should provide information which is local to that cgroup. 3 Interface A generic framework which can be extended in future. 3.1 Strcuts Following are data structures and interfaces. 3.1.1 This is the struct through which the information will be exchanged between library and application by calling the library functions. Each resource information like memfree, memavailable, numcpus etc will have a resource id. res_id filed should be filled before calling read interfaces. In some cases e.g. CPU_STAT etc (refer to resource info id file) hint will be needed. Right now hint can be an integer value or pointer to a string. Later on hint can be expanded to provide pointer to structures as well if needed. After library interface returns, “status” will tell if the operation was successful or an error code and “data” will have the information asked for. typedef struct res_unit { uint32 status; uint32 res_id; uint64 hint; union r_data data; } res_unit_t; 3.1.2 data will be union so that information can be accessed directly. There are many resources information which are returned back in form of a libres structure. union r_data { uint32 ui32; uint64 ui64; size_t sz; char str[RES_UNIT_OUT_SIZE]; char ch; boolean b; void *p; Struct mem_infoall; Struct cpu_stat; . . . void *p; }; 3.1.3 Many a times we want to get more than one information at one go. This structure will be used in such cases to get multiple resource information in one read. typedef struct res_blk { int res_count; res_unit_t *res_unit[1]; } res_blk_t; 3.2 APIs 3.2.1 For reading multiple information in one call - /* This will construct a resource block structure. This will take an array of resource IDs and count of resource IDs. This allocates memory internally and then initializes the struct. If this is used to construct resource block then a corresponding res_blk_destroy should be called.*/ res_blk_t *res_blk_build (int *res_ids, int res_count); /*resblk is pointer to resource block struct which should be created using res_blk_build interface. If application does not want to use res_blk_build to create resource block struct then it has to be allocated and initialized by the application. pid is provided if the information is asked for a specific process. If it is system-wide information then pid should be 0. resblk->res_unit[i]->status will show if there was any error or the information was fetched successfully. resblk->res_unit[i]->data will have the information asked for after the call. Right now flags is not used, but can be used in future.*/ /*We don't want this call to allocate any memory internally. Only for CGROUP_PROC_INFOALL, NET_INTERFACESTAT and DEV_INTERFACESTAT memory is allocated (if hint is 0) in this call because we don’t know how many devices or network interfaces are there*/ void res_read_blk(res_blk_t *resblk, int pid, int flags); 3.2.2 For reading single information – /* This will construct a resource unit struct in case we just need one resource information. This allocates memory internally and then initializes the struct */ res_unit_t *res_unit_build(int res_id); /*We don't want this call to allocate any memory internally. Only for CGROUP_PROC_INFOALL, NET_INTERFACESTAT and DEV_INTERFACESTAT memory is allocated (if hint is 0) in this call because we don’t know how many devices or network interfaces are there*/ void res_read_unit (res_unit_t *res, int pid, int flags); 3.2.3 Some applications want to keep track of memory allocations for various reasons. They can call res_read_blk or res_read_unit directly. But they will have to allocate memory first and populate res_unit structure. These helper functions are for these purposes. /*Helper function to return memory size needed for a particular resource.*/ uint32 res_unit_size(res_id); /*Helper function to initialize resblk struct */ void *res_blk_init(res_blk_t *resblk); /*Helper function to initialize res_unit struct */ void *res_unit_init(res_unit_t *resunit); 3.2.4 /* After calling read, following interfaces should be called to free up resources allocated */ void res_blk_destroy(res_blk_t *resblk); void res_unit_destroy(res_unit_t *res); 3.2.5 I am thinking of following interface as well which are single call interfaces for reading single resource information. /* To read resources directly. Out should be allocated properly before the call and it will be filled in the read call. "out" should be allocated/free’d properly by application. It cannot be used for resources which need hint to be provided.*/ int res_read_direct_ptr(int res_id, int pid, void *out, int flags) 4 Further work: Library will only provide interfaces to get the information. However most of the information will still be fetched from procfs and sysfs etc. opening a file and Reading/parsing information is not an efficient way to get the info. We need to find a way to get the information in faster manner. There are multiple ways to do that - a syscall? - using sysinfo, or having another interface which is like sysinfo. - using netlink between kernel and userland, People have tried it in past https://lwn.net/Articles/99600/ https://lkml.org/lkml/2016/4/11/924 - using a shared page between user and kernel space (shared structure) This will provide the library necessary performance improvement and then library can be used at places where the information is read very frequently. For example some observability script might fetch the information every couple of seconds to assess system health while system is up. Currently library provided only read APIs. We also might need to extend the APIs to write/update the resource info. 5 Example: 5.1: res_blk_t *b = NULL; int a[NUM] = {PAGESIZE, MEMFREE, MEMTOTAL}; b = res_blk_build(a, NUM); res_read(b, 0, 0); printf("%ld bytes, %ld kb, %ld kb\n", b->res_unit[0]->data.sz, b->res_unit[1]->data.sz, b->res_unit[2]->data.sz); res_blk_destroy(b); 5.2: res_unit_t *u = res_unit_build(CPU_STAT); u->hint = 1; res_read_unit(u, 0, 0); res_unit_destroy(u);