From 2f1d5994316a92e94bb47c15c6f78ca97eafa7cb Mon Sep 17 00:00:00 2001 From: Anton Tarasenko Date: Thu, 4 Mar 2021 14:21:12 +0700 Subject: [PATCH] Add `AcediaObject`/`AcediaActor` hash code caching Now all objects only have to calculate their hash code once and it's value will be stored for later `GetHashCode()` calls, since has code is not suppoed to change during their lifetime anyway. --- sources/Data/Collections/Tests/MockItem.uc | 2 +- sources/Text/MutableText.uc | 2 +- sources/Text/Text.uc | 2 +- sources/Types/AcediaActor.uc | 42 +++++++++++++++---- sources/Types/AcediaObject.uc | 40 ++++++++++++++---- sources/Types/Boxes/Native/BoolArrayBox.uc | Bin 8604 -> 8622 bytes sources/Types/Boxes/Native/BoolBox.uc | Bin 3768 -> 3786 bytes sources/Types/Boxes/Native/ByteArrayBox.uc | Bin 8332 -> 8350 bytes sources/Types/Boxes/Native/ByteBox.uc | Bin 3670 -> 3688 bytes sources/Types/Boxes/Native/FloatArrayBox.uc | Bin 8988 -> 9006 bytes sources/Types/Boxes/Native/FloatBox.uc | Bin 4218 -> 4236 bytes sources/Types/Boxes/Native/IntArrayBox.uc | Bin 8464 -> 8482 bytes sources/Types/Boxes/Native/IntBox.uc | Bin 3678 -> 3696 bytes sources/Types/Boxes/Native/StringArrayBox.uc | Bin 8648 -> 8666 bytes sources/Types/Boxes/Native/StringBox.uc | Bin 4010 -> 4028 bytes 15 files changed, 68 insertions(+), 20 deletions(-) diff --git a/sources/Data/Collections/Tests/MockItem.uc b/sources/Data/Collections/Tests/MockItem.uc index bbcf4ed..7e4857c 100644 --- a/sources/Data/Collections/Tests/MockItem.uc +++ b/sources/Data/Collections/Tests/MockItem.uc @@ -37,7 +37,7 @@ public function bool IsEqual(Object other) return true; } -public function int GetHashCode() +protected function int CalculateHashCode() { return 0; } diff --git a/sources/Text/MutableText.uc b/sources/Text/MutableText.uc index a216a70..92b4bda 100644 --- a/sources/Text/MutableText.uc +++ b/sources/Text/MutableText.uc @@ -358,7 +358,7 @@ private final function FormattedBlock CreateFormattedBlock(bool isOpening) * * @return Hash code for the caller `MutableText`. */ -public function int GetHashCode() +protected function int CalculateHashCode() { return super(AcediaObject).GetHashCode(); } diff --git a/sources/Text/Text.uc b/sources/Text/Text.uc index 557a513..8296a97 100644 --- a/sources/Text/Text.uc +++ b/sources/Text/Text.uc @@ -418,7 +418,7 @@ protected final function ConvertCase(bool toLower) * * @return Hash, that depends on textual contents only. */ -public function int GetHashCode() +protected function int CalculateHashCode() { local int i; local int hash; diff --git a/sources/Types/AcediaActor.uc b/sources/Types/AcediaActor.uc index 82f26df..df43dec 100644 --- a/sources/Types/AcediaActor.uc +++ b/sources/Types/AcediaActor.uc @@ -52,9 +52,10 @@ var private bool _isAllocated; // called for this object. var private bool _staticConstructorWasCalled; -// We want to have a common `GetHashCode()` method for all Acedia's objects. -// Just randomizing one at the time of allocation seems like a great idea. -var private int _randomizedHashCode; +// We only want to compute hash code once and reuse generated value later, +// since it cannot changed without reallocation. +var private int _cachedHashCode; +var private bool _hashCodeWasCached; // This object will provide hashed `string` to `Text` map, necessary for // efficient and convenient conversion methods. @@ -111,11 +112,11 @@ public function _constructor() if (_isAllocated) return; _isAllocated = true; _lifeVersion += 1; - _randomizedHashCode = Rand(MaxInt); if (_ == none) { default._ = class'Global'.static.GetInstance(); _ = default._; } + _hashCodeWasCached = false; Constructor(); } @@ -261,19 +262,42 @@ public function bool IsEqual(Object other) } /** - * Returns hash of an object. + * Calculated hash of an object. Overload this method if you want to change + * how object's hash is computed. + * + * `GetHashCode()` method uses it to calculate had code once and then cache it. * * If you overload `IsEqual()` method to allow two different objects to - * be equal, you must implement `GetHashCode()` to return the same hash + * be equal, you must implement `CalculateHashCode()` to return the same hash * for them. * * By default it is just a random value, generated at the time of allocation. * - * @return Hash code for the caller actor. + * @return Hash code for the caller object. + */ +protected function int CalculateHashCode() +{ + return Rand(MaxInt); +} + +/** + * Returns hash of an object. + * + * Calculated hash only once, later using internally cached value. + * + * By default it is just a random value. + * See `CalculateHashCode()` if you wish to change how hash code is computed. + * + * @return Hash code for the caller object. */ -public function int GetHashCode() +public final function int GetHashCode() { - return _randomizedHashCode; + if (_hashCodeWasCached) { + return _cachedHashCode; + } + _hashCodeWasCached = true; + _cachedHashCode = CalculateHashCode(); + return _cachedHashCode; } /** diff --git a/sources/Types/AcediaObject.uc b/sources/Types/AcediaObject.uc index 6a11470..0c8567d 100644 --- a/sources/Types/AcediaObject.uc +++ b/sources/Types/AcediaObject.uc @@ -53,9 +53,10 @@ var private bool _isAllocated; // called for this object. var private bool _staticConstructorWasCalled; -// We want to have a common `GetHashCode()` method for all Acedia's objects. -// Just randomizing one at the time of allocation seems like a great idea. -var private int _randomizedHashCode; +// We only want to compute hash code once and reuse generated value later, +// since it cannot changed without reallocation. +var private int _cachedHashCode; +var private bool _hashCodeWasCached; // This object will provide hashed `string` to `Text` map, necessary for // efficient and convenient conversion methods. @@ -112,7 +113,6 @@ public final function _constructor() if (_isAllocated) return; _isAllocated = true; _lifeVersion += 1; - _randomizedHashCode = Rand(MaxInt); if (_ == none) { default._ = class'Global'.static.GetInstance(); _ = default._; @@ -121,6 +121,7 @@ public final function _constructor() StaticConstructor(); default._staticConstructorWasCalled = true; } + _hashCodeWasCached = false; Constructor(); } @@ -266,19 +267,42 @@ public function bool IsEqual(Object other) } /** - * Returns hash of an object. + * Calculated hash of an object. Overload this method if you want to change + * how object's hash is computed. + * + * `GetHashCode()` method uses it to calculate had code once and then cache it. * * If you overload `IsEqual()` method to allow two different objects to - * be equal, you must implement `GetHashCode()` to return the same hash + * be equal, you must implement `CalculateHashCode()` to return the same hash * for them. * * By default it is just a random value, generated at the time of allocation. * * @return Hash code for the caller object. */ -public function int GetHashCode() +protected function int CalculateHashCode() { - return _randomizedHashCode; + return Rand(MaxInt); +} + +/** + * Returns hash of an object. + * + * Calculated hash only once, later using internally cached value. + * + * By default it is just a random value. + * See `CalculateHashCode()` if you wish to change how hash code is computed. + * + * @return Hash code for the caller object. + */ +public final function int GetHashCode() +{ + if (_hashCodeWasCached) { + return _cachedHashCode; + } + _hashCodeWasCached = true; + _cachedHashCode = CalculateHashCode(); + return _cachedHashCode; } /** diff --git a/sources/Types/Boxes/Native/BoolArrayBox.uc b/sources/Types/Boxes/Native/BoolArrayBox.uc index bfd0eb921ee853b402bc40719f525671018497de..b3800f5ac867e2b1a4850a58d8804053ec7418dd 100644 GIT binary patch delta 54 zcmbQ^yv}*UCOQ5hhJ1z+hE#@RFqtxWK9A_+04@$eXNE+E9H3|^kW2*0ZN4kFp9uh~ C{tplU delta 26 icmZ4IJjZ#%Cb`KQq~s?)J@@Nx(`GbA$PFeEdS0?9;%5{A^tCwbok0OV*3r2qf` delta 29 lcmX>lyF+%vJl@HFxaD{=8S)rP7!(-X8B!TaCg0|L4*;1N3DN)n diff --git a/sources/Types/Boxes/Native/ByteArrayBox.uc b/sources/Types/Boxes/Native/ByteArrayBox.uc index 9bc80354e5c96f2ff824a1e2269cf9b6b17c335a..7b9ebcbf9ca72b69d2b694cb25202094fb5ce810 100644 GIT binary patch delta 54 zcmeBioaeZqNshmWA)ldyA(bH+Or}iE=MkM8z{Mfx%#g^C0~9R&1>cEGXemW CJq~*S delta 26 icmbQ|*yFgNNp5n3l-%S1E)G_AhE#@<&HLr?)F(40#MC3w8&{gh8%wpLq0@hTP-~DY?mZf_$5o$<;6c08r8g1poj5 diff --git a/sources/Types/Boxes/Native/IntBox.uc b/sources/Types/Boxes/Native/IntBox.uc index 53dc7afa8823740b8834051fc106ca824ef23bbf..a11a718b285aa31d9bbfcfcbc2c79d1ceb39f9e0 100644 GIT binary patch delta 41 ucmca7^Fd}q8}H--b`{A?hCGH61_cIZhD3%OhGd3PAejghNu9ircP#(_v?)F(40#MC3