Files
UnrealEngineUWP/Engine/Source/Developer/DerivedDataCache/Public/DerivedDataBuildVersion.h
henrik karlsson 4feb09e0b3 Compile time optimizations Managed to reduce unnamed game's biggest file compiler frontend cost from 113 seconds to 60 seconds. This also impact other things such as pch size and memory footprint when compiling which is great.
Takeaways. Try to use "friend" on functions/operators that are frequently overloaded EXCEPT if they are in a templated type that is frequently instantiated. So do not put friends in TMap, TSet, TObjectPtr etc, this will slow down compile times. There is a break-even somewhere and hard to tell where it is but taking a class that is templatized on character type probably don't matter either way and then it is nicer to use a friend since that simplies error messages when compiler can't resolve functions/operators.

If it is possible to use member functions instead of friend that is the best option in terms of compile time performance. With c++20 you only have to write operator==(Foo, Bar) and the compiler will automatically provide operator==(Bar, Foo), operator!=(Foo, Bar) and operator!=(Bar, Foo).

Changes in this changelist involes
* Making operator<< friends in non-template types and not friends in template types
* Making operator==/!= members where possible and if not possible moved out if type is a frequently instantiated templated type.

#preflight 636970f5376a9cd6a80da54a
#rb steve.robb

[CL 23038965 by henrik karlsson in ue5-main branch]
2022-11-08 15:59:46 -05:00

88 lines
2.2 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#pragma once
#include "CoreTypes.h"
#include "Hash/xxhash.h"
#include "Misc/Guid.h"
#include "Serialization/Archive.h"
#include "UObject/NameTypes.h"
#include <type_traits>
namespace UE::DerivedData
{
/**
* A type that builds a build version from arbitrary values serialized to it.
*
* FGuid GetVersion() const final
* {
* FBuildVersionBuilder Builder;
* Builder << FGuid(TEXT("a3ae79ff-6a89-4124-afd6-dc095e000488"));
* Builder << ThirdPartyLibraryVersion;
* return Builder.Build();
* }
*/
class FBuildVersionBuilder final : public FArchive
{
public:
inline FBuildVersionBuilder();
inline FGuid Build() const;
inline FString GetArchiveName() const final { return TEXT("FBuildVersionBuilder"); }
inline void Serialize(void* Data, int64 Num) final;
using FArchive::operator<<;
FArchive& operator<<(FName& Name) final;
template <typename ArgType>
inline FBuildVersionBuilder& operator<<(ArgType&& Arg)
{
FArchive& Ar = *this;
Ar << const_cast<std::decay_t<ArgType>&>(Arg);
return *this;
}
private:
FXxHash128Builder HashBuilder;
};
inline FBuildVersionBuilder::FBuildVersionBuilder()
{
SetIsSaving(true);
SetIsPersistent(false);
// Hash this as the namespace of the Version 3 UUID created in Build().
static FGuid BaseVersion(TEXT("b9080e6a-9eb2-4c25-8810-e957009fa0a1"));
HashBuilder.Update(&BaseVersion, sizeof(FGuid));
}
inline FGuid FBuildVersionBuilder::Build() const
{
FXxHash128 Hash = HashBuilder.Finalize();
uint32 A = uint32(Hash.HashHigh >> 32);
uint32 B = uint32(Hash.HashHigh);
uint32 C = uint32(Hash.HashLow >> 32);
uint32 D = uint32(Hash.HashLow);
// Convert to a Variant 1 Version 3 UUID, which is meant to be created
// by hashing the namespace and name with MD5, but this is using XXH3.
B = (B & ~0x0000f000) | 0x00003000; // Version 3 (MD5)
C = (C & ~0xc0000000) | 0x80000000; // Variant 1 (RFC 4122 UUID)
return FGuid(A, B, C, D);
}
inline void FBuildVersionBuilder::Serialize(void* Data, int64 Num)
{
HashBuilder.Update(Data, uint64(Num));
}
inline FArchive& FBuildVersionBuilder::operator<<(FName& Name)
{
FString NameString = Name.ToString();
return *this << NameString;
}
} // UE::DerivedData