Compare commits

..

34 Commits

Author SHA1 Message Date
5251dcbce9 Merge pull request #431 from xiaogaozi/doc-add-juicefs
doc: add JuiceFS to known file systems
2022-06-22 09:06:13 +01:00
dd3adf34ef Sign contributor agreement 2022-06-22 13:24:51 +08:00
b8a6a8efed Reorder 2022-06-20 13:48:26 +08:00
d67acf3b3a doc: add JuiceFS to known file systems 2022-06-20 13:47:17 +08:00
3b104723af changelog: update for v1.11 2022-06-15 16:45:37 +01:00
699278a7ed appveyor: disable special pool 2022-06-15 10:58:47 +01:00
e070cdd6be build: bump to 2022+ARM64 2022-06-14 23:09:23 +01:00
fbbca110fb README: minor improvements 2022-06-14 23:06:03 +01:00
0083a45e31 doc: registry settings document 2022-06-13 17:52:33 +01:00
faaac2da3c doc: building document 2022-06-13 14:19:59 +01:00
e44cba033f update README 2022-06-12 17:39:23 +01:00
91400babe0 update README 2022-06-11 15:42:03 +01:00
e1ac7b60f7 update README 2022-06-11 15:38:43 +01:00
573897b06e appveyor: skip_commits 2022-06-11 15:25:58 +01:00
b77b0a51f4 appveyor: enable special pool 2022-06-10 17:43:06 +01:00
26af6c9363 sys: convert suitable ERESOURCE to FAST_MUTEX 2022-06-10 16:20:24 +01:00
2e441534a3 sys: FspFsvolDeviceLockVolumeNotify 2022-06-10 16:20:19 +01:00
66f3620808 sys: FSP_FSVOL_DEVICE_EXTENSION::VolumeDeleteResource 2022-06-10 16:20:13 +01:00
805742f306 sys: FSP_FSVOL_DEVICE_EXTENSION::VolumeDeleteResource 2022-06-10 16:20:08 +01:00
18842682c8 sys: inline FspFsvolDeviceFileRename* and FspFsvolDeviceLockContextTable 2022-06-10 16:19:57 +01:00
a7a526351f sys: keep extra fsvol device reference
Reference an fsvol device at CREATE time and dereference at CLOSE time,
to ensure that fsvol remains around for DeviceIoControl operations done
after CLEANUP.
2022-06-09 14:28:31 +01:00
22bf0b09ef dll: FspMountBroadcastDriveChange
Broadcast WM_DEVICECHANGE asynchronously.
2022-06-07 14:06:13 +01:00
0a919d317a dll: FspMountBroadcastDriveChange
Broadcast WM_DEVICECHANGE asynchronously.
2022-06-07 13:11:23 +01:00
8e45f7d795 doc: WinFsp Performance Testing
Update with new tests and analysis for 2022.
2022-06-06 15:58:19 +01:00
646818a65c doc: WinFsp Performance Testing
Update with new tests and analysis for 2022.
2022-06-06 15:44:45 +01:00
6023efa7e6 doc: WinFsp Performance Testing
Update with new tests and analysis for 2022.
2022-06-06 00:32:15 +01:00
2dcb21edf2 tools: perf testing 2022-06-03 22:45:38 +01:00
edc56df2b2 tools: perf testing 2022-06-03 17:54:35 +01:00
64b57476dc changelog: update for v1.11RC1 2022-06-03 12:28:01 +01:00
acfa0ad880 build: version: bump to 2022+ARM64 RC1 2022-06-03 12:26:42 +01:00
d63cbd4146 changelog: update for v1.11B3 2022-06-03 12:25:16 +01:00
a90f19dbe3 dll: FspMountBroadcastDriveChange: fix drive change unitmask 2022-06-03 12:10:54 +01:00
b0cfdc0396 tst: fsbench: OptEmptyCacheDrive, OptOpenCount 2022-06-02 13:10:31 +01:00
69257949ac sys: FspCompareUnicodeString 2022-06-02 13:09:40 +01:00
95 changed files with 2373 additions and 420 deletions

View File

@ -1,6 +1,94 @@
# Changelog
## v1.11 (2022+ARM64)
- [NEW] ARM64 support! For details see [WinFsp on ARM64](https://github.com/winfsp/winfsp/wiki/WinFsp-on-ARM64).
- [NEW] A new file system operation has been added to the FUSE API:
```C
int (*getpath)(const char *path, char *buf, size_t size,
struct fuse_file_info *fi);
```
The `getpath` operation allows a case-insensitive file system to report the correct case of a file path. For example, `getpath` can be used to report that the actual path of a file opened as `/PATH/TO/FILE` is really `/Path/To/File`. This capability is important for some Windows file system scenarios and can sometimes result in a performance improvement.
- [NEW] New `ntptfs` sample file system. This is a production quality pass through file system and should be used instead of the original `passthrough` file system that was developed for education purposes only.
- [NEW] Many performance improvements:
- A new `PostDispositionForDirOnly` setting has been added to `FSP_FSCTL_VOLUME_PARAMS`. This allows a file system to declare that it does not want to see `SetInformation/Disposition` requests for files (such requests will still be sent for directories, because a file system is supposed to check if a directory is empty before deletion). This makes file (not directory) deletion faster. This optimization should be safe to enable for most file systems. FUSE file systems get this optimization for free.
- The FSD now implements "fast I/O" reads and writes. Fast I/O is a technique for doing I/O without using IRP's (I/O Request Packets) and can only work for file systems using the cache manager (`FileInfoTimeout==-1`). This results in significant improvement in read/write scenarios.
- The FSD now implements "fast I/O" for "transact" messages. Transact messages are used in the communication protocol between the kernel-mode FSD and the user-mode file system. Fast I/O speeds this communication protocol by as much as 10% in some scenarios. (Fast I/O for transact messages is enabled only when using the new `FSP_IOCTL_TRANSACT` control code, but does not require any other special configuration to be enabled.)
- The FSD per directory cache limit has been increased from 16K to 64K. This should allow for more directory data to be maintained in kernel and reduce round-trips to the user mode file system.
- The user mode directory buffering mechanism (`FspFileSystemAcquireDirectoryBuffer`) has been improved. The mechanism uses the quick-sort algorithm internally which can exhibit bad performance when sorting already sorted data. The quick-sort algorithm has been improved with the use use of median of three partitioning, which alleviates this problem.
- [NEW] A new registry setting under `HKLM\SOFTWARE\WinFsp` (or `HKLM\SOFTWARE\WOW6432Node\WinFsp` on a 64-bit system) called `MountBroadcastDriveChange` has been introduced, which if set to 1 will broadcast an additional "drive change" message to all top-level windows (including Explorer) during mounting and unmounting.
- Normally the Windows infrastructure broadcasts a `WM_DEVICECHANGE` message whenever a drive gets added/removed. In some rare systems it is possible for this message to get lost or stalled. The workaround for these rare systems is to enable this registry setting, in which case WinFsp will broadcast the `WM_DEVICECHANGE` using a slightly different but more reliable method than the one Windows uses.
- For more details see source code comments at [`FspMountBroadcastDriveChange`](https://github.com/winfsp/winfsp/blob/v1.11B3/src/dll/mount.c#L390-L406).
- [FIX] The WinFsp Network Provider now implements `NPGetUniversalName`. This fixes problems with some apps (e.g. Photos app).
- [FIX] WinFsp-FUSE now supports Azure AD accounts when specifying the `-o uid=-1` option. In addition a new option `-o uidmap=UID:SID` allows the specification of arbitrary UID<->SID or UID<->UserName mappings.
- [FIX] All executables (`*.exe,*.dll,*.sys`) in the WinFsp installation `bin` folder are now signed.
- [FIX] The default value for the registry setting `DistinctPermsForSameOwnerGroup` has been changed from 0 to 1.
- [BUILD] Product configuration (`MyProductName`, etc.) is done by the file `build.version.props` located in `build\VStudio`. This file was previously named `version.properties`.
## v1.11RC1 (2022+ARM64 RC1)
- [NEW] ARM64 support! For details see [WinFsp on ARM64](https://github.com/winfsp/winfsp/wiki/WinFsp-on-ARM64).
- [NEW] A new file system operation has been added to the FUSE API:
```C
int (*getpath)(const char *path, char *buf, size_t size,
struct fuse_file_info *fi);
```
The `getpath` operation allows a case-insensitive file system to report the correct case of a file path. For example, `getpath` can be used to report that the actual path of a file opened as `/PATH/TO/FILE` is really `/Path/To/File`. This capability is important for some Windows file system scenarios and can sometimes result in a performance improvement.
- [NEW] New `ntptfs` sample file system. This is a production quality pass through file system and should be used instead of the original `passthrough` file system that was developed for education purposes only.
- [NEW] Many performance improvements:
- A new `PostDispositionForDirOnly` setting has been added to `FSP_FSCTL_VOLUME_PARAMS`. This allows a file system to declare that it does not want to see `SetInformation/Disposition` requests for files (such requests will still be sent for directories, because a file system is supposed to check if a directory is empty before deletion). This makes file (not directory) deletion faster. This optimization should be safe to enable for most file systems. FUSE file systems get this optimization for free.
- The FSD now implements "fast I/O" reads and writes. Fast I/O is a technique for doing I/O without using IRP's (I/O Request Packets) and can only work for file systems using the cache manager (`FileInfoTimeout==-1`). This results in significant improvement in read/write scenarios.
- The FSD now implements "fast I/O" for "transact" messages. Transact messages are used in the communication protocol between the kernel-mode FSD and the user-mode file system. Fast I/O speeds this communication protocol by as much as 10% in some scenarios. (Fast I/O for transact messages is enabled only when using the new `FSP_IOCTL_TRANSACT` control code, but does not require any other special configuration to be enabled.)
- The FSD per directory cache limit has been increased from 16K to 64K. This should allow for more directory data to be maintained in kernel and reduce round-trips to the user mode file system.
- The user mode directory buffering mechanism (`FspFileSystemAcquireDirectoryBuffer`) has been improved. The mechanism uses the quick-sort algorithm internally which can exhibit bad performance when sorting already sorted data. The quick-sort algorithm has been improved with the use use of median of three partitioning, which alleviates this problem.
- [NEW] A new registry setting under `HKLM\SOFTWARE\WinFsp` (or `HKLM\SOFTWARE\WOW6432Node\WinFsp` on a 64-bit system) called `MountBroadcastDriveChange` has been introduced, which if set to 1 will broadcast an additional "drive change" message to all top-level windows (including Explorer) during mounting and unmounting.
- Normally the Windows infrastructure broadcasts a `WM_DEVICECHANGE` message whenever a drive gets added/removed. In some rare systems it is possible for this message to get lost or stalled. The workaround for these rare systems is to enable this registry setting, in which case WinFsp will broadcast the `WM_DEVICECHANGE` using a slightly different but more reliable method than the one Windows uses.
- For more details see source code comments at [`FspMountBroadcastDriveChange`](https://github.com/winfsp/winfsp/blob/v1.11B3/src/dll/mount.c#L390-L406).
- [FIX] The WinFsp Network Provider now implements `NPGetUniversalName`. This fixes problems with some apps (e.g. Photos app).
- [FIX] WinFsp-FUSE now supports Azure AD accounts when specifying the `-o uid=-1` option. In addition a new option `-o uidmap=UID:SID` allows the specification of arbitrary UID<->SID or UID<->UserName mappings.
- [FIX] All executables (`*.exe,*.dll,*.sys`) in the WinFsp installation `bin` folder are now signed.
- [FIX] The default value for the registry setting `DistinctPermsForSameOwnerGroup` has been changed from 0 to 1.
- [BUILD] Product configuration (`MyProductName`, etc.) is done by the file `build.version.props` located in `build\VStudio`. This file was previously named `version.properties`.
## v1.11B3 (2022+ARM64 Beta3)
- [NEW] ARM64 support! For details see [WinFsp on ARM64](https://github.com/winfsp/winfsp/wiki/WinFsp-on-ARM64).
@ -28,6 +116,12 @@
- The user mode directory buffering mechanism (`FspFileSystemAcquireDirectoryBuffer`) has been improved. The mechanism uses the quick-sort algorithm internally which can exhibit bad performance when sorting already sorted data. The quick-sort algorithm has been improved with the use use of median of three partitioning, which alleviates this problem.
- [NEW] A new registry setting under `HKLM\SOFTWARE\WinFsp` (or `HKLM\SOFTWARE\WOW6432Node\WinFsp` on a 64-bit system) called `MountBroadcastDriveChange` has been introduced, which if set to 1 will broadcast an additional "drive change" message to all top-level windows (including Explorer) during mounting and unmounting.
- Normally the Windows infrastructure broadcasts a `WM_DEVICECHANGE` message whenever a drive gets added/removed. In some rare systems it is possible for this message to get lost or stalled. The workaround for these rare systems is to enable this registry setting, in which case WinFsp will broadcast the `WM_DEVICECHANGE` using a slightly different but more reliable method than the one Windows uses.
- For more details see source code comments at [`FspMountBroadcastDriveChange`](https://github.com/winfsp/winfsp/blob/v1.11B3/src/dll/mount.c#L390-L406).
- [FIX] The WinFsp Network Provider now implements `NPGetUniversalName`. This fixes problems with some apps (e.g. Photos app).
- [FIX] WinFsp-FUSE now supports Azure AD accounts when specifying the `-o uid=-1` option. In addition a new option `-o uidmap=UID:SID` allows the specification of arbitrary UID<->SID or UID<->UserName mappings.

View File

@ -58,6 +58,7 @@ CONTRIBUTOR LIST
|Ben Rubson |ben.rubson at gmail.com
|Bill Zissimopoulos |billziss at navimatics.com
|Brett Dutro |brett.dutro at gmail.com
|Changjian Gao (Juicedata, https://juicefs.com) |gcj at juicedata.io
|Colin Atkinson (Atakama, https://atakama.com) |colin at atakama.com
|Felix Croes |felix at dworkin.nl
|Francois Karam (KS2, http://www.ks2.fr) |francois.karam at ks2.fr

163
README.md
View File

@ -1,141 +1,110 @@
<h1 align="center">
<img src="art/winfsp-glow.png" width="256"/>
<br/>
<br/>
WinFsp &middot; Windows File System Proxy
</h1>
<h1 align="center">WinFsp &middot; Windows File System Proxy</h1>
<p align="center">
<b>Download</b><br>
<a href="https://github.com/winfsp/winfsp/releases/latest">
<img src="https://img.shields.io/github/release/winfsp/winfsp.svg?label=stable&style=for-the-badge"/>
</a>
<a href="https://github.com/winfsp/winfsp/releases">
<img src="https://img.shields.io/github/release/winfsp/winfsp/all.svg?label=latest&colorB=e52e4b&style=for-the-badge"/>
</a>
<a href="https://chocolatey.org/packages/winfsp">
<img src="https://img.shields.io/badge/choco-install%20winfsp-black.svg?style=for-the-badge"/>
</a>
<img src="art/winfsp-glow.png" width="128"/>
<br/>
<br/>
<a href="https://ci.appveyor.com/project/billziss-gh/winfsp">
<img src="https://img.shields.io/appveyor/ci/billziss-gh/winfsp.svg"/>
</a>
<i>WinFsp enables developers to write their own file systems (i.e. "Windows drives") as user mode programs and without any knowledge of Windows kernel programming. It is similar to FUSE (Filesystem in Userspace) for Linux and other UNIX-like computers.</i>
<br/>
<br/>
WinFsp is a set of software components for Windows computers that allows the creation of user mode file systems. In this sense it is similar to FUSE (Filesystem in Userspace), which provides the same functionality on UNIX-like computers.
<a href="https://winfsp.dev"><b>winfsp.dev</b></a>
<br/>
<br/>
<a href="https://github.com/winfsp/winfsp/releases/latest"><img src="https://img.shields.io/github/release/winfsp/winfsp.svg?label=stable&style=for-the-badge&logo=data:image/svg%2bxml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0ODAgNDgwIj48cGF0aCBkPSJNMzg3LjAwMiAyMDEuMDAxQzM3Mi45OTggMTMyLjAwMiAzMTIuOTk4IDgwIDI0MCA4MGMtNTcuOTk4IDAtMTA3Ljk5OCAzMi45OTgtMTMyLjk5OCA4MS4wMDFDNDcuMDAyIDE2Ny4wMDIgMCAyMTcuOTk4IDAgMjgwYzAgNjUuOTk2IDUzLjk5OSAxMjAgMTIwIDEyMGgyNjBjNTUgMCAxMDAtNDUgMTAwLTEwMCAwLTUyLjk5OC00MC45OTYtOTYuMDAxLTkyLjk5OC05OC45OTl6TTIwOCAyNTJ2LTc2aDY0djc2aDY4TDI0MCAzNTIgMTQwIDI1Mmg2OHoiIGZpbGw9IiNmZmYiLz48L3N2Zz4="/></a>
<a href="https://github.com/winfsp/winfsp/releases"><img src="https://img.shields.io/github/release/winfsp/winfsp/all.svg?label=latest&colorB=e52e4b&style=for-the-badge&logo=data:image/svg%2bxml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0ODAgNDgwIj48cGF0aCBkPSJNMzg3LjAwMiAyMDEuMDAxQzM3Mi45OTggMTMyLjAwMiAzMTIuOTk4IDgwIDI0MCA4MGMtNTcuOTk4IDAtMTA3Ljk5OCAzMi45OTgtMTMyLjk5OCA4MS4wMDFDNDcuMDAyIDE2Ny4wMDIgMCAyMTcuOTk4IDAgMjgwYzAgNjUuOTk2IDUzLjk5OSAxMjAgMTIwIDEyMGgyNjBjNTUgMCAxMDAtNDUgMTAwLTEwMCAwLTUyLjk5OC00MC45OTYtOTYuMDAxLTkyLjk5OC05OC45OTl6TTIwOCAyNTJ2LTc2aDY0djc2aDY4TDI0MCAzNTIgMTQwIDI1Mmg2OHoiIGZpbGw9IiNmZmYiLz48L3N2Zz4="/></a>
<a href="https://chocolatey.org/packages/winfsp"><img src="https://img.shields.io/badge/choco-install%20winfsp-black.svg?style=for-the-badge"/></a>
<br/>
<br/>
<img src="doc/cap.gif" width="75%" height="75%"/>
<br/>
<br/>
<img src="doc/cap.gif" height="450"/>
</p>
## Benefits
<hr/>
### Stability
## Overview
WinFsp is very stable. There are no known kernel mode crashes and it does not suffer from resource leaks or similar problems. WinFsp owes this stability to its [Design](doc/WinFsp-Design.asciidoc) and its rigorous [Testing Regime](doc/WinFsp-Testing.asciidoc).
WinFsp is a platform that provides development and runtime support for custom file systems on Windows computers. Typically any information or storage may be organized and presented as a file system via WinFsp, with the benefit being that the information can be accessed via the standand Windows file APIs by any Windows application.
### Performance
The core WinFsp consists of a kernel mode file system driver (FSD) and a user mode DLL. The FSD interfaces with the Windows kernel and handles all interactions necessary to present itself as a file system driver. The DLL interfaces with the FSD and presents an API that can be used to handle file system functions. For example, when an application attempts to open a file, the file system receives an `Open` call with the necessary information.
WinFsp outperforms its competition and in many scenarios performs as well as NTFS. Read more about its [Performance](doc/WinFsp-Performance-Testing.asciidoc).
Using WinFsp to build a file system has many benefits:
**Easy development**: Developing kernel mode file systems for Windows is a notoriously difficult task. WinFsp makes file system development relatively painless. This [Tutorial](doc/WinFsp-Tutorial.asciidoc) explains how to build a file system.
**Stability**: Stable software without any known kernel mode crashes, resource leaks or similar problems. WinFsp owes this stability to its [Design](doc/WinFsp-Design.asciidoc) and its rigorous [Testing Regime](doc/WinFsp-Testing.asciidoc).
**Correctness**: Strives for file system correctness and compatibility with NTFS. For details see the [Compatibility](doc/NTFS-Compatibility.asciidoc) document.
**Performance**: Has excellent performance that rivals or exceeds that of NTFS in many file system scenarios. Read more about its [Performance](doc/WinFsp-Performance-Testing.asciidoc).
<p align="center">
<img src="doc/WinFsp-Performance-Testing/file_tests.png" height="300"/>
<img src="doc/WinFsp-Performance-Testing/rdwr_tests.png" height="300"/>
</p>
### Compatibility
**Wide support**: Supports Windows 7 to Windows 11 and the x86, x64 and ARM64 architectures.
WinFsp strives for compatibility with NTFS and file system correctness. For the full details see the [Compatibility](doc/NTFS-Compatibility.asciidoc) document.
**Flexible API**: Includes Native, FUSE2, FUSE3 and .NET API's.
### Easy to Use
**Shell integration**: Provides facilities to integrate user mode file systems with the Windows shell. See the [Service Architecture](doc/WinFsp-Service-Architecture.asciidoc) document.
WinFsp has an easy to use but comprehensive API.
**Self-contained**: Self-contained software without external dependencies.
* This simple [Tutorial](doc/WinFsp-Tutorial.asciidoc) explains how to build a file system.
* Consult the [API Reference](https://winfsp.dev/apiref) for native development.
* Includes .NET layer for managed development. See [src/dotnet](src/dotnet).
* Includes FUSE 2.8 compatibility layer: [fuse/fuse.h](inc/fuse/fuse.h)
* Includes FUSE 3.2 compatibility layer: [fuse3/fuse.h](inc/fuse3/fuse.h)
**Widely used**: Used in many open-source and commercial applications with millions of installations (estimated: the WinFsp project does not track its users).
### Other Benefits
**Flexible licensing**: Available under the [GPLv3](License.txt) license with a special exception for Free/Libre and Open Source Software. A commercial license is also available. Please contact Bill Zissimopoulos \<billziss at navimatics.com> for more details.
* Signed drivers provided on every release.
* Available under the [GPLv3](License.txt) license with a special exception for Free/Libre and Open Source Software.
## Installation
To learn more about WinFsp, please visit its website: https://winfsp.dev
Download and run the [WinFsp installer](https://github.com/winfsp/winfsp/releases/latest). In the installer select the option to install the "Developer" files. These include the MEMFS sample file system, but also header and library files that let you develop your own user-mode file system.
## Project Organization
<img src="doc/WinFsp-Tutorial/Installer.png" height="290"/>
The project source code is organized as follows:
### Launch a file system for testing
* :file_folder: [build/VStudio](build/VStudio): WinFsp solution and project files.
* :file_folder: [doc](doc): The WinFsp design documents and additional documentation can be found here.
* :file_folder: [ext](ext): External dependencies.
* :file_folder: [ext/tlib](ext/tlib): A small test library originally from the secfs (Secure Cloud File System) project.
* :file_folder: ext/test: Submodule pointing to the secfs.test project, which contains a number of tools for testing Windows and POSIX file systems.
* :file_folder: [inc](inc): Public headers.
* :file_folder: [inc/fuse](inc/fuse): Public headers for the FUSE compatibility layer.
* :file_folder: [inc/fuse3](inc/fuse3): Public headers for the FUSE3 compatibility layer.
* :file_folder: [inc/winfsp](inc/winfsp): Public headers for the WinFsp API.
* :file_folder: [src](src): WinFsp source code.
* :file_folder: [src/dll](src/dll): Source code to the WinFsp DLL.
* :file_folder: [src/dll/fuse](src/dll/fuse): Source code to the FUSE compatibility layer.
* :file_folder: [src/dll/fuse3](src/dll/fuse3): Source code to the FUSE3 compatibility layer.
* :file_folder: [src/dotnet](src/dotnet): Source code to the .NET layer.
* :file_folder: [src/fsptool](src/fsptool): Source code to fsptool command line utility.
* :file_folder: [src/ku](src/ku): Source code that can be used from kernel or user mode.
* :file_folder: [src/launcher](src/launcher): Source code to the launcher service and the launchctl utility.
* :file_folder: [src/sys](src/sys): Source code to the WinFsp FSD.
* :file_folder: [opt/cygfuse](opt/cygfuse): Source code to the FUSE for Cygwin package.
* :file_folder: [tst](tst): Source code to example file systems and test suites.
* :file_folder: [tst/winfsp-tests](tst/winfsp-tests): WinFsp test suite.
* :file_folder: [tools](tools): Various tools for building and testing WinFsp.
You can test WinFsp by launching MEMFS from the command line:
## Building and Running
In order to build WinFsp you will need the following:
* Visual Studio 2015 - 2019
* Windows Driver Kit (WDK) 10
- **NOTE**: When using the latest WDK (Windows 10.0.18362.1) with Visual Studio 2015 you may get an error about a missing task `ValidateNTTargetVersion`. The fix is to edit the file `\Program Files (x86)\Windows Kits\10\build\WindowsDriver.Common.targets` and modify the `UsingTask` line for `ValidateNTTargetVersion` as follows:
```
<UsingTask TaskName="ValidateNTTargetVersion" AssemblyFile="$(WDKContentRoot)build\bin\Microsoft.DriverKit.Build.Tasks.16.0.dll"/>
billziss@xps ⟩ ~ ⟩ net use X: \\memfs64\test
The command completed successfully.
billziss@xps ⟩ ~ ⟩ X:
billziss@xps ⟩ X:\ ⟩ echo "hello world" > hello.txt
billziss@xps ⟩ X:\ ⟩ dir
Directory: X:\
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 6/12/2022 5:15 PM 28 hello.txt
billziss@xps ⟩ X:\ ⟩ type hello.txt
hello world
billziss@xps ⟩ X:\ ⟩ cd ~
billziss@xps ⟩ ~ ⟩ net use X: /delete
X: was deleted successfully.
```
* [Wix toolset](http://wixtoolset.org)
To fully build WinFsp (including the installer) you must use `tools\build.bat`. By default it builds a Release build, but you can choose either the Debug or Release configuration by using the syntax:
MEMFS (and all file systems that use the WinFsp Launcher as documented in the [Service Architecture](doc/WinFsp-Service-Architecture.asciidoc) document) can also be launched from Explorer using the "Map Network Drive" functionality.
tools\build.bat CONFIGURATION
## Resources
If you build the driver yourself it will not be signed and Windows will refuse to load it unless you enable "testsigning". You can enable "testsigning" using the command `bcdedit.exe -set testsigning on`. For more information see this [document](doc/WinFsp-Debugging-Setup.asciidoc).
**Documentation**:
WinFsp is designed to run on Windows 7 and above. It has been tested on the following platforms:
- [Tutorial](doc/WinFsp-Tutorial.asciidoc)
* Windows 7 Enterprise
* Windows 8 Pro
* Windows Server 2012
* Windows 10 Pro
* Windows Server 2016
* Windows 11 Pro
- [API Reference](doc/WinFsp-API-winfsp.h.md)
## How to Help
- [Building](doc/WinFsp-Building.asciidoc)
I am looking for help in the following areas:
- [Project wiki](https://github.com/winfsp/winfsp/wiki)
* If you have a file system that runs on FUSE please consider porting it to WinFsp. WinFsp has a native API, but it also has a FUSE (high-level) API.
* If you are working with a language other than C/C++ (e.g. Delphi, Java, etc.) and you are interested in porting/wrapping WinFsp I would love to hear from you.
* There are a number of outstanding issues listed in the [GitHub repository](https://github.com/winfsp/winfsp/issues). Many of these require knowledge of Windows kernel-mode and an understanding of the internals of WinFsp so they are not for the faint of heart.
In all cases I can provide ideas and/or support.
## Where to Discuss
If you wish to discuss WinFsp there are now two options:
**Discussion**:
- [WinFsp Google Group](https://groups.google.com/forum/#!forum/winfsp)
- [Author's Twitter](https://twitter.com/BZissimopoulos)
## License
WinFsp is available under the [GPLv3](License.txt) license with a special exception for Free/Libre and Open Source Software. A commercial license is also available. Please contact Bill Zissimopoulos \<billziss at navimatics.com> for more details.

View File

@ -1,6 +1,13 @@
version: '{build}'
skip_tags: true
skip_commits:
files:
- README.md
- Changelog.md
- Contributors.asciidoc
- art/**
- doc/**
environment:
# Disable the winfsp-tests built-in exception filter to allow WER to collect dumps.
@ -73,6 +80,7 @@ test_script:
- if %TESTING%==Func 7z x Test.Filter.Driver.zip.001
- if %TESTING%==Func start /wait msiexec /i "Test.Filter.Driver\HCK Filter.Driver Content-x86_en-us.msi" /qn
- if %TESTING%==Func tools\nmake-ext-test.bat %CONFIGURATION%
#- ps: . "C:\Program Files (x86)\Windows Kits\10\Debuggers\x64\gflags.exe" /k +spp *
- if %TESTING%==Func tools\run-tests.bat %CONFIGURATION%
- if %TESTING%==Func tools\run-tests.bat %CONFIGURATION% ifstest
- if %TESTING%==Func tools\run-tests.bat %CONFIGURATION% sample

View File

@ -20,8 +20,8 @@
<MyCanonicalVersion>1.11</MyCanonicalVersion>
<MyProductVersion>2022+ARM64 Beta3</MyProductVersion>
<MyProductStage>Beta</MyProductStage>
<MyProductVersion>2022+ARM64</MyProductVersion>
<MyProductStage>Gold</MyProductStage>
<MyCrossCert>DigiCert High Assurance EV Root CA.crt</MyCrossCert>
<MyCertIssuer>DigiCert</MyCertIssuer>

View File

@ -11,6 +11,7 @@ This document contains a list of known open-source file systems and file system
- https://github.com/ihaveamac/fuse-3ds[fuse-3ds] - FUSE Filesystem Python scripts for Nintendo 3DS files
- https://github.com/sganis/golddrive[golddrive] - Windows ssh network drive
- https://github.com/winfsp/hubfs[hubfs] - File system for GitHub
- https://github.com/juicedata/juicefs[JuiceFS] - a distributed POSIX file system built on top of Redis and S3
- https://github.com/FrKaram/KS2.Drive[KS2.Drive] - Mount a webDAV/AOS server as a local drive
- https://github.com/winfsp/nfs-win[nfs-win] - NFS for Windows
- https://github.com/winfsp/objfs[objfs] - Object Storage File System

View File

@ -0,0 +1,59 @@
= WinFsp Building
This document provides instructions on building WinFsp and describes the WinFsp project structure.
== Building
In order to build WinFsp you will need the following:
* Visual Studio 2019
* Windows Driver Kit (WDK)
* https://wixtoolset.org[Wix toolset]
Use the command `tools\build.bat Release` to produce a full build (including the installer). However the resulting product will not be properly signed and Windows will refuse to load the WinFsp driver, unless you enable testsigning with `bcdedit -set testsigning on`.
Producing a fully functional build requires an EV certificate and a Partner Center for Windows Hardware account. Assuming you have those, the steps to produce a full build are as follows:
* Produce a build signed with your EV certificate using `tools\build.bat Release`.
* Upload the signed `driver.cab` file to Microsoft for "attestation signing".
* Download the now Microsoft-signed `driver.cab` file and extract it into a folder (e.g. `signed-drivers`).
* Re-run the build using `tools\build.bat Release PATH\TO\signed-drivers`
== Versioning
WinFsp versioning (and branding) is controlled by the file `build\VStudio\build.version.props`. See the link:WinFsp-Rebranding.asciidoc[WinFsp Rebranding] document for details.
== Project Structure
The WinFsp project is structured as follows:
* 📁 https://github.com/winfsp/winfsp/tree/master/art[art]: Project logo and other art.
* 📁 https://github.com/winfsp/winfsp/tree/master/build[build]: Project build files.
** 📁 https://github.com/winfsp/winfsp/tree/master/build/choco[choco]: Chocolatey package files.
** 📁 https://github.com/winfsp/winfsp/tree/master/build/VStudio[VStudio]: Visual Studio solution and project files.
* 📁 https://github.com/winfsp/winfsp/tree/master/doc[doc]: Project documentation.
* 📁 https://github.com/winfsp/winfsp/tree/master/ext[ext]: External dependencies.
** 📁 https://github.com/winfsp/winfsp/tree/master/ext/tlib[tlib]: Test library for C originally from the secfs project.
** 📁 https://github.com/winfsp/winfsp/tree/master/ext/test[test]: Submodule containing additional file system testing tools.
* 📁 https://github.com/winfsp/winfsp/tree/master/inc[inc]: Public headers.
** 📁 https://github.com/winfsp/winfsp/tree/master/inc/fuse[fuse]: Public headers for the FUSE compatibility layer.
** 📁 https://github.com/winfsp/winfsp/tree/master/inc/fuse3[fuse3]: Public headers for the FUSE3 compatibility layer.
** 📁 https://github.com/winfsp/winfsp/tree/master/inc/winfsp[winfsp]: Public headers for the WinFsp API.
* 📁 https://github.com/winfsp/winfsp/tree/master/opt[opt]: Additional source code and files.
** 📁 https://github.com/winfsp/winfsp/tree/master/opt/cygfuse[cygfuse]: Source code for the FUSE for Cygwin package.
** 📁 https://github.com/winfsp/winfsp/tree/master/opt/fsext[fsext]: Source code for the fsext package.
* 📁 https://github.com/winfsp/winfsp/tree/master/src[src]: Project source code.
** 📁 https://github.com/winfsp/winfsp/tree/master/src/dll[dll]: Source code for the WinFsp DLL.
*** 📁 https://github.com/winfsp/winfsp/tree/master/src/dll/fuse[fuse]: Source code for the FUSE compatibility layer.
*** 📁 https://github.com/winfsp/winfsp/tree/master/src/dll/fuse3[fuse3]: Source code for the FUSE3 compatibility layer.
** 📁 https://github.com/winfsp/winfsp/tree/master/src/dotnet[dotnet]: Source code for the .NET layer.
** 📁 https://github.com/winfsp/winfsp/tree/master/src/fsptool[fsptool]: Source code for the fsptool command line utility.
** 📁 https://github.com/winfsp/winfsp/tree/master/src/launcher[launcher]: Source code for the launcher and the launchctl utility.
** 📁 https://github.com/winfsp/winfsp/tree/master/src/shared[shared]: Shared source code.
*** 📁 https://github.com/winfsp/winfsp/tree/master/src/shared/ku[ku]: Shared source code for kernel and user mode.
*** 📁 https://github.com/winfsp/winfsp/tree/master/src/shared/um[um]: Shared source code for user mode only.
** 📁 https://github.com/winfsp/winfsp/tree/master/src/sys[sys]: Source code for the WinFsp FSD.
* 📁 https://github.com/winfsp/winfsp/tree/master/tools[tools]: Tools for building and testing WinFsp.
* 📁 https://github.com/winfsp/winfsp/tree/master/tst[tst]: Source code for example file systems and test suites.
** 📁 https://github.com/winfsp/winfsp/tree/master/tst/memfs[memfs]: The MEMFS reference file system.
** 📁 https://github.com/winfsp/winfsp/tree/master/tst/winfsp-tests[winfsp-tests]: The primary WinFsp test suite.

View File

@ -1,192 +1,163 @@
= Performance Testing
:caption:
This document discusses performance testing for WinFsp. The goal of this performance testing is to discover optimization opportunities for WinFsp and compare its performance to that of NTFS and Dokany.
This document presents results from performance testing of WinFsp. These results show that WinFsp has excellent performance that rivals or exceeds that of NTFS in many file system scenarios. Some further optimization opportunities are also identified.
== Executive Summary
== Summary
This performance testing shows that WinFsp has excellent performance in all tested scenarios. It outperforms NTFS in most scenarios (an unfair comparison as NTFS is a disk file system and WinFsp is tested with an in-memory file system). It also outperforms Dokany in all scenarios, often by an order of magnitude.
Two reference WinFsp file systems, MEMFS and NTPTFS, are compared against NTFS in multiple file system scenarios. MEMFS is an in-memory file system, whereas NTPTFS (NT passthrough file system) is a file system that passes all file system requests onto an underlying NTFS file system.
ifdef::env-browser[chart::bar[data-uri="WinFsp-Performance-Testing/file_tests.csv",file="WinFsp-Performance-Testing/file_tests.png",opt="y-label=time"]]
ifndef::env-browser[image::WinFsp-Performance-Testing/file_tests.png[]]
The test results are summarized in the charts below. The "File Tests" chart summarizes performance of file path namespace manipulations (e.g. creating/deleting files, opening files, listing files, etc.). The "Read/Write Tests" chart summarizes performance of file I/O (e.g. cached read/write, memory mapped I/O, etc.)
ifdef::env-browser[chart::bar[data-uri="WinFsp-Performance-Testing/rdwr_tests.csv",file="WinFsp-Performance-Testing/rdwr_tests.png",opt="y-label=time"]]
ifndef::env-browser[image::WinFsp-Performance-Testing/rdwr_tests.png[]]
The important takeaways are:
== Fsbench
- MEMFS is faster than NTFS is most scenarios. This is a somewhat expected result because MEMFS is an in-memory file system, whereas NTFS is a disk file system. However it shows that WinFsp does not add significant overhead and user mode file systems can be fast.
All testing was performed using a new performance test suite developed as part of WinFsp, called https://github.com/winfsp/winfsp/blob/master/tst/fsbench/fsbench.c[fsbench]. Fsbench was developed because it allows the creation of tests that are important to file system developers; for example, it can answer questions of the type: "how long does it take to delete 1000 files" or "how long does it take to list a directory with 10000 files in it".
- MEMFS and NTPTFS both outperform NTFS when doing cached file I/O! This is a significant result because doing file I/O is the primary purpose of a file system. It is also an unexpected result at least in the case of NTPTFS, since NTPTFS runs on top of NTFS.
Fsbench is based on the https://github.com/winfsp/winfsp/tree/master/ext/tlib[tlib] library, originally from the *secfs* project. Tlib is usually used to develop regression test suites in C/C++, but can be also used to create performance tests.
The following sections present the testing methodology used, provide instructions for independent verification, describe the individual tests in detail and provide an explanation for the observed results.
Fsbench currently includes the following tests:
[width="100%",cols="20%,60%,20%",options="header"]
[cols="a,a", frame=none, grid=none]
|===
|Test |Measures performance of |Parameters
|file_create_test |CreateFileW(CREATE_NEW) / CloseHandle |file count
|file_open_test |CreateFileW(OPEN_EXISTING) / CloseHandle |file count
|file_overwrite_test|CreateFileW(CREATE_ALWAYS) / CloseHandle with existing files|file count
|file_list_test |FindFirstFileW / FindNextFile / FindClose |iterations
|file_delete_test |DeleteFileW |file count
|file_mkdir_test |CreateDirectoryW |file count
|file_rmdir_test |RemoveDirectoryW |file count
|rdwr_cc_write_page_test |WriteFile (1 page; cached) |iterations
|rdwr_cc_read_page_test |ReadFile (1 page; cached) |iterations
|rdwr_nc_write_page_test |WriteFile (1 page; non-cached) |iterations
|rdwr_nc_read_page_test |ReadFile (1 page; non-cached) |iterations
|rdwr_cc_write_large_test |WriteFile (16 pages; cached) |iterations
|rdwr_cc_read_large_test |ReadFile (16 pages; cached) |iterations
|rdwr_nc_write_large_test |WriteFile (16 pages; non-cached) |iterations
|rdwr_nc_read_large_test |ReadFile (16 pages; non-cached) |iterations
|mmap_write_test |Memory mapped write test |iterations
|mmap_write_test |Memory mapped read test |iterations
|image::WinFsp-Performance-Testing/file_tests.png[]
|image::WinFsp-Performance-Testing/rdwr_tests.png[]
|===
== Tested File Systems
== Methodology
=== NTFS
A test run consists of performance tests run one after the other (in sequence). The test driver is careful to clear system caches before each test to minimize timing interference between the tests (because we would not want operations performed in test A to affect measurements of test B). Tests are run on an idle computer to minimize interference from third party components.
The comparison to NTFS is very important to establish a baseline. It is also very misleading because NTFS is a disk file system and MEMFS (either the WinFsp or Dokany variants) is an in memory file system. The tests will show that MEMFS is faster than NTFS. This should not be taken to mean that we are trying to make the (obvious) claim that an in memory file system is faster than a disk file system, but to show that the approach of writing a file system in user mode is a valid proposition and can be efficient.
Each test run is run a number of times (default: 3) against each file system and the smallest time value for the particular test and file system is chosen. The assumption is that even in a seemingly idle system there is some activity that affects the results; the smallest value is the preferred one to use because it reflects the time when there is less or no other system activity.
=== WinFsp/MEMFS
For the NTFS file system we use the default configuration as it ships with Windows (e.g. 8.3 names are enabled). For the NTPTFS file system we disable anti-virus checks on the lower file system, because it makes no sense for NTPTFS to pay for virus checking twice. (Consider an NTPTFS file system that exposes a lower NTFS directory `C:\t` as an upper drive `X:`. Such a file system would have virus checking applied on file accesses to `X:`, but also to its own accesses to `C:\t`. This is unnecessary and counter-productive.)
MEMFS is the file system used to test WinFsp and shipped as a sample bundled with the WinFsp installer. MEMFS is a simple in memory file system and as such is very fast under most conditions. This is desirable because our goal with this performance testing is to measure the speed of the WinFsp system components rather the performance of a complex user mode file system. MEMFS has minimal overhead and is ideal for this purpose.
Note that the sequential nature of the tests represents a worst case scenario for WinFsp. The reason is that a single file system operation may require a roundtrip to the user mode file system and such a roundtrip requires two process context switches (i.e. address space and thread switches): one context switch to carry the file system request to the user mode file system and one context switch to carry the response back to the originating process. WinFsp performs better when multiple processes issue file system operations concurrently, because multiple requests are queued in its internal queues and multiple requests can be handled in a single context switch.
WinFsp/MEMFS can be run in different configurations, which enable or disable WinFsp caching features. The tested configurations were:
For more information refer to the link:WinFsp-Performance-Testing/WinFsp-Performance-Testing-Analysis.ipynb[Performance Testing Analysis] notebook. This notebook together with the `run-all-perf-tests.bat` script can be used for replication and independent verification of the results presented in this document.
- An infinite FileInfoTimeout, which enables caching of metadata and data.
- A FileInfoTimeout of 1s (second), which enables caching of metadata but disables caching of data.
- A FileInfoTimeout of 0, which completely disables caching.
The WinFsp git commit at the time of testing was d804f5674d76f11ea86d14f4bcb1157e6e40e719.
=== Dokany/MEMFS
To achieve fairness when comparing Dokany to WinFsp the MEMFS file system has been ported to Dokany. Substantial care was taken to ensure that WinFsp/MEMFS and Dokany/MEMFS perform equally well, so that the performance of the Dokany FSD and user-mode components can be measured and compared accurately.
The Dokany/MEMFS project has its own https://github.com/billziss-gh/memfs-dokany[repository]. The project comes without a license, which means that it may not be used for any purpose other than as a reference.
The Dokany version used for testing was 1.0.1. The Dokany/MEMFS git commit was 27a678d7c0d5ee2fb3fb2ecc8e38210857ae941c.
== Test Environment
Tests were performed on an idle computer/VM. There was a reboot of both the computer and VM before each file system was tested. Each test was run twice and the smaller time value chosen. The assumption is that even in a seemingly idle desktop system there is some activity which will affect the results; the smaller value is the preferred one to use because it reflects the time when there is less or no other activity.
The test environment was as follows:
The test environment for the results presented in this document is as follows:
----
MacBook Pro (Retina, 13-inch, Early 2015)
3.1 GHz Intel Core i7
16 GB 1867 MHz DDR3
500 GB SSD
Dell XPS 13 9300
Intel Core i7-1065G7 CPU
32GB 3733MHz LPDDR4x RAM
2TB M.2 PCIe NVMe SSD
VirtualBox Version 5.0.20 r106931
1 CPU
4 GB RAM
80 GB Dynamically allocated differencing storage
Windows 10 (64-bit) Version 1511 (OS Build 10586.420)
Windows 11 (64-bit) Version 21H2 (OS Build 22000.258)
WinFsp 2022+ARM64 Beta3 (v1.11B3)
----
== Test Results
== Results
In the graphs below we use consistent coloring to quickly identify a file system. Red is used for NTFS, yellow for WinFsp/MEMFS with a FileInfoTimeout of 0, green for WinFsp/MEMFS with a FileInfoTimeout of 1, light blue for WinFsp/MEMFS with an infinite FileInfoTimeout and deep blue for Dokany/MEMFS.
In the charts below we use consistent coloring and markers to quickly identify a file system. Blue and the letter 'N' is used for NTFS, orange and the letter 'M' is used for MEMFS, green and the letter 'P' is used for NTPTFS.
In bar charts shorter bars are better. In plot charts lower times are better. (Better means that the file system is faster).
In all tests lower times are better (the file system is faster).
=== File Tests
These tests measure the performance of creating, opening, overwriting and listing files and directories.
File tests are tests that are performed against the hierarchical path namespace of a file system. These tests measure the performance of creating, opening, overwriting, listing and deleting files.
Measured times for these tests are normalized against the NTFS time (so that the NTFS value is always 1). This allows for easy comparison between file systems across all file tests.
MEMFS has the best performance in most of these tests. NTFS performs better in some tests; these are discussed further below. NTPTFS is last as it has the overhead of both NTFS and WinFsp.
image::WinFsp-Performance-Testing/file_tests.png[]
==== file_create_test
This test measures the performance of CreateFileW(CREATE_NEW) / CloseHandle. WinFsp has the best performance here. Dokany follows and NTFS is last as it has to actually update its data structures on disk.
This test measures the performance of creating new files using `CreateFileW(CREATE_NEW)` / `CloseHandle`. MEMFS has the best performance here, while NTFS has worse performance as it has to update its data structures on disk.
ifdef::env-browser[chart::line[data-uri="WinFsp-Performance-Testing/file_create_test.csv",file="WinFsp-Performance-Testing/file_create_test.png",opt="x-label=file count,y-label=time"]]
ifndef::env-browser[image::WinFsp-Performance-Testing/file_create_test.png[]]
image::WinFsp-Performance-Testing/file_create_test.png[]
==== file_open_test
This test measures the performance of CreateFileW(OPEN_EXISTING) / CloseHandle. WinFsp again has the best (although uneven) performance, followed by NTFS and then Dokany.
This test measures the performance of opening different files using `CreateFileW(OPEN_EXISTING)` / `CloseHandle`. MEMFS again has the best performance, followed by NTFS and then NTPTFS.
WinFsp appears to have very uneven performance here. In particular notice that opening 1000 files is slower than opening 2000 files, which makes no sense! I suspect that the test observes an initial acquisition of resouces when the test first starts, which is not necessary when the test runs for 2000 files at a later time. This uneven performance should probably be investigated in the future.
image::WinFsp-Performance-Testing/file_open_test.png[]
ifdef::env-browser[chart::line[data-uri="WinFsp-Performance-Testing/file_open_test.csv",file="WinFsp-Performance-Testing/file_open_test.png",opt="x-label=file count,y-label=time"]]
ifndef::env-browser[image::WinFsp-Performance-Testing/file_open_test.png[]]
==== iter.file_open_test
This test measures the performance of opening the same files repeatedly using `CreateFileW(OPEN_EXISTING)` / `CloseHandle`. NTFS has the best performance, with MEMFS following and NTPTFS a distant third.
This test shows that NTFS does a better job than WinFsp when re-opening a file. The problem is that in most cases the WinFsp API design requires a round-trip to the user mode file system when opening a file. Improving WinFsp performance here would likely require substantial changes to the WinFsp API.
image::WinFsp-Performance-Testing/iter.file_open_test.png[]
==== file_overwrite_test
This test measures the performance of CreateFileW(CREATE_ALWAYS) / CloseHandle. WinFsp is fastest, followed by NTFS and then Dokany.
This test measures the performance of overwriting files using `CreateFileW(CREATE_ALWAYS)` / `CloseHandle`. MEMFS is fastest, followed by NTFS and then NTPTFS.
ifdef::env-browser[chart::line[data-uri="WinFsp-Performance-Testing/file_overwrite_test.csv",file="WinFsp-Performance-Testing/file_overwrite_test.png",opt="x-label=file count,y-label=time"]]
ifndef::env-browser[image::WinFsp-Performance-Testing/file_overwrite_test.png[]]
image::WinFsp-Performance-Testing/file_overwrite_test.png[]
==== file_list_test
This test measures the performance of FindFirstFileW / FindNextFile / FindClose. NTFS wins this scenario, likely because it can satisfy the list operation from cache. WinFsp has overall good performance. Dokany appears to show slightly quadratic performance in this scenario.
This test measures the performance of listing files using `FindFirstFileW` / `FindNextFile` / `FindClose`. MEMFS is again fastest with NTFS and NTPTFS following.
ifdef::env-browser[chart::line[data-uri="WinFsp-Performance-Testing/file_list_test.csv",file="WinFsp-Performance-Testing/file_list_test.png",opt="x-label=file count,y-label=time"]]
ifndef::env-browser[image::WinFsp-Performance-Testing/file_list_test.png[]]
It should be noted that NTFS can perform better in this test, if 8.3 (i.e. short) names are disabled (see `fsutil 8dot3name`). However Microsoft ships NTFS with 8.3 names enabled by default and these tests are performed against the default configuration of NTFS.
image::WinFsp-Performance-Testing/file_list_test.png[]
==== file_list_single_test
This test measures the performance of listing a single file using `FindFirstFileW` / `FindNextFile` / `FindClose`. NTFS has again best performance, with MEMFS following and NTPTFS a distant third.
This test shows that NTFS does a better job than WinFsp at caching directory data. Improving WinFsp performance here would likely require a more aggressive and/or intelligent directory caching scheme than the one used now.
image::WinFsp-Performance-Testing/file_list_single_test.png[]
==== file_delete_test
This test measures the performance of DeleteFileW. WinFsp has the best performance, followed by Dokany and NTFS with very similar performance.
This test measures the performance of deleting files using `DeleteFileW`. MEMFS has the best performance, followed by NTFS and NTPTFS.
ifdef::env-browser[chart::line[data-uri="WinFsp-Performance-Testing/file_delete_test.csv",file="WinFsp-Performance-Testing/file_delete_test.png",opt="x-label=file count,y-label=time"]]
ifndef::env-browser[image::WinFsp-Performance-Testing/file_delete_test.png[]]
image::WinFsp-Performance-Testing/file_delete_test.png[]
=== Read/Write Tests
These tests measure the performance of cached, non-cached and memory-mapped I/O.
Read/write tests are tests that measure the performance of cached, non-cached and memory-mapped I/O.
==== rdwr_cc_write_page_test
Measured times for these tests are normalized against the NTFS time (so that the NTFS value is always 1). This allows for easy comparison between file systems across all read/write tests.
This test measures the performance of cached WriteFile with 1 page writes. NTFS and WinFsp with an infinite FileInfoTimeout have the best performance, with a clear edge to NTFS (likely because of its use of FastIO, which WinFsp does not currently support). WinFsp with a FileInfoTimeout of 0 or 1 performance is next, because WinFsp does not use the NTOS Cache Manager in this scenario. Dokany performance is last.
MEMFS and NTPTFS outperform NTFS in cached and non-cached I/O tests and have equal performance to NTFS in memory mapped I/O tests. This result may be somewhat counter-intuitive (especially for NTPTFS), but the reasons are explained below.
ifdef::env-browser[chart::line[data-uri="WinFsp-Performance-Testing/rdwr_cc_write_page_test.csv",file="WinFsp-Performance-Testing/rdwr_cc_write_page_test.png",opt="x-label=iterations,y-label=time"]]
ifndef::env-browser[image::WinFsp-Performance-Testing/rdwr_cc_write_page_test.png[]]
image::WinFsp-Performance-Testing/rdwr_tests.png[]
==== rdwr_cc_read_page_test
This test measures the performance of cached ReadFile with 1 page reads. The results here are very similar to the rdwr_cc_write_page_test case and similar comments apply.
This test measures the performance of cached `ReadFile` with 1 page reads. MEMFS and NTPTFS outperform NTFS by a considerable margin.
ifdef::env-browser[chart::line[data-uri="WinFsp-Performance-Testing/rdwr_cc_read_page_test.csv",file="WinFsp-Performance-Testing/rdwr_cc_read_page_test.png",opt="x-label=iterations,y-label=time"]]
ifndef::env-browser[image::WinFsp-Performance-Testing/rdwr_cc_read_page_test.png[]]
Cached reads are satisfied from cache and they can effectively be a "memory copy" from the operating system's buffers into the `ReadFile` buffer. Both WinFsp and NTFS implement NT "fast I/O" and one explanation for the test's result is that the WinFsp "fast I/O" implementation is more performant than the NTFS one.
==== rdwr_nc_write_page_test
An alternative explanation is that MEMFS and NTPTFS are simply faster in filling the file system cache when a cache miss occurs. While this may be true for MEMFS (because it maintains file data in user mode memory), it cannot be true for NTPTFS. Recall that the test driver clears system caches prior to running every test, which means that when NTPTFS tries to fill its file system cache for the upper file system, it has to access lower file system data from disk (the same as NTFS).
This test measures the performance of non-cached WriteFile with 1 page writes. WinFsp has the best performance, followed by Dokany. NTFS shows bad performance, which of course make sense as we are asking it to write all data to the disk.
image::WinFsp-Performance-Testing/rdwr_cc_read_page_test.png[]
ifdef::env-browser[chart::line[data-uri="WinFsp-Performance-Testing/rdwr_nc_write_page_test.csv",file="WinFsp-Performance-Testing/rdwr_nc_write_page_test.png",opt="x-label=iterations,y-label=time"]]
ifndef::env-browser[image::WinFsp-Performance-Testing/rdwr_nc_write_page_test.png[]]
==== rdwr_cc_write_page_test
This test measures the performance of cached `WriteFile` with 1 page writes. As in the read case, MEMFS and NTPTFS outperform NTFS albeit with a smaller margin.
Similar comments as for `rdwr_cc_read_page_test` apply.
image::WinFsp-Performance-Testing/rdwr_cc_write_page_test.png[]
==== rdwr_nc_read_page_test
This test measures the performance of non-cached ReadFile with 1 page reads. The results here are very similar to the rdwr_nc_write_page_test case and similar comments apply.
This test measures the performance of non-cached `ReadFile` with 1 page reads. Although MEMFS and NTPTFS have better performance than NTFS, this result is not as interesting, because MEMFS is an in-memory file system and NTPTFS currently implements only cached I/O (this may change in the future). However we include this test for completeness.
ifdef::env-browser[chart::line[data-uri="WinFsp-Performance-Testing/rdwr_nc_read_page_test.csv",file="WinFsp-Performance-Testing/rdwr_nc_read_page_test.png",opt="x-label=iterations,y-label=time"]]
ifndef::env-browser[image::WinFsp-Performance-Testing/rdwr_nc_read_page_test.png[]]
image::WinFsp-Performance-Testing/rdwr_nc_read_page_test.png[]
==== mmap_write_test
==== rdwr_nc_write_page_test
This test measures the performance of memory mapped writes. NTFS and WinFsp seem to have identical performance here, which actually makes sense because memory mapped I/O is effectively always cached and most of the actual I/O is done asynchronously by the system.
This test measures the performance of non-cached `WriteFile` with 1 page writes. Again MEMFS and NTPTFS have better performance than NTFS, but similar comments as for `rdwr_nc_read_page_test` apply.
There are no results for Dokany as it seems to (still) not support memory mapped files:
----
Y:\>c:\Users\billziss\Projects\winfsp\build\VStudio\build\Release\fsbench-x64.exe --mmap=100 mmap*
mmap_write_test........................ KO
ASSERT(0 != Mapping) failed at fsbench.c:226:mmap_dotest
----
ifdef::env-browser[chart::line[data-uri="WinFsp-Performance-Testing/mmap_write_test.csv",file="WinFsp-Performance-Testing/mmap_write_test.png",opt="x-label=iterations,y-label=time"]]
ifndef::env-browser[image::WinFsp-Performance-Testing/mmap_write_test.png[]]
image::WinFsp-Performance-Testing/rdwr_nc_write_page_test.png[]
==== mmap_read_test
This test measures the performance of memory mapped reads. Again NTFS and WinFsp seem to have identical performance here.
This test measures the performance of memory mapped reads. NTFS and WinFsp have identical performance here, which actually makes sense because memory mapped I/O is effectively cached by buffers that are mapped into the address space of the process doing the I/O.
There are no results for Dokany as it faces the same issue as with mmap_write_test.
image::WinFsp-Performance-Testing/mmap_read_test.png[]
ifdef::env-browser[chart::line[data-uri="WinFsp-Performance-Testing/mmap_read_test.csv",file="WinFsp-Performance-Testing/mmap_read_test.png",opt="x-label=iterations,y-label=time"]]
ifndef::env-browser[image::WinFsp-Performance-Testing/mmap_read_test.png[]]
==== mmap_write_test
This test measures the performance of memory mapped writes. NTFS and WinFsp have again identical performance here. Similar comments as for `mmap_read_test` apply.
image::WinFsp-Performance-Testing/mmap_write_test.png[]

View File

@ -0,0 +1,238 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Performance Testing Analysis\n",
"\n",
"This notebook describes the methodology for analyzing WinFsp performance."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Data Collection\n",
"\n",
"Performance data is collected by running the script `run-all-perf-tests.bat`. This script runs a variety of performance tests against the NTFS, MEMFS and NTPTFS file systems. The tests are run a number of times (default: 3) and the results are saved in CSV files with names `ntfs-N.csv`, `memfs-N.csv` and `ntptfs-N.csv` (where `N` represents the results of test run `N`)."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Data Loading\n",
"\n",
"Data is loaded from all CSV files into a single pandas `DataFrame`. The resulting `DataFrame` has columns `test`, `iter`, `ntfs`, `memfs`, `ntptfs`. With multiple test runs there will be multiple time values for a `test`, `iter`, file system triple; in this case the smallest time value is entered into the `DataFrame`. The assumption is that even in a seemingly idle system there is some activity that affects the results; the smallest value is the preferred one to use because it reflects the time when there is less or no other system activity.\n",
"\n",
"The resulting `DataFrame` will contain data similar to the following:\n",
"\n",
"| test | iter | ntfs | memfs | ntptfs |\n",
"|:------------------|------:|-------:|-------:|-------:|\n",
"| file_create_test | 1000 | 0.20 | 0.06 | 0.28 |\n",
"| file_open_test | 1000 | 0.09 | 0.05 | 0.22 |\n",
"| ... | ... | ... | ... | ... |"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import glob, os\n",
"import matplotlib.pyplot as plt\n",
"import numpy as np\n",
"import pandas as pd\n",
"\n",
"nameord = [\"ntfs\", \"memfs\", \"ntptfs\"]\n",
"\n",
"datamap = {}\n",
"for f in sorted(glob.iglob(\"*.csv\")):\n",
" datamap.setdefault(f.rsplit(\"-\", maxsplit=1)[0], []).append(f)\n",
"\n",
"df = None\n",
"for n in nameord:\n",
" ndf = None\n",
" for f in datamap[n]:\n",
" df0 = pd.read_csv(f, header=None, names=[\"test\", \"iter\", n])\n",
" if ndf is None:\n",
" ndf = df0\n",
" else:\n",
" ndf = ndf.combine(df0, np.minimum)\n",
" if df is None:\n",
" df = ndf\n",
" else:\n",
" df = df.merge(ndf, how=\"left\")\n",
"#df"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Data Analysis\n",
"\n",
"For each test a plot is drawn that shows how each file system performs in the particular test. This allows for easy comparisons between file systems for a particular test."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"markermap = { \"ntfs\": \"$\\mathtt{N}$\", \"memfs\": \"$\\mathtt{M}$\", \"ntptfs\": \"$\\mathtt{P}$\"}\n",
"for t, tdf in df.groupby(\"test\", sort=False):\n",
" plt.figure(figsize=(10,8), dpi=100, facecolor=\"white\")\n",
" plt.title(t)\n",
" xlabel = \"iter\"\n",
" if t.startswith(\"file_\"):\n",
" xlabel = \"files\"\n",
" for n in nameord:\n",
" tdf.plot(ax=plt.gca(), x=\"iter\", xlabel=xlabel, y=n, ylabel=\"time\", marker=markermap[n], ms=8)\n",
" plt.legend(nameord)\n",
" plt.savefig(t + \".png\")\n",
" #plt.show()\n",
" plt.close()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"![](file_create_test.png)\n",
"![](file_open_test.png)\n",
"![](file_overwrite_test.png)\n",
"![](file_attr_test.png)\n",
"![](file_list_test.png)\n",
"![](file_list_single_test.png)\n",
"![](file_list_none_test.png)\n",
"![](file_delete_test.png)\n",
"![](file_mkdir_test.png)\n",
"![](file_rmdir_test.png)\n",
"\n",
"![](iter.file_open_test.png)\n",
"![](iter.file_attr_test.png)\n",
"![](iter.file_list_single_test.png)\n",
"![](iter.file_list_none_test.png)\n",
"\n",
"![](rdwr_cc_read_large_test.png)\n",
"![](rdwr_cc_read_page_test.png)\n",
"![](rdwr_cc_write_large_test.png)\n",
"![](rdwr_cc_write_page_test.png)\n",
"![](rdwr_nc_read_large_test.png)\n",
"![](rdwr_nc_read_page_test.png)\n",
"![](rdwr_nc_write_large_test.png)\n",
"![](rdwr_nc_write_page_test.png)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### File tests\n",
"\n",
"File tests are tests that are performed against the hierarchical path namespace of a file system. Such tests include `file_create_test`, `file_open_test`, etc. Measured times for these tests are normalized against the `ntfs` time (so that the `ntfs` time value becomes 1) and a single aggregate plot is produced.\n",
"\n",
"This allows for easy comparison between file systems across all file tests."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"fileord = [\"create\", \"open\", \"iter.open\", \"overwrite\", \"list\", \"list_single\", \"delete\"]\n",
"fdf = pd.concat([df[df.iter == 5000], df[df.iter == 50]])\n",
"fdf.test = fdf.test.map(lambda x: x.replace(\"file_\", \"\").replace(\"_test\", \"\"))\n",
"fdf = fdf.set_index(\"test\").loc[fileord]\n",
"fdf.memfs /= fdf.ntfs; fdf.ntptfs /= fdf.ntfs; fdf.ntfs = 1\n",
"plt.figure(figsize=(10,8), dpi=100, facecolor=\"white\")\n",
"plt.suptitle(\"File Tests\", fontweight=\"light\", fontsize=20, y=0.95)\n",
"plt.title(\"(Shorter bars are better)\")\n",
"fdf.plot.barh(ax=plt.gca(), y=nameord).invert_yaxis()\n",
"plt.gca().set(ylabel=None)\n",
"for container in plt.gca().containers:\n",
" plt.gca().bar_label(container, fmt=\"%0.2f\", padding=4.0, fontsize=\"xx-small\")\n",
"plt.savefig(\"file_tests.png\")\n",
"#plt.show()\n",
"plt.close()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"![](file_tests.png)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Read/write tests\n",
"\n",
"Read/write tests are file I/O tests. Such tests include `rdwr_cc_write_page_test`, `rdwr_cc_read_page_test`, etc. As before measured times for these tests are normalized against the `ntfs` time (so that the `ntfs` time value becomes 1) and a single aggregate plot is produced.\n",
"\n",
"This allows for easy comparison between file systems across all read/write tests."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"rdwrord = [\"cc_read_page\", \"cc_write_page\", \"nc_read_page\", \"nc_write_page\", \"mmap_read\", \"mmap_write\"]\n",
"sdf = df[df.iter == 500].copy()\n",
"sdf.test = sdf.test.map(lambda x: x.replace(\"rdwr_\", \"\").replace(\"_test\", \"\"))\n",
"sdf = sdf.set_index(\"test\").loc[rdwrord]\n",
"sdf.memfs /= sdf.ntfs; sdf.ntptfs /= sdf.ntfs; sdf.ntfs = 1\n",
"plt.figure(figsize=(10,8), dpi=100, facecolor=\"white\")\n",
"plt.suptitle(\"Read/Write Tests\", fontweight=\"light\", fontsize=20, y=0.95)\n",
"plt.title(\"(Shorter bars are better)\")\n",
"sdf.plot.barh(ax=plt.gca(), y=nameord).invert_yaxis()\n",
"plt.gca().set(ylabel=None)\n",
"for container in plt.gca().containers:\n",
" plt.gca().bar_label(container, fmt=\"%0.2f\", padding=4.0, fontsize=\"xx-small\")\n",
"plt.savefig(\"rdwr_tests.png\")\n",
"#plt.show()\n",
"plt.close()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"![](rdwr_tests.png)"
]
}
],
"metadata": {
"interpreter": {
"hash": "78f203ba605732dcd419e55e4a2fc56c1449fc8b262db510a48272adb5557637"
},
"kernelspec": {
"display_name": "Python 3.9.7 64-bit ('base': conda)",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.8.12"
},
"orig_nbformat": 4
},
"nbformat": 4,
"nbformat_minor": 2
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 60 KiB

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 59 KiB

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 49 KiB

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 55 KiB

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 50 KiB

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 55 KiB

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

View File

@ -0,0 +1,120 @@
file_create_test,1000,0.06
file_open_test,1000,0.06
file_overwrite_test,1000,0.06
file_attr_test,1000,0.03
file_list_test,1000,0.06
file_list_single_test,1000,0.12
file_list_none_test,1000,0.12
file_delete_test,1000,0.09
file_mkdir_test,1000,0.06
file_rmdir_test,1000,0.08
file_create_test,2000,0.14
file_open_test,2000,0.11
file_overwrite_test,2000,0.14
file_attr_test,2000,0.08
file_list_test,2000,0.16
file_list_single_test,2000,0.30
file_list_none_test,2000,0.25
file_delete_test,2000,0.17
file_mkdir_test,2000,0.14
file_rmdir_test,2000,0.17
file_create_test,3000,0.20
file_open_test,3000,0.16
file_overwrite_test,3000,0.20
file_attr_test,3000,0.12
file_list_test,3000,0.23
file_list_single_test,3000,0.44
file_list_none_test,3000,0.36
file_delete_test,3000,0.25
file_mkdir_test,3000,0.19
file_rmdir_test,3000,0.27
file_create_test,4000,0.28
file_open_test,4000,0.22
file_overwrite_test,4000,0.27
file_attr_test,4000,0.16
file_list_test,4000,0.31
file_list_single_test,4000,0.61
file_list_none_test,4000,0.52
file_delete_test,4000,0.34
file_mkdir_test,4000,0.25
file_rmdir_test,4000,0.36
file_create_test,5000,0.34
file_open_test,5000,0.27
file_overwrite_test,5000,0.33
file_attr_test,5000,0.22
file_list_test,5000,0.42
file_list_single_test,5000,0.80
file_list_none_test,5000,0.66
file_delete_test,5000,0.42
file_mkdir_test,5000,0.31
file_rmdir_test,5000,0.44
iter.file_open_test,10,0.55
iter.file_attr_test,10,0.41
iter.file_list_single_test,10,0.61
iter.file_list_none_test,10,0.61
iter.file_open_test,20,1.08
iter.file_attr_test,20,0.84
iter.file_list_single_test,20,1.25
iter.file_list_none_test,20,1.20
iter.file_open_test,30,1.62
iter.file_attr_test,30,1.30
iter.file_list_single_test,30,1.92
iter.file_list_none_test,30,1.83
iter.file_open_test,40,2.17
iter.file_attr_test,40,1.72
iter.file_list_single_test,40,2.52
iter.file_list_none_test,40,2.42
iter.file_open_test,50,2.77
iter.file_attr_test,50,2.14
iter.file_list_single_test,50,3.12
iter.file_list_none_test,50,2.98
rdwr_cc_write_page_test,100,0.23
rdwr_cc_read_page_test,100,0.23
rdwr_cc_write_large_test,100,0.06
rdwr_cc_read_large_test,100,0.06
rdwr_cc_write_page_test,200,0.45
rdwr_cc_read_page_test,200,0.45
rdwr_cc_write_large_test,200,0.12
rdwr_cc_read_large_test,200,0.11
rdwr_cc_write_page_test,300,0.66
rdwr_cc_read_page_test,300,0.59
rdwr_cc_write_large_test,300,0.19
rdwr_cc_read_large_test,300,0.19
rdwr_cc_write_page_test,400,0.89
rdwr_cc_read_page_test,400,0.86
rdwr_cc_write_large_test,400,0.25
rdwr_cc_read_large_test,400,0.25
rdwr_cc_write_page_test,500,1.11
rdwr_cc_read_page_test,500,0.91
rdwr_cc_write_large_test,500,0.31
rdwr_cc_read_large_test,500,0.25
rdwr_nc_write_page_test,100,1.81
rdwr_nc_read_page_test,100,1.88
rdwr_nc_write_large_test,100,0.14
rdwr_nc_read_large_test,100,0.16
rdwr_nc_write_page_test,200,3.66
rdwr_nc_read_page_test,200,3.77
rdwr_nc_write_large_test,200,0.30
rdwr_nc_read_large_test,200,0.30
rdwr_nc_write_page_test,300,5.42
rdwr_nc_read_page_test,300,5.66
rdwr_nc_write_large_test,300,0.44
rdwr_nc_read_large_test,300,0.47
rdwr_nc_write_page_test,400,7.28
rdwr_nc_read_page_test,400,7.58
rdwr_nc_write_large_test,400,0.58
rdwr_nc_read_large_test,400,0.61
rdwr_nc_write_page_test,500,9.08
rdwr_nc_read_page_test,500,9.56
rdwr_nc_write_large_test,500,0.81
rdwr_nc_read_large_test,500,0.78
mmap_write_test,100,0.01
mmap_read_test,100,0.06
mmap_write_test,200,0.03
mmap_read_test,200,0.11
mmap_write_test,300,0.05
mmap_read_test,300,0.17
mmap_write_test,400,0.05
mmap_read_test,400,0.22
mmap_write_test,500,0.06
mmap_read_test,500,0.27
1 file_create_test 1000 0.06
2 file_open_test 1000 0.06
3 file_overwrite_test 1000 0.06
4 file_attr_test 1000 0.03
5 file_list_test 1000 0.06
6 file_list_single_test 1000 0.12
7 file_list_none_test 1000 0.12
8 file_delete_test 1000 0.09
9 file_mkdir_test 1000 0.06
10 file_rmdir_test 1000 0.08
11 file_create_test 2000 0.14
12 file_open_test 2000 0.11
13 file_overwrite_test 2000 0.14
14 file_attr_test 2000 0.08
15 file_list_test 2000 0.16
16 file_list_single_test 2000 0.30
17 file_list_none_test 2000 0.25
18 file_delete_test 2000 0.17
19 file_mkdir_test 2000 0.14
20 file_rmdir_test 2000 0.17
21 file_create_test 3000 0.20
22 file_open_test 3000 0.16
23 file_overwrite_test 3000 0.20
24 file_attr_test 3000 0.12
25 file_list_test 3000 0.23
26 file_list_single_test 3000 0.44
27 file_list_none_test 3000 0.36
28 file_delete_test 3000 0.25
29 file_mkdir_test 3000 0.19
30 file_rmdir_test 3000 0.27
31 file_create_test 4000 0.28
32 file_open_test 4000 0.22
33 file_overwrite_test 4000 0.27
34 file_attr_test 4000 0.16
35 file_list_test 4000 0.31
36 file_list_single_test 4000 0.61
37 file_list_none_test 4000 0.52
38 file_delete_test 4000 0.34
39 file_mkdir_test 4000 0.25
40 file_rmdir_test 4000 0.36
41 file_create_test 5000 0.34
42 file_open_test 5000 0.27
43 file_overwrite_test 5000 0.33
44 file_attr_test 5000 0.22
45 file_list_test 5000 0.42
46 file_list_single_test 5000 0.80
47 file_list_none_test 5000 0.66
48 file_delete_test 5000 0.42
49 file_mkdir_test 5000 0.31
50 file_rmdir_test 5000 0.44
51 iter.file_open_test 10 0.55
52 iter.file_attr_test 10 0.41
53 iter.file_list_single_test 10 0.61
54 iter.file_list_none_test 10 0.61
55 iter.file_open_test 20 1.08
56 iter.file_attr_test 20 0.84
57 iter.file_list_single_test 20 1.25
58 iter.file_list_none_test 20 1.20
59 iter.file_open_test 30 1.62
60 iter.file_attr_test 30 1.30
61 iter.file_list_single_test 30 1.92
62 iter.file_list_none_test 30 1.83
63 iter.file_open_test 40 2.17
64 iter.file_attr_test 40 1.72
65 iter.file_list_single_test 40 2.52
66 iter.file_list_none_test 40 2.42
67 iter.file_open_test 50 2.77
68 iter.file_attr_test 50 2.14
69 iter.file_list_single_test 50 3.12
70 iter.file_list_none_test 50 2.98
71 rdwr_cc_write_page_test 100 0.23
72 rdwr_cc_read_page_test 100 0.23
73 rdwr_cc_write_large_test 100 0.06
74 rdwr_cc_read_large_test 100 0.06
75 rdwr_cc_write_page_test 200 0.45
76 rdwr_cc_read_page_test 200 0.45
77 rdwr_cc_write_large_test 200 0.12
78 rdwr_cc_read_large_test 200 0.11
79 rdwr_cc_write_page_test 300 0.66
80 rdwr_cc_read_page_test 300 0.59
81 rdwr_cc_write_large_test 300 0.19
82 rdwr_cc_read_large_test 300 0.19
83 rdwr_cc_write_page_test 400 0.89
84 rdwr_cc_read_page_test 400 0.86
85 rdwr_cc_write_large_test 400 0.25
86 rdwr_cc_read_large_test 400 0.25
87 rdwr_cc_write_page_test 500 1.11
88 rdwr_cc_read_page_test 500 0.91
89 rdwr_cc_write_large_test 500 0.31
90 rdwr_cc_read_large_test 500 0.25
91 rdwr_nc_write_page_test 100 1.81
92 rdwr_nc_read_page_test 100 1.88
93 rdwr_nc_write_large_test 100 0.14
94 rdwr_nc_read_large_test 100 0.16
95 rdwr_nc_write_page_test 200 3.66
96 rdwr_nc_read_page_test 200 3.77
97 rdwr_nc_write_large_test 200 0.30
98 rdwr_nc_read_large_test 200 0.30
99 rdwr_nc_write_page_test 300 5.42
100 rdwr_nc_read_page_test 300 5.66
101 rdwr_nc_write_large_test 300 0.44
102 rdwr_nc_read_large_test 300 0.47
103 rdwr_nc_write_page_test 400 7.28
104 rdwr_nc_read_page_test 400 7.58
105 rdwr_nc_write_large_test 400 0.58
106 rdwr_nc_read_large_test 400 0.61
107 rdwr_nc_write_page_test 500 9.08
108 rdwr_nc_read_page_test 500 9.56
109 rdwr_nc_write_large_test 500 0.81
110 rdwr_nc_read_large_test 500 0.78
111 mmap_write_test 100 0.01
112 mmap_read_test 100 0.06
113 mmap_write_test 200 0.03
114 mmap_read_test 200 0.11
115 mmap_write_test 300 0.05
116 mmap_read_test 300 0.17
117 mmap_write_test 400 0.05
118 mmap_read_test 400 0.22
119 mmap_write_test 500 0.06
120 mmap_read_test 500 0.27

View File

@ -0,0 +1,120 @@
file_create_test,1000,0.06
file_open_test,1000,0.05
file_overwrite_test,1000,0.06
file_attr_test,1000,0.03
file_list_test,1000,0.06
file_list_single_test,1000,0.12
file_list_none_test,1000,0.12
file_delete_test,1000,0.08
file_mkdir_test,1000,0.06
file_rmdir_test,1000,0.08
file_create_test,2000,0.14
file_open_test,2000,0.11
file_overwrite_test,2000,0.14
file_attr_test,2000,0.08
file_list_test,2000,0.14
file_list_single_test,2000,0.30
file_list_none_test,2000,0.27
file_delete_test,2000,0.17
file_mkdir_test,2000,0.14
file_rmdir_test,2000,0.17
file_create_test,3000,0.22
file_open_test,3000,0.16
file_overwrite_test,3000,0.20
file_attr_test,3000,0.12
file_list_test,3000,0.23
file_list_single_test,3000,0.47
file_list_none_test,3000,0.38
file_delete_test,3000,0.27
file_mkdir_test,3000,0.20
file_rmdir_test,3000,0.28
file_create_test,4000,0.42
file_open_test,4000,0.25
file_overwrite_test,4000,0.27
file_attr_test,4000,0.17
file_list_test,4000,0.34
file_list_single_test,4000,0.61
file_list_none_test,4000,0.52
file_delete_test,4000,0.34
file_mkdir_test,4000,0.25
file_rmdir_test,4000,0.36
file_create_test,5000,0.36
file_open_test,5000,0.28
file_overwrite_test,5000,0.34
file_attr_test,5000,0.22
file_list_test,5000,0.44
file_list_single_test,5000,0.78
file_list_none_test,5000,0.64
file_delete_test,5000,0.44
file_mkdir_test,5000,0.31
file_rmdir_test,5000,0.45
iter.file_open_test,10,0.55
iter.file_attr_test,10,0.42
iter.file_list_single_test,10,0.66
iter.file_list_none_test,10,0.61
iter.file_open_test,20,1.08
iter.file_attr_test,20,0.86
iter.file_list_single_test,20,1.26
iter.file_list_none_test,20,1.17
iter.file_open_test,30,1.61
iter.file_attr_test,30,1.28
iter.file_list_single_test,30,1.91
iter.file_list_none_test,30,1.81
iter.file_open_test,40,2.17
iter.file_attr_test,40,1.70
iter.file_list_single_test,40,2.61
iter.file_list_none_test,40,2.41
iter.file_open_test,50,2.70
iter.file_attr_test,50,2.09
iter.file_list_single_test,50,3.17
iter.file_list_none_test,50,2.94
rdwr_cc_write_page_test,100,0.23
rdwr_cc_read_page_test,100,0.22
rdwr_cc_write_large_test,100,0.06
rdwr_cc_read_large_test,100,0.06
rdwr_cc_write_page_test,200,0.44
rdwr_cc_read_page_test,200,0.45
rdwr_cc_write_large_test,200,0.12
rdwr_cc_read_large_test,200,0.12
rdwr_cc_write_page_test,300,0.66
rdwr_cc_read_page_test,300,0.64
rdwr_cc_write_large_test,300,0.19
rdwr_cc_read_large_test,300,0.17
rdwr_cc_write_page_test,400,0.87
rdwr_cc_read_page_test,400,0.73
rdwr_cc_write_large_test,400,0.25
rdwr_cc_read_large_test,400,0.31
rdwr_cc_write_page_test,500,1.09
rdwr_cc_read_page_test,500,1.02
rdwr_cc_write_large_test,500,0.31
rdwr_cc_read_large_test,500,0.39
rdwr_nc_write_page_test,100,1.83
rdwr_nc_read_page_test,100,1.86
rdwr_nc_write_large_test,100,0.16
rdwr_nc_read_large_test,100,0.16
rdwr_nc_write_page_test,200,3.61
rdwr_nc_read_page_test,200,3.81
rdwr_nc_write_large_test,200,0.30
rdwr_nc_read_large_test,200,0.31
rdwr_nc_write_page_test,300,5.50
rdwr_nc_read_page_test,300,5.72
rdwr_nc_write_large_test,300,0.44
rdwr_nc_read_large_test,300,0.47
rdwr_nc_write_page_test,400,7.31
rdwr_nc_read_page_test,400,7.45
rdwr_nc_write_large_test,400,0.59
rdwr_nc_read_large_test,400,0.61
rdwr_nc_write_page_test,500,9.00
rdwr_nc_read_page_test,500,9.42
rdwr_nc_write_large_test,500,0.73
rdwr_nc_read_large_test,500,0.77
mmap_write_test,100,0.01
mmap_read_test,100,0.06
mmap_write_test,200,0.03
mmap_read_test,200,0.11
mmap_write_test,300,0.03
mmap_read_test,300,0.16
mmap_write_test,400,0.05
mmap_read_test,400,0.22
mmap_write_test,500,0.06
mmap_read_test,500,0.27
1 file_create_test 1000 0.06
2 file_open_test 1000 0.05
3 file_overwrite_test 1000 0.06
4 file_attr_test 1000 0.03
5 file_list_test 1000 0.06
6 file_list_single_test 1000 0.12
7 file_list_none_test 1000 0.12
8 file_delete_test 1000 0.08
9 file_mkdir_test 1000 0.06
10 file_rmdir_test 1000 0.08
11 file_create_test 2000 0.14
12 file_open_test 2000 0.11
13 file_overwrite_test 2000 0.14
14 file_attr_test 2000 0.08
15 file_list_test 2000 0.14
16 file_list_single_test 2000 0.30
17 file_list_none_test 2000 0.27
18 file_delete_test 2000 0.17
19 file_mkdir_test 2000 0.14
20 file_rmdir_test 2000 0.17
21 file_create_test 3000 0.22
22 file_open_test 3000 0.16
23 file_overwrite_test 3000 0.20
24 file_attr_test 3000 0.12
25 file_list_test 3000 0.23
26 file_list_single_test 3000 0.47
27 file_list_none_test 3000 0.38
28 file_delete_test 3000 0.27
29 file_mkdir_test 3000 0.20
30 file_rmdir_test 3000 0.28
31 file_create_test 4000 0.42
32 file_open_test 4000 0.25
33 file_overwrite_test 4000 0.27
34 file_attr_test 4000 0.17
35 file_list_test 4000 0.34
36 file_list_single_test 4000 0.61
37 file_list_none_test 4000 0.52
38 file_delete_test 4000 0.34
39 file_mkdir_test 4000 0.25
40 file_rmdir_test 4000 0.36
41 file_create_test 5000 0.36
42 file_open_test 5000 0.28
43 file_overwrite_test 5000 0.34
44 file_attr_test 5000 0.22
45 file_list_test 5000 0.44
46 file_list_single_test 5000 0.78
47 file_list_none_test 5000 0.64
48 file_delete_test 5000 0.44
49 file_mkdir_test 5000 0.31
50 file_rmdir_test 5000 0.45
51 iter.file_open_test 10 0.55
52 iter.file_attr_test 10 0.42
53 iter.file_list_single_test 10 0.66
54 iter.file_list_none_test 10 0.61
55 iter.file_open_test 20 1.08
56 iter.file_attr_test 20 0.86
57 iter.file_list_single_test 20 1.26
58 iter.file_list_none_test 20 1.17
59 iter.file_open_test 30 1.61
60 iter.file_attr_test 30 1.28
61 iter.file_list_single_test 30 1.91
62 iter.file_list_none_test 30 1.81
63 iter.file_open_test 40 2.17
64 iter.file_attr_test 40 1.70
65 iter.file_list_single_test 40 2.61
66 iter.file_list_none_test 40 2.41
67 iter.file_open_test 50 2.70
68 iter.file_attr_test 50 2.09
69 iter.file_list_single_test 50 3.17
70 iter.file_list_none_test 50 2.94
71 rdwr_cc_write_page_test 100 0.23
72 rdwr_cc_read_page_test 100 0.22
73 rdwr_cc_write_large_test 100 0.06
74 rdwr_cc_read_large_test 100 0.06
75 rdwr_cc_write_page_test 200 0.44
76 rdwr_cc_read_page_test 200 0.45
77 rdwr_cc_write_large_test 200 0.12
78 rdwr_cc_read_large_test 200 0.12
79 rdwr_cc_write_page_test 300 0.66
80 rdwr_cc_read_page_test 300 0.64
81 rdwr_cc_write_large_test 300 0.19
82 rdwr_cc_read_large_test 300 0.17
83 rdwr_cc_write_page_test 400 0.87
84 rdwr_cc_read_page_test 400 0.73
85 rdwr_cc_write_large_test 400 0.25
86 rdwr_cc_read_large_test 400 0.31
87 rdwr_cc_write_page_test 500 1.09
88 rdwr_cc_read_page_test 500 1.02
89 rdwr_cc_write_large_test 500 0.31
90 rdwr_cc_read_large_test 500 0.39
91 rdwr_nc_write_page_test 100 1.83
92 rdwr_nc_read_page_test 100 1.86
93 rdwr_nc_write_large_test 100 0.16
94 rdwr_nc_read_large_test 100 0.16
95 rdwr_nc_write_page_test 200 3.61
96 rdwr_nc_read_page_test 200 3.81
97 rdwr_nc_write_large_test 200 0.30
98 rdwr_nc_read_large_test 200 0.31
99 rdwr_nc_write_page_test 300 5.50
100 rdwr_nc_read_page_test 300 5.72
101 rdwr_nc_write_large_test 300 0.44
102 rdwr_nc_read_large_test 300 0.47
103 rdwr_nc_write_page_test 400 7.31
104 rdwr_nc_read_page_test 400 7.45
105 rdwr_nc_write_large_test 400 0.59
106 rdwr_nc_read_large_test 400 0.61
107 rdwr_nc_write_page_test 500 9.00
108 rdwr_nc_read_page_test 500 9.42
109 rdwr_nc_write_large_test 500 0.73
110 rdwr_nc_read_large_test 500 0.77
111 mmap_write_test 100 0.01
112 mmap_read_test 100 0.06
113 mmap_write_test 200 0.03
114 mmap_read_test 200 0.11
115 mmap_write_test 300 0.03
116 mmap_read_test 300 0.16
117 mmap_write_test 400 0.05
118 mmap_read_test 400 0.22
119 mmap_write_test 500 0.06
120 mmap_read_test 500 0.27

View File

@ -0,0 +1,120 @@
file_create_test,1000,0.06
file_open_test,1000,0.05
file_overwrite_test,1000,0.06
file_attr_test,1000,0.03
file_list_test,1000,0.05
file_list_single_test,1000,0.14
file_list_none_test,1000,0.12
file_delete_test,1000,0.08
file_mkdir_test,1000,0.06
file_rmdir_test,1000,0.08
file_create_test,2000,0.14
file_open_test,2000,0.11
file_overwrite_test,2000,0.14
file_attr_test,2000,0.09
file_list_test,2000,0.14
file_list_single_test,2000,0.28
file_list_none_test,2000,0.25
file_delete_test,2000,0.17
file_mkdir_test,2000,0.12
file_rmdir_test,2000,0.17
file_create_test,3000,0.20
file_open_test,3000,0.17
file_overwrite_test,3000,0.20
file_attr_test,3000,0.14
file_list_test,3000,0.25
file_list_single_test,3000,0.44
file_list_none_test,3000,0.36
file_delete_test,3000,0.27
file_mkdir_test,3000,0.19
file_rmdir_test,3000,0.27
file_create_test,4000,0.28
file_open_test,4000,0.22
file_overwrite_test,4000,0.28
file_attr_test,4000,0.17
file_list_test,4000,0.33
file_list_single_test,4000,0.59
file_list_none_test,4000,0.50
file_delete_test,4000,0.34
file_mkdir_test,4000,0.27
file_rmdir_test,4000,0.36
file_create_test,5000,0.37
file_open_test,5000,0.27
file_overwrite_test,5000,0.36
file_attr_test,5000,0.22
file_list_test,5000,0.42
file_list_single_test,5000,0.75
file_list_none_test,5000,0.62
file_delete_test,5000,0.48
file_mkdir_test,5000,0.34
file_rmdir_test,5000,0.45
iter.file_open_test,10,0.53
iter.file_attr_test,10,0.42
iter.file_list_single_test,10,0.61
iter.file_list_none_test,10,0.61
iter.file_open_test,20,1.08
iter.file_attr_test,20,0.81
iter.file_list_single_test,20,1.20
iter.file_list_none_test,20,1.16
iter.file_open_test,30,1.61
iter.file_attr_test,30,1.25
iter.file_list_single_test,30,1.88
iter.file_list_none_test,30,1.81
iter.file_open_test,40,2.14
iter.file_attr_test,40,1.91
iter.file_list_single_test,40,2.66
iter.file_list_none_test,40,2.48
iter.file_open_test,50,2.73
iter.file_attr_test,50,2.14
iter.file_list_single_test,50,3.16
iter.file_list_none_test,50,3.08
rdwr_cc_write_page_test,100,0.23
rdwr_cc_read_page_test,100,0.22
rdwr_cc_write_large_test,100,0.06
rdwr_cc_read_large_test,100,0.06
rdwr_cc_write_page_test,200,0.45
rdwr_cc_read_page_test,200,0.41
rdwr_cc_write_large_test,200,0.12
rdwr_cc_read_large_test,200,0.11
rdwr_cc_write_page_test,300,0.67
rdwr_cc_read_page_test,300,0.62
rdwr_cc_write_large_test,300,0.19
rdwr_cc_read_large_test,300,0.23
rdwr_cc_write_page_test,400,0.87
rdwr_cc_read_page_test,400,0.94
rdwr_cc_write_large_test,400,0.25
rdwr_cc_read_large_test,400,0.33
rdwr_cc_write_page_test,500,1.09
rdwr_cc_read_page_test,500,1.12
rdwr_cc_write_large_test,500,0.31
rdwr_cc_read_large_test,500,0.44
rdwr_nc_write_page_test,100,1.86
rdwr_nc_read_page_test,100,1.94
rdwr_nc_write_large_test,100,0.16
rdwr_nc_read_large_test,100,0.16
rdwr_nc_write_page_test,200,3.66
rdwr_nc_read_page_test,200,3.83
rdwr_nc_write_large_test,200,0.28
rdwr_nc_read_large_test,200,0.30
rdwr_nc_write_page_test,300,5.42
rdwr_nc_read_page_test,300,5.86
rdwr_nc_write_large_test,300,0.45
rdwr_nc_read_large_test,300,0.45
rdwr_nc_write_page_test,400,7.36
rdwr_nc_read_page_test,400,7.56
rdwr_nc_write_large_test,400,0.58
rdwr_nc_read_large_test,400,0.61
rdwr_nc_write_page_test,500,9.09
rdwr_nc_read_page_test,500,9.45
rdwr_nc_write_large_test,500,0.73
rdwr_nc_read_large_test,500,0.75
mmap_write_test,100,0.01
mmap_read_test,100,0.06
mmap_write_test,200,0.03
mmap_read_test,200,0.11
mmap_write_test,300,0.05
mmap_read_test,300,0.16
mmap_write_test,400,0.05
mmap_read_test,400,0.22
mmap_write_test,500,0.06
mmap_read_test,500,0.27
1 file_create_test 1000 0.06
2 file_open_test 1000 0.05
3 file_overwrite_test 1000 0.06
4 file_attr_test 1000 0.03
5 file_list_test 1000 0.05
6 file_list_single_test 1000 0.14
7 file_list_none_test 1000 0.12
8 file_delete_test 1000 0.08
9 file_mkdir_test 1000 0.06
10 file_rmdir_test 1000 0.08
11 file_create_test 2000 0.14
12 file_open_test 2000 0.11
13 file_overwrite_test 2000 0.14
14 file_attr_test 2000 0.09
15 file_list_test 2000 0.14
16 file_list_single_test 2000 0.28
17 file_list_none_test 2000 0.25
18 file_delete_test 2000 0.17
19 file_mkdir_test 2000 0.12
20 file_rmdir_test 2000 0.17
21 file_create_test 3000 0.20
22 file_open_test 3000 0.17
23 file_overwrite_test 3000 0.20
24 file_attr_test 3000 0.14
25 file_list_test 3000 0.25
26 file_list_single_test 3000 0.44
27 file_list_none_test 3000 0.36
28 file_delete_test 3000 0.27
29 file_mkdir_test 3000 0.19
30 file_rmdir_test 3000 0.27
31 file_create_test 4000 0.28
32 file_open_test 4000 0.22
33 file_overwrite_test 4000 0.28
34 file_attr_test 4000 0.17
35 file_list_test 4000 0.33
36 file_list_single_test 4000 0.59
37 file_list_none_test 4000 0.50
38 file_delete_test 4000 0.34
39 file_mkdir_test 4000 0.27
40 file_rmdir_test 4000 0.36
41 file_create_test 5000 0.37
42 file_open_test 5000 0.27
43 file_overwrite_test 5000 0.36
44 file_attr_test 5000 0.22
45 file_list_test 5000 0.42
46 file_list_single_test 5000 0.75
47 file_list_none_test 5000 0.62
48 file_delete_test 5000 0.48
49 file_mkdir_test 5000 0.34
50 file_rmdir_test 5000 0.45
51 iter.file_open_test 10 0.53
52 iter.file_attr_test 10 0.42
53 iter.file_list_single_test 10 0.61
54 iter.file_list_none_test 10 0.61
55 iter.file_open_test 20 1.08
56 iter.file_attr_test 20 0.81
57 iter.file_list_single_test 20 1.20
58 iter.file_list_none_test 20 1.16
59 iter.file_open_test 30 1.61
60 iter.file_attr_test 30 1.25
61 iter.file_list_single_test 30 1.88
62 iter.file_list_none_test 30 1.81
63 iter.file_open_test 40 2.14
64 iter.file_attr_test 40 1.91
65 iter.file_list_single_test 40 2.66
66 iter.file_list_none_test 40 2.48
67 iter.file_open_test 50 2.73
68 iter.file_attr_test 50 2.14
69 iter.file_list_single_test 50 3.16
70 iter.file_list_none_test 50 3.08
71 rdwr_cc_write_page_test 100 0.23
72 rdwr_cc_read_page_test 100 0.22
73 rdwr_cc_write_large_test 100 0.06
74 rdwr_cc_read_large_test 100 0.06
75 rdwr_cc_write_page_test 200 0.45
76 rdwr_cc_read_page_test 200 0.41
77 rdwr_cc_write_large_test 200 0.12
78 rdwr_cc_read_large_test 200 0.11
79 rdwr_cc_write_page_test 300 0.67
80 rdwr_cc_read_page_test 300 0.62
81 rdwr_cc_write_large_test 300 0.19
82 rdwr_cc_read_large_test 300 0.23
83 rdwr_cc_write_page_test 400 0.87
84 rdwr_cc_read_page_test 400 0.94
85 rdwr_cc_write_large_test 400 0.25
86 rdwr_cc_read_large_test 400 0.33
87 rdwr_cc_write_page_test 500 1.09
88 rdwr_cc_read_page_test 500 1.12
89 rdwr_cc_write_large_test 500 0.31
90 rdwr_cc_read_large_test 500 0.44
91 rdwr_nc_write_page_test 100 1.86
92 rdwr_nc_read_page_test 100 1.94
93 rdwr_nc_write_large_test 100 0.16
94 rdwr_nc_read_large_test 100 0.16
95 rdwr_nc_write_page_test 200 3.66
96 rdwr_nc_read_page_test 200 3.83
97 rdwr_nc_write_large_test 200 0.28
98 rdwr_nc_read_large_test 200 0.30
99 rdwr_nc_write_page_test 300 5.42
100 rdwr_nc_read_page_test 300 5.86
101 rdwr_nc_write_large_test 300 0.45
102 rdwr_nc_read_large_test 300 0.45
103 rdwr_nc_write_page_test 400 7.36
104 rdwr_nc_read_page_test 400 7.56
105 rdwr_nc_write_large_test 400 0.58
106 rdwr_nc_read_large_test 400 0.61
107 rdwr_nc_write_page_test 500 9.09
108 rdwr_nc_read_page_test 500 9.45
109 rdwr_nc_write_large_test 500 0.73
110 rdwr_nc_read_large_test 500 0.75
111 mmap_write_test 100 0.01
112 mmap_read_test 100 0.06
113 mmap_write_test 200 0.03
114 mmap_read_test 200 0.11
115 mmap_write_test 300 0.05
116 mmap_read_test 300 0.16
117 mmap_write_test 400 0.05
118 mmap_read_test 400 0.22
119 mmap_write_test 500 0.06
120 mmap_read_test 500 0.27

Binary file not shown.

Before

Width:  |  Height:  |  Size: 44 KiB

After

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 39 KiB

After

Width:  |  Height:  |  Size: 40 KiB

View File

@ -0,0 +1,120 @@
file_create_test,1000,0.20
file_open_test,1000,0.09
file_overwrite_test,1000,0.16
file_attr_test,1000,0.08
file_list_test,1000,0.11
file_list_single_test,1000,0.08
file_list_none_test,1000,0.03
file_delete_test,1000,0.14
file_mkdir_test,1000,0.14
file_rmdir_test,1000,0.12
file_create_test,2000,0.45
file_open_test,2000,0.19
file_overwrite_test,2000,0.38
file_attr_test,2000,0.17
file_list_test,2000,0.22
file_list_single_test,2000,0.16
file_list_none_test,2000,0.06
file_delete_test,2000,0.31
file_mkdir_test,2000,0.30
file_rmdir_test,2000,0.28
file_create_test,3000,0.64
file_open_test,3000,0.28
file_overwrite_test,3000,0.55
file_attr_test,3000,0.25
file_list_test,3000,0.36
file_list_single_test,3000,0.25
file_list_none_test,3000,0.08
file_delete_test,3000,0.50
file_mkdir_test,3000,0.47
file_rmdir_test,3000,0.42
file_create_test,4000,0.83
file_open_test,4000,0.36
file_overwrite_test,4000,0.73
file_attr_test,4000,0.33
file_list_test,4000,0.45
file_list_single_test,4000,0.33
file_list_none_test,4000,0.11
file_delete_test,4000,0.64
file_mkdir_test,4000,0.64
file_rmdir_test,4000,0.53
file_create_test,5000,1.03
file_open_test,5000,0.44
file_overwrite_test,5000,0.92
file_attr_test,5000,0.38
file_list_test,5000,0.56
file_list_single_test,5000,0.39
file_list_none_test,5000,0.14
file_delete_test,5000,0.80
file_mkdir_test,5000,0.73
file_rmdir_test,5000,0.64
iter.file_open_test,10,0.25
iter.file_attr_test,10,0.19
iter.file_list_single_test,10,0.34
iter.file_list_none_test,10,0.27
iter.file_open_test,20,0.42
iter.file_attr_test,20,0.33
iter.file_list_single_test,20,0.59
iter.file_list_none_test,20,0.53
iter.file_open_test,30,0.64
iter.file_attr_test,30,0.50
iter.file_list_single_test,30,0.95
iter.file_list_none_test,30,0.77
iter.file_open_test,40,0.78
iter.file_attr_test,40,0.61
iter.file_list_single_test,40,1.19
iter.file_list_none_test,40,1.03
iter.file_open_test,50,0.98
iter.file_attr_test,50,0.73
iter.file_list_single_test,50,1.47
iter.file_list_none_test,50,1.27
rdwr_cc_write_page_test,100,0.28
rdwr_cc_read_page_test,100,0.27
rdwr_cc_write_large_test,100,0.08
rdwr_cc_read_large_test,100,0.09
rdwr_cc_write_page_test,200,0.56
rdwr_cc_read_page_test,200,0.47
rdwr_cc_write_large_test,200,0.16
rdwr_cc_read_large_test,200,0.20
rdwr_cc_write_page_test,300,0.86
rdwr_cc_read_page_test,300,0.73
rdwr_cc_write_large_test,300,0.23
rdwr_cc_read_large_test,300,0.25
rdwr_cc_write_page_test,400,1.11
rdwr_cc_read_page_test,400,0.95
rdwr_cc_write_large_test,400,0.30
rdwr_cc_read_large_test,400,0.30
rdwr_cc_write_page_test,500,1.39
rdwr_cc_read_page_test,500,1.16
rdwr_cc_write_large_test,500,0.39
rdwr_cc_read_large_test,500,0.33
rdwr_nc_write_page_test,100,4.94
rdwr_nc_read_page_test,100,4.55
rdwr_nc_write_large_test,100,0.48
rdwr_nc_read_large_test,100,0.58
rdwr_nc_write_page_test,200,9.84
rdwr_nc_read_page_test,200,9.17
rdwr_nc_write_large_test,200,0.98
rdwr_nc_read_large_test,200,1.14
rdwr_nc_write_page_test,300,14.62
rdwr_nc_read_page_test,300,13.78
rdwr_nc_write_large_test,300,1.42
rdwr_nc_read_large_test,300,1.74
rdwr_nc_write_page_test,400,19.27
rdwr_nc_read_page_test,400,17.14
rdwr_nc_write_large_test,400,1.89
rdwr_nc_read_large_test,400,2.78
rdwr_nc_write_page_test,500,23.80
rdwr_nc_read_page_test,500,21.61
rdwr_nc_write_large_test,500,2.28
rdwr_nc_read_large_test,500,3.98
mmap_write_test,100,0.01
mmap_read_test,100,0.08
mmap_write_test,200,0.03
mmap_read_test,200,0.12
mmap_write_test,300,0.05
mmap_read_test,300,0.17
mmap_write_test,400,0.05
mmap_read_test,400,0.22
mmap_write_test,500,0.06
mmap_read_test,500,0.27
1 file_create_test 1000 0.20
2 file_open_test 1000 0.09
3 file_overwrite_test 1000 0.16
4 file_attr_test 1000 0.08
5 file_list_test 1000 0.11
6 file_list_single_test 1000 0.08
7 file_list_none_test 1000 0.03
8 file_delete_test 1000 0.14
9 file_mkdir_test 1000 0.14
10 file_rmdir_test 1000 0.12
11 file_create_test 2000 0.45
12 file_open_test 2000 0.19
13 file_overwrite_test 2000 0.38
14 file_attr_test 2000 0.17
15 file_list_test 2000 0.22
16 file_list_single_test 2000 0.16
17 file_list_none_test 2000 0.06
18 file_delete_test 2000 0.31
19 file_mkdir_test 2000 0.30
20 file_rmdir_test 2000 0.28
21 file_create_test 3000 0.64
22 file_open_test 3000 0.28
23 file_overwrite_test 3000 0.55
24 file_attr_test 3000 0.25
25 file_list_test 3000 0.36
26 file_list_single_test 3000 0.25
27 file_list_none_test 3000 0.08
28 file_delete_test 3000 0.50
29 file_mkdir_test 3000 0.47
30 file_rmdir_test 3000 0.42
31 file_create_test 4000 0.83
32 file_open_test 4000 0.36
33 file_overwrite_test 4000 0.73
34 file_attr_test 4000 0.33
35 file_list_test 4000 0.45
36 file_list_single_test 4000 0.33
37 file_list_none_test 4000 0.11
38 file_delete_test 4000 0.64
39 file_mkdir_test 4000 0.64
40 file_rmdir_test 4000 0.53
41 file_create_test 5000 1.03
42 file_open_test 5000 0.44
43 file_overwrite_test 5000 0.92
44 file_attr_test 5000 0.38
45 file_list_test 5000 0.56
46 file_list_single_test 5000 0.39
47 file_list_none_test 5000 0.14
48 file_delete_test 5000 0.80
49 file_mkdir_test 5000 0.73
50 file_rmdir_test 5000 0.64
51 iter.file_open_test 10 0.25
52 iter.file_attr_test 10 0.19
53 iter.file_list_single_test 10 0.34
54 iter.file_list_none_test 10 0.27
55 iter.file_open_test 20 0.42
56 iter.file_attr_test 20 0.33
57 iter.file_list_single_test 20 0.59
58 iter.file_list_none_test 20 0.53
59 iter.file_open_test 30 0.64
60 iter.file_attr_test 30 0.50
61 iter.file_list_single_test 30 0.95
62 iter.file_list_none_test 30 0.77
63 iter.file_open_test 40 0.78
64 iter.file_attr_test 40 0.61
65 iter.file_list_single_test 40 1.19
66 iter.file_list_none_test 40 1.03
67 iter.file_open_test 50 0.98
68 iter.file_attr_test 50 0.73
69 iter.file_list_single_test 50 1.47
70 iter.file_list_none_test 50 1.27
71 rdwr_cc_write_page_test 100 0.28
72 rdwr_cc_read_page_test 100 0.27
73 rdwr_cc_write_large_test 100 0.08
74 rdwr_cc_read_large_test 100 0.09
75 rdwr_cc_write_page_test 200 0.56
76 rdwr_cc_read_page_test 200 0.47
77 rdwr_cc_write_large_test 200 0.16
78 rdwr_cc_read_large_test 200 0.20
79 rdwr_cc_write_page_test 300 0.86
80 rdwr_cc_read_page_test 300 0.73
81 rdwr_cc_write_large_test 300 0.23
82 rdwr_cc_read_large_test 300 0.25
83 rdwr_cc_write_page_test 400 1.11
84 rdwr_cc_read_page_test 400 0.95
85 rdwr_cc_write_large_test 400 0.30
86 rdwr_cc_read_large_test 400 0.30
87 rdwr_cc_write_page_test 500 1.39
88 rdwr_cc_read_page_test 500 1.16
89 rdwr_cc_write_large_test 500 0.39
90 rdwr_cc_read_large_test 500 0.33
91 rdwr_nc_write_page_test 100 4.94
92 rdwr_nc_read_page_test 100 4.55
93 rdwr_nc_write_large_test 100 0.48
94 rdwr_nc_read_large_test 100 0.58
95 rdwr_nc_write_page_test 200 9.84
96 rdwr_nc_read_page_test 200 9.17
97 rdwr_nc_write_large_test 200 0.98
98 rdwr_nc_read_large_test 200 1.14
99 rdwr_nc_write_page_test 300 14.62
100 rdwr_nc_read_page_test 300 13.78
101 rdwr_nc_write_large_test 300 1.42
102 rdwr_nc_read_large_test 300 1.74
103 rdwr_nc_write_page_test 400 19.27
104 rdwr_nc_read_page_test 400 17.14
105 rdwr_nc_write_large_test 400 1.89
106 rdwr_nc_read_large_test 400 2.78
107 rdwr_nc_write_page_test 500 23.80
108 rdwr_nc_read_page_test 500 21.61
109 rdwr_nc_write_large_test 500 2.28
110 rdwr_nc_read_large_test 500 3.98
111 mmap_write_test 100 0.01
112 mmap_read_test 100 0.08
113 mmap_write_test 200 0.03
114 mmap_read_test 200 0.12
115 mmap_write_test 300 0.05
116 mmap_read_test 300 0.17
117 mmap_write_test 400 0.05
118 mmap_read_test 400 0.22
119 mmap_write_test 500 0.06
120 mmap_read_test 500 0.27

View File

@ -0,0 +1,120 @@
file_create_test,1000,0.20
file_open_test,1000,0.09
file_overwrite_test,1000,0.17
file_attr_test,1000,0.08
file_list_test,1000,0.11
file_list_single_test,1000,0.08
file_list_none_test,1000,0.03
file_delete_test,1000,0.16
file_mkdir_test,1000,0.14
file_rmdir_test,1000,0.12
file_create_test,2000,0.42
file_open_test,2000,0.19
file_overwrite_test,2000,0.41
file_attr_test,2000,0.17
file_list_test,2000,0.22
file_list_single_test,2000,0.17
file_list_none_test,2000,0.06
file_delete_test,2000,0.34
file_mkdir_test,2000,0.33
file_rmdir_test,2000,0.28
file_create_test,3000,0.66
file_open_test,3000,0.30
file_overwrite_test,3000,0.59
file_attr_test,3000,0.27
file_list_test,3000,0.36
file_list_single_test,3000,0.28
file_list_none_test,3000,0.09
file_delete_test,3000,0.52
file_mkdir_test,3000,0.48
file_rmdir_test,3000,0.41
file_create_test,4000,0.89
file_open_test,4000,0.36
file_overwrite_test,4000,0.72
file_attr_test,4000,0.34
file_list_test,4000,0.47
file_list_single_test,4000,0.33
file_list_none_test,4000,0.11
file_delete_test,4000,0.66
file_mkdir_test,4000,0.61
file_rmdir_test,4000,0.56
file_create_test,5000,1.01
file_open_test,5000,0.44
file_overwrite_test,5000,0.89
file_attr_test,5000,0.39
file_list_test,5000,0.56
file_list_single_test,5000,0.39
file_list_none_test,5000,0.14
file_delete_test,5000,0.78
file_mkdir_test,5000,0.73
file_rmdir_test,5000,0.64
iter.file_open_test,10,0.25
iter.file_attr_test,10,0.19
iter.file_list_single_test,10,0.33
iter.file_list_none_test,10,0.25
iter.file_open_test,20,0.44
iter.file_attr_test,20,0.33
iter.file_list_single_test,20,0.61
iter.file_list_none_test,20,0.52
iter.file_open_test,30,0.59
iter.file_attr_test,30,0.47
iter.file_list_single_test,30,0.89
iter.file_list_none_test,30,0.81
iter.file_open_test,40,0.84
iter.file_attr_test,40,0.67
iter.file_list_single_test,40,1.17
iter.file_list_none_test,40,1.00
iter.file_open_test,50,0.97
iter.file_attr_test,50,0.73
iter.file_list_single_test,50,1.45
iter.file_list_none_test,50,1.28
rdwr_cc_write_page_test,100,0.25
rdwr_cc_read_page_test,100,0.23
rdwr_cc_write_large_test,100,0.06
rdwr_cc_read_large_test,100,0.08
rdwr_cc_write_page_test,200,0.50
rdwr_cc_read_page_test,200,0.45
rdwr_cc_write_large_test,200,0.12
rdwr_cc_read_large_test,200,0.14
rdwr_cc_write_page_test,300,0.73
rdwr_cc_read_page_test,300,0.70
rdwr_cc_write_large_test,300,0.19
rdwr_cc_read_large_test,300,0.25
rdwr_cc_write_page_test,400,0.98
rdwr_cc_read_page_test,400,0.91
rdwr_cc_write_large_test,400,0.27
rdwr_cc_read_large_test,400,0.34
rdwr_cc_write_page_test,500,1.22
rdwr_cc_read_page_test,500,1.14
rdwr_cc_write_large_test,500,0.33
rdwr_cc_read_large_test,500,0.30
rdwr_nc_write_page_test,100,4.78
rdwr_nc_read_page_test,100,4.28
rdwr_nc_write_large_test,100,0.48
rdwr_nc_read_large_test,100,0.59
rdwr_nc_write_page_test,200,9.44
rdwr_nc_read_page_test,200,8.78
rdwr_nc_write_large_test,200,0.94
rdwr_nc_read_large_test,200,1.16
rdwr_nc_write_page_test,300,14.53
rdwr_nc_read_page_test,300,13.44
rdwr_nc_write_large_test,300,1.50
rdwr_nc_read_large_test,300,1.73
rdwr_nc_write_page_test,400,19.16
rdwr_nc_read_page_test,400,17.14
rdwr_nc_write_large_test,400,1.86
rdwr_nc_read_large_test,400,2.66
rdwr_nc_write_page_test,500,23.55
rdwr_nc_read_page_test,500,21.91
rdwr_nc_write_large_test,500,2.39
rdwr_nc_read_large_test,500,3.36
mmap_write_test,100,0.01
mmap_read_test,100,0.06
mmap_write_test,200,0.03
mmap_read_test,200,0.12
mmap_write_test,300,0.05
mmap_read_test,300,0.19
mmap_write_test,400,0.05
mmap_read_test,400,0.23
mmap_write_test,500,0.08
mmap_read_test,500,0.28
1 file_create_test 1000 0.20
2 file_open_test 1000 0.09
3 file_overwrite_test 1000 0.17
4 file_attr_test 1000 0.08
5 file_list_test 1000 0.11
6 file_list_single_test 1000 0.08
7 file_list_none_test 1000 0.03
8 file_delete_test 1000 0.16
9 file_mkdir_test 1000 0.14
10 file_rmdir_test 1000 0.12
11 file_create_test 2000 0.42
12 file_open_test 2000 0.19
13 file_overwrite_test 2000 0.41
14 file_attr_test 2000 0.17
15 file_list_test 2000 0.22
16 file_list_single_test 2000 0.17
17 file_list_none_test 2000 0.06
18 file_delete_test 2000 0.34
19 file_mkdir_test 2000 0.33
20 file_rmdir_test 2000 0.28
21 file_create_test 3000 0.66
22 file_open_test 3000 0.30
23 file_overwrite_test 3000 0.59
24 file_attr_test 3000 0.27
25 file_list_test 3000 0.36
26 file_list_single_test 3000 0.28
27 file_list_none_test 3000 0.09
28 file_delete_test 3000 0.52
29 file_mkdir_test 3000 0.48
30 file_rmdir_test 3000 0.41
31 file_create_test 4000 0.89
32 file_open_test 4000 0.36
33 file_overwrite_test 4000 0.72
34 file_attr_test 4000 0.34
35 file_list_test 4000 0.47
36 file_list_single_test 4000 0.33
37 file_list_none_test 4000 0.11
38 file_delete_test 4000 0.66
39 file_mkdir_test 4000 0.61
40 file_rmdir_test 4000 0.56
41 file_create_test 5000 1.01
42 file_open_test 5000 0.44
43 file_overwrite_test 5000 0.89
44 file_attr_test 5000 0.39
45 file_list_test 5000 0.56
46 file_list_single_test 5000 0.39
47 file_list_none_test 5000 0.14
48 file_delete_test 5000 0.78
49 file_mkdir_test 5000 0.73
50 file_rmdir_test 5000 0.64
51 iter.file_open_test 10 0.25
52 iter.file_attr_test 10 0.19
53 iter.file_list_single_test 10 0.33
54 iter.file_list_none_test 10 0.25
55 iter.file_open_test 20 0.44
56 iter.file_attr_test 20 0.33
57 iter.file_list_single_test 20 0.61
58 iter.file_list_none_test 20 0.52
59 iter.file_open_test 30 0.59
60 iter.file_attr_test 30 0.47
61 iter.file_list_single_test 30 0.89
62 iter.file_list_none_test 30 0.81
63 iter.file_open_test 40 0.84
64 iter.file_attr_test 40 0.67
65 iter.file_list_single_test 40 1.17
66 iter.file_list_none_test 40 1.00
67 iter.file_open_test 50 0.97
68 iter.file_attr_test 50 0.73
69 iter.file_list_single_test 50 1.45
70 iter.file_list_none_test 50 1.28
71 rdwr_cc_write_page_test 100 0.25
72 rdwr_cc_read_page_test 100 0.23
73 rdwr_cc_write_large_test 100 0.06
74 rdwr_cc_read_large_test 100 0.08
75 rdwr_cc_write_page_test 200 0.50
76 rdwr_cc_read_page_test 200 0.45
77 rdwr_cc_write_large_test 200 0.12
78 rdwr_cc_read_large_test 200 0.14
79 rdwr_cc_write_page_test 300 0.73
80 rdwr_cc_read_page_test 300 0.70
81 rdwr_cc_write_large_test 300 0.19
82 rdwr_cc_read_large_test 300 0.25
83 rdwr_cc_write_page_test 400 0.98
84 rdwr_cc_read_page_test 400 0.91
85 rdwr_cc_write_large_test 400 0.27
86 rdwr_cc_read_large_test 400 0.34
87 rdwr_cc_write_page_test 500 1.22
88 rdwr_cc_read_page_test 500 1.14
89 rdwr_cc_write_large_test 500 0.33
90 rdwr_cc_read_large_test 500 0.30
91 rdwr_nc_write_page_test 100 4.78
92 rdwr_nc_read_page_test 100 4.28
93 rdwr_nc_write_large_test 100 0.48
94 rdwr_nc_read_large_test 100 0.59
95 rdwr_nc_write_page_test 200 9.44
96 rdwr_nc_read_page_test 200 8.78
97 rdwr_nc_write_large_test 200 0.94
98 rdwr_nc_read_large_test 200 1.16
99 rdwr_nc_write_page_test 300 14.53
100 rdwr_nc_read_page_test 300 13.44
101 rdwr_nc_write_large_test 300 1.50
102 rdwr_nc_read_large_test 300 1.73
103 rdwr_nc_write_page_test 400 19.16
104 rdwr_nc_read_page_test 400 17.14
105 rdwr_nc_write_large_test 400 1.86
106 rdwr_nc_read_large_test 400 2.66
107 rdwr_nc_write_page_test 500 23.55
108 rdwr_nc_read_page_test 500 21.91
109 rdwr_nc_write_large_test 500 2.39
110 rdwr_nc_read_large_test 500 3.36
111 mmap_write_test 100 0.01
112 mmap_read_test 100 0.06
113 mmap_write_test 200 0.03
114 mmap_read_test 200 0.12
115 mmap_write_test 300 0.05
116 mmap_read_test 300 0.19
117 mmap_write_test 400 0.05
118 mmap_read_test 400 0.23
119 mmap_write_test 500 0.08
120 mmap_read_test 500 0.28

View File

@ -0,0 +1,120 @@
file_create_test,1000,0.20
file_open_test,1000,0.09
file_overwrite_test,1000,0.17
file_attr_test,1000,0.08
file_list_test,1000,0.11
file_list_single_test,1000,0.08
file_list_none_test,1000,0.03
file_delete_test,1000,0.14
file_mkdir_test,1000,0.14
file_rmdir_test,1000,0.14
file_create_test,2000,0.42
file_open_test,2000,0.19
file_overwrite_test,2000,0.38
file_attr_test,2000,0.19
file_list_test,2000,0.23
file_list_single_test,2000,0.17
file_list_none_test,2000,0.06
file_delete_test,2000,0.33
file_mkdir_test,2000,0.30
file_rmdir_test,2000,0.27
file_create_test,3000,0.64
file_open_test,3000,0.30
file_overwrite_test,3000,0.59
file_attr_test,3000,0.25
file_list_test,3000,0.36
file_list_single_test,3000,0.27
file_list_none_test,3000,0.08
file_delete_test,3000,0.48
file_mkdir_test,3000,0.47
file_rmdir_test,3000,0.42
file_create_test,4000,0.86
file_open_test,4000,0.38
file_overwrite_test,4000,0.73
file_attr_test,4000,0.33
file_list_test,4000,0.48
file_list_single_test,4000,0.33
file_list_none_test,4000,0.11
file_delete_test,4000,0.64
file_mkdir_test,4000,0.62
file_rmdir_test,4000,0.52
file_create_test,5000,1.03
file_open_test,5000,0.44
file_overwrite_test,5000,0.92
file_attr_test,5000,0.38
file_list_test,5000,0.58
file_list_single_test,5000,0.38
file_list_none_test,5000,0.14
file_delete_test,5000,0.80
file_mkdir_test,5000,0.73
file_rmdir_test,5000,0.69
iter.file_open_test,10,0.25
iter.file_attr_test,10,0.19
iter.file_list_single_test,10,0.33
iter.file_list_none_test,10,0.26
iter.file_open_test,20,0.44
iter.file_attr_test,20,0.34
iter.file_list_single_test,20,0.61
iter.file_list_none_test,20,0.52
iter.file_open_test,30,0.61
iter.file_attr_test,30,0.48
iter.file_list_single_test,30,0.88
iter.file_list_none_test,30,0.78
iter.file_open_test,40,0.77
iter.file_attr_test,40,0.61
iter.file_list_single_test,40,1.19
iter.file_list_none_test,40,1.03
iter.file_open_test,50,0.95
iter.file_attr_test,50,0.73
iter.file_list_single_test,50,1.42
iter.file_list_none_test,50,1.28
rdwr_cc_write_page_test,100,0.25
rdwr_cc_read_page_test,100,0.23
rdwr_cc_write_large_test,100,0.08
rdwr_cc_read_large_test,100,0.08
rdwr_cc_write_page_test,200,0.48
rdwr_cc_read_page_test,200,0.45
rdwr_cc_write_large_test,200,0.12
rdwr_cc_read_large_test,200,0.17
rdwr_cc_write_page_test,300,0.73
rdwr_cc_read_page_test,300,0.61
rdwr_cc_write_large_test,300,0.19
rdwr_cc_read_large_test,300,0.23
rdwr_cc_write_page_test,400,0.97
rdwr_cc_read_page_test,400,0.88
rdwr_cc_write_large_test,400,0.27
rdwr_cc_read_large_test,400,0.33
rdwr_cc_write_page_test,500,1.20
rdwr_cc_read_page_test,500,1.14
rdwr_cc_write_large_test,500,0.31
rdwr_cc_read_large_test,500,0.39
rdwr_nc_write_page_test,100,4.76
rdwr_nc_read_page_test,100,4.24
rdwr_nc_write_large_test,100,0.47
rdwr_nc_read_large_test,100,0.56
rdwr_nc_write_page_test,200,9.44
rdwr_nc_read_page_test,200,8.44
rdwr_nc_write_large_test,200,0.94
rdwr_nc_read_large_test,200,1.14
rdwr_nc_write_page_test,300,14.19
rdwr_nc_read_page_test,300,12.70
rdwr_nc_write_large_test,300,1.39
rdwr_nc_read_large_test,300,1.74
rdwr_nc_write_page_test,400,19.20
rdwr_nc_read_page_test,400,17.41
rdwr_nc_write_large_test,400,1.95
rdwr_nc_read_large_test,400,2.53
rdwr_nc_write_page_test,500,24.02
rdwr_nc_read_page_test,500,22.16
rdwr_nc_write_large_test,500,2.42
rdwr_nc_read_large_test,500,3.14
mmap_write_test,100,0.01
mmap_read_test,100,0.08
mmap_write_test,200,0.03
mmap_read_test,200,0.14
mmap_write_test,300,0.05
mmap_read_test,300,0.17
mmap_write_test,400,0.05
mmap_read_test,400,0.22
mmap_write_test,500,0.06
mmap_read_test,500,0.28
1 file_create_test 1000 0.20
2 file_open_test 1000 0.09
3 file_overwrite_test 1000 0.17
4 file_attr_test 1000 0.08
5 file_list_test 1000 0.11
6 file_list_single_test 1000 0.08
7 file_list_none_test 1000 0.03
8 file_delete_test 1000 0.14
9 file_mkdir_test 1000 0.14
10 file_rmdir_test 1000 0.14
11 file_create_test 2000 0.42
12 file_open_test 2000 0.19
13 file_overwrite_test 2000 0.38
14 file_attr_test 2000 0.19
15 file_list_test 2000 0.23
16 file_list_single_test 2000 0.17
17 file_list_none_test 2000 0.06
18 file_delete_test 2000 0.33
19 file_mkdir_test 2000 0.30
20 file_rmdir_test 2000 0.27
21 file_create_test 3000 0.64
22 file_open_test 3000 0.30
23 file_overwrite_test 3000 0.59
24 file_attr_test 3000 0.25
25 file_list_test 3000 0.36
26 file_list_single_test 3000 0.27
27 file_list_none_test 3000 0.08
28 file_delete_test 3000 0.48
29 file_mkdir_test 3000 0.47
30 file_rmdir_test 3000 0.42
31 file_create_test 4000 0.86
32 file_open_test 4000 0.38
33 file_overwrite_test 4000 0.73
34 file_attr_test 4000 0.33
35 file_list_test 4000 0.48
36 file_list_single_test 4000 0.33
37 file_list_none_test 4000 0.11
38 file_delete_test 4000 0.64
39 file_mkdir_test 4000 0.62
40 file_rmdir_test 4000 0.52
41 file_create_test 5000 1.03
42 file_open_test 5000 0.44
43 file_overwrite_test 5000 0.92
44 file_attr_test 5000 0.38
45 file_list_test 5000 0.58
46 file_list_single_test 5000 0.38
47 file_list_none_test 5000 0.14
48 file_delete_test 5000 0.80
49 file_mkdir_test 5000 0.73
50 file_rmdir_test 5000 0.69
51 iter.file_open_test 10 0.25
52 iter.file_attr_test 10 0.19
53 iter.file_list_single_test 10 0.33
54 iter.file_list_none_test 10 0.26
55 iter.file_open_test 20 0.44
56 iter.file_attr_test 20 0.34
57 iter.file_list_single_test 20 0.61
58 iter.file_list_none_test 20 0.52
59 iter.file_open_test 30 0.61
60 iter.file_attr_test 30 0.48
61 iter.file_list_single_test 30 0.88
62 iter.file_list_none_test 30 0.78
63 iter.file_open_test 40 0.77
64 iter.file_attr_test 40 0.61
65 iter.file_list_single_test 40 1.19
66 iter.file_list_none_test 40 1.03
67 iter.file_open_test 50 0.95
68 iter.file_attr_test 50 0.73
69 iter.file_list_single_test 50 1.42
70 iter.file_list_none_test 50 1.28
71 rdwr_cc_write_page_test 100 0.25
72 rdwr_cc_read_page_test 100 0.23
73 rdwr_cc_write_large_test 100 0.08
74 rdwr_cc_read_large_test 100 0.08
75 rdwr_cc_write_page_test 200 0.48
76 rdwr_cc_read_page_test 200 0.45
77 rdwr_cc_write_large_test 200 0.12
78 rdwr_cc_read_large_test 200 0.17
79 rdwr_cc_write_page_test 300 0.73
80 rdwr_cc_read_page_test 300 0.61
81 rdwr_cc_write_large_test 300 0.19
82 rdwr_cc_read_large_test 300 0.23
83 rdwr_cc_write_page_test 400 0.97
84 rdwr_cc_read_page_test 400 0.88
85 rdwr_cc_write_large_test 400 0.27
86 rdwr_cc_read_large_test 400 0.33
87 rdwr_cc_write_page_test 500 1.20
88 rdwr_cc_read_page_test 500 1.14
89 rdwr_cc_write_large_test 500 0.31
90 rdwr_cc_read_large_test 500 0.39
91 rdwr_nc_write_page_test 100 4.76
92 rdwr_nc_read_page_test 100 4.24
93 rdwr_nc_write_large_test 100 0.47
94 rdwr_nc_read_large_test 100 0.56
95 rdwr_nc_write_page_test 200 9.44
96 rdwr_nc_read_page_test 200 8.44
97 rdwr_nc_write_large_test 200 0.94
98 rdwr_nc_read_large_test 200 1.14
99 rdwr_nc_write_page_test 300 14.19
100 rdwr_nc_read_page_test 300 12.70
101 rdwr_nc_write_large_test 300 1.39
102 rdwr_nc_read_large_test 300 1.74
103 rdwr_nc_write_page_test 400 19.20
104 rdwr_nc_read_page_test 400 17.41
105 rdwr_nc_write_large_test 400 1.95
106 rdwr_nc_read_large_test 400 2.53
107 rdwr_nc_write_page_test 500 24.02
108 rdwr_nc_read_page_test 500 22.16
109 rdwr_nc_write_large_test 500 2.42
110 rdwr_nc_read_large_test 500 3.14
111 mmap_write_test 100 0.01
112 mmap_read_test 100 0.08
113 mmap_write_test 200 0.03
114 mmap_read_test 200 0.14
115 mmap_write_test 300 0.05
116 mmap_read_test 300 0.17
117 mmap_write_test 400 0.05
118 mmap_read_test 400 0.22
119 mmap_write_test 500 0.06
120 mmap_read_test 500 0.28

View File

@ -0,0 +1,120 @@
file_create_test,1000,0.28
file_open_test,1000,0.22
file_overwrite_test,1000,0.33
file_attr_test,1000,0.20
file_list_test,1000,0.19
file_list_single_test,1000,0.22
file_list_none_test,1000,0.17
file_delete_test,1000,0.30
file_mkdir_test,1000,0.23
file_rmdir_test,1000,0.28
file_create_test,2000,0.64
file_open_test,2000,0.45
file_overwrite_test,2000,0.73
file_attr_test,2000,0.42
file_list_test,2000,0.39
file_list_single_test,2000,0.52
file_list_none_test,2000,0.38
file_delete_test,2000,0.62
file_mkdir_test,2000,0.47
file_rmdir_test,2000,0.56
file_create_test,3000,0.94
file_open_test,3000,0.70
file_overwrite_test,3000,1.12
file_attr_test,3000,0.66
file_list_test,3000,0.62
file_list_single_test,3000,0.83
file_list_none_test,3000,0.55
file_delete_test,3000,0.98
file_mkdir_test,3000,0.72
file_rmdir_test,3000,0.84
file_create_test,4000,1.22
file_open_test,4000,0.90
file_overwrite_test,4000,1.45
file_attr_test,4000,0.84
file_list_test,4000,0.84
file_list_single_test,4000,1.14
file_list_none_test,4000,0.73
file_delete_test,4000,1.26
file_mkdir_test,4000,0.97
file_rmdir_test,4000,1.20
file_create_test,5000,1.53
file_open_test,5000,1.09
file_overwrite_test,5000,1.75
file_attr_test,5000,1.02
file_list_test,5000,1.02
file_list_single_test,5000,1.41
file_list_none_test,5000,0.91
file_delete_test,5000,1.62
file_mkdir_test,5000,1.19
file_rmdir_test,5000,1.45
iter.file_open_test,10,1.47
iter.file_attr_test,10,1.34
iter.file_list_single_test,10,1.28
iter.file_list_none_test,10,1.16
iter.file_open_test,20,2.84
iter.file_attr_test,20,2.61
iter.file_list_single_test,20,2.52
iter.file_list_none_test,20,2.27
iter.file_open_test,30,4.22
iter.file_attr_test,30,3.91
iter.file_list_single_test,30,3.77
iter.file_list_none_test,30,3.50
iter.file_open_test,40,5.61
iter.file_attr_test,40,5.22
iter.file_list_single_test,40,5.09
iter.file_list_none_test,40,4.64
iter.file_open_test,50,7.00
iter.file_attr_test,50,6.42
iter.file_list_single_test,50,6.16
iter.file_list_none_test,50,5.66
rdwr_cc_write_page_test,100,0.23
rdwr_cc_read_page_test,100,0.23
rdwr_cc_write_large_test,100,0.06
rdwr_cc_read_large_test,100,0.06
rdwr_cc_write_page_test,200,0.44
rdwr_cc_read_page_test,200,0.42
rdwr_cc_write_large_test,200,0.12
rdwr_cc_read_large_test,200,0.12
rdwr_cc_write_page_test,300,0.66
rdwr_cc_read_page_test,300,0.59
rdwr_cc_write_large_test,300,0.20
rdwr_cc_read_large_test,300,0.17
rdwr_cc_write_page_test,400,0.88
rdwr_cc_read_page_test,400,0.77
rdwr_cc_write_large_test,400,0.27
rdwr_cc_read_large_test,400,0.20
rdwr_cc_write_page_test,500,1.09
rdwr_cc_read_page_test,500,0.97
rdwr_cc_write_large_test,500,0.31
rdwr_cc_read_large_test,500,0.25
rdwr_nc_write_page_test,100,2.61
rdwr_nc_read_page_test,100,2.41
rdwr_nc_write_large_test,100,0.25
rdwr_nc_read_large_test,100,0.25
rdwr_nc_write_page_test,200,5.22
rdwr_nc_read_page_test,200,4.81
rdwr_nc_write_large_test,200,0.48
rdwr_nc_read_large_test,200,0.47
rdwr_nc_write_page_test,300,7.95
rdwr_nc_read_page_test,300,7.08
rdwr_nc_write_large_test,300,0.72
rdwr_nc_read_large_test,300,0.70
rdwr_nc_write_page_test,400,10.38
rdwr_nc_read_page_test,400,9.25
rdwr_nc_write_large_test,400,0.98
rdwr_nc_read_large_test,400,0.94
rdwr_nc_write_page_test,500,13.05
rdwr_nc_read_page_test,500,11.56
rdwr_nc_write_large_test,500,1.23
rdwr_nc_read_large_test,500,1.23
mmap_write_test,100,0.01
mmap_read_test,100,0.06
mmap_write_test,200,0.03
mmap_read_test,200,0.12
mmap_write_test,300,0.05
mmap_read_test,300,0.17
mmap_write_test,400,0.06
mmap_read_test,400,0.22
mmap_write_test,500,0.06
mmap_read_test,500,0.28
1 file_create_test 1000 0.28
2 file_open_test 1000 0.22
3 file_overwrite_test 1000 0.33
4 file_attr_test 1000 0.20
5 file_list_test 1000 0.19
6 file_list_single_test 1000 0.22
7 file_list_none_test 1000 0.17
8 file_delete_test 1000 0.30
9 file_mkdir_test 1000 0.23
10 file_rmdir_test 1000 0.28
11 file_create_test 2000 0.64
12 file_open_test 2000 0.45
13 file_overwrite_test 2000 0.73
14 file_attr_test 2000 0.42
15 file_list_test 2000 0.39
16 file_list_single_test 2000 0.52
17 file_list_none_test 2000 0.38
18 file_delete_test 2000 0.62
19 file_mkdir_test 2000 0.47
20 file_rmdir_test 2000 0.56
21 file_create_test 3000 0.94
22 file_open_test 3000 0.70
23 file_overwrite_test 3000 1.12
24 file_attr_test 3000 0.66
25 file_list_test 3000 0.62
26 file_list_single_test 3000 0.83
27 file_list_none_test 3000 0.55
28 file_delete_test 3000 0.98
29 file_mkdir_test 3000 0.72
30 file_rmdir_test 3000 0.84
31 file_create_test 4000 1.22
32 file_open_test 4000 0.90
33 file_overwrite_test 4000 1.45
34 file_attr_test 4000 0.84
35 file_list_test 4000 0.84
36 file_list_single_test 4000 1.14
37 file_list_none_test 4000 0.73
38 file_delete_test 4000 1.26
39 file_mkdir_test 4000 0.97
40 file_rmdir_test 4000 1.20
41 file_create_test 5000 1.53
42 file_open_test 5000 1.09
43 file_overwrite_test 5000 1.75
44 file_attr_test 5000 1.02
45 file_list_test 5000 1.02
46 file_list_single_test 5000 1.41
47 file_list_none_test 5000 0.91
48 file_delete_test 5000 1.62
49 file_mkdir_test 5000 1.19
50 file_rmdir_test 5000 1.45
51 iter.file_open_test 10 1.47
52 iter.file_attr_test 10 1.34
53 iter.file_list_single_test 10 1.28
54 iter.file_list_none_test 10 1.16
55 iter.file_open_test 20 2.84
56 iter.file_attr_test 20 2.61
57 iter.file_list_single_test 20 2.52
58 iter.file_list_none_test 20 2.27
59 iter.file_open_test 30 4.22
60 iter.file_attr_test 30 3.91
61 iter.file_list_single_test 30 3.77
62 iter.file_list_none_test 30 3.50
63 iter.file_open_test 40 5.61
64 iter.file_attr_test 40 5.22
65 iter.file_list_single_test 40 5.09
66 iter.file_list_none_test 40 4.64
67 iter.file_open_test 50 7.00
68 iter.file_attr_test 50 6.42
69 iter.file_list_single_test 50 6.16
70 iter.file_list_none_test 50 5.66
71 rdwr_cc_write_page_test 100 0.23
72 rdwr_cc_read_page_test 100 0.23
73 rdwr_cc_write_large_test 100 0.06
74 rdwr_cc_read_large_test 100 0.06
75 rdwr_cc_write_page_test 200 0.44
76 rdwr_cc_read_page_test 200 0.42
77 rdwr_cc_write_large_test 200 0.12
78 rdwr_cc_read_large_test 200 0.12
79 rdwr_cc_write_page_test 300 0.66
80 rdwr_cc_read_page_test 300 0.59
81 rdwr_cc_write_large_test 300 0.20
82 rdwr_cc_read_large_test 300 0.17
83 rdwr_cc_write_page_test 400 0.88
84 rdwr_cc_read_page_test 400 0.77
85 rdwr_cc_write_large_test 400 0.27
86 rdwr_cc_read_large_test 400 0.20
87 rdwr_cc_write_page_test 500 1.09
88 rdwr_cc_read_page_test 500 0.97
89 rdwr_cc_write_large_test 500 0.31
90 rdwr_cc_read_large_test 500 0.25
91 rdwr_nc_write_page_test 100 2.61
92 rdwr_nc_read_page_test 100 2.41
93 rdwr_nc_write_large_test 100 0.25
94 rdwr_nc_read_large_test 100 0.25
95 rdwr_nc_write_page_test 200 5.22
96 rdwr_nc_read_page_test 200 4.81
97 rdwr_nc_write_large_test 200 0.48
98 rdwr_nc_read_large_test 200 0.47
99 rdwr_nc_write_page_test 300 7.95
100 rdwr_nc_read_page_test 300 7.08
101 rdwr_nc_write_large_test 300 0.72
102 rdwr_nc_read_large_test 300 0.70
103 rdwr_nc_write_page_test 400 10.38
104 rdwr_nc_read_page_test 400 9.25
105 rdwr_nc_write_large_test 400 0.98
106 rdwr_nc_read_large_test 400 0.94
107 rdwr_nc_write_page_test 500 13.05
108 rdwr_nc_read_page_test 500 11.56
109 rdwr_nc_write_large_test 500 1.23
110 rdwr_nc_read_large_test 500 1.23
111 mmap_write_test 100 0.01
112 mmap_read_test 100 0.06
113 mmap_write_test 200 0.03
114 mmap_read_test 200 0.12
115 mmap_write_test 300 0.05
116 mmap_read_test 300 0.17
117 mmap_write_test 400 0.06
118 mmap_read_test 400 0.22
119 mmap_write_test 500 0.06
120 mmap_read_test 500 0.28

View File

@ -0,0 +1,120 @@
file_create_test,1000,0.30
file_open_test,1000,0.22
file_overwrite_test,1000,0.34
file_attr_test,1000,0.20
file_list_test,1000,0.19
file_list_single_test,1000,0.22
file_list_none_test,1000,0.17
file_delete_test,1000,0.31
file_mkdir_test,1000,0.22
file_rmdir_test,1000,0.27
file_create_test,2000,0.61
file_open_test,2000,0.44
file_overwrite_test,2000,0.69
file_attr_test,2000,0.44
file_list_test,2000,0.41
file_list_single_test,2000,0.53
file_list_none_test,2000,0.36
file_delete_test,2000,0.64
file_mkdir_test,2000,0.47
file_rmdir_test,2000,0.55
file_create_test,3000,0.97
file_open_test,3000,0.69
file_overwrite_test,3000,1.08
file_attr_test,3000,0.64
file_list_test,3000,0.64
file_list_single_test,3000,0.88
file_list_none_test,3000,0.56
file_delete_test,3000,0.97
file_mkdir_test,3000,0.73
file_rmdir_test,3000,0.80
file_create_test,4000,1.20
file_open_test,4000,0.91
file_overwrite_test,4000,1.49
file_attr_test,4000,0.83
file_list_test,4000,0.83
file_list_single_test,4000,1.19
file_list_none_test,4000,0.75
file_delete_test,4000,1.28
file_mkdir_test,4000,0.92
file_rmdir_test,4000,1.08
file_create_test,5000,1.44
file_open_test,5000,1.09
file_overwrite_test,5000,1.83
file_attr_test,5000,1.02
file_list_test,5000,1.03
file_list_single_test,5000,1.50
file_list_none_test,5000,0.94
file_delete_test,5000,1.58
file_mkdir_test,5000,1.12
file_rmdir_test,5000,1.42
iter.file_open_test,10,1.47
iter.file_attr_test,10,1.34
iter.file_list_single_test,10,1.31
iter.file_list_none_test,10,1.17
iter.file_open_test,20,2.84
iter.file_attr_test,20,2.61
iter.file_list_single_test,20,2.53
iter.file_list_none_test,20,2.31
iter.file_open_test,30,4.20
iter.file_attr_test,30,3.88
iter.file_list_single_test,30,3.78
iter.file_list_none_test,30,3.58
iter.file_open_test,40,5.59
iter.file_attr_test,40,5.12
iter.file_list_single_test,40,4.89
iter.file_list_none_test,40,4.62
iter.file_open_test,50,7.05
iter.file_attr_test,50,6.42
iter.file_list_single_test,50,6.22
iter.file_list_none_test,50,5.72
rdwr_cc_write_page_test,100,0.23
rdwr_cc_read_page_test,100,0.25
rdwr_cc_write_large_test,100,0.06
rdwr_cc_read_large_test,100,0.06
rdwr_cc_write_page_test,200,0.45
rdwr_cc_read_page_test,200,0.41
rdwr_cc_write_large_test,200,0.12
rdwr_cc_read_large_test,200,0.12
rdwr_cc_write_page_test,300,0.66
rdwr_cc_read_page_test,300,0.59
rdwr_cc_write_large_test,300,0.20
rdwr_cc_read_large_test,300,0.16
rdwr_cc_write_page_test,400,0.87
rdwr_cc_read_page_test,400,0.77
rdwr_cc_write_large_test,400,0.25
rdwr_cc_read_large_test,400,0.20
rdwr_cc_write_page_test,500,1.08
rdwr_cc_read_page_test,500,0.95
rdwr_cc_write_large_test,500,0.31
rdwr_cc_read_large_test,500,0.25
rdwr_nc_write_page_test,100,2.61
rdwr_nc_read_page_test,100,2.41
rdwr_nc_write_large_test,100,0.27
rdwr_nc_read_large_test,100,0.23
rdwr_nc_write_page_test,200,5.23
rdwr_nc_read_page_test,200,4.76
rdwr_nc_write_large_test,200,0.50
rdwr_nc_read_large_test,200,0.45
rdwr_nc_write_page_test,300,8.03
rdwr_nc_read_page_test,300,7.17
rdwr_nc_write_large_test,300,0.73
rdwr_nc_read_large_test,300,0.66
rdwr_nc_write_page_test,400,10.75
rdwr_nc_read_page_test,400,9.47
rdwr_nc_write_large_test,400,0.98
rdwr_nc_read_large_test,400,0.86
rdwr_nc_write_page_test,500,13.12
rdwr_nc_read_page_test,500,11.69
rdwr_nc_write_large_test,500,1.25
rdwr_nc_read_large_test,500,1.27
mmap_write_test,100,0.01
mmap_read_test,100,0.08
mmap_write_test,200,0.03
mmap_read_test,200,0.12
mmap_write_test,300,0.05
mmap_read_test,300,0.17
mmap_write_test,400,0.06
mmap_read_test,400,0.22
mmap_write_test,500,0.08
mmap_read_test,500,0.27
1 file_create_test 1000 0.30
2 file_open_test 1000 0.22
3 file_overwrite_test 1000 0.34
4 file_attr_test 1000 0.20
5 file_list_test 1000 0.19
6 file_list_single_test 1000 0.22
7 file_list_none_test 1000 0.17
8 file_delete_test 1000 0.31
9 file_mkdir_test 1000 0.22
10 file_rmdir_test 1000 0.27
11 file_create_test 2000 0.61
12 file_open_test 2000 0.44
13 file_overwrite_test 2000 0.69
14 file_attr_test 2000 0.44
15 file_list_test 2000 0.41
16 file_list_single_test 2000 0.53
17 file_list_none_test 2000 0.36
18 file_delete_test 2000 0.64
19 file_mkdir_test 2000 0.47
20 file_rmdir_test 2000 0.55
21 file_create_test 3000 0.97
22 file_open_test 3000 0.69
23 file_overwrite_test 3000 1.08
24 file_attr_test 3000 0.64
25 file_list_test 3000 0.64
26 file_list_single_test 3000 0.88
27 file_list_none_test 3000 0.56
28 file_delete_test 3000 0.97
29 file_mkdir_test 3000 0.73
30 file_rmdir_test 3000 0.80
31 file_create_test 4000 1.20
32 file_open_test 4000 0.91
33 file_overwrite_test 4000 1.49
34 file_attr_test 4000 0.83
35 file_list_test 4000 0.83
36 file_list_single_test 4000 1.19
37 file_list_none_test 4000 0.75
38 file_delete_test 4000 1.28
39 file_mkdir_test 4000 0.92
40 file_rmdir_test 4000 1.08
41 file_create_test 5000 1.44
42 file_open_test 5000 1.09
43 file_overwrite_test 5000 1.83
44 file_attr_test 5000 1.02
45 file_list_test 5000 1.03
46 file_list_single_test 5000 1.50
47 file_list_none_test 5000 0.94
48 file_delete_test 5000 1.58
49 file_mkdir_test 5000 1.12
50 file_rmdir_test 5000 1.42
51 iter.file_open_test 10 1.47
52 iter.file_attr_test 10 1.34
53 iter.file_list_single_test 10 1.31
54 iter.file_list_none_test 10 1.17
55 iter.file_open_test 20 2.84
56 iter.file_attr_test 20 2.61
57 iter.file_list_single_test 20 2.53
58 iter.file_list_none_test 20 2.31
59 iter.file_open_test 30 4.20
60 iter.file_attr_test 30 3.88
61 iter.file_list_single_test 30 3.78
62 iter.file_list_none_test 30 3.58
63 iter.file_open_test 40 5.59
64 iter.file_attr_test 40 5.12
65 iter.file_list_single_test 40 4.89
66 iter.file_list_none_test 40 4.62
67 iter.file_open_test 50 7.05
68 iter.file_attr_test 50 6.42
69 iter.file_list_single_test 50 6.22
70 iter.file_list_none_test 50 5.72
71 rdwr_cc_write_page_test 100 0.23
72 rdwr_cc_read_page_test 100 0.25
73 rdwr_cc_write_large_test 100 0.06
74 rdwr_cc_read_large_test 100 0.06
75 rdwr_cc_write_page_test 200 0.45
76 rdwr_cc_read_page_test 200 0.41
77 rdwr_cc_write_large_test 200 0.12
78 rdwr_cc_read_large_test 200 0.12
79 rdwr_cc_write_page_test 300 0.66
80 rdwr_cc_read_page_test 300 0.59
81 rdwr_cc_write_large_test 300 0.20
82 rdwr_cc_read_large_test 300 0.16
83 rdwr_cc_write_page_test 400 0.87
84 rdwr_cc_read_page_test 400 0.77
85 rdwr_cc_write_large_test 400 0.25
86 rdwr_cc_read_large_test 400 0.20
87 rdwr_cc_write_page_test 500 1.08
88 rdwr_cc_read_page_test 500 0.95
89 rdwr_cc_write_large_test 500 0.31
90 rdwr_cc_read_large_test 500 0.25
91 rdwr_nc_write_page_test 100 2.61
92 rdwr_nc_read_page_test 100 2.41
93 rdwr_nc_write_large_test 100 0.27
94 rdwr_nc_read_large_test 100 0.23
95 rdwr_nc_write_page_test 200 5.23
96 rdwr_nc_read_page_test 200 4.76
97 rdwr_nc_write_large_test 200 0.50
98 rdwr_nc_read_large_test 200 0.45
99 rdwr_nc_write_page_test 300 8.03
100 rdwr_nc_read_page_test 300 7.17
101 rdwr_nc_write_large_test 300 0.73
102 rdwr_nc_read_large_test 300 0.66
103 rdwr_nc_write_page_test 400 10.75
104 rdwr_nc_read_page_test 400 9.47
105 rdwr_nc_write_large_test 400 0.98
106 rdwr_nc_read_large_test 400 0.86
107 rdwr_nc_write_page_test 500 13.12
108 rdwr_nc_read_page_test 500 11.69
109 rdwr_nc_write_large_test 500 1.25
110 rdwr_nc_read_large_test 500 1.27
111 mmap_write_test 100 0.01
112 mmap_read_test 100 0.08
113 mmap_write_test 200 0.03
114 mmap_read_test 200 0.12
115 mmap_write_test 300 0.05
116 mmap_read_test 300 0.17
117 mmap_write_test 400 0.06
118 mmap_read_test 400 0.22
119 mmap_write_test 500 0.08
120 mmap_read_test 500 0.27

View File

@ -0,0 +1,120 @@
file_create_test,1000,0.28
file_open_test,1000,0.22
file_overwrite_test,1000,0.36
file_attr_test,1000,0.19
file_list_test,1000,0.17
file_list_single_test,1000,0.22
file_list_none_test,1000,0.19
file_delete_test,1000,0.31
file_mkdir_test,1000,0.23
file_rmdir_test,1000,0.28
file_create_test,2000,0.58
file_open_test,2000,0.52
file_overwrite_test,2000,0.84
file_attr_test,2000,0.52
file_list_test,2000,0.44
file_list_single_test,2000,0.56
file_list_none_test,2000,0.38
file_delete_test,2000,0.64
file_mkdir_test,2000,0.47
file_rmdir_test,2000,0.55
file_create_test,3000,0.92
file_open_test,3000,0.66
file_overwrite_test,3000,1.06
file_attr_test,3000,0.66
file_list_test,3000,0.64
file_list_single_test,3000,0.86
file_list_none_test,3000,0.56
file_delete_test,3000,1.00
file_mkdir_test,3000,0.77
file_rmdir_test,3000,0.86
file_create_test,4000,1.22
file_open_test,4000,0.89
file_overwrite_test,4000,1.44
file_attr_test,4000,0.81
file_list_test,4000,0.84
file_list_single_test,4000,1.12
file_list_none_test,4000,0.73
file_delete_test,4000,1.31
file_mkdir_test,4000,0.97
file_rmdir_test,4000,1.12
file_create_test,5000,1.53
file_open_test,5000,1.05
file_overwrite_test,5000,1.73
file_attr_test,5000,1.02
file_list_test,5000,1.03
file_list_single_test,5000,1.41
file_list_none_test,5000,0.94
file_delete_test,5000,1.61
file_mkdir_test,5000,1.20
file_rmdir_test,5000,1.36
iter.file_open_test,10,1.44
iter.file_attr_test,10,1.38
iter.file_list_single_test,10,1.26
iter.file_list_none_test,10,1.14
iter.file_open_test,20,2.89
iter.file_attr_test,20,2.61
iter.file_list_single_test,20,2.52
iter.file_list_none_test,20,2.45
iter.file_open_test,30,4.19
iter.file_attr_test,30,3.86
iter.file_list_single_test,30,3.77
iter.file_list_none_test,30,3.47
iter.file_open_test,40,5.64
iter.file_attr_test,40,5.17
iter.file_list_single_test,40,4.84
iter.file_list_none_test,40,4.55
iter.file_open_test,50,7.00
iter.file_attr_test,50,6.44
iter.file_list_single_test,50,6.12
iter.file_list_none_test,50,5.64
rdwr_cc_write_page_test,100,0.27
rdwr_cc_read_page_test,100,0.23
rdwr_cc_write_large_test,100,0.06
rdwr_cc_read_large_test,100,0.06
rdwr_cc_write_page_test,200,0.44
rdwr_cc_read_page_test,200,0.41
rdwr_cc_write_large_test,200,0.12
rdwr_cc_read_large_test,200,0.11
rdwr_cc_write_page_test,300,0.67
rdwr_cc_read_page_test,300,0.59
rdwr_cc_write_large_test,300,0.19
rdwr_cc_read_large_test,300,0.16
rdwr_cc_write_page_test,400,0.87
rdwr_cc_read_page_test,400,0.77
rdwr_cc_write_large_test,400,0.25
rdwr_cc_read_large_test,400,0.22
rdwr_cc_write_page_test,500,1.09
rdwr_cc_read_page_test,500,0.94
rdwr_cc_write_large_test,500,0.31
rdwr_cc_read_large_test,500,0.27
rdwr_nc_write_page_test,100,2.56
rdwr_nc_read_page_test,100,2.38
rdwr_nc_write_large_test,100,0.23
rdwr_nc_read_large_test,100,0.23
rdwr_nc_write_page_test,200,5.20
rdwr_nc_read_page_test,200,4.62
rdwr_nc_write_large_test,200,0.48
rdwr_nc_read_large_test,200,0.45
rdwr_nc_write_page_test,300,7.70
rdwr_nc_read_page_test,300,6.86
rdwr_nc_write_large_test,300,0.73
rdwr_nc_read_large_test,300,0.70
rdwr_nc_write_page_test,400,10.23
rdwr_nc_read_page_test,400,9.17
rdwr_nc_write_large_test,400,0.95
rdwr_nc_read_large_test,400,0.94
rdwr_nc_write_page_test,500,12.91
rdwr_nc_read_page_test,500,11.66
rdwr_nc_write_large_test,500,1.22
rdwr_nc_read_large_test,500,1.25
mmap_write_test,100,0.01
mmap_read_test,100,0.06
mmap_write_test,200,0.03
mmap_read_test,200,0.12
mmap_write_test,300,0.05
mmap_read_test,300,0.17
mmap_write_test,400,0.06
mmap_read_test,400,0.23
mmap_write_test,500,0.06
mmap_read_test,500,0.28
1 file_create_test 1000 0.28
2 file_open_test 1000 0.22
3 file_overwrite_test 1000 0.36
4 file_attr_test 1000 0.19
5 file_list_test 1000 0.17
6 file_list_single_test 1000 0.22
7 file_list_none_test 1000 0.19
8 file_delete_test 1000 0.31
9 file_mkdir_test 1000 0.23
10 file_rmdir_test 1000 0.28
11 file_create_test 2000 0.58
12 file_open_test 2000 0.52
13 file_overwrite_test 2000 0.84
14 file_attr_test 2000 0.52
15 file_list_test 2000 0.44
16 file_list_single_test 2000 0.56
17 file_list_none_test 2000 0.38
18 file_delete_test 2000 0.64
19 file_mkdir_test 2000 0.47
20 file_rmdir_test 2000 0.55
21 file_create_test 3000 0.92
22 file_open_test 3000 0.66
23 file_overwrite_test 3000 1.06
24 file_attr_test 3000 0.66
25 file_list_test 3000 0.64
26 file_list_single_test 3000 0.86
27 file_list_none_test 3000 0.56
28 file_delete_test 3000 1.00
29 file_mkdir_test 3000 0.77
30 file_rmdir_test 3000 0.86
31 file_create_test 4000 1.22
32 file_open_test 4000 0.89
33 file_overwrite_test 4000 1.44
34 file_attr_test 4000 0.81
35 file_list_test 4000 0.84
36 file_list_single_test 4000 1.12
37 file_list_none_test 4000 0.73
38 file_delete_test 4000 1.31
39 file_mkdir_test 4000 0.97
40 file_rmdir_test 4000 1.12
41 file_create_test 5000 1.53
42 file_open_test 5000 1.05
43 file_overwrite_test 5000 1.73
44 file_attr_test 5000 1.02
45 file_list_test 5000 1.03
46 file_list_single_test 5000 1.41
47 file_list_none_test 5000 0.94
48 file_delete_test 5000 1.61
49 file_mkdir_test 5000 1.20
50 file_rmdir_test 5000 1.36
51 iter.file_open_test 10 1.44
52 iter.file_attr_test 10 1.38
53 iter.file_list_single_test 10 1.26
54 iter.file_list_none_test 10 1.14
55 iter.file_open_test 20 2.89
56 iter.file_attr_test 20 2.61
57 iter.file_list_single_test 20 2.52
58 iter.file_list_none_test 20 2.45
59 iter.file_open_test 30 4.19
60 iter.file_attr_test 30 3.86
61 iter.file_list_single_test 30 3.77
62 iter.file_list_none_test 30 3.47
63 iter.file_open_test 40 5.64
64 iter.file_attr_test 40 5.17
65 iter.file_list_single_test 40 4.84
66 iter.file_list_none_test 40 4.55
67 iter.file_open_test 50 7.00
68 iter.file_attr_test 50 6.44
69 iter.file_list_single_test 50 6.12
70 iter.file_list_none_test 50 5.64
71 rdwr_cc_write_page_test 100 0.27
72 rdwr_cc_read_page_test 100 0.23
73 rdwr_cc_write_large_test 100 0.06
74 rdwr_cc_read_large_test 100 0.06
75 rdwr_cc_write_page_test 200 0.44
76 rdwr_cc_read_page_test 200 0.41
77 rdwr_cc_write_large_test 200 0.12
78 rdwr_cc_read_large_test 200 0.11
79 rdwr_cc_write_page_test 300 0.67
80 rdwr_cc_read_page_test 300 0.59
81 rdwr_cc_write_large_test 300 0.19
82 rdwr_cc_read_large_test 300 0.16
83 rdwr_cc_write_page_test 400 0.87
84 rdwr_cc_read_page_test 400 0.77
85 rdwr_cc_write_large_test 400 0.25
86 rdwr_cc_read_large_test 400 0.22
87 rdwr_cc_write_page_test 500 1.09
88 rdwr_cc_read_page_test 500 0.94
89 rdwr_cc_write_large_test 500 0.31
90 rdwr_cc_read_large_test 500 0.27
91 rdwr_nc_write_page_test 100 2.56
92 rdwr_nc_read_page_test 100 2.38
93 rdwr_nc_write_large_test 100 0.23
94 rdwr_nc_read_large_test 100 0.23
95 rdwr_nc_write_page_test 200 5.20
96 rdwr_nc_read_page_test 200 4.62
97 rdwr_nc_write_large_test 200 0.48
98 rdwr_nc_read_large_test 200 0.45
99 rdwr_nc_write_page_test 300 7.70
100 rdwr_nc_read_page_test 300 6.86
101 rdwr_nc_write_large_test 300 0.73
102 rdwr_nc_read_large_test 300 0.70
103 rdwr_nc_write_page_test 400 10.23
104 rdwr_nc_read_page_test 400 9.17
105 rdwr_nc_write_large_test 400 0.95
106 rdwr_nc_read_large_test 400 0.94
107 rdwr_nc_write_page_test 500 12.91
108 rdwr_nc_read_page_test 500 11.66
109 rdwr_nc_write_large_test 500 1.22
110 rdwr_nc_read_large_test 500 1.25
111 mmap_write_test 100 0.01
112 mmap_read_test 100 0.06
113 mmap_write_test 200 0.03
114 mmap_read_test 200 0.12
115 mmap_write_test 300 0.05
116 mmap_read_test 300 0.17
117 mmap_write_test 400 0.06
118 mmap_read_test 400 0.23
119 mmap_write_test 500 0.06
120 mmap_read_test 500 0.28

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 55 KiB

After

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 53 KiB

After

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 50 KiB

After

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 48 KiB

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 68 KiB

After

Width:  |  Height:  |  Size: 37 KiB

View File

@ -0,0 +1,124 @@
# WinFsp Registry Settings
<details>
<summary>
📁 <code>HKLM\SYSTEM\CurrentControlSet\Services\WinFsp</code>
</summary>
<blockquote>
Stores information about the WinFsp file system driver as required by the Windows OS.
</blockquote>
</details>
<details>
<summary>
📁 <code>HKLM\SYSTEM\CurrentControlSet\Services\WinFsp.Launcher</code>
</summary>
<blockquote>
Stores information about the WinFsp Launcher service as required by the Windows OS.
</blockquote>
</details>
<details>
<summary>
📁 <code>HKLM\SYSTEM\CurrentControlSet\Services\WinFsp.Np</code>
</summary>
<blockquote>
Stores information about the WinFsp network provider as required by the Windows OS.
</blockquote>
</details>
<details>
<summary>
📁 <code>HKLM\SYSTEM\CurrentControlSet\Services\EventLog\Application\WinFsp</code>
</summary>
<blockquote>
Stores information about the WinFsp event source as required by the Windows OS.
</blockquote>
</details>
<details>
<summary>
📁 <code>HKLM\SYSTEM\CurrentControlSet\Control\NetworkProvider\Order</code>
</summary>
<blockquote>
Stores information about the WinFsp network provider as required by the Windows OS.
</blockquote>
</details>
<details>
<summary>
📁 <code>HKLM\SOFTWARE\WinFsp</code>
</summary>
<blockquote>
Primary registry key used to store WinFsp settings. On a 64-bit system (x64 or ARM64) this key is stored in the 32-bit portion of the registry and its true location is `HKLM\SOFTWARE\WOW6432Node\WinFsp`.
* `InstallDir (REG_SZ)`: Contains the WinFsp installation directory.
* `DistinctPermsForSameOwnerGroup (REG_DWORD)`: Directs how WinFsp-FUSE should consider UNIX owner and group permissions in the case when the Windows owner and group SID are the same (for example, this can happen when someone uses a Microsoft account as their primary login). When this setting is 0 and the Windows owner and group SID are the same, WinFsp-FUSE combines the UNIX owner and group permissions (for example, user permission `rw-` and group permission `---` combine to `---`), which can result in inadvertent "access denied" errors. When this setting is 1 and even if the Windows owner and group SID are the same, WinFsp-FUSE looks at the UNIX owner permissions and the UNIX group permissions separately. The default value is 1 since v1.11B1 and was 0 in earlier versions.
* `MountBroadcastDriveChange (REG_DWORD)`: A value of 1 instructs WinFsp to broadcast an additional "drive change" message to all top-level windows during mounting and unmounting. The default value is 0. Normally the Windows infrastructure broadcasts a `WM_DEVICECHANGE` message whenever a drive gets added/removed. In some rare systems it is possible for this message to get lost or stalled. The workaround for these rare systems is to enable this registry setting, in which case WinFsp will broadcast the `WM_DEVICECHANGE` using a slightly different but more reliable method than the one Windows uses.
* `MountDoNotUseLauncher (REG_DWORD)`: A value of 1 disallows the use of the Launcher for drive mounting. The default value of 0 allows use of the Launcher for drive mounting when necessary. In general the Launcher is not necessary for mounting. However when running a file system in the Windows Service context (session 0) under an account that is not LocalSystem (e.g. `NT AUTHORITY\NETWORK SERVICE`), the Launcher is used to create global drives.
</blockquote>
</details>
<details>
<summary>
📁 <code>HKLM\SOFTWARE\WinFsp\Services\:SERVICE</code>
</summary>
<blockquote>
Registry key used to store information about the WinFsp service with name `:SERVICE`. WinFsp services are user mode file systems controlled by the Launcher; for more information see the [Service Architecture](WinFsp-Service-Architecture.asciidoc) document. On a 64-bit system (x64 or ARM64) this key is stored in the 32-bit portion of the registry and its true location is `HKLM\SOFTWARE\WOW6432Node\WinFsp\Services\:SERVICE`.
* `Agent (REG_SZ)`: UNDOCUMENTED (see source code).
* `Executable (REG_SZ)`: Contains the path to the executable to use when launching the service.
* `CommandLine (REG_SZ)`: Contains the command line to use when launching the service.
* `WorkDirectory (REG_SZ)`: Contains the working directory to use when launching the service.
* `RunAs (REG_SZ)`: Controls the account used when launching the service. Possible values are `LocalSystem` (default), `LocalService`, `NetworkService` and `.` (dot). The `.` (dot) value means that the service should be launched as the account that is launching the file system (e.g. via `net use` or Explorer's "Map Network Drive").
* `Security (REG_SZ)`: Controls which users can launch the service.
* `AuthPackage (REG_SZ)`: UNDOCUMENTED (see source code).
* `Stderr (REG_SZ)`: Specifies a path that the Launcher will redirect service error output to.
* `JobControl (REG_DWORD)`: Controls whether the service is running in the same job as the Launcher. The default value is 1.
* `Credentials (REG_DWORD)`: Controls whether the file system requires credentials.
* `AuthPackageId (REG_DWORD)`: UNDOCUMENTED (see source code).
* `Recovery (REG_DWORD)`: A value of 1 instructs the Launcher to restart a service that has crashed. The default value is 0.
</blockquote>
</details>
<details>
<summary>
📁 <code>HKLM\SOFTWARE\WinFsp\Fsext</code>
</summary>
<blockquote>
Registry key used to store WinFsp fsext provider information. Fsext providers are kernel mode file systems that interface with WinFsp; for more information see the [Kernel Mode File Systems](WinFsp-Kernel-Mode-File-Systems.asciidoc) document. On a 64-bit system (x64 or ARM64) this key is stored in the 32-bit portion of the registry and its true location is `HKLM\SOFTWARE\WOW6432Node\WinFsp\Fsext`.
* `:CTLCODE (REG_SZ)`: The `:CTLCODE` name is the string representation of the fsext provider's transact code in `%08lx` format and the value is the provider's driver name.
</blockquote>
</details>

View File

@ -0,0 +1,192 @@
= Performance Testing
:caption:
This document discusses performance testing for WinFsp. The goal of this performance testing is to discover optimization opportunities for WinFsp and compare its performance to that of NTFS and Dokany.
== Executive Summary
This performance testing shows that WinFsp has excellent performance in all tested scenarios. It outperforms NTFS in most scenarios (an unfair comparison as NTFS is a disk file system and WinFsp is tested with an in-memory file system). It also outperforms Dokany in all scenarios, often by an order of magnitude.
ifdef::env-browser[chart::bar[data-uri="WinFsp-Performance-Testing/file_tests.csv",file="WinFsp-Performance-Testing/file_tests.png",opt="y-label=time"]]
ifndef::env-browser[image::WinFsp-Performance-Testing/file_tests.png[]]
ifdef::env-browser[chart::bar[data-uri="WinFsp-Performance-Testing/rdwr_tests.csv",file="WinFsp-Performance-Testing/rdwr_tests.png",opt="y-label=time"]]
ifndef::env-browser[image::WinFsp-Performance-Testing/rdwr_tests.png[]]
== Fsbench
All testing was performed using a new performance test suite developed as part of WinFsp, called https://github.com/winfsp/winfsp/blob/master/tst/fsbench/fsbench.c[fsbench]. Fsbench was developed because it allows the creation of tests that are important to file system developers; for example, it can answer questions of the type: "how long does it take to delete 1000 files" or "how long does it take to list a directory with 10000 files in it".
Fsbench is based on the https://github.com/winfsp/winfsp/tree/master/ext/tlib[tlib] library, originally from the *secfs* project. Tlib is usually used to develop regression test suites in C/C++, but can be also used to create performance tests.
Fsbench currently includes the following tests:
[width="100%",cols="20%,60%,20%",options="header"]
|===
|Test |Measures performance of |Parameters
|file_create_test |CreateFileW(CREATE_NEW) / CloseHandle |file count
|file_open_test |CreateFileW(OPEN_EXISTING) / CloseHandle |file count
|file_overwrite_test|CreateFileW(CREATE_ALWAYS) / CloseHandle with existing files|file count
|file_list_test |FindFirstFileW / FindNextFile / FindClose |iterations
|file_delete_test |DeleteFileW |file count
|file_mkdir_test |CreateDirectoryW |file count
|file_rmdir_test |RemoveDirectoryW |file count
|rdwr_cc_write_page_test |WriteFile (1 page; cached) |iterations
|rdwr_cc_read_page_test |ReadFile (1 page; cached) |iterations
|rdwr_nc_write_page_test |WriteFile (1 page; non-cached) |iterations
|rdwr_nc_read_page_test |ReadFile (1 page; non-cached) |iterations
|rdwr_cc_write_large_test |WriteFile (16 pages; cached) |iterations
|rdwr_cc_read_large_test |ReadFile (16 pages; cached) |iterations
|rdwr_nc_write_large_test |WriteFile (16 pages; non-cached) |iterations
|rdwr_nc_read_large_test |ReadFile (16 pages; non-cached) |iterations
|mmap_write_test |Memory mapped write test |iterations
|mmap_write_test |Memory mapped read test |iterations
|===
== Tested File Systems
=== NTFS
The comparison to NTFS is very important to establish a baseline. It is also very misleading because NTFS is a disk file system and MEMFS (either the WinFsp or Dokany variants) is an in memory file system. The tests will show that MEMFS is faster than NTFS. This should not be taken to mean that we are trying to make the (obvious) claim that an in memory file system is faster than a disk file system, but to show that the approach of writing a file system in user mode is a valid proposition and can be efficient.
=== WinFsp/MEMFS
MEMFS is the file system used to test WinFsp and shipped as a sample bundled with the WinFsp installer. MEMFS is a simple in memory file system and as such is very fast under most conditions. This is desirable because our goal with this performance testing is to measure the speed of the WinFsp system components rather the performance of a complex user mode file system. MEMFS has minimal overhead and is ideal for this purpose.
WinFsp/MEMFS can be run in different configurations, which enable or disable WinFsp caching features. The tested configurations were:
- An infinite FileInfoTimeout, which enables caching of metadata and data.
- A FileInfoTimeout of 1s (second), which enables caching of metadata but disables caching of data.
- A FileInfoTimeout of 0, which completely disables caching.
The WinFsp git commit at the time of testing was d804f5674d76f11ea86d14f4bcb1157e6e40e719.
=== Dokany/MEMFS
To achieve fairness when comparing Dokany to WinFsp the MEMFS file system has been ported to Dokany. Substantial care was taken to ensure that WinFsp/MEMFS and Dokany/MEMFS perform equally well, so that the performance of the Dokany FSD and user-mode components can be measured and compared accurately.
The Dokany/MEMFS project has its own https://github.com/billziss-gh/memfs-dokany[repository]. The project comes without a license, which means that it may not be used for any purpose other than as a reference.
The Dokany version used for testing was 1.0.1. The Dokany/MEMFS git commit was 27a678d7c0d5ee2fb3fb2ecc8e38210857ae941c.
== Test Environment
Tests were performed on an idle computer/VM. There was a reboot of both the computer and VM before each file system was tested. Each test was run twice and the smaller time value chosen. The assumption is that even in a seemingly idle desktop system there is some activity which will affect the results; the smaller value is the preferred one to use because it reflects the time when there is less or no other activity.
The test environment was as follows:
----
MacBook Pro (Retina, 13-inch, Early 2015)
3.1 GHz Intel Core i7
16 GB 1867 MHz DDR3
500 GB SSD
VirtualBox Version 5.0.20 r106931
1 CPU
4 GB RAM
80 GB Dynamically allocated differencing storage
Windows 10 (64-bit) Version 1511 (OS Build 10586.420)
----
== Test Results
In the graphs below we use consistent coloring to quickly identify a file system. Red is used for NTFS, yellow for WinFsp/MEMFS with a FileInfoTimeout of 0, green for WinFsp/MEMFS with a FileInfoTimeout of 1, light blue for WinFsp/MEMFS with an infinite FileInfoTimeout and deep blue for Dokany/MEMFS.
In all tests lower times are better (the file system is faster).
=== File Tests
These tests measure the performance of creating, opening, overwriting and listing files and directories.
==== file_create_test
This test measures the performance of CreateFileW(CREATE_NEW) / CloseHandle. WinFsp has the best performance here. Dokany follows and NTFS is last as it has to actually update its data structures on disk.
ifdef::env-browser[chart::line[data-uri="WinFsp-Performance-Testing/file_create_test.csv",file="WinFsp-Performance-Testing/file_create_test.png",opt="x-label=file count,y-label=time"]]
ifndef::env-browser[image::WinFsp-Performance-Testing/file_create_test.png[]]
==== file_open_test
This test measures the performance of CreateFileW(OPEN_EXISTING) / CloseHandle. WinFsp again has the best (although uneven) performance, followed by NTFS and then Dokany.
WinFsp appears to have very uneven performance here. In particular notice that opening 1000 files is slower than opening 2000 files, which makes no sense! I suspect that the test observes an initial acquisition of resouces when the test first starts, which is not necessary when the test runs for 2000 files at a later time. This uneven performance should probably be investigated in the future.
ifdef::env-browser[chart::line[data-uri="WinFsp-Performance-Testing/file_open_test.csv",file="WinFsp-Performance-Testing/file_open_test.png",opt="x-label=file count,y-label=time"]]
ifndef::env-browser[image::WinFsp-Performance-Testing/file_open_test.png[]]
==== file_overwrite_test
This test measures the performance of CreateFileW(CREATE_ALWAYS) / CloseHandle. WinFsp is fastest, followed by NTFS and then Dokany.
ifdef::env-browser[chart::line[data-uri="WinFsp-Performance-Testing/file_overwrite_test.csv",file="WinFsp-Performance-Testing/file_overwrite_test.png",opt="x-label=file count,y-label=time"]]
ifndef::env-browser[image::WinFsp-Performance-Testing/file_overwrite_test.png[]]
==== file_list_test
This test measures the performance of FindFirstFileW / FindNextFile / FindClose. NTFS wins this scenario, likely because it can satisfy the list operation from cache. WinFsp has overall good performance. Dokany appears to show slightly quadratic performance in this scenario.
ifdef::env-browser[chart::line[data-uri="WinFsp-Performance-Testing/file_list_test.csv",file="WinFsp-Performance-Testing/file_list_test.png",opt="x-label=file count,y-label=time"]]
ifndef::env-browser[image::WinFsp-Performance-Testing/file_list_test.png[]]
==== file_delete_test
This test measures the performance of DeleteFileW. WinFsp has the best performance, followed by Dokany and NTFS with very similar performance.
ifdef::env-browser[chart::line[data-uri="WinFsp-Performance-Testing/file_delete_test.csv",file="WinFsp-Performance-Testing/file_delete_test.png",opt="x-label=file count,y-label=time"]]
ifndef::env-browser[image::WinFsp-Performance-Testing/file_delete_test.png[]]
=== Read/Write Tests
These tests measure the performance of cached, non-cached and memory-mapped I/O.
==== rdwr_cc_write_page_test
This test measures the performance of cached WriteFile with 1 page writes. NTFS and WinFsp with an infinite FileInfoTimeout have the best performance, with a clear edge to NTFS (likely because of its use of FastIO, which WinFsp does not currently support). WinFsp with a FileInfoTimeout of 0 or 1 performance is next, because WinFsp does not use the NTOS Cache Manager in this scenario. Dokany performance is last.
ifdef::env-browser[chart::line[data-uri="WinFsp-Performance-Testing/rdwr_cc_write_page_test.csv",file="WinFsp-Performance-Testing/rdwr_cc_write_page_test.png",opt="x-label=iterations,y-label=time"]]
ifndef::env-browser[image::WinFsp-Performance-Testing/rdwr_cc_write_page_test.png[]]
==== rdwr_cc_read_page_test
This test measures the performance of cached ReadFile with 1 page reads. The results here are very similar to the rdwr_cc_write_page_test case and similar comments apply.
ifdef::env-browser[chart::line[data-uri="WinFsp-Performance-Testing/rdwr_cc_read_page_test.csv",file="WinFsp-Performance-Testing/rdwr_cc_read_page_test.png",opt="x-label=iterations,y-label=time"]]
ifndef::env-browser[image::WinFsp-Performance-Testing/rdwr_cc_read_page_test.png[]]
==== rdwr_nc_write_page_test
This test measures the performance of non-cached WriteFile with 1 page writes. WinFsp has the best performance, followed by Dokany. NTFS shows bad performance, which of course make sense as we are asking it to write all data to the disk.
ifdef::env-browser[chart::line[data-uri="WinFsp-Performance-Testing/rdwr_nc_write_page_test.csv",file="WinFsp-Performance-Testing/rdwr_nc_write_page_test.png",opt="x-label=iterations,y-label=time"]]
ifndef::env-browser[image::WinFsp-Performance-Testing/rdwr_nc_write_page_test.png[]]
==== rdwr_nc_read_page_test
This test measures the performance of non-cached ReadFile with 1 page reads. The results here are very similar to the rdwr_nc_write_page_test case and similar comments apply.
ifdef::env-browser[chart::line[data-uri="WinFsp-Performance-Testing/rdwr_nc_read_page_test.csv",file="WinFsp-Performance-Testing/rdwr_nc_read_page_test.png",opt="x-label=iterations,y-label=time"]]
ifndef::env-browser[image::WinFsp-Performance-Testing/rdwr_nc_read_page_test.png[]]
==== mmap_write_test
This test measures the performance of memory mapped writes. NTFS and WinFsp seem to have identical performance here, which actually makes sense because memory mapped I/O is effectively always cached and most of the actual I/O is done asynchronously by the system.
There are no results for Dokany as it seems to (still) not support memory mapped files:
----
Y:\>c:\Users\billziss\Projects\winfsp\build\VStudio\build\Release\fsbench-x64.exe --mmap=100 mmap*
mmap_write_test........................ KO
ASSERT(0 != Mapping) failed at fsbench.c:226:mmap_dotest
----
ifdef::env-browser[chart::line[data-uri="WinFsp-Performance-Testing/mmap_write_test.csv",file="WinFsp-Performance-Testing/mmap_write_test.png",opt="x-label=iterations,y-label=time"]]
ifndef::env-browser[image::WinFsp-Performance-Testing/mmap_write_test.png[]]
==== mmap_read_test
This test measures the performance of memory mapped reads. Again NTFS and WinFsp seem to have identical performance here.
There are no results for Dokany as it faces the same issue as with mmap_write_test.
ifdef::env-browser[chart::line[data-uri="WinFsp-Performance-Testing/mmap_read_test.csv",file="WinFsp-Performance-Testing/mmap_read_test.png",opt="x-label=iterations,y-label=time"]]
ifndef::env-browser[image::WinFsp-Performance-Testing/mmap_read_test.png[]]

Binary file not shown.

After

Width:  |  Height:  |  Size: 60 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 59 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 55 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 55 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 55 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 53 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 KiB

View File

@ -385,7 +385,47 @@ static NTSTATUS FspLauncherDefineDosDevice(
return !NT_SUCCESS(Result) ? Result : FspNtStatusFromWin32(ErrorCode);
}
static VOID FspMountBroadcastDriveChange(PWSTR MountPoint, WPARAM WParam)
struct FspMountBroadcastDriveChangeData
{
HMODULE Module;
WPARAM WParam;
WCHAR MountPoint[];
};
static DWORD WINAPI FspMountBroadcastDriveChangeThread(PVOID Data0)
{
struct FspMountBroadcastDriveChangeData *Data = Data0;
HMODULE Module = Data->Module;
WPARAM WParam = Data->WParam;
PWSTR MountPoint = Data->MountPoint;
BOOLEAN IsLocalSystem;
DEV_BROADCAST_VOLUME DriveChange;
DWORD Recipients;
FspServiceContextCheck(0, &IsLocalSystem);
memset(&DriveChange, 0, sizeof DriveChange);
DriveChange.dbcv_size = sizeof DriveChange;
DriveChange.dbcv_devicetype = DBT_DEVTYP_VOLUME;
DriveChange.dbcv_flags = DBTF_NET;
DriveChange.dbcv_unitmask = 1 << ((MountPoint[0] | 0x20) - 'a');
Recipients = BSM_APPLICATIONS | (IsLocalSystem ? BSM_ALLDESKTOPS : 0);
BroadcastSystemMessageW(
BSF_POSTMESSAGE,
&Recipients,
WM_DEVICECHANGE,
WParam,
(LPARAM)&DriveChange);
MemFree(Data);
FreeLibraryAndExitThread(Module, 0);
return 0;
}
static NTSTATUS FspMountBroadcastDriveChange(PWSTR MountPoint, WPARAM WParam)
{
/*
* DefineDosDeviceW (either directly or via the CSRSS) broadcasts a WM_DEVICECHANGE message
@ -402,29 +442,54 @@ static VOID FspMountBroadcastDriveChange(PWSTR MountPoint, WPARAM WParam)
*
* To resolve this we simply call BroadcastSystemMessage with BSF_POSTMESSAGE. (It would work
* with BSF_NOHANG | BSF_FORCEIFHUNG and without NOTIMEOUTIFNOTHUNG, but BSF_POSTMESSAGE is
* faster).
* faster). We do this in a separate thread to avoid blocking caller's thread.
*/
BOOLEAN IsLocalSystem;
DEV_BROADCAST_VOLUME DriveChange;
DWORD Flags, Recipients;
NTSTATUS Result;
HMODULE Module;
HANDLE Thread;
struct FspMountBroadcastDriveChangeData *Data = 0;
int Size;
FspServiceContextCheck(0, &IsLocalSystem);
if (!GetModuleHandleExW(
GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
(PVOID)FspMountBroadcastDriveChangeThread,
&Module))
{
Result = FspNtStatusFromWin32(GetLastError());
goto exit;
}
memset(&DriveChange, 0, sizeof DriveChange);
DriveChange.dbcv_size = sizeof DriveChange;
DriveChange.dbcv_devicetype = DBT_DEVTYP_VOLUME;
DriveChange.dbcv_flags = DBTF_NET;
DriveChange.dbcv_unitmask = 1 << (MountPoint[0] - 'a');
Size = (lstrlenW(MountPoint) + 1) * sizeof(WCHAR);
Data = MemAlloc(sizeof *Data + Size);
if (0 == Data)
{
Result = STATUS_INSUFFICIENT_RESOURCES;
goto exit;
}
Flags = BSF_POSTMESSAGE;
Recipients = BSM_APPLICATIONS | (IsLocalSystem ? BSM_ALLDESKTOPS : 0);
BroadcastSystemMessageW(
Flags,
&Recipients,
WM_DEVICECHANGE,
WParam,
(LPARAM)&DriveChange);
Data->Module = Module;
Data->WParam = WParam;
memcpy(Data->MountPoint, MountPoint, Size);
Thread = CreateThread(0, 0, FspMountBroadcastDriveChangeThread, Data, 0, 0);
if (0 == Thread)
{
Result = FspNtStatusFromWin32(GetLastError());
goto exit;
}
CloseHandle(Thread);
Result = STATUS_SUCCESS;
exit:
if (!NT_SUCCESS(Result))
{
MemFree(Data);
FreeLibrary(Module);
}
return Result;
}
static NTSTATUS FspMountSet_Drive(PWSTR VolumeName, PWSTR MountPoint, PHANDLE PMountHandle)

View File

@ -43,6 +43,9 @@ static NTSTATUS FspFsctlClose(
{
PAGED_CODE();
if (0 != IrpSp->FileObject->FsContext2)
FspDeviceDereference(IrpSp->FileObject->FsContext2);
Irp->IoStatus.Information = 0;
return STATUS_SUCCESS;
}

View File

@ -116,7 +116,11 @@ static NTSTATUS FspFsctlCreate(
if (0 == FileObject->RelatedFileObject &&
PREFIXW_SIZE <= FileObject->FileName.Length &&
RtlEqualMemory(PREFIXW, FileObject->FileName.Buffer, PREFIXW_SIZE))
{
Result = FspVolumeCreate(DeviceObject, Irp, IrpSp);
if (NT_SUCCESS(Result) && 0 != IrpSp->FileObject->FsContext2)
FspDeviceReference(IrpSp->FileObject->FsContext2);
}
else
{
Result = STATUS_SUCCESS;

View File

@ -40,16 +40,6 @@ static NTSTATUS FspFsvolDeviceInit(PDEVICE_OBJECT DeviceObject);
static VOID FspFsvolDeviceFini(PDEVICE_OBJECT DeviceObject);
static IO_TIMER_ROUTINE FspFsvolDeviceTimerRoutine;
static WORKER_THREAD_ROUTINE FspFsvolDeviceExpirationRoutine;
VOID FspFsvolDeviceFileRenameAcquireShared(PDEVICE_OBJECT DeviceObject);
BOOLEAN FspFsvolDeviceFileRenameTryAcquireShared(PDEVICE_OBJECT DeviceObject);
VOID FspFsvolDeviceFileRenameAcquireExclusive(PDEVICE_OBJECT DeviceObject);
BOOLEAN FspFsvolDeviceFileRenameTryAcquireExclusive(PDEVICE_OBJECT DeviceObject);
VOID FspFsvolDeviceFileRenameSetOwner(PDEVICE_OBJECT DeviceObject, PVOID Owner);
VOID FspFsvolDeviceFileRenameRelease(PDEVICE_OBJECT DeviceObject);
VOID FspFsvolDeviceFileRenameReleaseOwner(PDEVICE_OBJECT DeviceObject, PVOID Owner);
BOOLEAN FspFsvolDeviceFileRenameIsAcquiredExclusive(PDEVICE_OBJECT DeviceObject);
VOID FspFsvolDeviceLockContextTable(PDEVICE_OBJECT DeviceObject);
VOID FspFsvolDeviceUnlockContextTable(PDEVICE_OBJECT DeviceObject);
NTSTATUS FspFsvolDeviceCopyContextList(PDEVICE_OBJECT DeviceObject,
PVOID **PContexts, PULONG PContextCount);
NTSTATUS FspFsvolDeviceCopyContextByNameList(PDEVICE_OBJECT DeviceObject,
@ -84,16 +74,6 @@ VOID FspDeviceDeleteAll(VOID);
#pragma alloc_text(PAGE, FspDeviceDelete)
#pragma alloc_text(PAGE, FspFsvolDeviceInit)
#pragma alloc_text(PAGE, FspFsvolDeviceFini)
#pragma alloc_text(PAGE, FspFsvolDeviceFileRenameAcquireShared)
#pragma alloc_text(PAGE, FspFsvolDeviceFileRenameTryAcquireShared)
#pragma alloc_text(PAGE, FspFsvolDeviceFileRenameAcquireExclusive)
#pragma alloc_text(PAGE, FspFsvolDeviceFileRenameTryAcquireExclusive)
#pragma alloc_text(PAGE, FspFsvolDeviceFileRenameSetOwner)
#pragma alloc_text(PAGE, FspFsvolDeviceFileRenameRelease)
#pragma alloc_text(PAGE, FspFsvolDeviceFileRenameReleaseOwner)
#pragma alloc_text(PAGE, FspFsvolDeviceFileRenameIsAcquiredExclusive)
#pragma alloc_text(PAGE, FspFsvolDeviceLockContextTable)
#pragma alloc_text(PAGE, FspFsvolDeviceUnlockContextTable)
#pragma alloc_text(PAGE, FspFsvolDeviceCopyContextList)
#pragma alloc_text(PAGE, FspFsvolDeviceCopyContextByNameList)
#pragma alloc_text(PAGE, FspFsvolDeviceDeleteContextList)
@ -430,8 +410,9 @@ static NTSTATUS FspFsvolDeviceInit(PDEVICE_OBJECT DeviceObject)
FsvolDeviceExtension->InitDoneStat = 1;
/* initialize our context table */
ExInitializeResourceLite(&FsvolDeviceExtension->VolumeDeleteResource);
ExInitializeResourceLite(&FsvolDeviceExtension->FileRenameResource);
ExInitializeResourceLite(&FsvolDeviceExtension->ContextTableResource);
ExInitializeFastMutex(&FsvolDeviceExtension->ContextTableMutex);
InitializeListHead(&FsvolDeviceExtension->ContextList);
RtlInitializeGenericTableAvl(&FsvolDeviceExtension->ContextByNameTable,
FspFsvolDeviceCompareContextByName,
@ -513,8 +494,8 @@ static VOID FspFsvolDeviceFini(PDEVICE_OBJECT DeviceObject)
* to enumerate and delete all entries in the ContextTable.
*/
ExDeleteResourceLite(&FsvolDeviceExtension->ContextTableResource);
ExDeleteResourceLite(&FsvolDeviceExtension->FileRenameResource);
ExDeleteResourceLite(&FsvolDeviceExtension->VolumeDeleteResource);
}
/* is there a virtual disk? */
@ -592,101 +573,6 @@ static VOID FspFsvolDeviceExpirationRoutine(PVOID Context)
FspDeviceDereference(DeviceObject);
}
VOID FspFsvolDeviceFileRenameAcquireShared(PDEVICE_OBJECT DeviceObject)
{
PAGED_CODE();
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(DeviceObject);
ExAcquireResourceSharedLite(&FsvolDeviceExtension->FileRenameResource, TRUE);
}
BOOLEAN FspFsvolDeviceFileRenameTryAcquireShared(PDEVICE_OBJECT DeviceObject)
{
PAGED_CODE();
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(DeviceObject);
return ExAcquireResourceSharedLite(&FsvolDeviceExtension->FileRenameResource, FALSE);
}
VOID FspFsvolDeviceFileRenameAcquireExclusive(PDEVICE_OBJECT DeviceObject)
{
PAGED_CODE();
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(DeviceObject);
ExAcquireResourceExclusiveLite(&FsvolDeviceExtension->FileRenameResource, TRUE);
}
BOOLEAN FspFsvolDeviceFileRenameTryAcquireExclusive(PDEVICE_OBJECT DeviceObject)
{
PAGED_CODE();
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(DeviceObject);
return ExAcquireResourceExclusiveLite(&FsvolDeviceExtension->FileRenameResource, FALSE);
}
VOID FspFsvolDeviceFileRenameSetOwner(PDEVICE_OBJECT DeviceObject, PVOID Owner)
{
PAGED_CODE();
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(DeviceObject);
Owner = (PVOID)((UINT_PTR)Owner | 3);
ExSetResourceOwnerPointer(&FsvolDeviceExtension->FileRenameResource, Owner);
}
VOID FspFsvolDeviceFileRenameRelease(PDEVICE_OBJECT DeviceObject)
{
PAGED_CODE();
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(DeviceObject);
ExReleaseResourceLite(&FsvolDeviceExtension->FileRenameResource);
}
VOID FspFsvolDeviceFileRenameReleaseOwner(PDEVICE_OBJECT DeviceObject, PVOID Owner)
{
PAGED_CODE();
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(DeviceObject);
Owner = (PVOID)((UINT_PTR)Owner | 3);
if (ExIsResourceAcquiredLite(&FsvolDeviceExtension->FileRenameResource))
ExReleaseResourceLite(&FsvolDeviceExtension->FileRenameResource);
else
ExReleaseResourceForThreadLite(&FsvolDeviceExtension->FileRenameResource, (ERESOURCE_THREAD)Owner);
}
BOOLEAN FspFsvolDeviceFileRenameIsAcquiredExclusive(PDEVICE_OBJECT DeviceObject)
{
PAGED_CODE();
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(DeviceObject);
return ExIsResourceAcquiredExclusiveLite(&FsvolDeviceExtension->FileRenameResource);
}
VOID FspFsvolDeviceLockContextTable(PDEVICE_OBJECT DeviceObject)
{
PAGED_CODE();
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(DeviceObject);
ExAcquireResourceExclusiveLite(&FsvolDeviceExtension->ContextTableResource, TRUE);
}
VOID FspFsvolDeviceUnlockContextTable(PDEVICE_OBJECT DeviceObject)
{
PAGED_CODE();
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(DeviceObject);
ExReleaseResourceLite(&FsvolDeviceExtension->ContextTableResource);
}
NTSTATUS FspFsvolDeviceCopyContextList(PDEVICE_OBJECT DeviceObject,
PVOID **PContexts, PULONG PContextCount)
{
@ -969,7 +855,7 @@ static NTSTATUS FspFsmupDeviceInit(PDEVICE_OBJECT DeviceObject)
FSP_FSMUP_DEVICE_EXTENSION *FsmupDeviceExtension = FspFsmupDeviceExtension(DeviceObject);
/* initialize our prefix table */
ExInitializeResourceLite(&FsmupDeviceExtension->PrefixTableResource);
ExInitializeFastMutex(&FsmupDeviceExtension->PrefixTableMutex);
RtlInitializeUnicodePrefix(&FsmupDeviceExtension->PrefixTable);
RtlInitializeUnicodePrefix(&FsmupDeviceExtension->ClassTable);
FsmupDeviceExtension->InitDonePfxTab = 1;
@ -991,7 +877,6 @@ static VOID FspFsmupDeviceFini(PDEVICE_OBJECT DeviceObject)
*/
ASSERT(0 == RtlNextUnicodePrefix(&FsmupDeviceExtension->PrefixTable, TRUE));
ASSERT(0 == RtlNextUnicodePrefix(&FsmupDeviceExtension->ClassTable, TRUE));
ExDeleteResourceLite(&FsmupDeviceExtension->PrefixTableResource);
}
}
@ -1049,4 +934,4 @@ VOID FspDeviceDeleteAll(VOID)
FspDeviceDeleteList(DeviceObjects, DeviceObjectCount);
}
ERESOURCE FspDeviceGlobalResource;
FAST_MUTEX FspDeviceGlobalMutex;

View File

@ -122,14 +122,13 @@ NTSTATUS DriverEntry(
#pragma prefast(suppress:28175, "We are a filesystem: ok to access FastIoDispatch")
DriverObject->FastIoDispatch = &FspFastIoDispatch;
BOOLEAN InitDoneGRes = FALSE, InitDoneSilo = FALSE, InitDonePsBuf = FALSE,
BOOLEAN InitDoneSilo = FALSE, InitDonePsBuf = FALSE,
InitDoneTimers = FALSE, InitDoneDevices = FALSE;
FspDriverObject = DriverObject;
FspDriverMultiVersionInitialize();
ExInitializeResourceLite(&FspDeviceGlobalResource);
InitDoneGRes = TRUE;
ExInitializeFastMutex(&FspDeviceGlobalMutex);
Result = FspSiloInitialize(FspDriverInitializeDevices, FspDriverFinalizeDevices);
if (!NT_SUCCESS(Result))
@ -164,8 +163,6 @@ exit:
FspProcessBufferFinalize();
if (InitDoneSilo)
FspSiloFinalize();
if (InitDoneGRes)
ExDeleteResourceLite(&FspDeviceGlobalResource);
FSP_TRACE_FINI();
}

View File

@ -566,7 +566,7 @@ BOOLEAN FspFileNameIsPrefix(
#else
#define FspFileNameUpcase(D,S,U) (ASSERT(0 == (U)), RtlUpcaseUnicodeString(D,S,FALSE))
#define FspEaNameUpcase(D,S,U) (ASSERT(0 == (U)), RtlUpperString(D,S))
#define FspFileNameCompare(N1,N2,I,U) (ASSERT(0 == (U)), RtlCompareUnicodeString(N1,N2,I))
#define FspFileNameCompare(N1,N2,I,U) (ASSERT(0 == (U)), FspCompareUnicodeString(N1,N2,I))
#define FspFileNameIsPrefix(N1,N2,I,U) (ASSERT(0 == (U)), RtlPrefixUnicodeString(N1,N2,I))
#endif
NTSTATUS FspFileNameInExpression(
@ -733,6 +733,12 @@ VOID FspIrpHookReset(PIRP Irp);
PVOID FspIrpHookContext(PVOID Context);
NTSTATUS FspIrpHookNext(PDEVICE_OBJECT DeviceObject, PIRP Irp, PVOID Context);
/* utility: string compare */
LONG FspCompareUnicodeString(
PCUNICODE_STRING String1,
PCUNICODE_STRING String2,
BOOLEAN CaseInsensitive);
/* silos */
typedef struct
{
@ -1205,8 +1211,10 @@ typedef struct
KSPIN_LOCK ExpirationLock;
WORK_QUEUE_ITEM ExpirationWorkItem;
BOOLEAN ExpirationInProgress;
ERESOURCE VolumeDeleteResource;
BOOLEAN VolumeDeleted;
ERESOURCE FileRenameResource;
ERESOURCE ContextTableResource;
FAST_MUTEX ContextTableMutex;
LIST_ENTRY ContextList;
RTL_AVL_TABLE ContextByNameTable;
PVOID ContextByNameTableElementStorage;
@ -1236,7 +1244,7 @@ typedef struct
{
FSP_DEVICE_EXTENSION Base;
UINT32 InitDonePfxTab:1;
ERESOURCE PrefixTableResource;
FAST_MUTEX PrefixTableMutex;
UNICODE_PREFIX_TABLE PrefixTable;
UNICODE_PREFIX_TABLE ClassTable;
} FSP_FSMUP_DEVICE_EXTENSION;
@ -1274,16 +1282,106 @@ NTSTATUS FspDeviceInitialize(PDEVICE_OBJECT DeviceObject);
VOID FspDeviceDelete(PDEVICE_OBJECT DeviceObject);
BOOLEAN FspDeviceReference(PDEVICE_OBJECT DeviceObject);
VOID FspDeviceDereference(PDEVICE_OBJECT DeviceObject);
VOID FspFsvolDeviceFileRenameAcquireShared(PDEVICE_OBJECT DeviceObject);
BOOLEAN FspFsvolDeviceFileRenameTryAcquireShared(PDEVICE_OBJECT DeviceObject);
VOID FspFsvolDeviceFileRenameAcquireExclusive(PDEVICE_OBJECT DeviceObject);
BOOLEAN FspFsvolDeviceFileRenameTryAcquireExclusive(PDEVICE_OBJECT DeviceObject);
VOID FspFsvolDeviceFileRenameSetOwner(PDEVICE_OBJECT DeviceObject, PVOID Owner);
VOID FspFsvolDeviceFileRenameRelease(PDEVICE_OBJECT DeviceObject);
VOID FspFsvolDeviceFileRenameReleaseOwner(PDEVICE_OBJECT DeviceObject, PVOID Owner);
BOOLEAN FspFsvolDeviceFileRenameIsAcquiredExclusive(PDEVICE_OBJECT DeviceObject);
VOID FspFsvolDeviceLockContextTable(PDEVICE_OBJECT DeviceObject);
VOID FspFsvolDeviceUnlockContextTable(PDEVICE_OBJECT DeviceObject);
static inline
VOID FspFsvolDeviceVolumeDeleteAcquireShared(PDEVICE_OBJECT DeviceObject)
{
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(DeviceObject);
ExAcquireResourceSharedLite(&FsvolDeviceExtension->VolumeDeleteResource, TRUE);
}
static inline
VOID FspFsvolDeviceVolumeDeleteAcquireExclusive(PDEVICE_OBJECT DeviceObject)
{
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(DeviceObject);
ExAcquireResourceExclusiveLite(&FsvolDeviceExtension->VolumeDeleteResource, TRUE);
}
static inline
VOID FspFsvolDeviceVolumeDeleteSetOwner(PDEVICE_OBJECT DeviceObject, PVOID Owner)
{
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(DeviceObject);
Owner = (PVOID)((UINT_PTR)Owner | 3);
ExSetResourceOwnerPointer(&FsvolDeviceExtension->VolumeDeleteResource, Owner);
}
static inline
VOID FspFsvolDeviceVolumeDeleteRelease(PDEVICE_OBJECT DeviceObject)
{
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(DeviceObject);
ExReleaseResourceLite(&FsvolDeviceExtension->VolumeDeleteResource);
}
static inline
VOID FspFsvolDeviceVolumeDeleteReleaseOwner(PDEVICE_OBJECT DeviceObject, PVOID Owner)
{
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(DeviceObject);
Owner = (PVOID)((UINT_PTR)Owner | 3);
if (ExIsResourceAcquiredLite(&FsvolDeviceExtension->VolumeDeleteResource))
ExReleaseResourceLite(&FsvolDeviceExtension->VolumeDeleteResource);
else
ExReleaseResourceForThreadLite(&FsvolDeviceExtension->VolumeDeleteResource, (ERESOURCE_THREAD)Owner);
}
static inline
VOID FspFsvolDeviceFileRenameAcquireShared(PDEVICE_OBJECT DeviceObject)
{
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(DeviceObject);
ExAcquireResourceSharedLite(&FsvolDeviceExtension->FileRenameResource, TRUE);
}
static inline
BOOLEAN FspFsvolDeviceFileRenameTryAcquireShared(PDEVICE_OBJECT DeviceObject)
{
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(DeviceObject);
return ExAcquireResourceSharedLite(&FsvolDeviceExtension->FileRenameResource, FALSE);
}
static inline
VOID FspFsvolDeviceFileRenameAcquireExclusive(PDEVICE_OBJECT DeviceObject)
{
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(DeviceObject);
ExAcquireResourceExclusiveLite(&FsvolDeviceExtension->FileRenameResource, TRUE);
}
static inline
BOOLEAN FspFsvolDeviceFileRenameTryAcquireExclusive(PDEVICE_OBJECT DeviceObject)
{
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(DeviceObject);
return ExAcquireResourceExclusiveLite(&FsvolDeviceExtension->FileRenameResource, FALSE);
}
static inline
VOID FspFsvolDeviceFileRenameSetOwner(PDEVICE_OBJECT DeviceObject, PVOID Owner)
{
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(DeviceObject);
Owner = (PVOID)((UINT_PTR)Owner | 3);
ExSetResourceOwnerPointer(&FsvolDeviceExtension->FileRenameResource, Owner);
}
static inline
VOID FspFsvolDeviceFileRenameRelease(PDEVICE_OBJECT DeviceObject)
{
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(DeviceObject);
ExReleaseResourceLite(&FsvolDeviceExtension->FileRenameResource);
}
static inline
VOID FspFsvolDeviceFileRenameReleaseOwner(PDEVICE_OBJECT DeviceObject, PVOID Owner)
{
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(DeviceObject);
Owner = (PVOID)((UINT_PTR)Owner | 3);
if (ExIsResourceAcquiredLite(&FsvolDeviceExtension->FileRenameResource))
ExReleaseResourceLite(&FsvolDeviceExtension->FileRenameResource);
else
ExReleaseResourceForThreadLite(&FsvolDeviceExtension->FileRenameResource, (ERESOURCE_THREAD)Owner);
}
static inline
BOOLEAN FspFsvolDeviceFileRenameIsAcquiredExclusive(PDEVICE_OBJECT DeviceObject)
{
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(DeviceObject);
return ExIsResourceAcquiredExclusiveLite(&FsvolDeviceExtension->FileRenameResource);
}
static inline
VOID FspFsvolDeviceLockContextTable(PDEVICE_OBJECT DeviceObject)
{
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(DeviceObject);
ExAcquireFastMutexUnsafe(&FsvolDeviceExtension->ContextTableMutex);
}
static inline
VOID FspFsvolDeviceUnlockContextTable(PDEVICE_OBJECT DeviceObject)
{
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(DeviceObject);
ExReleaseFastMutexUnsafe(&FsvolDeviceExtension->ContextTableMutex);
}
NTSTATUS FspFsvolDeviceCopyContextList(PDEVICE_OBJECT DeviceObject,
PVOID **PContexts, PULONG PContextCount);
NTSTATUS FspFsvolDeviceCopyContextByNameList(PDEVICE_OBJECT DeviceObject,
@ -1300,6 +1398,18 @@ VOID FspFsvolDeviceGetVolumeInfo(PDEVICE_OBJECT DeviceObject, FSP_FSCTL_VOLUME_I
BOOLEAN FspFsvolDeviceTryGetVolumeInfo(PDEVICE_OBJECT DeviceObject, FSP_FSCTL_VOLUME_INFO *VolumeInfo);
VOID FspFsvolDeviceSetVolumeInfo(PDEVICE_OBJECT DeviceObject, const FSP_FSCTL_VOLUME_INFO *VolumeInfo);
VOID FspFsvolDeviceInvalidateVolumeInfo(PDEVICE_OBJECT DeviceObject);
static inline
VOID FspFsvolDeviceLockVolumeNotify(PDEVICE_OBJECT DeviceObject)
{
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(DeviceObject);
ExAcquireFastMutexUnsafe(&FsvolDeviceExtension->VolumeNotifyMutex);
}
static inline
VOID FspFsvolDeviceUnlockVolumeNotify(PDEVICE_OBJECT DeviceObject)
{
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(DeviceObject);
ExReleaseFastMutexUnsafe(&FsvolDeviceExtension->VolumeNotifyMutex);
}
#if defined(FSP_CFG_REJECT_EARLY_IRP)
static inline
BOOLEAN FspFsvolDeviceReadyToAcceptIrp(PDEVICE_OBJECT DeviceObject)
@ -1324,6 +1434,18 @@ BOOLEAN FspFsvolDeviceVolumePrefixInString(PDEVICE_OBJECT DeviceObject, PUNICODE
return RtlPrefixUnicodeString(&FspFsvolDeviceExtension(DeviceObject)->VolumePrefix, String,
TRUE);
}
static inline
VOID FspFsmupDeviceLockPrefixTable(PDEVICE_OBJECT DeviceObject)
{
FSP_FSMUP_DEVICE_EXTENSION *FsmupDeviceExtension = FspFsmupDeviceExtension(DeviceObject);
ExAcquireFastMutexUnsafe(&FsmupDeviceExtension->PrefixTableMutex);
}
static inline
VOID FspFsmupDeviceUnlockPrefixTable(PDEVICE_OBJECT DeviceObject)
{
FSP_FSMUP_DEVICE_EXTENSION *FsmupDeviceExtension = FspFsmupDeviceExtension(DeviceObject);
ExReleaseFastMutexUnsafe(&FsmupDeviceExtension->PrefixTableMutex);
}
NTSTATUS FspDeviceCopyList(
PDEVICE_OBJECT **PDeviceObjects, PULONG PDeviceObjectCount);
VOID FspDeviceDeleteList(
@ -1338,14 +1460,14 @@ VOID FspDeviceStopTimer(PDEVICE_OBJECT DeviceObject);
static inline
VOID FspDeviceGlobalLock(VOID)
{
extern ERESOURCE FspDeviceGlobalResource;
ExAcquireResourceExclusiveLite(&FspDeviceGlobalResource, TRUE);
extern FAST_MUTEX FspDeviceGlobalMutex;
ExAcquireFastMutexUnsafe(&FspDeviceGlobalMutex);
}
static inline
VOID FspDeviceGlobalUnlock(VOID)
{
extern ERESOURCE FspDeviceGlobalResource;
ExReleaseResourceLite(&FspDeviceGlobalResource);
extern FAST_MUTEX FspDeviceGlobalMutex;
ExReleaseFastMutexUnsafe(&FspDeviceGlobalMutex);
}
#define FspFsvolDeviceStatistics(DeviceObject)\
FspStatistics(FspFsvolDeviceExtension(DeviceObject)->Statistics)
@ -1486,7 +1608,7 @@ typedef struct FSP_FILE_NODE
/* interlocked access */
LONG RefCount;
UINT32 DeletePending;
/* locked under FSP_FSVOL_DEVICE_EXTENSION::ContextTableResource */
/* locked under FSP_FSVOL_DEVICE_EXTENSION::ContextTableMutex */
LONG ActiveCount; /* CREATE w/o CLOSE count */
LONG OpenCount; /* ContextTable ref count */
LONG HandleCount; /* HANDLE count (CREATE/CLEANUP) */
@ -1850,7 +1972,7 @@ extern FAST_IO_DISPATCH FspFastIoDispatch;
extern CACHE_MANAGER_CALLBACKS FspCacheManagerCallbacks;
extern FSP_IOPREP_DISPATCH *FspIopPrepareFunction[];
extern FSP_IOCMPL_DISPATCH *FspIopCompleteFunction[];
extern ERESOURCE FspDeviceGlobalResource;
extern FAST_MUTEX FspDeviceGlobalMutex;
extern WCHAR FspFileDescDirectoryPatternMatchAll[];
extern const GUID FspMainFileOpenEcpGuid;
extern ULONG FspProcessorCount;

View File

@ -121,7 +121,7 @@ NTSTATUS FspMupRegister(
Class->Name.Buffer = Class->Buffer;
RtlCopyMemory(Class->Buffer, ClassName.Buffer, ClassName.Length);
ExAcquireResourceExclusiveLite(&FsmupDeviceExtension->PrefixTableResource, TRUE);
FspFsmupDeviceLockPrefixTable(FsmupDeviceObject);
Success = RtlInsertUnicodePrefix(&FsmupDeviceExtension->PrefixTable,
&FsvolDeviceExtension->VolumePrefix, &FsvolDeviceExtension->VolumePrefixEntry);
if (Success)
@ -144,7 +144,7 @@ NTSTATUS FspMupRegister(
}
else
Result = STATUS_OBJECT_NAME_COLLISION;
ExReleaseResourceLite(&FsmupDeviceExtension->PrefixTableResource);
FspFsmupDeviceUnlockPrefixTable(FsmupDeviceObject);
exit:
if (0 != Class)
@ -169,7 +169,7 @@ VOID FspMupUnregister(
Result = FspMupGetClassName(&FsvolDeviceExtension->VolumePrefix, &ClassName);
ASSERT(NT_SUCCESS(Result));
ExAcquireResourceExclusiveLite(&FsmupDeviceExtension->PrefixTableResource, TRUE);
FspFsmupDeviceLockPrefixTable(FsmupDeviceObject);
PrefixEntry = RtlFindUnicodePrefix(&FsmupDeviceExtension->PrefixTable,
&FsvolDeviceExtension->VolumePrefix, 0);
if (0 != PrefixEntry)
@ -191,7 +191,7 @@ VOID FspMupUnregister(
}
}
}
ExReleaseResourceLite(&FsmupDeviceExtension->PrefixTableResource);
FspFsmupDeviceUnlockPrefixTable(FsmupDeviceObject);
}
PDEVICE_OBJECT FspMupGetFsvolDeviceObject(
@ -253,7 +253,7 @@ NTSTATUS FspMupHandleIrp(
if (0 != FileObject->RelatedFileObject)
FileObject = FileObject->RelatedFileObject;
ExAcquireResourceExclusiveLite(&FsmupDeviceExtension->PrefixTableResource, TRUE);
FspFsmupDeviceLockPrefixTable(FsmupDeviceObject);
PrefixEntry = RtlFindUnicodePrefix(&FsmupDeviceExtension->PrefixTable,
&FileObject->FileName, 0);
if (0 != PrefixEntry)
@ -263,7 +263,7 @@ NTSTATUS FspMupHandleIrp(
FspDeviceReference(FsvolDeviceObject);
DeviceDeref = TRUE;
}
ExReleaseResourceLite(&FsmupDeviceExtension->PrefixTableResource);
FspFsmupDeviceUnlockPrefixTable(FsmupDeviceObject);
break;
case IRP_MJ_DEVICE_CONTROL:
@ -419,19 +419,19 @@ static NTSTATUS FspMupRedirQueryPathEx(
return STATUS_BAD_NETWORK_PATH;
Result = STATUS_BAD_NETWORK_PATH;
ExAcquireResourceExclusiveLite(&FsmupDeviceExtension->PrefixTableResource, TRUE);
FspFsmupDeviceLockPrefixTable(FsmupDeviceObject);
Entry = RtlFindUnicodePrefix(&FsmupDeviceExtension->ClassTable, &ClassName, 0);
if (0 != Entry)
{
QueryPathResponse->LengthAccepted = ClassName.Length;
Result = STATUS_SUCCESS;
}
ExReleaseResourceLite(&FsmupDeviceExtension->PrefixTableResource);
FspFsmupDeviceUnlockPrefixTable(FsmupDeviceObject);
#else
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension;
Result = STATUS_BAD_NETWORK_PATH;
ExAcquireResourceExclusiveLite(&FsmupDeviceExtension->PrefixTableResource, TRUE);
FspFsmupDeviceLockPrefixTable(FsmupDeviceObject);
Entry = RtlFindUnicodePrefix(&FsmupDeviceExtension->PrefixTable,
&QueryPathRequest->PathName, 0);
if (0 != Entry)
@ -450,7 +450,7 @@ static NTSTATUS FspMupRedirQueryPathEx(
}
}
}
ExReleaseResourceLite(&FsmupDeviceExtension->PrefixTableResource);
FspFsmupDeviceUnlockPrefixTable(FsmupDeviceObject);
#endif
return Result;

View File

@ -131,6 +131,10 @@ NTSTATUS FspIrpHook(PIRP Irp, PIO_COMPLETION_ROUTINE CompletionRoutine, PVOID Ow
VOID FspIrpHookReset(PIRP Irp);
PVOID FspIrpHookContext(PVOID Context);
NTSTATUS FspIrpHookNext(PDEVICE_OBJECT DeviceObject, PIRP Irp, PVOID Context);
LONG FspCompareUnicodeString(
PCUNICODE_STRING String1,
PCUNICODE_STRING String2,
BOOLEAN CaseInsensitive);
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, FspIsNtDdiVersionAvailable)
@ -174,6 +178,7 @@ NTSTATUS FspIrpHookNext(PDEVICE_OBJECT DeviceObject, PIRP Irp, PVOID Context);
#pragma alloc_text(PAGE, FspSafeMdlDelete)
#pragma alloc_text(PAGE, FspIrpHook)
#pragma alloc_text(PAGE, FspIrpHookReset)
#pragma alloc_text(PAGE, FspCompareUnicodeString)
#endif
static const LONG Delays[] =
@ -1493,3 +1498,82 @@ NTSTATUS FspIrpHookNext(PDEVICE_OBJECT DeviceObject, PIRP Irp, PVOID Context)
return Result;
}
static inline
USHORT FspUpcaseAscii(USHORT c)
{
/*
* Bit-twiddling upper case char:
*
* - Let signbit(x) = x & 0x100 (treat bit 0x100 as "signbit").
* - 'A' <= c && c <= 'Z' <=> s = signbit(c - 'A') ^ signbit(c - ('Z' + 1)) == 1
* - c >= 'A' <=> c - 'A' >= 0 <=> signbit(c - 'A') = 0
* - c <= 'Z' <=> c - ('Z' + 1) < 0 <=> signbit(c - ('Z' + 1)) = 1
* - Bit 0x20 = 0x100 >> 3 toggles uppercase to lowercase and vice-versa.
*
* This is actually faster than `(c - 'a' <= 'z' - 'a') ? (c & ~0x20) : c`, even
* when compiled using cmov conditional moves at least on this system (i7-1065G7).
*
* See https://godbolt.org/z/ebv131Wrh
*/
USHORT s = ((c - 'a') ^ (c - ('z' + 1))) & 0x100;
return c & ~(s >> 3);
}
#if DBG
static
LONG FspCompareUnicodeStringReal(
PCUNICODE_STRING S1,
PCUNICODE_STRING S2,
BOOLEAN CaseInsensitive)
#else
LONG FspCompareUnicodeString(
PCUNICODE_STRING S1,
PCUNICODE_STRING S2,
BOOLEAN CaseInsensitive)
#endif
{
PAGED_CODE();
LONG LResult = S1->Length - S2->Length;
PWCH P1 = S1->Buffer;
PWCH P2 = S2->Buffer;
PWCH EndP1 = P1 + (0 >= LResult ? S1->Length : S2->Length) / sizeof(WCHAR);
if (CaseInsensitive)
{
for (; EndP1 != P1; ++P1, ++P2)
{
USHORT C1 = *P1, C2 = *P2;
if (0xff80 & (C1 | C2))
return RtlCompareUnicodeString(S1, S2, TRUE);
C1 = FspUpcaseAscii(C1);
C2 = FspUpcaseAscii(C2);
if (C1 != C2)
return C1 - C2;
}
}
else
{
for (; EndP1 != P1; ++P1, ++P2)
{
USHORT C1 = *P1, C2 = *P2;
if (C1 != C2)
return C1 - C2;
}
}
return LResult;
}
#if DBG
LONG FspCompareUnicodeString(
PCUNICODE_STRING S1,
PCUNICODE_STRING S2,
BOOLEAN CaseInsensitive)
{
LONG Result0 = FspCompareUnicodeStringReal(S1, S2, CaseInsensitive);
LONG Result1 = RtlCompareUnicodeString(S1, S2, CaseInsensitive);
ASSERT((0 < Result0) - (0 > Result0) == (0 < Result1) - (0 > Result1));
return Result0;
}
#endif

View File

@ -369,6 +369,9 @@ VOID FspVolumeDelete(
ULONG FileNodeCount, Index;
NTSTATUS Result;
FspFsvolDeviceVolumeDeleteAcquireExclusive(FsvolDeviceObject);
FsvolDeviceExtension->VolumeDeleted = TRUE;
/*
* If we have an fsvrt that is a mountdev, finalize it now! Finalizing a mountdev
* involves interaction with the MountManager, which tries to open our devices.
@ -403,6 +406,8 @@ VOID FspVolumeDelete(
FspFileNodeDeleteList(FileNodes, FileNodeCount);
}
FspFsvolDeviceVolumeDeleteRelease(FsvolDeviceObject);
FspDeviceDereference(FsvolDeviceObject);
}
@ -417,7 +422,6 @@ static VOID FspVolumeDeleteNoLock(
PDEVICE_OBJECT FsvolDeviceObject = IrpSp->FileObject->FsContext2;
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(FsvolDeviceObject);
IrpSp->FileObject->FsContext2 = 0;
/* stop the I/O queue */
FspIoqStop(FsvolDeviceExtension->Ioq, TRUE);
@ -486,12 +490,12 @@ static VOID FspVolumeDeleteNoLock(
FspMupUnregister(Globals->FsmupDeviceObject, FsvolDeviceObject);
}
ExAcquireFastMutex(&FsvolDeviceExtension->VolumeNotifyMutex);
FspFsvolDeviceLockVolumeNotify(FsvolDeviceObject);
if (1 <= FsvolDeviceExtension->VolumeNotifyCount)
FspFsvolDeviceFileRenameReleaseOwner(FsvolDeviceObject,
&FsvolDeviceExtension->VolumeNotifyCount);
FsvolDeviceExtension->VolumeNotifyCount = -1;
ExReleaseFastMutex(&FsvolDeviceExtension->VolumeNotifyMutex);
FspFsvolDeviceUnlockVolumeNotify(FsvolDeviceObject);
/* release the volume device object */
FspDeviceDereference(FsvolDeviceObject);
@ -1185,6 +1189,13 @@ NTSTATUS FspVolumeNotify(
if (!FspDeviceReference(FsvolDeviceObject))
return STATUS_CANCELLED;
FspFsvolDeviceVolumeDeleteAcquireShared(FsvolDeviceObject);
if (FspFsvolDeviceExtension(FsvolDeviceObject)->VolumeDeleted)
{
Result = STATUS_CANCELLED;
goto fail;
}
NotifyWorkItem = FspAllocNonPaged(
FIELD_OFFSET(FSP_VOLUME_NOTIFY_WORK_ITEM, InputBuffer) + InputBufferLength);
if (0 == NotifyWorkItem)
@ -1206,6 +1217,8 @@ NTSTATUS FspVolumeNotify(
goto fail;
}
FspFsvolDeviceVolumeDeleteSetOwner(FsvolDeviceObject, NotifyWorkItem);
ExInitializeWorkItem(&NotifyWorkItem->WorkItem, FspVolumeNotifyWork, NotifyWorkItem);
NotifyWorkItem->FsvolDeviceObject = FsvolDeviceObject;
@ -1217,6 +1230,8 @@ fail:
if (0 != NotifyWorkItem)
FspFree(NotifyWorkItem);
FspFsvolDeviceVolumeDeleteRelease(FsvolDeviceObject);
FspDeviceDereference(FsvolDeviceObject);
return Result;
@ -1242,7 +1257,7 @@ static NTSTATUS FspVolumeNotifyLock(
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(FsvolDeviceObject);
NTSTATUS Result = STATUS_SUCCESS;
ExAcquireFastMutex(&FsvolDeviceExtension->VolumeNotifyMutex);
FspFsvolDeviceLockVolumeNotify(FsvolDeviceObject);
if (0 == FsvolDeviceExtension->VolumeNotifyCount)
{
if (FspFsvolDeviceFileRenameTryAcquireShared(FsvolDeviceObject))
@ -1256,7 +1271,7 @@ static NTSTATUS FspVolumeNotifyLock(
}
else if (0 < FsvolDeviceExtension->VolumeNotifyCount)
FsvolDeviceExtension->VolumeNotifyCount++;
ExReleaseFastMutex(&FsvolDeviceExtension->VolumeNotifyMutex);
FspFsvolDeviceUnlockVolumeNotify(FsvolDeviceObject);
FspDeviceDereference(FsvolDeviceObject);
@ -1354,7 +1369,7 @@ static VOID FspVolumeNotifyWork(PVOID NotifyWorkItem0)
if (Unlock)
{
ExAcquireFastMutex(&FsvolDeviceExtension->VolumeNotifyMutex);
FspFsvolDeviceLockVolumeNotify(FsvolDeviceObject);
if (1 == FsvolDeviceExtension->VolumeNotifyCount)
{
FspFsvolDeviceFileRenameReleaseOwner(FsvolDeviceObject,
@ -1363,9 +1378,11 @@ static VOID FspVolumeNotifyWork(PVOID NotifyWorkItem0)
}
else if (1 < FsvolDeviceExtension->VolumeNotifyCount)
FsvolDeviceExtension->VolumeNotifyCount--;
ExReleaseFastMutex(&FsvolDeviceExtension->VolumeNotifyMutex);
FspFsvolDeviceUnlockVolumeNotify(FsvolDeviceObject);
}
FspFsvolDeviceVolumeDeleteReleaseOwner(FsvolDeviceObject, NotifyWorkItem);
FspDeviceDereference(FsvolDeviceObject);
FsRtlExitFileSystem();

View File

@ -21,6 +21,11 @@ set ntptfs="%ProjRoot%\tst\ntptfs\build\Release\ntptfs-x64.exe"
if not exist %memfs% echo cannot find memfs >&2 & goto fail
if not exist %ntptfs% echo cannot find ntptfs >&2 & goto fail
fsutil 8dot3name query C:
echo:
echo Performing performance testing...
mkdir C:\t
pushd C:\t
for /l %%i in (1,1,%Count%) do (

View File

@ -30,25 +30,33 @@ pushd fsbench
set OptFiles=1000 2000 3000 4000 5000
if X%2==Xbaseline set OptFiles=10000
for %%a in (%OptFiles%) do (
call :csv %%a "%fsbench% --empty-cache --files=%%a file_*"
call :csv "" %%a "%fsbench% --empty-cache=C --files=%%a --open=1 file_*"
)
%fsbench% --empty-cache=C --files=1000 file_create_test >nul
set OptOpen=10 20 30 40 50
if X%2==Xbaseline set OptOpen=100
for %%a in (%OptOpen%) do (
call :csv "iter." %%a "%fsbench% --empty-cache=C --files=1000 --open=%%a file_open_test file_attr_test file_list_single_test file_list_none_test"
)
%fsbench% --empty-cache=C --files=1000 file_delete_test >nul
set OptRdwrCc=100 200 300 400 500
if X%2==Xbaseline set OptRdwrCc=1000
for %%a in (%OptRdwrCc%) do (
call :csv %%a "%fsbench% --empty-cache --rdwr-cc=%%a rdwr_cc_*"
call :csv "" %%a "%fsbench% --empty-cache=C --rdwr-cc=%%a rdwr_cc_*"
)
set OptRdwrNc=100 200 300 400 500
if X%2==Xbaseline set OptRdwrNc=100
for %%a in (%OptRdwrNc%) do (
call :csv %%a "%fsbench% --empty-cache --rdwr-nc=%%a rdwr_nc_*"
call :csv "" %%a "%fsbench% --empty-cache=C --rdwr-nc=%%a rdwr_nc_*"
)
set OptMmap=100 200 300 400 500
if X%2==Xbaseline set OptMmap=1000
for %%a in (%OptMmap%) do (
call :csv %%a "%fsbench% --empty-cache --mmap=%%a mmap_*"
call :csv "" %%a "%fsbench% --empty-cache=C --mmap=%%a mmap_*"
)
popd
@ -66,15 +74,16 @@ exit /b 0
exit /b 1
:csv
set Iter=%1
for /F "tokens=1,2,3" %%i in ('%2') do (
set Prfx=%~1
set Iter=%2
for /F "tokens=1,2,3" %%i in ('%3') do (
if %%j==OK (
set Name=%%i
set Name=!Name:.=!
set Time=%%k
set Time=!Time:s=!
echo !Name!,!Iter!,!Time!
echo !Prfx!!Name!,!Iter!,!Time!
)
)
exit /b 0

View File

@ -24,7 +24,9 @@
#include <tlib/testsuite.h>
static BOOLEAN OptEmptyCache = FALSE;
static CHAR OptEmptyCacheDrive = 0;
static ULONG OptFileCount = 1000;
static ULONG OptOpenCount = 10;
static ULONG OptListCount = 100;
static ULONG OptRdwrFileSize = 4096 * 1024;
static ULONG OptRdwrCcCount = 100;
@ -32,12 +34,13 @@ static ULONG OptRdwrNcCount = 100;
static ULONG OptMmapFileSize = 4096 * 1024;
static ULONG OptMmapCount = 100;
static void file_create_dotest(ULONG CreateDisposition)
static void file_create_dotest(ULONG CreateDisposition, ULONG OpenCount)
{
HANDLE Handle;
BOOL Success;
WCHAR FileName[MAX_PATH];
for (ULONG OpenIndex = 0; OpenCount > OpenIndex; OpenIndex++)
for (ULONG Index = 0; OptFileCount > Index; Index++)
{
StringCbPrintfW(FileName, sizeof FileName, L"fsbench-file%lu", Index);
@ -53,22 +56,22 @@ static void file_create_dotest(ULONG CreateDisposition)
}
static void file_create_test(void)
{
file_create_dotest(CREATE_NEW);
file_create_dotest(CREATE_NEW, 1);
}
static void file_open_test(void)
{
file_create_dotest(OPEN_EXISTING);
file_create_dotest(OPEN_EXISTING, OptOpenCount);
}
static void file_overwrite_test(void)
{
file_create_dotest(CREATE_ALWAYS);
file_create_dotest(CREATE_ALWAYS, 1);
}
static void file_attr_test(void)
{
WCHAR FileName[MAX_PATH];
DWORD FileAttributes;
for (ULONG ListIndex = 0; OptListCount > ListIndex; ListIndex++)
for (ULONG OpenIndex = 0; OptOpenCount > OpenIndex; OpenIndex++)
for (ULONG Index = 0; OptFileCount > Index; Index++)
{
StringCbPrintfW(FileName, sizeof FileName, L"fsbench-file%lu", Index);
@ -100,7 +103,7 @@ static void file_list_single_test(void)
WCHAR FileName[MAX_PATH];
WIN32_FIND_DATAW FindData;
for (ULONG ListIndex = 0; OptListCount > ListIndex; ListIndex++)
for (ULONG OpenIndex = 0; OptOpenCount > OpenIndex; OpenIndex++)
for (ULONG Index = 0; OptFileCount > Index; Index++)
{
StringCbPrintfW(FileName, sizeof FileName, L"fsbench-file%lu", Index);
@ -119,7 +122,7 @@ static void file_list_none_test(void)
WCHAR FileName[MAX_PATH];
WIN32_FIND_DATAW FindData;
for (ULONG ListIndex = 0; OptListCount > ListIndex; ListIndex++)
for (ULONG OpenIndex = 0; OptOpenCount > OpenIndex; OpenIndex++)
for (ULONG Index = 0; OptFileCount > Index; Index++)
{
StringCbPrintfW(FileName, sizeof FileName, L"{5F849D7F-73AF-49AC-B7C3-657B36EAD5C4}");
@ -418,6 +421,17 @@ static void EmptyCache(const char *name, void (*fn)(void), int v)
ASSERT(0 == NtSetSystemInformation(80 /*SystemMemoryListInformation*/, &Command, sizeof Command));
Command = 4 /*MemoryPurgeStandbyList*/;
ASSERT(0 == NtSetSystemInformation(80 /*SystemMemoryListInformation*/, &Command, sizeof Command));
/* optionally invalidate the volume cache; see https://stackoverflow.com/a/7701908/568557 */
if (OptEmptyCacheDrive)
{
WCHAR VolumeNameBuf[] = L"\\\\.\\X:";
HANDLE VolumeHandle;
VolumeNameBuf[4] = OptEmptyCacheDrive;
VolumeHandle = CreateFileW(VolumeNameBuf, FILE_READ_DATA, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
if (INVALID_HANDLE_VALUE != VolumeHandle)
CloseHandle(VolumeHandle);
}
}
else
if (-1 == v) /* teardown */
@ -478,11 +492,22 @@ int main(int argc, char *argv[])
OptEmptyCache = TRUE;
rmarg(argv, argc, argi);
}
else if (0 == strncmp("--empty-cache=", a, sizeof "--empty-cache=" - 1))
{
OptEmptyCache = TRUE;
OptEmptyCacheDrive = *(a + sizeof "--empty-cache=" - 1);
rmarg(argv, argc, argi);
}
else if (0 == strncmp("--files=", a, sizeof "--files=" - 1))
{
OptFileCount = strtoul(a + sizeof "--files=" - 1, 0, 10);
rmarg(argv, argc, argi);
}
else if (0 == strncmp("--open=", a, sizeof "--open=" - 1))
{
OptOpenCount = strtoul(a + sizeof "--open=" - 1, 0, 10);
rmarg(argv, argc, argi);
}
else if (0 == strncmp("--list=", a, sizeof "--list=" - 1))
{
OptListCount = strtoul(a + sizeof "--list=" - 1, 0, 10);