Skip to content

Commit

Permalink
Revert "Main - Replace Fast Hash system with native hashmaps" (#1331)
Browse files Browse the repository at this point in the history
  • Loading branch information
jonpas authored Jul 3, 2024
1 parent 16e9c6b commit 3a32c1b
Show file tree
Hide file tree
Showing 11 changed files with 300 additions and 11 deletions.
13 changes: 13 additions & 0 deletions addons/main/CfgLocationTypes.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
class CfgLocationTypes {
// For use in Fast Hashes ONLY!
class ACRE_FastHashNamespaceDummy {
name = "";
drawStyle = "ACRE_RequiredDrawStyle"; // Any valid drawStyle causes FPS drop on map controls due to the amount of fast hashes
texture = "";
color[] = {0,0,0,0};
size = 0;
textSize = 0;
shadow = 0;
font = "PuristaMedium";
};
};
8 changes: 8 additions & 0 deletions addons/main/XEH_PREP.hpp
Original file line number Diff line number Diff line change
@@ -1,2 +1,10 @@
PREP(garbageCollector);
PREP(hashMonitor);

PREP(fastHashCopy);
PREP(fastHashCopyArray);
PREP(fastHashCreate);
PREP(fastHashKeys);

PREP(dumpPerformanceCounters);
PREP(dumpCallStack);
25 changes: 25 additions & 0 deletions addons/main/XEH_preInit.sqf
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,29 @@ ACRE_STACK_TRACE = [];
ACRE_STACK_DEPTH = 0;
ACRE_CURRENT_FUNCTION = "";

// Fast Hashes
// All hash stuff must be in main to guarantee it is compiled and executed first for proper data handling.
if (isNil "ACRE_FAST_HASH_POOL") then {
ACRE_FAST_HASH_POOL = [];
for "_i" from 1 to 50000 do {
ACRE_FAST_HASH_POOL pushBack HASH_CREATE_NAMESPACE;
};
};
ACRE_FAST_HASH_TO_DELETE = [];

[FUNC(hashMonitor), 0.33, []] call CBA_fnc_addPerFrameHandler;

ACRE_FAST_HASH_CREATED_HASHES = [];
ACRE_FAST_HASH_VAR_STATE = (allVariables missionNamespace);
ACRE_FAST_HASH_VAR_LENGTH = count ACRE_FAST_HASH_VAR_STATE;
ACRE_FAST_HASH_GC_INDEX = 0;
ACRE_FAST_HASH_GC_FOUND_OBJECTS = [];
ACRE_FAST_HASH_GC_FOUND_ARRAYS = [];
ACRE_FAST_HASH_GC_CHECK_OBJECTS = [];
ACRE_FAST_HASH_CREATED_HASHES_NEW = [];
ACRE_FAST_HASH_GC_IGNORE = ["acre_fast_hash_gc_found_objects","acre_fast_hash_gc_found_arrays","acre_fast_hash_created_hashes","acre_fast_hash_gc_check_objects","acre_fast_hash_created_hashes_new","acre_fast_hash_var_state","acre_fast_hash_pool","acre_fast_hash_to_delete"];
ACRE_FAST_HASH_GC_ORPHAN_CHECK_INDEX = 0;

[FUNC(garbageCollector), 0.25, []] call CBA_fnc_addPerFrameHandler;

ADDON = true;
1 change: 1 addition & 0 deletions addons/main/config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,5 @@ class CfgMods {
#include "CfgSettings.hpp"

#include "CfgEventHandlers.hpp"
#include "CfgLocationTypes.hpp"
#include "CfgWeapons.hpp"
39 changes: 39 additions & 0 deletions addons/main/fnc_fastHashCopy.sqf
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#include "script_component.hpp"
/*
* Author: ACRE2Team
* Copies one hash to another or creates an ACRE2 hash with the object variables if the input is an object.
*
* Arguments:
* 0: ACRE 2 Hash <HASH>/<OBJECT>
*
* Return Value:
* ACRE 2 Hash <HASH>
*
* Example:
* new_acreHash = [acreHash] call acre_main_fnc_fastHashCopy
* new_acreHash = [player] call acre_main_fnc_fastHashCopy
*
* Public: No
*/

private _return = [];

if (IS_ARRAY(_this)) then {
_return = _this call FUNC(fastHashCopyArray);
} else {
_return = call FUNC(fastHashCreate);
{
private _el = _this getVariable _x;
private _eln = _x;
if (IS_ARRAY(_el)) then {
_return setVariable [_eln, _el call FUNC(fastHashCopyArray)];
} else {
if (IS_HASH(_el)) then {
_return setVariable [_eln, _el call FUNC(fastHashCopy)];
} else {
_return setVariable [_eln, _el];
};
};
} forEach (allVariables _this);
};
_return;
29 changes: 29 additions & 0 deletions addons/main/fnc_fastHashCopyArray.sqf
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#include "script_component.hpp"
/*
* Author: ACRE2Team
* Copies an array or an ACRE2 hash entry inside an ACRE 2 hash
*
* Arguments:
* 0: ACRE 2 Hash to be copied <HASH>/<ARRAY>
*
* Return Value:
* Extracted array of values to be copied <ARRAY>
*
* Example:
* [["foo1", "foo2"]] call acre_main_fnc_fastHashCopyArray
* [acreHash] call acre_sys_core_fnc_fastHashCopyArray
*
* Public: No
*/

_this apply {
if (IS_HASH(_x)) then {
(_x call FUNC(fastHashCopy));
} else {
if (IS_ARRAY(_x)) then {
(_x call FUNC(fastHashCopyArray));
} else {
_x;
};
};
};
26 changes: 26 additions & 0 deletions addons/main/fnc_fastHashCreate.sqf
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#include "script_component.hpp"
/*
* Author: ACRE2Team
* Creates an ACRE2 hash. This function can also be accessed through the macro HASH_CREATE.
*
* Arguments:
* None
*
* Return Value:
* ACRE2 Hash <HASH>
*
* Example:
* [] call acre_main_fnc_fastHashCreate
*
* Public: No
*/

if (ACRE_FAST_HASH_POOL isNotEqualTo []) exitWith {
private _ret = ACRE_FAST_HASH_POOL deleteAt 0;
ACRE_FAST_HASH_CREATED_HASHES_NEW pushBack _ret;
_ret
};

private _ret = HASH_CREATE_NAMESPACE;
ACRE_FAST_HASH_CREATED_HASHES_NEW pushBack _ret;
_ret
20 changes: 20 additions & 0 deletions addons/main/fnc_fastHashKeys.sqf
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#include "script_component.hpp"
/*
* Author: ACRE2Team
* Retrieves a list of keys inside an ACRE 2 hash or variable names defined in an object.
* This function can be accessed through the macro HASH_KEYS.
*
* Arguments:
* 0: ACRE 2 Hash <HASH>/<OBJECT>
*
* Return Value:
* Array of keys inside an ACRE 2 Hash or object <ARRAY>
*
* Example:
* keys = [acreHash] call acre_main_fnc_fastHashKeys
* keys = [player] call acre_main_fnc_fastHashKeys
*
* Public: No
*/

(allVariables _this) select {!(isNil {_this getVariable _x})};
98 changes: 98 additions & 0 deletions addons/main/fnc_garbageCollector.sqf
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
#include "script_component.hpp"
/*
* Author: ACRE2Team
* ACRE2 garbage collector. Run as a per frame event handler.
*
* Arguments:
* Mone
*
* Return Value:
* None
*
* Example:
* [] call acre_main_fnc_garbageCollector
*
* Public: No
*/

if (count ACRE_FAST_HASH_CREATED_HASHES_NEW < ((count ACRE_FAST_HASH_CREATED_HASHES)*0.1)/2) exitWith {};
// diag_log text format["---------------------------------------------------"];
private _init_time = diag_tickTime;
while {diag_tickTime - _init_time < 0.001 && {ACRE_FAST_HASH_GC_INDEX < ACRE_FAST_HASH_VAR_LENGTH}} do {
private _var_name = ACRE_FAST_HASH_VAR_STATE select ACRE_FAST_HASH_GC_INDEX;
private _x = missionNamespace getVariable [_var_name, nil];

ACRE_FAST_HASH_GC_INDEX = ACRE_FAST_HASH_GC_INDEX + 1;
if (!(_var_name in ACRE_FAST_HASH_GC_IGNORE)) then {
if (IS_HASH(_x)) then {

ACRE_FAST_HASH_GC_FOUND_OBJECTS pushBack _x;
} else {
if (IS_ARRAY(_x)) then {
// diag_log text format["pushBack: %1: %2", _var_name, _x];
ACRE_FAST_HASH_GC_FOUND_ARRAYS pushBack _x;
};
};
};
};
// diag_log text format["GC Objects Left: %1", ACRE_FAST_HASH_VAR_LENGTH - ACRE_FAST_HASH_GC_INDEX];

_init_time = diag_tickTime;
while {diag_tickTime - _init_time < 0.001 && {ACRE_FAST_HASH_GC_FOUND_ARRAYS isNotEqualTo []}} do {
private _array = ACRE_FAST_HASH_GC_FOUND_ARRAYS deleteAt 0;
{
if (IS_HASH(_x)) then {
// diag_log text format["pushBack: %1", _name];
ACRE_FAST_HASH_GC_FOUND_OBJECTS pushBack _x;
} else {
if (IS_ARRAY(_x)) then {
// diag_log text format["pushBack sub-array: %1", _x];
ACRE_FAST_HASH_GC_FOUND_ARRAYS pushBack _x;
};
};
} forEach _array;
};
// diag_log text format["GC Arrays Left: %1", (count ACRE_FAST_HASH_GC_FOUND_ARRAYS)];

_init_time = diag_tickTime;
while {diag_tickTime - _init_time < 0.001 && {ACRE_FAST_HASH_GC_FOUND_OBJECTS isNotEqualTo []}} do {
private _hash = ACRE_FAST_HASH_GC_FOUND_OBJECTS deleteAt 0;
ACRE_FAST_HASH_GC_CHECK_OBJECTS pushBack _hash;
private _array = allVariables _hash;
{
_x = _hash getVariable _x;
if (IS_HASH(_x)) then {
ACRE_FAST_HASH_GC_FOUND_OBJECTS pushBack _x;
} else {
if (IS_ARRAY(_x)) then {
// diag_log text format["pushBack hash-array: %1", _x];
ACRE_FAST_HASH_GC_FOUND_ARRAYS pushBack _x;
};
};
} forEach _array;
};
// diag_log text format["GC Hashes Left: %1", (count ACRE_FAST_HASH_GC_FOUND_OBJECTS)];

if (ACRE_FAST_HASH_GC_INDEX >= ACRE_FAST_HASH_VAR_LENGTH && {ACRE_FAST_HASH_GC_FOUND_ARRAYS isEqualTo []} && {ACRE_FAST_HASH_GC_FOUND_OBJECTS isEqualTo []}) then {
if (ACRE_FAST_HASH_GC_ORPHAN_CHECK_INDEX < (count ACRE_FAST_HASH_CREATED_HASHES)) then {
_init_time = diag_tickTime;
while {diag_tickTime - _init_time < 0.001 && {ACRE_FAST_HASH_GC_ORPHAN_CHECK_INDEX < (count ACRE_FAST_HASH_CREATED_HASHES)}} do {
private _check = ACRE_FAST_HASH_CREATED_HASHES select ACRE_FAST_HASH_GC_ORPHAN_CHECK_INDEX;
ACRE_FAST_HASH_GC_ORPHAN_CHECK_INDEX = ACRE_FAST_HASH_GC_ORPHAN_CHECK_INDEX + 1;
if (!(_check in ACRE_FAST_HASH_GC_CHECK_OBJECTS)) then {
ACRE_FAST_HASH_TO_DELETE pushBack _check;
};
};
} else {
ACRE_FAST_HASH_VAR_STATE = (allVariables missionNamespace);
ACRE_FAST_HASH_CREATED_HASHES = ACRE_FAST_HASH_GC_CHECK_OBJECTS;
ACRE_FAST_HASH_GC_CHECK_OBJECTS = [];
ACRE_FAST_HASH_GC_FOUND_ARRAYS = [];
ACRE_FAST_HASH_VAR_LENGTH = count ACRE_FAST_HASH_VAR_STATE;
ACRE_FAST_HASH_GC_INDEX = 0;
ACRE_FAST_HASH_CREATED_HASHES append ACRE_FAST_HASH_CREATED_HASHES_NEW;
ACRE_FAST_HASH_CREATED_HASHES_NEW = [];
ACRE_FAST_HASH_GC_FOUND_OBJECTS = [];
ACRE_FAST_HASH_GC_ORPHAN_CHECK_INDEX = 0;
};
};
30 changes: 30 additions & 0 deletions addons/main/fnc_hashMonitor.sqf
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#include "script_component.hpp"
/*
* Author: ACRE2Team
* Handles deletion and creation of ACRE2 hashes.
*
* Arguments:
* None
*
* Return Value:
* None
*
* Example:
* [] call acre_main_fnc_hashMonitor
*
* Public: No
*/

if (count ACRE_FAST_HASH_TO_DELETE > 0) then {
private _init_time = diag_tickTime;
while {(diag_tickTime - _init_time) * 1000 < 2.0 && {ACRE_FAST_HASH_TO_DELETE isNotEqualTo []}} do {
deleteLocation (ACRE_FAST_HASH_TO_DELETE deleteAt 0);
ACRE_FAST_HASH_POOL pushBack HASH_CREATE_NAMESPACE;
};
};

if (count ACRE_FAST_HASH_POOL <= (count ACRE_FAST_HASH_CREATED_HASHES) * 0.1) then {
for "_i" from 1 to 10 do {
ACRE_FAST_HASH_POOL pushBack HASH_CREATE_NAMESPACE;
};
};
22 changes: 11 additions & 11 deletions addons/main/script_macros.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -110,17 +110,17 @@ SQF equivalent of extensions/src/ACRE2Shared/Types.h

#define GET_TS3ID(object) (object call { private _ret = (_this getVariable [QGVAR(ts3id), -1]); if (_ret == -1) then { WARNING_1("%1 has no TS3 ID",_this); }; _ret })

#define IS_HASH(hash) (hash isEqualType createHashMap)

#define HASH_CREATE_NAMESPACE (createHashMap)
#define HASH_CREATE (createHashMap)
#define HASH_DELETE(hash) (hash = nil)
#define HASH_HASKEY(hash, key) (key in hash)
#define HASH_SET(hash, key, val) (hash set [key,val])
#define HASH_GET(hash, key) (hash get key)
#define HASH_REM(hash, key) (hash deleteAt key)
#define HASH_COPY(hash) (+hash)
#define HASH_KEYS(hash) (keys hash)
#define IS_HASH(hash) (hash isEqualType locationNull && {(type hash) isEqualTo "ACRE_FastHashNamespaceDummy"})

#define HASH_CREATE_NAMESPACE (createLocation ["ACRE_FastHashNamespaceDummy", [-1000, -1000, 0], 0, 0])
#define HASH_CREATE (call EFUNC(main,fastHashCreate))
#define HASH_DELETE(hash) (ACRE_FAST_HASH_TO_DELETE pushBack hash)
#define HASH_HASKEY(hash, key) (!(isNil {hash getVariable key}))
#define HASH_SET(hash, key, val) (hash setVariable [key,val])
#define HASH_GET(hash, key) (hash getVariable key)
#define HASH_REM(hash, key) (hash setVariable [key,nil])
#define HASH_COPY(hash) (hash call EFUNC(main,fastHashCopy))
#define HASH_KEYS(hash) (hash call EFUNC(main,fastHashKeys))

#define HASHLIST_CREATELIST(keys) []
#define HASHLIST_CREATEHASH(hashList) HASH_CREATE
Expand Down

0 comments on commit 3a32c1b

Please sign in to comment.