Skip to content

speed_patching

Nightinggale edited this page Dec 18, 2017 · 3 revisions

This is a guide on how to write fast running patch files. Using this guide will allow you to write patches, which can run potentially hundreds of times faster than what is being used in released mods a the time this was written.

A patch xml file with two additions for the same xml file will look like this:

<Patch>
    <Operation Class="PatchOperationAdd">
        <!-- some patching code -->
    </Operation>
    <Operation Class="PatchOperationAdd">
        <!-- some other patching code -->
    </Operation>
<Patch>

The patching engine will try to apply both PatchOperationAdd to every single xml file in Defs in every single mod, including Core. It works just fine because if the xpath search fails to find anything, nothing happens. The problem is that it searches lots of xml files for no reason and it's dead slow.

What is needed is a way to skip searching when the patch writer know it will fail anyway. Introducing PatchOperationSequence from vanilla. It's used like this:

<Patch>
    <Operation Class="PatchOperationSequence">
        <success>Always</success>
        <operations>
            <li Class="PatchOperationAdd">
                <!-- some patching code -->
            </li>
            <li Class="PatchOperationAdd">
                <!-- some other patching code -->
            </li>
        </operations>
    </Operation>
<Patch>

It's mostly the same code. However the difference is that a sequence listens to each operation result and if it fails, it stops the sequence. This mean it will use the fact that if the first fails, the patch writer knows that the second will fail too and it's not applied. This will effectively make the patch run twice as fast because most time is spend on "wrong" files.

However it can be much faster than that. ModCheck 1.6 introduces ModCheck.FindFile. Using it will look like this:

<Patch>
    <Operation Class="PatchOperationSequence">
        <success>Always</success>
        <operations>
            <li Class="ModCheck.FindFile">
                <modName>Core</modName>
                <file>Items_Food.xml</file>
            </li>
            <li Class="PatchOperationAdd">
                <!-- some patching code -->
            </li>
            <li Class="PatchOperationAdd">
                <!-- some other patching code -->
            </li>
        </operations>
    </Operation>
<Patch>

Now it's ModCheck.FindFile, which is in charge of rejecting the wrong xml files. Usage is simple. Just write modName and file for the xml data you plan to patch. This simplification of comparisons combined with highly optimized code will make this approach much faster. One profiling result indicates around 800 times faster than xpath searches when it comes to rejecting wrong files and that's an average and using an optimized xpath search.

FindFile vs isModLoaded

If you can use FindFile, do not use isModLoaded as the same time. Obviously if modName is correct, the mod is loaded. This mean isModLoaded will just become overhead and not do anything.

Clone this wiki locally