Revision Difference
Filesystem#561687
<title>Filesystem</title>
This page will explain different things about Gmod's Filesystem.
<note>This page is still being worked and is currently unfinished</note>
# Searchpaths
The Filesystem uses search paths to find all necessary files.
A search path is just a normal path to a folder with a given name like `GAME`
You can add custom search paths by adding them to the `garrysmod/cfg/mount.cfg`
You can see all search paths <page text="here">File_Search_Paths</page> or you can print them with the `path` command.
The `LUA` search path is just a redirect to the `lsv`, `lsc` or `LuaMenu` search path depending on your <page text="Realm">States</page>.
## Search order
This is how the filesystem currently searches thru the `GAME` path:
- All `thirdparty` search paths (Including the `garrysmod/workshop` folder)
- `garrysmod/overrides/` folder
- `garrysmod/` folder
- `sourceengine/` folder
- `platform/` folder
- Mounted Games
- `garrysmod/download/` folder
- `garrysmod/fallbacks` folder
This is how the filesystem currently searches thru the `MOD` path:
- `garrysmod/overrides/` folder
- `garrysmod/` folder
- `garrysmod/fallbacks` folder
### garrysmod/overrides/
The overrides folder is used by some .vpk files, and it allows you to override the results of the filesystem.
This can be useful for this like this:
You can create the folder and copy the `lua` folder into it and for example edit the `menu.lua` file without having to worry about Steam deleting your changes.
<note>Creating the `garrysmod/overrides` folder can cause Issues with Gmod when you for example don't copy all Lua Files.</note>
### garrysmod/workshop/
The workshop folder only exists in the filesystem.
The workshop folder contains the content of all workshop addons that are mounted.
You could create it on your drive and mess with it, but you probably shouldn't. You could create it on your drive and mess with it, but you probably shouldn't. ⤶
⤶
# Performance⤶
The Performance of the filesystem can be different for everything. ⤶
Functions like <page>file.Exists</page>, <page>file.Open</page> and <page>file.Size</page> internally call `CBaseFileSystem::Open`. ⤶
And functions like <page>file.Time</page> and <page>file.IsDir</page> use their own code. ⤶
⤶
Your goal should always be to minimize the amount of search path searched. ⤶
For example, if you try to read `garrysmod.ver`, you could use the `GAME` path, but the `MOD` path would be far faster. ⤶
⤶
## file.Exists⤶
<page>file.Exists</page> for example tries to first open the file and if it can't open it, it checks if it's a directory. ⤶
Now, if you only need to check if the file exists, you should use <page>file.Open</page> because it skips the directory check. ⤶
⤶
## Opening files⤶
On Windows, the filesystem performance can be a bit different because of `filesystem_native`. ⤶
⤶
When opening a file while `filesystem_native` is set to `1` and the read mode is `rb` it will first try to use a `CWin32ReadOnlyFile` to open it. ⤶
If it fails, it tries to use a `CStdioFile` before finally returning. ⤶
⤶
The Issue with that is that it tries to open the same file two times. ⤶
The filesystem also tries to open the file for each search path, and because of that it can make a really noticeable difference if you disable `filesystem_native`. ⤶
Also, the more search paths you have, the bigger the performance improvement from disabling `filesystem_native` can be.⤶
⤶
<note>Functions like <page>file.Time</page> and <page>file.IsDir</page> are not affected by `filesystem_native`</note>⤶
<validate>What are the consequences of disabling `filesystem_native`?</validate>⤶
⤶
<example>⤶
<description>An Example of the Performance difference. Base Gmod with `-noaddons` and `-noworkshop`</description>⤶
<code>⤶
local function RunTest()⤶
for k=1, 100 do⤶
local f = file.Open("garrysmod.ver", "rb", "GAME")⤶
if f then⤶
f:Close()⤶
end⤶
end⤶
end⤶
⤶
RunConsoleCommand("filesystem_native", "1")⤶
timer.Create("fs_test", 0.1, 10, function()⤶
if !GetConVar("filesystem_native"):GetBool() then -- Wait for filesystem_native to be enabled⤶
return⤶
end⤶
⤶
local native_start = SysTime()⤶
RunTest()⤶
local native_end = SysTime()⤶
⤶
RunConsoleCommand("filesystem_native", "0")⤶
timer.Create("fs_test", 0.1, 10, function()⤶
if GetConVar("filesystem_native"):GetBool() then -- Wait for filesystem_native to be disabled⤶
return⤶
end⤶
⤶
local no_native_start = SysTime()⤶
RunTest()⤶
local no_native_end = SysTime()⤶
⤶
print("Native: " .. native_end - native_start)⤶
print("No Native: " .. no_native_end - no_native_start)⤶
⤶
timer.Remove("fs_test")⤶
end)⤶
end)⤶
</code>⤶
<output>⤶
```lua⤶
Native: 0.029838299999994⤶
No Native: 0.023882999999998⤶
``` ⤶
</output>⤶
</example>