Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Optimization Handling (part 3) and Remove big use eVehicleTypes #3848

Merged
merged 31 commits into from
Dec 21, 2024

Conversation

G-Moris
Copy link
Contributor

@G-Moris G-Moris commented Nov 8, 2024

Continuation of PR - #3580;
Removed the frequent useless use of eVehicleTypes.

@Fernando-A-Rocha
Copy link
Contributor

Good initiative! 😀

@G-Moris
Copy link
Contributor Author

G-Moris commented Nov 9, 2024

@TracerDS Hello. Maybe I should add WriteDebugEvent to some events?

@TracerDS
Copy link
Contributor

TracerDS commented Nov 9, 2024

@TracerDS Hello. Maybe I should add WriteDebugEvent to some events?

what for

@G-Moris
Copy link
Contributor Author

G-Moris commented Nov 9, 2024

@TracerDS Hello. Maybe I should add WriteDebugEvent to some events?

what for

For try-catch

Example:

void CHandlingEntrySA::Recalculate() noexcept
{
    // Real GTA class?
    if (!m_HandlingSA)
        return;

    try
    {
        // Copy our stored field to GTA's
        memcpy(m_HandlingSA.get(), &m_Handling, sizeof(m_Handling));
        ((void(_stdcall*)(tHandlingDataSA*))FUNC_HandlingDataMgr_ConvertDataToGameUnits)(m_HandlingSA.get());
    }
    catch (...)
    {
        WriteDebugEvent("Failed recalculate vehicle handling!");
    }
}

@TracerDS
Copy link
Contributor

TracerDS commented Nov 9, 2024

@TracerDS Hello. Maybe I should add WriteDebugEvent to some events?

what for

For try-catch

Example:

void CHandlingEntrySA::Recalculate() noexcept
{
    // Real GTA class?
    if (!m_HandlingSA)
        return;

    try
    {
        // Copy our stored field to GTA's
        memcpy(m_HandlingSA.get(), &m_Handling, sizeof(m_Handling));
        ((void(_stdcall*)(tHandlingDataSA*))FUNC_HandlingDataMgr_ConvertDataToGameUnits)(m_HandlingSA.get());
    }
    catch (...)
    {
        WriteDebugEvent("Failed recalculate vehicle handling!");
    }
}

No need.
In this case that try catch is kinda meh. Only ConvertDataToGameUnits could potentially throw but judging from the name it shouldnt

@G-Moris
Copy link
Contributor Author

G-Moris commented Nov 9, 2024

@TracerDS Would it be worth making AddVehicle return std::unique_ptr?

@TracerDS
Copy link
Contributor

TracerDS commented Nov 9, 2024

@TracerDS Would it be worth making AddVehicle return std::unique_ptr?

if it returns raw pointer then yes

@G-Moris
Copy link
Contributor Author

G-Moris commented Nov 10, 2024

@TracerDS Do you like the idea of refining the function this way?

CHandlingEntry* CHandlingManager::GetModelHandlingData(std::uint32_t model) const noexcept
{
    // Within range?
    if (!CVehicleManager::IsValidModel(model))
        return nullptr;

    auto entries = m_ModelEntries.find(model);
    if (entries == m_ModelEntries.end())
    {
        // Get our Handling ID
        eHandlingTypes eHandling = GetHandlingID(model);

        auto entry = std::make_unique<CHandlingEntry>(&m_OriginalHandlingData[eHandling]);
        entries = m_ModelEntries.emplace(model, std::move(entry)).first;
    }

    return entries->second.get();
}

@TracerDS
Copy link
Contributor

TracerDS commented Nov 10, 2024

@TracerDS Do you like the idea of refining the function this way?

CHandlingEntry* CHandlingManager::GetModelHandlingData(std::uint32_t model) const noexcept
{
    // Within range?
    if (!CVehicleManager::IsValidModel(model))
        return nullptr;

    auto entries = m_ModelEntries.find(model);
    if (entries == m_ModelEntries.end())
    {
        // Get our Handling ID
        eHandlingTypes eHandling = GetHandlingID(model);

        auto entry = std::make_unique<CHandlingEntry>(&m_OriginalHandlingData[eHandling]);
        entries = m_ModelEntries.emplace(model, std::move(entry)).first;
    }

    return entries->second.get();
}

I very much do not like the std::move(entry) on an unique_ptr. Btw thats not a refactor but a huge change how GetModelHandlingData fetches data.

this is pretty bad because it will always construct entry, even if insertion fails

@G-Moris
Copy link
Contributor Author

G-Moris commented Nov 10, 2024

@TracerDS Do you like the idea of refining the function this way?

CHandlingEntry* CHandlingManager::GetModelHandlingData(std::uint32_t model) const noexcept
{
    // Within range?
    if (!CVehicleManager::IsValidModel(model))
        return nullptr;

    auto entries = m_ModelEntries.find(model);
    if (entries == m_ModelEntries.end())
    {
        // Get our Handling ID
        eHandlingTypes eHandling = GetHandlingID(model);

        auto entry = std::make_unique<CHandlingEntry>(&m_OriginalHandlingData[eHandling]);
        entries = m_ModelEntries.emplace(model, std::move(entry)).first;
    }

    return entries->second.get();
}

I very much do not like the std::move(entry) on an unique_ptr. Btw thats not a refactor but a huge change how GetModelHandlingData fetches data.

this is pretty bad because it will always construct entry, even if insertion fails

@TracerDS Do you like the idea of refining the function this way?

CHandlingEntry* CHandlingManager::GetModelHandlingData(std::uint32_t model) const noexcept
{
    // Within range?
    if (!CVehicleManager::IsValidModel(model))
        return nullptr;

    auto entries = m_ModelEntries.find(model);
    if (entries == m_ModelEntries.end())
    {
        // Get our Handling ID
        eHandlingTypes eHandling = GetHandlingID(model);

        auto entry = std::make_unique<CHandlingEntry>(&m_OriginalHandlingData[eHandling]);
        entries = m_ModelEntries.emplace(model, std::move(entry)).first;
    }

    return entries->second.get();
}

I very much do not like the std::move(entry) on an unique_ptr. Btw thats not a refactor but a huge change how GetModelHandlingData fetches data.

this is pretty bad because it will always construct entry, even if insertion fails

std::move transfers the owner to m_ModelEntries, at least I don't see anything wrong or risky in this. Can set a condition with the "entry" check

@TracerDS
Copy link
Contributor

std::move transfers the owner to m_ModelEntries, at least I don't see anything wrong or risky in this. Can set a condition with the "entry" check

No. std::move doesnt "move" anything.

@G-Moris
Copy link
Contributor Author

G-Moris commented Nov 10, 2024

std::move transfers the owner to m_ModelEntries, at least I don't see anything wrong or risky in this. Can set a condition with the "entry" check

No. std::move doesnt "move" anything.

It transfers ownership, as I know

@TracerDS
Copy link
Contributor

TracerDS commented Nov 10, 2024

It transfers ownership, as I know

No. It only converts the value to rvalue. Thats all. If the value is already a rvalue then the conversion does nothing.
It only marks the value can be transferred but does not automatically move the ownership.

This is the basic implementation of std::move:

template <typename T>
typename remove_reference<T>::type&& move(T&& arg)
{
  return static_cast<typename remove_reference<T>::type&&>(arg);
}

Lets format it into int only:

template<class T> struct remove_reference { typedef T type; };
template<class T> struct remove_reference<T&> { typedef T type; };
template<class T> struct remove_reference<T&&> { typedef T type; };

inline
int&& move(int&& arg)
{
  return static_cast<int&&>(arg);
}

As you can see no transfer is done by move manually.

@G-Moris
Copy link
Contributor Author

G-Moris commented Nov 10, 2024

As you can see no transfer is done by move manually.

Is that better?

// Get our Handling ID
eHandlingTypes eHandling = GetHandlingID(model);

m_ModelEntries[model] = std::make_unique<CHandlingEntry>(&m_OriginalHandlingData[eHandling]);
if (!m_ModelEntries[model])
    return nullptr;

entries = m_ModelEntries.find(model);

@TracerDS
Copy link
Contributor

Is that better?

// Get our Handling ID
eHandlingTypes eHandling = GetHandlingID(model);

m_ModelEntries[model] = std::make_unique<CHandlingEntry>(&m_OriginalHandlingData[eHandling]);
if (!m_ModelEntries[model])
    return nullptr;

entries = m_ModelEntries.find(model);

Yes

@G-Moris
Copy link
Contributor Author

G-Moris commented Nov 10, 2024

Yes

Is it possible to change to this?

// Original handling data
static std::unordered_map<std::size_t, tHandlingData>                   m_OriginalHandlingData;
static std::unordered_map<std::size_t, std::unique_ptr<CHandlingEntry>> m_OriginalEntries;

// Model handling data
static std::unordered_map<std::size_t, std::unique_ptr<CHandlingEntry>> m_ModelEntries;
static std::unordered_map<std::size_t, bool>                            m_bModelHandlingChanged;

static std::map<std::string, eHandlingProperty> m_HandlingNames;

@TracerDS
Copy link
Contributor

// Original handling data
static std::unordered_map<std::size_t, tHandlingData>                   m_OriginalHandlingData;
static std::unordered_map<std::size_t, std::unique_ptr<CHandlingEntry>> m_OriginalEntries;

// Model handling data
static std::unordered_map<std::size_t, std::unique_ptr<CHandlingEntry>> m_ModelEntries;
static std::unordered_map<std::size_t, bool>                            m_bModelHandlingChanged;

static std::map<std::string, eHandlingProperty> m_HandlingNames;

what are the original declarations?

@G-Moris
Copy link
Contributor Author

G-Moris commented Nov 10, 2024

what are the original declarations?

std::unordered_map will help us for a more dynamic and convenient use

    std::map<std::string, eHandlingProperty> m_HandlingNames;
    
    // Original handling data unaffected by handling.cfg changes
    static SFixedArray<tHandlingData, HT_MAX> m_OriginalHandlingData;

    // Array with the original handling entries
    static SFixedArray<std::unique_ptr<CHandlingEntry>, HT_MAX> m_OriginalEntries;

    // Array with the model handling entries
    static SFixedArray<std::unique_ptr<CHandlingEntry>, HT_MAX> m_ModelEntries;

    SFixedArray<bool, HT_MAX> m_bModelHandlingChanged;

@Dutchman101 Dutchman101 requested review from TheNormalnij and tederis and removed request for FileEX and TracerDS November 21, 2024 22:27
@Dutchman101
Copy link
Member

I've requested reviews from @TheNormalnij and @tederis, this PR has to be scrutinized for the same reasons as author's prior PR's. Thanks for the PR!

@Dutchman101
Copy link
Member

Dutchman101 commented Dec 21, 2024

Thanks for addressing all code reviews, the ones requested by me as per this comment were also fulfilled.

Good work with the PR, merging, @G-Moris

// Edit: you need to address this one asap, for now we'll have the PR's changes in (and in the upcoming build) with that review comment up for clarification later, because the PR already gives more performance boost than any (trivial) effect of copying data would, so it'll allow early testing and performance benefits for users. Still, answer it, and resolve it properly, thanks.

@Dutchman101 Dutchman101 merged commit c0376c9 into multitheftauto:master Dec 21, 2024
6 checks passed
TheNormalnij added a commit that referenced this pull request Dec 21, 2024
@Dutchman101
Copy link
Member

Comment due to #mtasa-blue in discord bridge not having that this PR was in fact merged.

After discussing with TheNormalnij, we need to keep these things in mind too: #3848 (comment) (see "Edit" at bottom)

@G-Moris
Copy link
Contributor Author

G-Moris commented Dec 22, 2024

Sorry, I'll make the edits today, I just didn't have time before.

@botder botder added this to the 1.6.1 milestone Dec 22, 2024
tederis pushed a commit that referenced this pull request Dec 23, 2024
* Update

* Update 2

* Update 3

---------

Co-authored-by: G_Moris <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants