Garry's Mod Wiki

Revision Difference

Filesystem#562968

<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/ ⤶ <removed>It seems like this search path was recently removed</removed>⤶ 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. # 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>