goatcorp / FFXIVQuickLauncher

Custom launcher for FFXIV
https://goatcorp.github.io/
GNU General Public License v3.0
2.84k stars 330 forks source link

Improper Use of aria2 on SSDs #1632

Open Kobi-Blade opened 5 days ago

Kobi-Blade commented 5 days ago

Update disclaimer

What did you do?

I have noticed that the current implementation of aria2 in XIV Launcher does not utilize the --file-allocation=none parameter when running on SSD systems. This parameter is crucial for optimizing performance on SSDs, as it prevents unnecessary wear and tear caused by file allocation operations that are only beneficial on HDDs.

Steps to Reproduce:

Launch XIV Launcher on a system with an SSD.

Observe the file allocation behavior during game updates.

Expected Behavior: The --file-allocation=none parameter should be used to prevent unnecessary file allocation on SSDs.

Actual Behavior: File allocation is performed, which is unnecessary and can lead to increased wear on the SSD.

Platform

Windows

Wine/Proton runner version

No response

Relevant log output

2024-11-12 11:35:14.131590 [NOTICE] [HttpListenCommand.cc:108] IPv4 RPC: listening on TCP port 62813
2024-11-12 11:35:17.278317 [NOTICE] [SingleFileAllocationIterator.cc:77] Allocating disk space. Use --file-allocation=none to disable it. See --file-allocation option in man page for more details.
2024-11-12 11:35:18.071824 [NOTICE] [RequestGroup.cc:1216] Download complete: C:/Users/%username%/AppData/Roaming/XIVLauncher/patches/boot/2b5cbc63/D2024.11.01.0001.0001.patch
2024-11-12 11:35:35.403523 [NOTICE] [HttpListenCommand.cc:108] IPv4 RPC: listening on TCP port 62820
2024-11-12 11:35:38.416198 [NOTICE] [SingleFileAllocationIterator.cc:77] Allocating disk space. Use --file-allocation=none to disable it. See --file-allocation option in man page for more details.
Kobi-Blade commented 5 days ago

Adding to my original post, SSDs have a limited number of write cycles, and pre-allocating space means writing unnecessary data. By using the --file-allocation=none parameter, we can avoid these unnecessary writes and extend the lifespan of the SSD.

To detect if a system is using an SSD or HDD in C++, you can use the Windows API to query the drive type. Here's a sample code snippet that demonstrates how to do this:

#include <windows.h>
#include <string>
#include <cstdlib>

bool IsSSD(const std::wstring& drive) {
    HANDLE hDevice = CreateFileW((L"\\\\.\\" + drive).c_str(), 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
    if (hDevice == INVALID_HANDLE_VALUE) {
        return false;
    }

    STORAGE_PROPERTY_QUERY storagePropertyQuery;
    ZeroMemory(&storagePropertyQuery, sizeof(STORAGE_PROPERTY_QUERY));
    storagePropertyQuery.PropertyId = StorageDeviceSeekPenaltyProperty;
    storagePropertyQuery.QueryType = PropertyStandardQuery;

    DEVICE_SEEK_PENALTY_DESCRIPTOR seekPenaltyDescriptor;
    ZeroMemory(&seekPenaltyDescriptor, sizeof(DEVICE_SEEK_PENALTY_DESCRIPTOR));

    DWORD bytesReturned = 0;
    if (!DeviceIoControl(hDevice, IOCTL_STORAGE_QUERY_PROPERTY, &storagePropertyQuery, sizeof(STORAGE_PROPERTY_QUERY), &seekPenaltyDescriptor, sizeof(DEVICE_SEEK_PENALTY_DESCRIPTOR), &bytesReturned, NULL)) {
        CloseHandle(hDevice);
        return false;
    }

    CloseHandle(hDevice);
    return !seekPenaltyDescriptor.IncursSeekPenalty;
}

The snippet above checks if the specified drive (in this case, C:) is an SSD by querying the StorageDeviceSeekPenaltyProperty. SSDs do not incur a seek penalty, so if the IncursSeekPenalty property is false, the drive is an SSD.

reiichi001 commented 5 days ago

I know it's probably not your intention, but you don't need to explain SSD write cycles to us. Despite the FFXI themed raid getting people nostalgic, it's not the mid 2000s and the first post explaining that there's an argument we can supply to the binary was plenty.

But additionally, if patching FFXIV has you concerned about your disk's overall lifetime, there may be larger issues at play.

Adding a c++ binary to pinvoke to check the storage medium type would be excessive. Even something managed inside of dotnet like that detailed on < https://stackoverflow.com/a/76883160> would be. We can just add the argument.