Skip to content

Commit

Permalink
Perf: Enable CGRF caching for all loaded resources
Browse files Browse the repository at this point in the history
All fetch requests should go through the unified resources API, so at the end of the day this should speed up the one major bottleneck (decoding the table of contents) that exists.
  • Loading branch information
rdw-software committed Feb 6, 2024
1 parent c929e4c commit aedadc4
Show file tree
Hide file tree
Showing 2 changed files with 66 additions and 2 deletions.
23 changes: 22 additions & 1 deletion Core/NativeClient/C_Resources.lua
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
local CompiledGRF = require("Core.FileFormats.Optimized.CompiledGRF")
local FogParameters = require("Core.FileFormats.FogParameters")
local RagnarokGRF = require("Core.FileFormats.RagnarokGRF")

Expand All @@ -8,13 +9,33 @@ local C_Resources = {
["data/sprite/cursors.spr"] = false,
["data/fogparametertable.txt"] = FogParameters,
},
ENABLE_CGRF_CACHING = true,
}

local self = C_Resources

function C_Resources.PreloadPersistentResources()
local grfFilePath = self.GRF_FILE_PATH

local hasUpdatedCacheEntry = self.ENABLE_CGRF_CACHING and CompiledGRF:IsCacheUpdated(grfFilePath) or false
local grfName = path.basename(grfFilePath, path.extname(grfFilePath))
local cgrfFilePath = path.join(CompiledGRF.CGRF_CACHE_DIRECTORY, grfName .. ".cgrf")

local cgrfFileContents
if hasUpdatedCacheEntry then
printf("CGRF_CACHE_HIT: %s (Restoring table of contents)", cgrfFilePath)
cgrfFileContents = C_FileSystem.ReadFile(cgrfFilePath)
end

local grf = RagnarokGRF()
grf:Open(self.GRF_FILE_PATH)
grf:Open(self.GRF_FILE_PATH, cgrfFileContents)

local needsCacheWrite = self.ENABLE_CGRF_CACHING and not hasUpdatedCacheEntry
if needsCacheWrite then
cgrfFileContents = CompiledGRF:CompileTableOfContents(grf)
printf("CGRF_CACHE_WRITE: %s (%s)", cgrfFilePath, string.filesize(#cgrfFileContents))
C_FileSystem.WriteFile(cgrfFilePath, cgrfFileContents)
end

printf("Preloading %d persistent resources from %s", table.count(self.PERSISTENT_RESOURCES), self.GRF_FILE_PATH)
for filePath, decoder in pairs(self.PERSISTENT_RESOURCES) do
Expand Down
45 changes: 44 additions & 1 deletion Tests/NativeClient/C_Resources.spec.lua
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
local CompiledGRF = require("Core.FileFormats.Optimized.CompiledGRF")
local RagnarokGRF = require("Core.FileFormats.RagnarokGRF")

local C_Resources = require("Core.NativeClient.C_Resources")

local TEST_GRF_PATH = path.join("Tests", "Fixtures", "test.grf")

describe("C_Resources", function()
describe("PreloadPersistentResources", function()
local DEFAULT_GRF_PATH = C_Resources.GRF_FILE_PATH
Expand All @@ -14,6 +17,7 @@ describe("C_Resources", function()

it("should throw if the configured asset container doesn't exist", function()
local function preloadFromNonExistingGRF()
C_Resources.ENABLE_CGRF_CACHING = false -- Cache access would throw
C_Resources.GRF_FILE_PATH = "invalid.grf"
C_Resources.PreloadPersistentResources()
end
Expand All @@ -32,7 +36,7 @@ describe("C_Resources", function()
end)

it("should load and store all persistent resources from the configured asset container", function()
C_Resources.GRF_FILE_PATH = path.join("Tests", "Fixtures", "test.grf")
C_Resources.GRF_FILE_PATH = TEST_GRF_PATH
C_Resources.PERSISTENT_RESOURCES = {
["hello-grf.txt"] = false,
["subdirectory/hello.txt"] = false,
Expand Down Expand Up @@ -98,5 +102,44 @@ describe("C_Resources", function()
local preloadedAssetFiles = C_Resources.PERSISTENT_RESOURCES
assertEquals(preloadedAssetFiles["uppercase.png"], expectedFileContents["uppercase.png"])
end)

it("should generate a CGRF cache entry after loading the configured asset container", function()
C_Resources.ENABLE_CGRF_CACHING = true
C_Resources.GRF_FILE_PATH = TEST_GRF_PATH
C_Resources.PERSISTENT_RESOURCES = {}
C_Resources.PreloadPersistentResources()

local cgrfFilePath = path.join("Tests", "Fixtures", "test.cgrf")
local expectedFileContents = C_FileSystem.ReadFile(cgrfFilePath)

-- Creating a new cache entry manually should ensure it's considered up-to-date
local cacheEntryPath = path.join(CompiledGRF.CGRF_CACHE_DIRECTORY, "test.cgrf")
local cgrfFileContents = C_FileSystem.ReadFile(cacheEntryPath)

C_FileSystem.Delete(cacheEntryPath)

assertEquals(cgrfFileContents, expectedFileContents)
end)

it("should use an existing CGRF cache entry if it exists and is still up-to-date", function()
-- Assumes that the fixture's CGRF is always more recent than the GRF itself
-- This should always be the case as it's regenerated from the GRF after each format change
local cgrfFilePath = path.join("Tests", "Fixtures", "test.cgrf")
local cgrfFileContents = C_FileSystem.ReadFile(cgrfFilePath)

-- Creating a new cache entry manually should ensure it's considered up-to-date
local cacheEntryPath = path.join(CompiledGRF.CGRF_CACHE_DIRECTORY, "test.cgrf")
C_FileSystem.WriteFile(cacheEntryPath, cgrfFileContents)

C_Resources.ENABLE_CGRF_CACHING = true
C_Resources.GRF_FILE_PATH = TEST_GRF_PATH
C_Resources.PERSISTENT_RESOURCES = {}
C_Resources.PreloadPersistentResources()

C_FileSystem.Delete(cacheEntryPath)

assertEquals(C_Resources.grf.fileTable.compressedSizeInBytes, 0)
assertEquals(C_Resources.grf.fileTable.decompressedSizeInBytes, 0)
end)
end)
end)

0 comments on commit aedadc4

Please sign in to comment.