Skip to content

Commit 5361d4f

Browse files
committed
fs: Add Kernel-level VFS Performance Profiler
This adds a kernel-level performance profiler for the VFS. By enabling CONFIG_FS_PROFILER, the core VFS system calls (file_read, file_write, file_open, and file_close) are instrumented to track high-resolution execution times using clock_systime_timespec() seamlessly. The collected statistics are exposed dynamically via a new procfs node at /proc/fs/profile, allowing CI regression testing without needing external debugging tools. Signed-off-by: Sumit6307 <sumitkesar6307@gmail.com>
1 parent a09dfcd commit 5361d4f

File tree

17 files changed

+327
-0
lines changed

17 files changed

+327
-0
lines changed

Documentation/components/filesystem/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -543,6 +543,7 @@ NuttX provides support for a variety of file systems out of the box.
543543
nxffs.rst
544544
partition.rst
545545
procfs.rst
546+
profiler.rst
546547
romfs.rst
547548
rpmsgfs.rst
548549
smartfs.rst
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
==============================
2+
VFS Performance Profiler
3+
==============================
4+
5+
The Virtual File System (VFS) Performance Profiler provides a simple, in-kernel
6+
mechanism to track execution times and invocation counts for core VFS operations
7+
(read, write, open, close) seamlessly. This is highly suitable for
8+
CI/CD automated regression testing and performance bottleneck identification.
9+
10+
Configuration
11+
=============
12+
13+
To enable the profiler, select ``CONFIG_FS_PROFILER`` in your Kconfig.
14+
To expose the metrics dynamically via procfs, ensure ``CONFIG_FS_PROCFS`` is enabled, and
15+
the profiler node is included via ``CONFIG_FS_PROCFS_PROFILER``.
16+
17+
Usage
18+
=====
19+
20+
When enabled, the profiler automatically intercepts calls to the underlying
21+
inode operations and records the execution elapsed times using ``perf_gettime()``.
22+
Since no blocking mutexes are used during updates (fast ``atomic.h`` operations
23+
are utilized instead), the overhead is extremely minimal and safely scales on SMP.
24+
25+
To view the current statistics collectively from the NuttShell (NSH), simply
26+
read the node:
27+
28+
.. code-block:: bash
29+
30+
nsh> cat /proc/fs/profile
31+
VFS Performance Profile:
32+
Reads: 12 (Total time: 4500120 ns)
33+
Writes: 3 (Total time: 95050 ns)
34+
Opens: 15 (Total time: 1005000 ns)
35+
Closes: 15 (Total time: 45000 ns)
36+
37+
The reported times are in the raw ticks/units provided by ``perf_gettime()`` on
38+
your specific architecture.

boards/sim/sim/sim/configs/citest/defconfig

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,3 +152,5 @@ CONFIG_TESTS_TESTSUITES=y
152152
CONFIG_TLS_NCLEANUP=4
153153
CONFIG_TLS_NELEM=16
154154
CONFIG_TLS_TASK_NELEM=8
155+
CONFIG_FS_PROFILER=y
156+
CONFIG_FS_PROCFS_PROFILER=y

fs/Kconfig

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,14 @@
55

66
comment "File system configuration"
77

8+
config FS_PROFILER
9+
bool "VFS Performance Profiler"
10+
default n
11+
---help---
12+
Enable nanosecond/microsecond-level profiling for the Virtual File
13+
System (VFS) operations (open, close, read, write). The profile stats
14+
can be read via /proc/fs/profile if PROCFS is enabled.
15+
816
config DISABLE_MOUNTPOINT
917
bool "Disable support for mount points"
1018
default n

fs/procfs/CMakeLists.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,10 @@ if(NOT CONFIG_DISABLE_MOUNTPOINT)
4040
list(APPEND SRCS fs_procfspressure.c)
4141
endif()
4242

43+
if(CONFIG_FS_PROCFS_PROFILER)
44+
list(APPEND SRCS fs_procfsprofile.c)
45+
endif()
46+
4347
target_sources(fs PRIVATE ${SRCS})
4448

4549
endif()

fs/procfs/Kconfig

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,16 @@ config FS_PROCFS_EXCLUDE_VERSION
148148
bool "Exclude version"
149149
default DEFAULT_SMALL
150150

151+
config FS_PROCFS_PROFILER
152+
bool "Include fs/profile information"
153+
depends on FS_PROFILER && !DEFAULT_SMALL
154+
default n
155+
---help---
156+
Enable the VFS performance profiler procfs node at /proc/fs/profile.
157+
This node provides real-time dynamic statistics (call counts, elapsed
158+
time) for core VFS operations (read, write, open, close) to help
159+
identify filesystem performance bottlenecks and regressions.
160+
151161
config FS_PROCFS_INCLUDE_PRESSURE
152162
bool "Include memory pressure notification"
153163
default n

fs/procfs/Make.defs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,10 @@ ifeq ($(CONFIG_FS_PROCFS_INCLUDE_PRESSURE),y)
3232
CSRCS += fs_procfspressure.c
3333
endif
3434

35+
ifeq ($(CONFIG_FS_PROCFS_PROFILER),y)
36+
CSRCS += fs_procfsprofile.c
37+
endif
38+
3539
# Include procfs build support
3640

3741
DEPPATH += --dep-path procfs

fs/procfs/fs_procfs.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,9 @@ extern const struct procfs_operations g_thermal_operations;
7474
extern const struct procfs_operations g_uptime_operations;
7575
extern const struct procfs_operations g_version_operations;
7676
extern const struct procfs_operations g_pressure_operations;
77+
#if defined(CONFIG_FS_PROFILER) && defined(CONFIG_FS_PROCFS_PROFILER)
78+
extern const struct procfs_operations g_vfs_profile_operations;
79+
#endif
7780

7881
/* This is not good. These are implemented in other sub-systems. Having to
7982
* deal with them here is not a good coupling. What is really needed is a
@@ -208,6 +211,9 @@ static const struct procfs_entry_s g_procfs_entries[] =
208211
#ifndef CONFIG_FS_PROCFS_EXCLUDE_VERSION
209212
{ "version", &g_version_operations, PROCFS_FILE_TYPE },
210213
#endif
214+
#if defined(CONFIG_FS_PROFILER) && defined(CONFIG_FS_PROCFS_PROFILER)
215+
{ "profile", &g_vfs_profile_operations, PROCFS_FILE_TYPE },
216+
#endif
211217
};
212218

213219
#ifdef CONFIG_FS_PROCFS_REGISTER

fs/procfs/fs_procfsprofile.c

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
/****************************************************************************
2+
* fs/procfs/fs_procfsprofile.c
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*
6+
* Licensed to the Apache Software Foundation (ASF) under one or more
7+
* contributor license agreements. See the NOTICE file distributed with
8+
* this work for additional information regarding copyright ownership. The
9+
* ASF licenses this file to you under the Apache License, Version 2.0 (the
10+
* "License"); you may not use this file except in compliance with the
11+
* License. You may obtain a copy of the License at
12+
*
13+
* http://www.apache.org/licenses/LICENSE-2.0
14+
*
15+
* Unless required by applicable law or agreed to in writing, software
16+
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
17+
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
18+
* License for the specific language governing permissions and limitations
19+
* under the License.
20+
*
21+
****************************************************************************/
22+
23+
/****************************************************************************
24+
* Included Files
25+
****************************************************************************/
26+
27+
#include <nuttx/config.h>
28+
29+
#if defined(CONFIG_FS_PROCFS) && defined(CONFIG_FS_PROFILER) && \
30+
defined(CONFIG_FS_PROCFS_PROFILER)
31+
32+
#include <sys/types.h>
33+
#include <sys/stat.h>
34+
#include <stdio.h>
35+
#include <string.h>
36+
37+
#include <nuttx/fs/fs.h>
38+
#include <nuttx/fs/procfs.h>
39+
#include "../vfs/vfs.h"
40+
41+
/****************************************************************************
42+
* Private Functions
43+
****************************************************************************/
44+
45+
static int profile_open(FAR struct file *filep, FAR const char *relpath,
46+
int oflags, mode_t mode)
47+
{
48+
return OK;
49+
}
50+
51+
static int profile_close(FAR struct file *filep)
52+
{
53+
return OK;
54+
}
55+
56+
static ssize_t profile_read(FAR struct file *filep, FAR char *buffer,
57+
size_t buflen)
58+
{
59+
char buf[256];
60+
size_t linesize;
61+
off_t offset = filep->f_pos;
62+
63+
if (offset > 0)
64+
{
65+
return 0;
66+
}
67+
68+
procfs_snprintf(buf, sizeof(buf),
69+
"VFS Performance Profile:\n"
70+
" Reads: %10lu (Total time: %llu ns)\n"
71+
" Writes: %10lu (Total time: %llu ns)\n"
72+
" Opens: %10lu (Total time: %llu ns)\n"
73+
" Closes: %10lu (Total time: %llu ns)\n",
74+
(unsigned long)g_vfs_profile.reads,
75+
(unsigned long long)g_vfs_profile.total_read_time,
76+
(unsigned long)g_vfs_profile.writes,
77+
(unsigned long long)g_vfs_profile.total_write_time,
78+
(unsigned long)g_vfs_profile.opens,
79+
(unsigned long long)g_vfs_profile.total_open_time,
80+
(unsigned long)g_vfs_profile.closes,
81+
(unsigned long long)g_vfs_profile.total_close_time);
82+
83+
linesize = strlen(buf);
84+
if (linesize > buflen)
85+
{
86+
linesize = buflen;
87+
}
88+
89+
memcpy(buffer, buf, linesize);
90+
filep->f_pos += linesize;
91+
return linesize;
92+
}
93+
94+
static int profile_dup(FAR const struct file *oldp, FAR struct file *newp)
95+
{
96+
return OK;
97+
}
98+
99+
static int profile_stat(FAR const char *relpath, FAR struct stat *buf)
100+
{
101+
memset(buf, 0, sizeof(struct stat));
102+
buf->st_mode = S_IFREG | S_IROTH | S_IRGRP | S_IRUSR;
103+
return OK;
104+
}
105+
106+
/****************************************************************************
107+
* Public Data
108+
****************************************************************************/
109+
110+
const struct procfs_operations g_vfs_profile_operations =
111+
{
112+
profile_open, /* open */
113+
profile_close, /* close */
114+
profile_read, /* read */
115+
NULL, /* write */
116+
NULL, /* poll */
117+
profile_dup, /* dup */
118+
NULL, /* opendir */
119+
NULL, /* closedir */
120+
NULL, /* readdir */
121+
NULL, /* rewinddir */
122+
profile_stat /* stat */
123+
};
124+
125+
#endif
126+

fs/vfs/CMakeLists.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,4 +93,10 @@ if(CONFIG_SIGNAL_FD)
9393
list(APPEND SRCS fs_signalfd.c)
9494
endif()
9595

96+
# Support for profiler
97+
98+
if(CONFIG_FS_PROFILER)
99+
list(APPEND SRCS fs_profile.c)
100+
endif()
101+
96102
target_sources(fs PRIVATE ${SRCS})

0 commit comments

Comments
 (0)