{"id":13578683,"url":"https://github.com/Overv/vramfs","last_synced_at":"2025-04-05T19:33:28.038Z","repository":{"id":22738549,"uuid":"26083608","full_name":"Overv/vramfs","owner":"Overv","description":"VRAM based file system for Linux","archived":false,"fork":false,"pushed_at":"2023-11-06T13:32:15.000Z","size":458,"stargazers_count":1377,"open_issues_count":16,"forks_count":69,"subscribers_count":38,"default_branch":"master","last_synced_at":"2025-04-01T13:04:49.550Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Overv.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2014-11-02T15:01:47.000Z","updated_at":"2025-04-01T10:02:08.000Z","dependencies_parsed_at":"2024-01-13T16:52:01.482Z","dependency_job_id":"a828b688-102e-4a5a-9cc5-e94758f2c748","html_url":"https://github.com/Overv/vramfs","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Overv%2Fvramfs","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Overv%2Fvramfs/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Overv%2Fvramfs/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Overv%2Fvramfs/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Overv","download_url":"https://codeload.github.com/Overv/vramfs/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247393095,"owners_count":20931804,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-08-01T15:01:32.883Z","updated_at":"2025-04-05T19:33:27.070Z","avatar_url":"https://github.com/Overv.png","language":"C++","funding_links":[],"categories":["\u003ca name=\"cpp\"\u003e\u003c/a\u003eC++","C++"],"sub_categories":[],"readme":"vramfs\n======\n\nUnused RAM is wasted RAM, so why not put some of that VRAM in your graphics card\nto work?\n\nvramfs is a utility that uses the [FUSE library](http://fuse.sourceforge.net/)\nto create a file system in VRAM. The idea is pretty much the same as a ramdisk,\nexcept that it uses the video RAM of a discrete graphics card to store\nfiles. It is not intented for serious use, but it does actually work fairly\nwell, especially since consumer GPUs with 4GB or more VRAM are now available.\n\nOn the developer's system, the continuous read performance is ~2.4 GB/s and\nwrite performance 2.0 GB/s, which is about 1/3 of what is achievable with a\nramdisk. That is already decent enough for a device not designed for large data\ntransfers to the host, but future development should aim to get closer to the\nPCI-e bandwidth limits. See the *benchmarks* section for more info.\n\n#### Requirements\n\n- Linux with kernel 2.6+\n- FUSE development files\n- A graphics card with support for OpenCL 1.2\n\n#### Building\n\nFirst, install the OpenCL driver for your graphics card and verify that it's\nrecognized as an OpenCL device by running `clinfo`. Then install the `libfuse3-dev`\npackage or build it from source. You will also need `pkg-config` and OpenCL \ndevelopment files, (`opencl-dev`, `opencl-clhpp-headers` package or equivalent), \nwith version 1.2 of the OpenCL headers at least.\n\nJust run `make` to build `vramfs`.\n\nIf you want to debug with valgrind, you should compile with the minimal fake\nOpenCL implementation to avoid filling your screen with warnings caused by the\nOpenCL driver:\n\n* **valgrind:** `make DEBUG=1`\n\n#### Mounting\n\nMount a disk by running `bin/vramfs \u003cmountdir\u003e \u003csize\u003e`. The `mountdir` can be\nany empty directory. The `size` is the disk size in bytes. For more information,\nrun `bin/vramfs` without arguments.\n\nThe recommended maximum size of a vramdisk is 50% of your VRAM. If you go over\nthat, your driver or system may become unstable because it has to start\nswapping. For example, webpages in Chrome will stop rendering properly.\n\nIf the disk has been inactive for a while, the graphics card will likely lower\nits memory clock, which means it'll take a second to get up to speed again.\n\nImplementation\n--------------\n\nThe FUSE library is used to implement vramfs as a user space file system. This\neases development and makes working with APIs such as OpenCL straightforward.\n\n#### Basic architecture\n\n![Architecture overview](http://i.imgur.com/e8tQ168.png)\n\nWhen the program is started, it checks for an OpenCL capable GPU and attempts to\nallocate the specified amount of memory. Once the memory has been allocated, the\nroot entry object is created and a global reference to it is stored.\n\nFUSE then forwards calls like `stat`, `readdir` and `write` to the file system\nfunctions. These will then locate the entry through the root entry using the\nspecified path. The required operations will then be performed on the entry\nobject. If the entry is a file object, the operation may lead to OpenCL\n`cvEnqueueReadBuffer` or `cvEnqueueWriteBuffer` calls to manipulate the data.\n\nWhen a file is created or opened, a `file_session` object is created to store\nthe reference to the file object and any other data that is persistent between\nan `fopen` and `fclose` call.\n\n#### VRAM block allocation\n\nOpenCL is used to allocate blocks of memory on the graphics card by creating\nbuffer objects. When a new disk is mounted, a pool of `disk size / block size`\nbuffers is created and initialised with zeros. That is not just a good practice,\nbut it's also required with some OpenCL drivers to check if the VRAM required\nfor the block is actually available. Unfortunately Nvidia cards don't support\nOpenCL 1.2, which means the `cvEnqueueFillBuffer` call has to be simulated by\ncopying from a preallocated buffer filled with zeros. Somewhat interestingly, it\ndoesn't seem to make a difference in performance on cards that support both.\n\nWrites to blocks are generally asynchronous, whereas reads are synchronous.\nLuckily, OpenCL guarantees in-order execution of commands by default, which\nmeans reads of a block will wait for the writes to complete. OpenCL 1.1 is\ncompletely thread safe, so no special care is required when sending commands.\n\nBlock objects are managed using a `shared_ptr` so that they can automatically\nreinsert themselves into the pool on deconstruction.\n\n#### File system\n\nThe file system is a tree of `entry_t` objects with members for attributes like\nthe parent directory, mode and access time. Each type of entry has its own\nsubclass that derives from it: `file_t`, `dir_t` and `symlink_t`. The main file\nthat implements all of the FUSE callbacks has a permanent reference to the root\ndirectory entry.\n\nThe `file_t` class contains extra `write`, `read` and `size` methods and manages\nthe blocks to store the file data.\n\nThe `dir_t` class has an extra `unordered_map` that maps names to `entry_t`\nreferences for quick child lookup using its member function `find`.\n\nFinally, the `symlink_t` class has an extra `target` string member that stores\nthe pointer of the symlink.\n\nAll of the entry objects are also managed using `shared_ptr` so that an object\nand its data (e.g. file blocks) are automatically deallocated when they're\nunlinked and no process holds a file handle to them anymore. This can also be\nused to easily implement hard links later on.\n\nThe classes use getter/setter functions to automatically update the access,\nmodification and change times at the appropriate moment. For example, calling\nthe `children` member function of `dir_t` changes the access time and change\ntime of the directory.\n\n#### Thread safety\n\nUnfortunately most of the operations are not thread safe, so all of the FUSE\ncallbacks share a mutex to ensure that only one thread is mutating the file\nsystem at a time. The exceptions are `read` and `write`, which will temporarily\nrelease the lock while waiting for a read or write to complete.\n\nBenchmarks\n----------\n\nThe system used for testing has the following specifications:\n\n* **OS:** Ubuntu 14.04.01 LTS (64 bit)\n* **CPU:** Intel Core i5-2500K @ 4.0 Ghz\n* **RAM:** 8GB DDR3-1600\n* **GPU:** AMD R9 290 4GB (Sapphire Tri-X)\n\nPerformance of continuous read, write and write+sync has been measured for\ndifferent block allocation sizes by creating a new 2GiB disk for each new size\nand reading/writing a 2GiB file.\n\nThe disk is created using:\n\n    bin/vramfs /tmp/vram 2G\n\nAnd the file is written and read using the `dd` command:\n\n    # write\n    dd if=/dev/zero of=/tmp/vram/test bs=128K count=16000\n\n    # write+sync\n    dd if=/dev/zero of=/tmp/vram/test bs=128K count=16000 conv=fdatasync\n\n    # read\n    dd if=/tmp/vram/test of=/dev/null bs=128K count=16000\n\nThese commands were repeated 5 times for each block size and then averaged to\nproduce the results shown in the graph. No block sizes lower than 32KiB could\nbe tested because the driver would fail to allocate that many OpenCL buffers.\nThis may be solved in the future by using subbuffers.\n\n![Performance for different block sizes](http://i.imgur.com/93UNs1u.png)\n\nAlthough 128KiB blocks offers the highest performance, 64KiB may be preferable\nbecause of the lower space overhead.\n\nFuture ideas\n------------\n\n- Implement RAID-0 for SLI/Crossfire setups\n\nLicense\n-------\n\n    The MIT License (MIT)\n\n    Copyright (c) 2014 Alexander Overvoorde\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to\n    deal in the Software without restriction, including without limitation the\n    rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n    sell copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n    IN THE SOFTWARE.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FOverv%2Fvramfs","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FOverv%2Fvramfs","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FOverv%2Fvramfs/lists"}