diff --git a/README.md b/README.md index 98f7cdd7..06a65f70 100644 --- a/README.md +++ b/README.md @@ -334,11 +334,12 @@ Table Compile Flags: Table Create Parameters: - --GraphImpl=1|2 [default: 2] + --GraphImpl=1|2|3 [default: 3] Selects the backend version of the graph assignment step. Version 1 matches the original CHM algorithm, version 2 is faster and was derived - from NetBSD's nbperf routine. Defaults to version 2. + from NetBSD's nbperf module, version 3 is even faster and was derived + from additional improvements to NetBSD's nbperf module in 2020. --ValueSizeInBytes=4|8 @@ -462,6 +463,18 @@ Table Create Parameters: N.B. Only applies to PerfectHashCreate.exe. + --TargetNumberOfSolutions=N + + Where N is a positive integer and represents a target number of + solutions to find before stopping graph solving. Typically only useful + for benchmarking. + + --FixedAttempts=N + + Where N is a positive integer and represents a fixed number of attempts + that will be made (irrespective of whether or not a solution was found) + before graph solving stops. Typically only useful for benchmarking. + --Seeds= Supplies an optional comma-separated list of up to 8 integers that diff --git a/include/PerfectHash.h b/include/PerfectHash.h index 6726a30b..45e3b74d 100644 --- a/include/PerfectHash.h +++ b/include/PerfectHash.h @@ -3097,6 +3097,10 @@ typedef RNG_VTBL *PRNG_VTBL; FIRST_ENTRY(AttemptsBeforeTableResize) \ ENTRY(MaxNumberOfTableResizes) \ ENTRY(InitialNumberOfTableResizes) \ + ENTRY(MinAttempts) \ + ENTRY(MaxAttempts) \ + ENTRY(FixedAttempts) \ + ENTRY(TargetNumberOfSolutions) \ ENTRY(BestCoverageAttempts) \ ENTRY(BestCoverageType) \ ENTRY(MaxNumberOfEqualBestGraphs) \ diff --git a/include/PerfectHashErrors.h b/include/PerfectHashErrors.h index 17a55304..655ecacc 100644 --- a/include/PerfectHashErrors.h +++ b/include/PerfectHashErrors.h @@ -144,6 +144,15 @@ Module Name: // #define PH_S_NO_KEY_SIZE_EXTRACTED_FROM_FILENAME ((HRESULT)0x20040009L) +// +// MessageId: PH_S_MAX_ATTEMPTS_REACHED +// +// MessageText: +// +// Maximum attempts at solving reached. +// +#define PH_S_MAX_ATTEMPTS_REACHED ((HRESULT)0x2004000AL) + //////////////////////////////////////////////////////////////////////////////// // PH_SEVERITY_INFORMATIONAL @@ -3825,3 +3834,93 @@ Module Name: // #define PH_E_RNG_NOT_INITIALIZED ((HRESULT)0xE00403C6L) +// +// MessageId: PH_E_INVALID_FIXED_ATTEMPTS +// +// MessageText: +// +// Invalid FixedAttempts. +// +#define PH_E_INVALID_FIXED_ATTEMPTS ((HRESULT)0xE00403C7L) + +// +// MessageId: PH_E_INVALID_MIN_ATTEMPTS +// +// MessageText: +// +// Invalid MinAttempts. +// +#define PH_E_INVALID_MIN_ATTEMPTS ((HRESULT)0xE00403C8L) + +// +// MessageId: PH_E_INVALID_MAX_ATTEMPTS +// +// MessageText: +// +// Invalid MaxAttempts. +// +#define PH_E_INVALID_MAX_ATTEMPTS ((HRESULT)0xE00403C9L) + +// +// MessageId: PH_E_FIXED_ATTEMPTS_CONFLICTS_WITH_MINMAX_ATTEMPTS +// +// MessageText: +// +// FixedAttempts conflicts with MinAttempts/MaxAttempts. +// +#define PH_E_FIXED_ATTEMPTS_CONFLICTS_WITH_MINMAX_ATTEMPTS ((HRESULT)0xE00403CAL) + +// +// MessageId: PH_E_MIN_ATTEMPTS_EXCEEDS_MAX_ATTEMPTS +// +// MessageText: +// +// MinAttempts must be less than or equal to MaxAttempts. +// +#define PH_E_MIN_ATTEMPTS_EXCEEDS_MAX_ATTEMPTS ((HRESULT)0xE00403CBL) + +// +// MessageId: PH_E_FIXED_ATTEMPTS_CONFLICTS_WITH_FIND_BEST_GRAPH +// +// MessageText: +// +// FixedAttempts conflicts with FindBestGraph. +// +#define PH_E_FIXED_ATTEMPTS_CONFLICTS_WITH_FIND_BEST_GRAPH ((HRESULT)0xE00403CCL) + +// +// MessageId: PH_E_MIN_ATTEMPTS_CONFLICTS_WITH_FIND_BEST_GRAPH +// +// MessageText: +// +// MinAttempts conflicts with FindBestGraph. +// +#define PH_E_MIN_ATTEMPTS_CONFLICTS_WITH_FIND_BEST_GRAPH ((HRESULT)0xE00403CDL) + +// +// MessageId: PH_E_INVALID_TARGET_NUMBER_OF_SOLUTIONS +// +// MessageText: +// +// Invalid TargetNumberOfSolutions. +// +#define PH_E_INVALID_TARGET_NUMBER_OF_SOLUTIONS ((HRESULT)0xE00403CEL) + +// +// MessageId: PH_E_TARGET_NUMBER_OF_SOLUTIONS_CONFLICTS_WITH_FIND_BEST_GRAPH +// +// MessageText: +// +// TargetNumberOfSolutions conflicts with FindBestGraph. +// +#define PH_E_TARGET_NUMBER_OF_SOLUTIONS_CONFLICTS_WITH_FIND_BEST_GRAPH ((HRESULT)0xE00403CFL) + +// +// MessageId: PH_E_TARGET_NUMBER_OF_SOLUTIONS_EXCEEDS_MIN_ATTEMPTS +// +// MessageText: +// +// TargetNumberOfSolutions exceeds MinAttempts. +// +#define PH_E_TARGET_NUMBER_OF_SOLUTIONS_EXCEEDS_MIN_ATTEMPTS ((HRESULT)0xE00403D0L) + diff --git a/include/PerfectHashEvents.h b/include/PerfectHashEvents.h index 308aa063..bbb5f474 100644 --- a/include/PerfectHashEvents.h +++ b/include/PerfectHashEvents.h @@ -547,7 +547,7 @@ Routine Description: #endif // MCGEN_DISABLE_PROVIDER_CODE_GENERATION //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -// Provider "PerfectHash" event count 11 +// Provider "PerfectHash" event count 12 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // Provider GUID = d0b3028e-70a7-410f-af7e-4d495b4a3c8b @@ -573,6 +573,7 @@ EXTERN_C __declspec(selectany) const GUID PerfectHashEvents = {0xd0b3028e, 0x70a #define PerfectHashEvents_TASK_FoundGraph 0x6 #define PerfectHashEvents_TASK_Assign 0x7 #define PerfectHashEvents_TASK_GenerateRandomBytes 0x8 +#define PerfectHashEvents_TASK_IsAcyclic 0x9 // // Keyword @@ -583,6 +584,7 @@ EXTERN_C __declspec(selectany) const GUID PerfectHashEvents = {0xd0b3028e, 0x70a #define PH_ETW_GRAPH_FOUND 0x8 #define PH_ETW_GRAPH_ASSIGN 0x10 #define PH_ETW_RTL_RANDOM 0x20 +#define PH_ETW_GRAPH_IS_ACYCLIC 0x40 // // Event Descriptors @@ -593,22 +595,24 @@ EXTERN_C __declspec(selectany) const EVENT_DESCRIPTOR GraphHashKeysEvent = {0x1, #define GraphHashKeysEvent_value 0x1 EXTERN_C __declspec(selectany) const EVENT_DESCRIPTOR GraphAddHashedKeysEvent = {0x2, 0x1, 0x10, 0x4, 0x0, 0x3, 0x8000000000000001}; #define GraphAddHashedKeysEvent_value 0x2 -EXTERN_C __declspec(selectany) const EVENT_DESCRIPTOR GraphFoundNewBest = {0x3, 0x0, 0x10, 0x4, 0x0, 0x4, 0x8000000000000002}; -#define GraphFoundNewBest_value 0x3 -EXTERN_C __declspec(selectany) const EVENT_DESCRIPTOR GraphFoundEqualBest = {0x4, 0x0, 0x10, 0x4, 0x0, 0x5, 0x8000000000000004}; -#define GraphFoundEqualBest_value 0x4 -EXTERN_C __declspec(selectany) const EVENT_DESCRIPTOR GraphFound = {0x5, 0x0, 0x10, 0x4, 0x0, 0x6, 0x8000000000000008}; -#define GraphFound_value 0x5 -EXTERN_C __declspec(selectany) const EVENT_DESCRIPTOR GraphAssignStart = {0x6, 0x0, 0x10, 0x4, 0x1, 0x7, 0x8000000000000010}; -#define GraphAssignStart_value 0x6 -EXTERN_C __declspec(selectany) const EVENT_DESCRIPTOR GraphAssignStop = {0x7, 0x0, 0x10, 0x4, 0x2, 0x7, 0x8000000000000010}; -#define GraphAssignStop_value 0x7 -EXTERN_C __declspec(selectany) const EVENT_DESCRIPTOR RtlGenerateRandomBytesStart = {0x8, 0x0, 0x10, 0x4, 0x1, 0x8, 0x8000000000000020}; -#define RtlGenerateRandomBytesStart_value 0x8 -EXTERN_C __declspec(selectany) const EVENT_DESCRIPTOR RtlGenerateRandomBytesStop = {0x9, 0x0, 0x10, 0x4, 0x2, 0x8, 0x8000000000000020}; -#define RtlGenerateRandomBytesStop_value 0x9 -EXTERN_C __declspec(selectany) const EVENT_DESCRIPTOR GraphAssignResult = {0xa, 0x0, 0x10, 0x4, 0x0, 0x7, 0x8000000000000010}; -#define GraphAssignResult_value 0xa +EXTERN_C __declspec(selectany) const EVENT_DESCRIPTOR GraphFoundNewBestEvent = {0x3, 0x0, 0x10, 0x4, 0x0, 0x4, 0x8000000000000002}; +#define GraphFoundNewBestEvent_value 0x3 +EXTERN_C __declspec(selectany) const EVENT_DESCRIPTOR GraphFoundEqualBestEvent = {0x4, 0x0, 0x10, 0x4, 0x0, 0x5, 0x8000000000000004}; +#define GraphFoundEqualBestEvent_value 0x4 +EXTERN_C __declspec(selectany) const EVENT_DESCRIPTOR GraphFoundEvent = {0x5, 0x0, 0x10, 0x4, 0x0, 0x6, 0x8000000000000008}; +#define GraphFoundEvent_value 0x5 +EXTERN_C __declspec(selectany) const EVENT_DESCRIPTOR GraphAssignStartEvent = {0x6, 0x0, 0x10, 0x4, 0x1, 0x7, 0x8000000000000010}; +#define GraphAssignStartEvent_value 0x6 +EXTERN_C __declspec(selectany) const EVENT_DESCRIPTOR GraphAssignStopEvent = {0x7, 0x0, 0x10, 0x4, 0x2, 0x7, 0x8000000000000010}; +#define GraphAssignStopEvent_value 0x7 +EXTERN_C __declspec(selectany) const EVENT_DESCRIPTOR RtlGenerateRandomBytesStartEvent = {0x8, 0x0, 0x10, 0x4, 0x1, 0x8, 0x8000000000000020}; +#define RtlGenerateRandomBytesStartEvent_value 0x8 +EXTERN_C __declspec(selectany) const EVENT_DESCRIPTOR RtlGenerateRandomBytesStopEvent = {0x9, 0x0, 0x10, 0x4, 0x2, 0x8, 0x8000000000000020}; +#define RtlGenerateRandomBytesStopEvent_value 0x9 +EXTERN_C __declspec(selectany) const EVENT_DESCRIPTOR GraphAssignResultEvent = {0xa, 0x0, 0x10, 0x4, 0x0, 0x7, 0x8000000000000010}; +#define GraphAssignResultEvent_value 0xa +EXTERN_C __declspec(selectany) const EVENT_DESCRIPTOR GraphIsAcyclicEvent = {0xb, 0x0, 0x10, 0x4, 0x0, 0x9, 0x8000000000000040}; +#define GraphIsAcyclicEvent_value 0xb // // MCGEN_DISABLE_PROVIDER_CODE_GENERATION macro: @@ -621,13 +625,13 @@ EXTERN_C __declspec(selectany) const EVENT_DESCRIPTOR GraphAssignResult = {0xa, // Event Enablement Bits // EXTERN_C __declspec(selectany) DECLSPEC_CACHEALIGN ULONG PerfectHashEnableBits[1]; -EXTERN_C __declspec(selectany) const ULONGLONG PerfectHashKeywords[6] = {0x8000000000000001, 0x8000000000000002, 0x8000000000000004, 0x8000000000000008, 0x8000000000000010, 0x8000000000000020}; -EXTERN_C __declspec(selectany) const unsigned char PerfectHashLevels[6] = {4, 4, 4, 4, 4, 4}; +EXTERN_C __declspec(selectany) const ULONGLONG PerfectHashKeywords[7] = {0x8000000000000001, 0x8000000000000002, 0x8000000000000004, 0x8000000000000008, 0x8000000000000010, 0x8000000000000020, 0x8000000000000040}; +EXTERN_C __declspec(selectany) const unsigned char PerfectHashLevels[7] = {4, 4, 4, 4, 4, 4, 4}; // // Provider context // -EXTERN_C __declspec(selectany) MCGEN_TRACE_CONTEXT PerfectHashEvents_Context = {0, (ULONG_PTR)PerfectHashEvents_Traits, 0, 0, 0, 0, 0, 0, 6, PerfectHashEnableBits, PerfectHashKeywords, PerfectHashLevels}; +EXTERN_C __declspec(selectany) MCGEN_TRACE_CONTEXT PerfectHashEvents_Context = {0, (ULONG_PTR)PerfectHashEvents_Traits, 0, 0, 0, 0, 0, 0, 7, PerfectHashEnableBits, PerfectHashKeywords, PerfectHashLevels}; // // Provider REGHANDLE @@ -716,116 +720,130 @@ EXTERN_C __declspec(selectany) MCGEN_TRACE_CONTEXT PerfectHashEvents_Context = { McTemplateK0zqii(&PerfectHashEvents_Context, &GraphAddHashedKeysEvent, NULL, KeysFileName, NumberOfKeys, Cycles, Microseconds) // -// Enablement check macro for GraphFoundNewBest +// Enablement check macro for GraphFoundNewBestEvent // -#define EventEnabledGraphFoundNewBest() MCGEN_EVENT_BIT_SET(PerfectHashEnableBits, 1) +#define EventEnabledGraphFoundNewBestEvent() MCGEN_EVENT_BIT_SET(PerfectHashEnableBits, 1) // -// Event write macros for GraphFoundNewBest +// Event write macros for GraphFoundNewBestEvent // -#define EventWriteGraphFoundNewBest(Activity, KeysFileName, Attempt, ElapsedMilliseconds, CoverageType, CoverageValue, CoverageValueAsDouble, StopGraphSolving, IsBest, IsEqual, IsCoverageValueDouble, EqualCount, TotalNumberOfPages, TotalNumberOfLargePages, TotalNumberOfCacheLines, NumberOfUsedPages, NumberOfUsedLargePages, NumberOfUsedCacheLines, NumberOfEmptyPages, NumberOfEmptyLargePages, NumberOfEmptyCacheLines, FirstPageUsed, FirstLargePageUsed, FirstCacheLineUsed, LastPageUsed, LastLargePageUsed, LastCacheLineUsed, TotalNumberOfAssigned, NumberOfKeysWithVerticesMappingToSamePage, NumberOfKeysWithVerticesMappingToSameLargePage, NumberOfKeysWithVerticesMappingToSameCacheLine, MaxGraphTraversalDepth, TotalGraphTraversals, Seed1, Seed2, Seed3, Seed4, Seed5, Seed6, Seed7, Seed8, NumberOfAssignedPerCacheLineCounts_0, NumberOfAssignedPerCacheLineCounts_1, NumberOfAssignedPerCacheLineCounts_2, NumberOfAssignedPerCacheLineCounts_3, NumberOfAssignedPerCacheLineCounts_4, NumberOfAssignedPerCacheLineCounts_5, NumberOfAssignedPerCacheLineCounts_6, NumberOfAssignedPerCacheLineCounts_7, NumberOfAssignedPerCacheLineCounts_8, NumberOfAssignedPerCacheLineCounts_9, NumberOfAssignedPerCacheLineCounts_10, NumberOfAssignedPerCacheLineCounts_11, NumberOfAssignedPerCacheLineCounts_12, NumberOfAssignedPerCacheLineCounts_13, NumberOfAssignedPerCacheLineCounts_14, NumberOfAssignedPerCacheLineCounts_15, NumberOfAssignedPerCacheLineCounts_16, Slope, Intercept, CorrelationCoefficient, Score, Rank) \ - MCGEN_EVENT_ENABLED(GraphFoundNewBest) \ - ? McTemplateK0zixqqgttttqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqgggxg(&PerfectHashEvents_Context, &GraphFoundNewBest, Activity, KeysFileName, Attempt, ElapsedMilliseconds, CoverageType, CoverageValue, CoverageValueAsDouble, StopGraphSolving, IsBest, IsEqual, IsCoverageValueDouble, EqualCount, TotalNumberOfPages, TotalNumberOfLargePages, TotalNumberOfCacheLines, NumberOfUsedPages, NumberOfUsedLargePages, NumberOfUsedCacheLines, NumberOfEmptyPages, NumberOfEmptyLargePages, NumberOfEmptyCacheLines, FirstPageUsed, FirstLargePageUsed, FirstCacheLineUsed, LastPageUsed, LastLargePageUsed, LastCacheLineUsed, TotalNumberOfAssigned, NumberOfKeysWithVerticesMappingToSamePage, NumberOfKeysWithVerticesMappingToSameLargePage, NumberOfKeysWithVerticesMappingToSameCacheLine, MaxGraphTraversalDepth, TotalGraphTraversals, Seed1, Seed2, Seed3, Seed4, Seed5, Seed6, Seed7, Seed8, NumberOfAssignedPerCacheLineCounts_0, NumberOfAssignedPerCacheLineCounts_1, NumberOfAssignedPerCacheLineCounts_2, NumberOfAssignedPerCacheLineCounts_3, NumberOfAssignedPerCacheLineCounts_4, NumberOfAssignedPerCacheLineCounts_5, NumberOfAssignedPerCacheLineCounts_6, NumberOfAssignedPerCacheLineCounts_7, NumberOfAssignedPerCacheLineCounts_8, NumberOfAssignedPerCacheLineCounts_9, NumberOfAssignedPerCacheLineCounts_10, NumberOfAssignedPerCacheLineCounts_11, NumberOfAssignedPerCacheLineCounts_12, NumberOfAssignedPerCacheLineCounts_13, NumberOfAssignedPerCacheLineCounts_14, NumberOfAssignedPerCacheLineCounts_15, NumberOfAssignedPerCacheLineCounts_16, Slope, Intercept, CorrelationCoefficient, Score, Rank) : 0 -#define EventWriteGraphFoundNewBest_AssumeEnabled(KeysFileName, Attempt, ElapsedMilliseconds, CoverageType, CoverageValue, CoverageValueAsDouble, StopGraphSolving, IsBest, IsEqual, IsCoverageValueDouble, EqualCount, TotalNumberOfPages, TotalNumberOfLargePages, TotalNumberOfCacheLines, NumberOfUsedPages, NumberOfUsedLargePages, NumberOfUsedCacheLines, NumberOfEmptyPages, NumberOfEmptyLargePages, NumberOfEmptyCacheLines, FirstPageUsed, FirstLargePageUsed, FirstCacheLineUsed, LastPageUsed, LastLargePageUsed, LastCacheLineUsed, TotalNumberOfAssigned, NumberOfKeysWithVerticesMappingToSamePage, NumberOfKeysWithVerticesMappingToSameLargePage, NumberOfKeysWithVerticesMappingToSameCacheLine, MaxGraphTraversalDepth, TotalGraphTraversals, Seed1, Seed2, Seed3, Seed4, Seed5, Seed6, Seed7, Seed8, NumberOfAssignedPerCacheLineCounts_0, NumberOfAssignedPerCacheLineCounts_1, NumberOfAssignedPerCacheLineCounts_2, NumberOfAssignedPerCacheLineCounts_3, NumberOfAssignedPerCacheLineCounts_4, NumberOfAssignedPerCacheLineCounts_5, NumberOfAssignedPerCacheLineCounts_6, NumberOfAssignedPerCacheLineCounts_7, NumberOfAssignedPerCacheLineCounts_8, NumberOfAssignedPerCacheLineCounts_9, NumberOfAssignedPerCacheLineCounts_10, NumberOfAssignedPerCacheLineCounts_11, NumberOfAssignedPerCacheLineCounts_12, NumberOfAssignedPerCacheLineCounts_13, NumberOfAssignedPerCacheLineCounts_14, NumberOfAssignedPerCacheLineCounts_15, NumberOfAssignedPerCacheLineCounts_16, Slope, Intercept, CorrelationCoefficient, Score, Rank) \ - McTemplateK0zixqqgttttqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqgggxg(&PerfectHashEvents_Context, &GraphFoundNewBest, NULL, KeysFileName, Attempt, ElapsedMilliseconds, CoverageType, CoverageValue, CoverageValueAsDouble, StopGraphSolving, IsBest, IsEqual, IsCoverageValueDouble, EqualCount, TotalNumberOfPages, TotalNumberOfLargePages, TotalNumberOfCacheLines, NumberOfUsedPages, NumberOfUsedLargePages, NumberOfUsedCacheLines, NumberOfEmptyPages, NumberOfEmptyLargePages, NumberOfEmptyCacheLines, FirstPageUsed, FirstLargePageUsed, FirstCacheLineUsed, LastPageUsed, LastLargePageUsed, LastCacheLineUsed, TotalNumberOfAssigned, NumberOfKeysWithVerticesMappingToSamePage, NumberOfKeysWithVerticesMappingToSameLargePage, NumberOfKeysWithVerticesMappingToSameCacheLine, MaxGraphTraversalDepth, TotalGraphTraversals, Seed1, Seed2, Seed3, Seed4, Seed5, Seed6, Seed7, Seed8, NumberOfAssignedPerCacheLineCounts_0, NumberOfAssignedPerCacheLineCounts_1, NumberOfAssignedPerCacheLineCounts_2, NumberOfAssignedPerCacheLineCounts_3, NumberOfAssignedPerCacheLineCounts_4, NumberOfAssignedPerCacheLineCounts_5, NumberOfAssignedPerCacheLineCounts_6, NumberOfAssignedPerCacheLineCounts_7, NumberOfAssignedPerCacheLineCounts_8, NumberOfAssignedPerCacheLineCounts_9, NumberOfAssignedPerCacheLineCounts_10, NumberOfAssignedPerCacheLineCounts_11, NumberOfAssignedPerCacheLineCounts_12, NumberOfAssignedPerCacheLineCounts_13, NumberOfAssignedPerCacheLineCounts_14, NumberOfAssignedPerCacheLineCounts_15, NumberOfAssignedPerCacheLineCounts_16, Slope, Intercept, CorrelationCoefficient, Score, Rank) +#define EventWriteGraphFoundNewBestEvent(Activity, KeysFileName, Attempt, SolutionNumber, ElapsedMilliseconds, CoverageType, CoverageValue, CoverageValueAsDouble, StopGraphSolving, IsBest, IsEqual, IsCoverageValueDouble, EqualCount, TotalNumberOfPages, TotalNumberOfLargePages, TotalNumberOfCacheLines, NumberOfUsedPages, NumberOfUsedLargePages, NumberOfUsedCacheLines, NumberOfEmptyPages, NumberOfEmptyLargePages, NumberOfEmptyCacheLines, FirstPageUsed, FirstLargePageUsed, FirstCacheLineUsed, LastPageUsed, LastLargePageUsed, LastCacheLineUsed, TotalNumberOfAssigned, NumberOfKeysWithVerticesMappingToSamePage, NumberOfKeysWithVerticesMappingToSameLargePage, NumberOfKeysWithVerticesMappingToSameCacheLine, MaxGraphTraversalDepth, TotalGraphTraversals, Seed1, Seed2, Seed3, Seed4, Seed5, Seed6, Seed7, Seed8, NumberOfAssignedPerCacheLineCounts_0, NumberOfAssignedPerCacheLineCounts_1, NumberOfAssignedPerCacheLineCounts_2, NumberOfAssignedPerCacheLineCounts_3, NumberOfAssignedPerCacheLineCounts_4, NumberOfAssignedPerCacheLineCounts_5, NumberOfAssignedPerCacheLineCounts_6, NumberOfAssignedPerCacheLineCounts_7, NumberOfAssignedPerCacheLineCounts_8, NumberOfAssignedPerCacheLineCounts_9, NumberOfAssignedPerCacheLineCounts_10, NumberOfAssignedPerCacheLineCounts_11, NumberOfAssignedPerCacheLineCounts_12, NumberOfAssignedPerCacheLineCounts_13, NumberOfAssignedPerCacheLineCounts_14, NumberOfAssignedPerCacheLineCounts_15, NumberOfAssignedPerCacheLineCounts_16, Slope, Intercept, CorrelationCoefficient, Score, Rank) \ + MCGEN_EVENT_ENABLED(GraphFoundNewBestEvent) \ + ? McTemplateK0zixxqqgttttqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqgggxg(&PerfectHashEvents_Context, &GraphFoundNewBestEvent, Activity, KeysFileName, Attempt, SolutionNumber, ElapsedMilliseconds, CoverageType, CoverageValue, CoverageValueAsDouble, StopGraphSolving, IsBest, IsEqual, IsCoverageValueDouble, EqualCount, TotalNumberOfPages, TotalNumberOfLargePages, TotalNumberOfCacheLines, NumberOfUsedPages, NumberOfUsedLargePages, NumberOfUsedCacheLines, NumberOfEmptyPages, NumberOfEmptyLargePages, NumberOfEmptyCacheLines, FirstPageUsed, FirstLargePageUsed, FirstCacheLineUsed, LastPageUsed, LastLargePageUsed, LastCacheLineUsed, TotalNumberOfAssigned, NumberOfKeysWithVerticesMappingToSamePage, NumberOfKeysWithVerticesMappingToSameLargePage, NumberOfKeysWithVerticesMappingToSameCacheLine, MaxGraphTraversalDepth, TotalGraphTraversals, Seed1, Seed2, Seed3, Seed4, Seed5, Seed6, Seed7, Seed8, NumberOfAssignedPerCacheLineCounts_0, NumberOfAssignedPerCacheLineCounts_1, NumberOfAssignedPerCacheLineCounts_2, NumberOfAssignedPerCacheLineCounts_3, NumberOfAssignedPerCacheLineCounts_4, NumberOfAssignedPerCacheLineCounts_5, NumberOfAssignedPerCacheLineCounts_6, NumberOfAssignedPerCacheLineCounts_7, NumberOfAssignedPerCacheLineCounts_8, NumberOfAssignedPerCacheLineCounts_9, NumberOfAssignedPerCacheLineCounts_10, NumberOfAssignedPerCacheLineCounts_11, NumberOfAssignedPerCacheLineCounts_12, NumberOfAssignedPerCacheLineCounts_13, NumberOfAssignedPerCacheLineCounts_14, NumberOfAssignedPerCacheLineCounts_15, NumberOfAssignedPerCacheLineCounts_16, Slope, Intercept, CorrelationCoefficient, Score, Rank) : 0 +#define EventWriteGraphFoundNewBestEvent_AssumeEnabled(KeysFileName, Attempt, SolutionNumber, ElapsedMilliseconds, CoverageType, CoverageValue, CoverageValueAsDouble, StopGraphSolving, IsBest, IsEqual, IsCoverageValueDouble, EqualCount, TotalNumberOfPages, TotalNumberOfLargePages, TotalNumberOfCacheLines, NumberOfUsedPages, NumberOfUsedLargePages, NumberOfUsedCacheLines, NumberOfEmptyPages, NumberOfEmptyLargePages, NumberOfEmptyCacheLines, FirstPageUsed, FirstLargePageUsed, FirstCacheLineUsed, LastPageUsed, LastLargePageUsed, LastCacheLineUsed, TotalNumberOfAssigned, NumberOfKeysWithVerticesMappingToSamePage, NumberOfKeysWithVerticesMappingToSameLargePage, NumberOfKeysWithVerticesMappingToSameCacheLine, MaxGraphTraversalDepth, TotalGraphTraversals, Seed1, Seed2, Seed3, Seed4, Seed5, Seed6, Seed7, Seed8, NumberOfAssignedPerCacheLineCounts_0, NumberOfAssignedPerCacheLineCounts_1, NumberOfAssignedPerCacheLineCounts_2, NumberOfAssignedPerCacheLineCounts_3, NumberOfAssignedPerCacheLineCounts_4, NumberOfAssignedPerCacheLineCounts_5, NumberOfAssignedPerCacheLineCounts_6, NumberOfAssignedPerCacheLineCounts_7, NumberOfAssignedPerCacheLineCounts_8, NumberOfAssignedPerCacheLineCounts_9, NumberOfAssignedPerCacheLineCounts_10, NumberOfAssignedPerCacheLineCounts_11, NumberOfAssignedPerCacheLineCounts_12, NumberOfAssignedPerCacheLineCounts_13, NumberOfAssignedPerCacheLineCounts_14, NumberOfAssignedPerCacheLineCounts_15, NumberOfAssignedPerCacheLineCounts_16, Slope, Intercept, CorrelationCoefficient, Score, Rank) \ + McTemplateK0zixxqqgttttqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqgggxg(&PerfectHashEvents_Context, &GraphFoundNewBestEvent, NULL, KeysFileName, Attempt, SolutionNumber, ElapsedMilliseconds, CoverageType, CoverageValue, CoverageValueAsDouble, StopGraphSolving, IsBest, IsEqual, IsCoverageValueDouble, EqualCount, TotalNumberOfPages, TotalNumberOfLargePages, TotalNumberOfCacheLines, NumberOfUsedPages, NumberOfUsedLargePages, NumberOfUsedCacheLines, NumberOfEmptyPages, NumberOfEmptyLargePages, NumberOfEmptyCacheLines, FirstPageUsed, FirstLargePageUsed, FirstCacheLineUsed, LastPageUsed, LastLargePageUsed, LastCacheLineUsed, TotalNumberOfAssigned, NumberOfKeysWithVerticesMappingToSamePage, NumberOfKeysWithVerticesMappingToSameLargePage, NumberOfKeysWithVerticesMappingToSameCacheLine, MaxGraphTraversalDepth, TotalGraphTraversals, Seed1, Seed2, Seed3, Seed4, Seed5, Seed6, Seed7, Seed8, NumberOfAssignedPerCacheLineCounts_0, NumberOfAssignedPerCacheLineCounts_1, NumberOfAssignedPerCacheLineCounts_2, NumberOfAssignedPerCacheLineCounts_3, NumberOfAssignedPerCacheLineCounts_4, NumberOfAssignedPerCacheLineCounts_5, NumberOfAssignedPerCacheLineCounts_6, NumberOfAssignedPerCacheLineCounts_7, NumberOfAssignedPerCacheLineCounts_8, NumberOfAssignedPerCacheLineCounts_9, NumberOfAssignedPerCacheLineCounts_10, NumberOfAssignedPerCacheLineCounts_11, NumberOfAssignedPerCacheLineCounts_12, NumberOfAssignedPerCacheLineCounts_13, NumberOfAssignedPerCacheLineCounts_14, NumberOfAssignedPerCacheLineCounts_15, NumberOfAssignedPerCacheLineCounts_16, Slope, Intercept, CorrelationCoefficient, Score, Rank) // -// Enablement check macro for GraphFoundEqualBest +// Enablement check macro for GraphFoundEqualBestEvent // -#define EventEnabledGraphFoundEqualBest() MCGEN_EVENT_BIT_SET(PerfectHashEnableBits, 2) +#define EventEnabledGraphFoundEqualBestEvent() MCGEN_EVENT_BIT_SET(PerfectHashEnableBits, 2) // -// Event write macros for GraphFoundEqualBest +// Event write macros for GraphFoundEqualBestEvent // -#define EventWriteGraphFoundEqualBest(Activity, KeysFileName, Attempt, ElapsedMilliseconds, CoverageType, CoverageValue, CoverageValueAsDouble, StopGraphSolving, IsBest, IsEqual, IsCoverageValueDouble, EqualCount, TotalNumberOfPages, TotalNumberOfLargePages, TotalNumberOfCacheLines, NumberOfUsedPages, NumberOfUsedLargePages, NumberOfUsedCacheLines, NumberOfEmptyPages, NumberOfEmptyLargePages, NumberOfEmptyCacheLines, FirstPageUsed, FirstLargePageUsed, FirstCacheLineUsed, LastPageUsed, LastLargePageUsed, LastCacheLineUsed, TotalNumberOfAssigned, NumberOfKeysWithVerticesMappingToSamePage, NumberOfKeysWithVerticesMappingToSameLargePage, NumberOfKeysWithVerticesMappingToSameCacheLine, MaxGraphTraversalDepth, TotalGraphTraversals, Seed1, Seed2, Seed3, Seed4, Seed5, Seed6, Seed7, Seed8, NumberOfAssignedPerCacheLineCounts_0, NumberOfAssignedPerCacheLineCounts_1, NumberOfAssignedPerCacheLineCounts_2, NumberOfAssignedPerCacheLineCounts_3, NumberOfAssignedPerCacheLineCounts_4, NumberOfAssignedPerCacheLineCounts_5, NumberOfAssignedPerCacheLineCounts_6, NumberOfAssignedPerCacheLineCounts_7, NumberOfAssignedPerCacheLineCounts_8, NumberOfAssignedPerCacheLineCounts_9, NumberOfAssignedPerCacheLineCounts_10, NumberOfAssignedPerCacheLineCounts_11, NumberOfAssignedPerCacheLineCounts_12, NumberOfAssignedPerCacheLineCounts_13, NumberOfAssignedPerCacheLineCounts_14, NumberOfAssignedPerCacheLineCounts_15, NumberOfAssignedPerCacheLineCounts_16, Slope, Intercept, CorrelationCoefficient, Score, Rank) \ - MCGEN_EVENT_ENABLED(GraphFoundEqualBest) \ - ? McTemplateK0zixqqgttttqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqgggxg(&PerfectHashEvents_Context, &GraphFoundEqualBest, Activity, KeysFileName, Attempt, ElapsedMilliseconds, CoverageType, CoverageValue, CoverageValueAsDouble, StopGraphSolving, IsBest, IsEqual, IsCoverageValueDouble, EqualCount, TotalNumberOfPages, TotalNumberOfLargePages, TotalNumberOfCacheLines, NumberOfUsedPages, NumberOfUsedLargePages, NumberOfUsedCacheLines, NumberOfEmptyPages, NumberOfEmptyLargePages, NumberOfEmptyCacheLines, FirstPageUsed, FirstLargePageUsed, FirstCacheLineUsed, LastPageUsed, LastLargePageUsed, LastCacheLineUsed, TotalNumberOfAssigned, NumberOfKeysWithVerticesMappingToSamePage, NumberOfKeysWithVerticesMappingToSameLargePage, NumberOfKeysWithVerticesMappingToSameCacheLine, MaxGraphTraversalDepth, TotalGraphTraversals, Seed1, Seed2, Seed3, Seed4, Seed5, Seed6, Seed7, Seed8, NumberOfAssignedPerCacheLineCounts_0, NumberOfAssignedPerCacheLineCounts_1, NumberOfAssignedPerCacheLineCounts_2, NumberOfAssignedPerCacheLineCounts_3, NumberOfAssignedPerCacheLineCounts_4, NumberOfAssignedPerCacheLineCounts_5, NumberOfAssignedPerCacheLineCounts_6, NumberOfAssignedPerCacheLineCounts_7, NumberOfAssignedPerCacheLineCounts_8, NumberOfAssignedPerCacheLineCounts_9, NumberOfAssignedPerCacheLineCounts_10, NumberOfAssignedPerCacheLineCounts_11, NumberOfAssignedPerCacheLineCounts_12, NumberOfAssignedPerCacheLineCounts_13, NumberOfAssignedPerCacheLineCounts_14, NumberOfAssignedPerCacheLineCounts_15, NumberOfAssignedPerCacheLineCounts_16, Slope, Intercept, CorrelationCoefficient, Score, Rank) : 0 -#define EventWriteGraphFoundEqualBest_AssumeEnabled(KeysFileName, Attempt, ElapsedMilliseconds, CoverageType, CoverageValue, CoverageValueAsDouble, StopGraphSolving, IsBest, IsEqual, IsCoverageValueDouble, EqualCount, TotalNumberOfPages, TotalNumberOfLargePages, TotalNumberOfCacheLines, NumberOfUsedPages, NumberOfUsedLargePages, NumberOfUsedCacheLines, NumberOfEmptyPages, NumberOfEmptyLargePages, NumberOfEmptyCacheLines, FirstPageUsed, FirstLargePageUsed, FirstCacheLineUsed, LastPageUsed, LastLargePageUsed, LastCacheLineUsed, TotalNumberOfAssigned, NumberOfKeysWithVerticesMappingToSamePage, NumberOfKeysWithVerticesMappingToSameLargePage, NumberOfKeysWithVerticesMappingToSameCacheLine, MaxGraphTraversalDepth, TotalGraphTraversals, Seed1, Seed2, Seed3, Seed4, Seed5, Seed6, Seed7, Seed8, NumberOfAssignedPerCacheLineCounts_0, NumberOfAssignedPerCacheLineCounts_1, NumberOfAssignedPerCacheLineCounts_2, NumberOfAssignedPerCacheLineCounts_3, NumberOfAssignedPerCacheLineCounts_4, NumberOfAssignedPerCacheLineCounts_5, NumberOfAssignedPerCacheLineCounts_6, NumberOfAssignedPerCacheLineCounts_7, NumberOfAssignedPerCacheLineCounts_8, NumberOfAssignedPerCacheLineCounts_9, NumberOfAssignedPerCacheLineCounts_10, NumberOfAssignedPerCacheLineCounts_11, NumberOfAssignedPerCacheLineCounts_12, NumberOfAssignedPerCacheLineCounts_13, NumberOfAssignedPerCacheLineCounts_14, NumberOfAssignedPerCacheLineCounts_15, NumberOfAssignedPerCacheLineCounts_16, Slope, Intercept, CorrelationCoefficient, Score, Rank) \ - McTemplateK0zixqqgttttqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqgggxg(&PerfectHashEvents_Context, &GraphFoundEqualBest, NULL, KeysFileName, Attempt, ElapsedMilliseconds, CoverageType, CoverageValue, CoverageValueAsDouble, StopGraphSolving, IsBest, IsEqual, IsCoverageValueDouble, EqualCount, TotalNumberOfPages, TotalNumberOfLargePages, TotalNumberOfCacheLines, NumberOfUsedPages, NumberOfUsedLargePages, NumberOfUsedCacheLines, NumberOfEmptyPages, NumberOfEmptyLargePages, NumberOfEmptyCacheLines, FirstPageUsed, FirstLargePageUsed, FirstCacheLineUsed, LastPageUsed, LastLargePageUsed, LastCacheLineUsed, TotalNumberOfAssigned, NumberOfKeysWithVerticesMappingToSamePage, NumberOfKeysWithVerticesMappingToSameLargePage, NumberOfKeysWithVerticesMappingToSameCacheLine, MaxGraphTraversalDepth, TotalGraphTraversals, Seed1, Seed2, Seed3, Seed4, Seed5, Seed6, Seed7, Seed8, NumberOfAssignedPerCacheLineCounts_0, NumberOfAssignedPerCacheLineCounts_1, NumberOfAssignedPerCacheLineCounts_2, NumberOfAssignedPerCacheLineCounts_3, NumberOfAssignedPerCacheLineCounts_4, NumberOfAssignedPerCacheLineCounts_5, NumberOfAssignedPerCacheLineCounts_6, NumberOfAssignedPerCacheLineCounts_7, NumberOfAssignedPerCacheLineCounts_8, NumberOfAssignedPerCacheLineCounts_9, NumberOfAssignedPerCacheLineCounts_10, NumberOfAssignedPerCacheLineCounts_11, NumberOfAssignedPerCacheLineCounts_12, NumberOfAssignedPerCacheLineCounts_13, NumberOfAssignedPerCacheLineCounts_14, NumberOfAssignedPerCacheLineCounts_15, NumberOfAssignedPerCacheLineCounts_16, Slope, Intercept, CorrelationCoefficient, Score, Rank) +#define EventWriteGraphFoundEqualBestEvent(Activity, KeysFileName, Attempt, SolutionNumber, ElapsedMilliseconds, CoverageType, CoverageValue, CoverageValueAsDouble, StopGraphSolving, IsBest, IsEqual, IsCoverageValueDouble, EqualCount, TotalNumberOfPages, TotalNumberOfLargePages, TotalNumberOfCacheLines, NumberOfUsedPages, NumberOfUsedLargePages, NumberOfUsedCacheLines, NumberOfEmptyPages, NumberOfEmptyLargePages, NumberOfEmptyCacheLines, FirstPageUsed, FirstLargePageUsed, FirstCacheLineUsed, LastPageUsed, LastLargePageUsed, LastCacheLineUsed, TotalNumberOfAssigned, NumberOfKeysWithVerticesMappingToSamePage, NumberOfKeysWithVerticesMappingToSameLargePage, NumberOfKeysWithVerticesMappingToSameCacheLine, MaxGraphTraversalDepth, TotalGraphTraversals, Seed1, Seed2, Seed3, Seed4, Seed5, Seed6, Seed7, Seed8, NumberOfAssignedPerCacheLineCounts_0, NumberOfAssignedPerCacheLineCounts_1, NumberOfAssignedPerCacheLineCounts_2, NumberOfAssignedPerCacheLineCounts_3, NumberOfAssignedPerCacheLineCounts_4, NumberOfAssignedPerCacheLineCounts_5, NumberOfAssignedPerCacheLineCounts_6, NumberOfAssignedPerCacheLineCounts_7, NumberOfAssignedPerCacheLineCounts_8, NumberOfAssignedPerCacheLineCounts_9, NumberOfAssignedPerCacheLineCounts_10, NumberOfAssignedPerCacheLineCounts_11, NumberOfAssignedPerCacheLineCounts_12, NumberOfAssignedPerCacheLineCounts_13, NumberOfAssignedPerCacheLineCounts_14, NumberOfAssignedPerCacheLineCounts_15, NumberOfAssignedPerCacheLineCounts_16, Slope, Intercept, CorrelationCoefficient, Score, Rank) \ + MCGEN_EVENT_ENABLED(GraphFoundEqualBestEvent) \ + ? McTemplateK0zixxqqgttttqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqgggxg(&PerfectHashEvents_Context, &GraphFoundEqualBestEvent, Activity, KeysFileName, Attempt, SolutionNumber, ElapsedMilliseconds, CoverageType, CoverageValue, CoverageValueAsDouble, StopGraphSolving, IsBest, IsEqual, IsCoverageValueDouble, EqualCount, TotalNumberOfPages, TotalNumberOfLargePages, TotalNumberOfCacheLines, NumberOfUsedPages, NumberOfUsedLargePages, NumberOfUsedCacheLines, NumberOfEmptyPages, NumberOfEmptyLargePages, NumberOfEmptyCacheLines, FirstPageUsed, FirstLargePageUsed, FirstCacheLineUsed, LastPageUsed, LastLargePageUsed, LastCacheLineUsed, TotalNumberOfAssigned, NumberOfKeysWithVerticesMappingToSamePage, NumberOfKeysWithVerticesMappingToSameLargePage, NumberOfKeysWithVerticesMappingToSameCacheLine, MaxGraphTraversalDepth, TotalGraphTraversals, Seed1, Seed2, Seed3, Seed4, Seed5, Seed6, Seed7, Seed8, NumberOfAssignedPerCacheLineCounts_0, NumberOfAssignedPerCacheLineCounts_1, NumberOfAssignedPerCacheLineCounts_2, NumberOfAssignedPerCacheLineCounts_3, NumberOfAssignedPerCacheLineCounts_4, NumberOfAssignedPerCacheLineCounts_5, NumberOfAssignedPerCacheLineCounts_6, NumberOfAssignedPerCacheLineCounts_7, NumberOfAssignedPerCacheLineCounts_8, NumberOfAssignedPerCacheLineCounts_9, NumberOfAssignedPerCacheLineCounts_10, NumberOfAssignedPerCacheLineCounts_11, NumberOfAssignedPerCacheLineCounts_12, NumberOfAssignedPerCacheLineCounts_13, NumberOfAssignedPerCacheLineCounts_14, NumberOfAssignedPerCacheLineCounts_15, NumberOfAssignedPerCacheLineCounts_16, Slope, Intercept, CorrelationCoefficient, Score, Rank) : 0 +#define EventWriteGraphFoundEqualBestEvent_AssumeEnabled(KeysFileName, Attempt, SolutionNumber, ElapsedMilliseconds, CoverageType, CoverageValue, CoverageValueAsDouble, StopGraphSolving, IsBest, IsEqual, IsCoverageValueDouble, EqualCount, TotalNumberOfPages, TotalNumberOfLargePages, TotalNumberOfCacheLines, NumberOfUsedPages, NumberOfUsedLargePages, NumberOfUsedCacheLines, NumberOfEmptyPages, NumberOfEmptyLargePages, NumberOfEmptyCacheLines, FirstPageUsed, FirstLargePageUsed, FirstCacheLineUsed, LastPageUsed, LastLargePageUsed, LastCacheLineUsed, TotalNumberOfAssigned, NumberOfKeysWithVerticesMappingToSamePage, NumberOfKeysWithVerticesMappingToSameLargePage, NumberOfKeysWithVerticesMappingToSameCacheLine, MaxGraphTraversalDepth, TotalGraphTraversals, Seed1, Seed2, Seed3, Seed4, Seed5, Seed6, Seed7, Seed8, NumberOfAssignedPerCacheLineCounts_0, NumberOfAssignedPerCacheLineCounts_1, NumberOfAssignedPerCacheLineCounts_2, NumberOfAssignedPerCacheLineCounts_3, NumberOfAssignedPerCacheLineCounts_4, NumberOfAssignedPerCacheLineCounts_5, NumberOfAssignedPerCacheLineCounts_6, NumberOfAssignedPerCacheLineCounts_7, NumberOfAssignedPerCacheLineCounts_8, NumberOfAssignedPerCacheLineCounts_9, NumberOfAssignedPerCacheLineCounts_10, NumberOfAssignedPerCacheLineCounts_11, NumberOfAssignedPerCacheLineCounts_12, NumberOfAssignedPerCacheLineCounts_13, NumberOfAssignedPerCacheLineCounts_14, NumberOfAssignedPerCacheLineCounts_15, NumberOfAssignedPerCacheLineCounts_16, Slope, Intercept, CorrelationCoefficient, Score, Rank) \ + McTemplateK0zixxqqgttttqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqgggxg(&PerfectHashEvents_Context, &GraphFoundEqualBestEvent, NULL, KeysFileName, Attempt, SolutionNumber, ElapsedMilliseconds, CoverageType, CoverageValue, CoverageValueAsDouble, StopGraphSolving, IsBest, IsEqual, IsCoverageValueDouble, EqualCount, TotalNumberOfPages, TotalNumberOfLargePages, TotalNumberOfCacheLines, NumberOfUsedPages, NumberOfUsedLargePages, NumberOfUsedCacheLines, NumberOfEmptyPages, NumberOfEmptyLargePages, NumberOfEmptyCacheLines, FirstPageUsed, FirstLargePageUsed, FirstCacheLineUsed, LastPageUsed, LastLargePageUsed, LastCacheLineUsed, TotalNumberOfAssigned, NumberOfKeysWithVerticesMappingToSamePage, NumberOfKeysWithVerticesMappingToSameLargePage, NumberOfKeysWithVerticesMappingToSameCacheLine, MaxGraphTraversalDepth, TotalGraphTraversals, Seed1, Seed2, Seed3, Seed4, Seed5, Seed6, Seed7, Seed8, NumberOfAssignedPerCacheLineCounts_0, NumberOfAssignedPerCacheLineCounts_1, NumberOfAssignedPerCacheLineCounts_2, NumberOfAssignedPerCacheLineCounts_3, NumberOfAssignedPerCacheLineCounts_4, NumberOfAssignedPerCacheLineCounts_5, NumberOfAssignedPerCacheLineCounts_6, NumberOfAssignedPerCacheLineCounts_7, NumberOfAssignedPerCacheLineCounts_8, NumberOfAssignedPerCacheLineCounts_9, NumberOfAssignedPerCacheLineCounts_10, NumberOfAssignedPerCacheLineCounts_11, NumberOfAssignedPerCacheLineCounts_12, NumberOfAssignedPerCacheLineCounts_13, NumberOfAssignedPerCacheLineCounts_14, NumberOfAssignedPerCacheLineCounts_15, NumberOfAssignedPerCacheLineCounts_16, Slope, Intercept, CorrelationCoefficient, Score, Rank) // -// Enablement check macro for GraphFound +// Enablement check macro for GraphFoundEvent // -#define EventEnabledGraphFound() MCGEN_EVENT_BIT_SET(PerfectHashEnableBits, 3) +#define EventEnabledGraphFoundEvent() MCGEN_EVENT_BIT_SET(PerfectHashEnableBits, 3) // -// Event write macros for GraphFound +// Event write macros for GraphFoundEvent // -#define EventWriteGraphFound(Activity, KeysFileName, Attempt, ElapsedMilliseconds, CoverageType, CoverageValue, CoverageValueAsDouble, StopGraphSolving, IsBest, IsEqual, IsCoverageValueDouble, EqualCount, TotalNumberOfPages, TotalNumberOfLargePages, TotalNumberOfCacheLines, NumberOfUsedPages, NumberOfUsedLargePages, NumberOfUsedCacheLines, NumberOfEmptyPages, NumberOfEmptyLargePages, NumberOfEmptyCacheLines, FirstPageUsed, FirstLargePageUsed, FirstCacheLineUsed, LastPageUsed, LastLargePageUsed, LastCacheLineUsed, TotalNumberOfAssigned, NumberOfKeysWithVerticesMappingToSamePage, NumberOfKeysWithVerticesMappingToSameLargePage, NumberOfKeysWithVerticesMappingToSameCacheLine, MaxGraphTraversalDepth, TotalGraphTraversals, Seed1, Seed2, Seed3, Seed4, Seed5, Seed6, Seed7, Seed8, NumberOfAssignedPerCacheLineCounts_0, NumberOfAssignedPerCacheLineCounts_1, NumberOfAssignedPerCacheLineCounts_2, NumberOfAssignedPerCacheLineCounts_3, NumberOfAssignedPerCacheLineCounts_4, NumberOfAssignedPerCacheLineCounts_5, NumberOfAssignedPerCacheLineCounts_6, NumberOfAssignedPerCacheLineCounts_7, NumberOfAssignedPerCacheLineCounts_8, NumberOfAssignedPerCacheLineCounts_9, NumberOfAssignedPerCacheLineCounts_10, NumberOfAssignedPerCacheLineCounts_11, NumberOfAssignedPerCacheLineCounts_12, NumberOfAssignedPerCacheLineCounts_13, NumberOfAssignedPerCacheLineCounts_14, NumberOfAssignedPerCacheLineCounts_15, NumberOfAssignedPerCacheLineCounts_16, Slope, Intercept, CorrelationCoefficient, Score, Rank) \ - MCGEN_EVENT_ENABLED(GraphFound) \ - ? McTemplateK0zixqqgttttqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqgggxg(&PerfectHashEvents_Context, &GraphFound, Activity, KeysFileName, Attempt, ElapsedMilliseconds, CoverageType, CoverageValue, CoverageValueAsDouble, StopGraphSolving, IsBest, IsEqual, IsCoverageValueDouble, EqualCount, TotalNumberOfPages, TotalNumberOfLargePages, TotalNumberOfCacheLines, NumberOfUsedPages, NumberOfUsedLargePages, NumberOfUsedCacheLines, NumberOfEmptyPages, NumberOfEmptyLargePages, NumberOfEmptyCacheLines, FirstPageUsed, FirstLargePageUsed, FirstCacheLineUsed, LastPageUsed, LastLargePageUsed, LastCacheLineUsed, TotalNumberOfAssigned, NumberOfKeysWithVerticesMappingToSamePage, NumberOfKeysWithVerticesMappingToSameLargePage, NumberOfKeysWithVerticesMappingToSameCacheLine, MaxGraphTraversalDepth, TotalGraphTraversals, Seed1, Seed2, Seed3, Seed4, Seed5, Seed6, Seed7, Seed8, NumberOfAssignedPerCacheLineCounts_0, NumberOfAssignedPerCacheLineCounts_1, NumberOfAssignedPerCacheLineCounts_2, NumberOfAssignedPerCacheLineCounts_3, NumberOfAssignedPerCacheLineCounts_4, NumberOfAssignedPerCacheLineCounts_5, NumberOfAssignedPerCacheLineCounts_6, NumberOfAssignedPerCacheLineCounts_7, NumberOfAssignedPerCacheLineCounts_8, NumberOfAssignedPerCacheLineCounts_9, NumberOfAssignedPerCacheLineCounts_10, NumberOfAssignedPerCacheLineCounts_11, NumberOfAssignedPerCacheLineCounts_12, NumberOfAssignedPerCacheLineCounts_13, NumberOfAssignedPerCacheLineCounts_14, NumberOfAssignedPerCacheLineCounts_15, NumberOfAssignedPerCacheLineCounts_16, Slope, Intercept, CorrelationCoefficient, Score, Rank) : 0 -#define EventWriteGraphFound_AssumeEnabled(KeysFileName, Attempt, ElapsedMilliseconds, CoverageType, CoverageValue, CoverageValueAsDouble, StopGraphSolving, IsBest, IsEqual, IsCoverageValueDouble, EqualCount, TotalNumberOfPages, TotalNumberOfLargePages, TotalNumberOfCacheLines, NumberOfUsedPages, NumberOfUsedLargePages, NumberOfUsedCacheLines, NumberOfEmptyPages, NumberOfEmptyLargePages, NumberOfEmptyCacheLines, FirstPageUsed, FirstLargePageUsed, FirstCacheLineUsed, LastPageUsed, LastLargePageUsed, LastCacheLineUsed, TotalNumberOfAssigned, NumberOfKeysWithVerticesMappingToSamePage, NumberOfKeysWithVerticesMappingToSameLargePage, NumberOfKeysWithVerticesMappingToSameCacheLine, MaxGraphTraversalDepth, TotalGraphTraversals, Seed1, Seed2, Seed3, Seed4, Seed5, Seed6, Seed7, Seed8, NumberOfAssignedPerCacheLineCounts_0, NumberOfAssignedPerCacheLineCounts_1, NumberOfAssignedPerCacheLineCounts_2, NumberOfAssignedPerCacheLineCounts_3, NumberOfAssignedPerCacheLineCounts_4, NumberOfAssignedPerCacheLineCounts_5, NumberOfAssignedPerCacheLineCounts_6, NumberOfAssignedPerCacheLineCounts_7, NumberOfAssignedPerCacheLineCounts_8, NumberOfAssignedPerCacheLineCounts_9, NumberOfAssignedPerCacheLineCounts_10, NumberOfAssignedPerCacheLineCounts_11, NumberOfAssignedPerCacheLineCounts_12, NumberOfAssignedPerCacheLineCounts_13, NumberOfAssignedPerCacheLineCounts_14, NumberOfAssignedPerCacheLineCounts_15, NumberOfAssignedPerCacheLineCounts_16, Slope, Intercept, CorrelationCoefficient, Score, Rank) \ - McTemplateK0zixqqgttttqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqgggxg(&PerfectHashEvents_Context, &GraphFound, NULL, KeysFileName, Attempt, ElapsedMilliseconds, CoverageType, CoverageValue, CoverageValueAsDouble, StopGraphSolving, IsBest, IsEqual, IsCoverageValueDouble, EqualCount, TotalNumberOfPages, TotalNumberOfLargePages, TotalNumberOfCacheLines, NumberOfUsedPages, NumberOfUsedLargePages, NumberOfUsedCacheLines, NumberOfEmptyPages, NumberOfEmptyLargePages, NumberOfEmptyCacheLines, FirstPageUsed, FirstLargePageUsed, FirstCacheLineUsed, LastPageUsed, LastLargePageUsed, LastCacheLineUsed, TotalNumberOfAssigned, NumberOfKeysWithVerticesMappingToSamePage, NumberOfKeysWithVerticesMappingToSameLargePage, NumberOfKeysWithVerticesMappingToSameCacheLine, MaxGraphTraversalDepth, TotalGraphTraversals, Seed1, Seed2, Seed3, Seed4, Seed5, Seed6, Seed7, Seed8, NumberOfAssignedPerCacheLineCounts_0, NumberOfAssignedPerCacheLineCounts_1, NumberOfAssignedPerCacheLineCounts_2, NumberOfAssignedPerCacheLineCounts_3, NumberOfAssignedPerCacheLineCounts_4, NumberOfAssignedPerCacheLineCounts_5, NumberOfAssignedPerCacheLineCounts_6, NumberOfAssignedPerCacheLineCounts_7, NumberOfAssignedPerCacheLineCounts_8, NumberOfAssignedPerCacheLineCounts_9, NumberOfAssignedPerCacheLineCounts_10, NumberOfAssignedPerCacheLineCounts_11, NumberOfAssignedPerCacheLineCounts_12, NumberOfAssignedPerCacheLineCounts_13, NumberOfAssignedPerCacheLineCounts_14, NumberOfAssignedPerCacheLineCounts_15, NumberOfAssignedPerCacheLineCounts_16, Slope, Intercept, CorrelationCoefficient, Score, Rank) +#define EventWriteGraphFoundEvent(Activity, KeysFileName, Attempt, SolutionNumber, ElapsedMilliseconds, CoverageType, CoverageValue, CoverageValueAsDouble, StopGraphSolving, IsBest, IsEqual, IsCoverageValueDouble, EqualCount, TotalNumberOfPages, TotalNumberOfLargePages, TotalNumberOfCacheLines, NumberOfUsedPages, NumberOfUsedLargePages, NumberOfUsedCacheLines, NumberOfEmptyPages, NumberOfEmptyLargePages, NumberOfEmptyCacheLines, FirstPageUsed, FirstLargePageUsed, FirstCacheLineUsed, LastPageUsed, LastLargePageUsed, LastCacheLineUsed, TotalNumberOfAssigned, NumberOfKeysWithVerticesMappingToSamePage, NumberOfKeysWithVerticesMappingToSameLargePage, NumberOfKeysWithVerticesMappingToSameCacheLine, MaxGraphTraversalDepth, TotalGraphTraversals, Seed1, Seed2, Seed3, Seed4, Seed5, Seed6, Seed7, Seed8, NumberOfAssignedPerCacheLineCounts_0, NumberOfAssignedPerCacheLineCounts_1, NumberOfAssignedPerCacheLineCounts_2, NumberOfAssignedPerCacheLineCounts_3, NumberOfAssignedPerCacheLineCounts_4, NumberOfAssignedPerCacheLineCounts_5, NumberOfAssignedPerCacheLineCounts_6, NumberOfAssignedPerCacheLineCounts_7, NumberOfAssignedPerCacheLineCounts_8, NumberOfAssignedPerCacheLineCounts_9, NumberOfAssignedPerCacheLineCounts_10, NumberOfAssignedPerCacheLineCounts_11, NumberOfAssignedPerCacheLineCounts_12, NumberOfAssignedPerCacheLineCounts_13, NumberOfAssignedPerCacheLineCounts_14, NumberOfAssignedPerCacheLineCounts_15, NumberOfAssignedPerCacheLineCounts_16, Slope, Intercept, CorrelationCoefficient, Score, Rank) \ + MCGEN_EVENT_ENABLED(GraphFoundEvent) \ + ? McTemplateK0zixxqqgttttqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqgggxg(&PerfectHashEvents_Context, &GraphFoundEvent, Activity, KeysFileName, Attempt, SolutionNumber, ElapsedMilliseconds, CoverageType, CoverageValue, CoverageValueAsDouble, StopGraphSolving, IsBest, IsEqual, IsCoverageValueDouble, EqualCount, TotalNumberOfPages, TotalNumberOfLargePages, TotalNumberOfCacheLines, NumberOfUsedPages, NumberOfUsedLargePages, NumberOfUsedCacheLines, NumberOfEmptyPages, NumberOfEmptyLargePages, NumberOfEmptyCacheLines, FirstPageUsed, FirstLargePageUsed, FirstCacheLineUsed, LastPageUsed, LastLargePageUsed, LastCacheLineUsed, TotalNumberOfAssigned, NumberOfKeysWithVerticesMappingToSamePage, NumberOfKeysWithVerticesMappingToSameLargePage, NumberOfKeysWithVerticesMappingToSameCacheLine, MaxGraphTraversalDepth, TotalGraphTraversals, Seed1, Seed2, Seed3, Seed4, Seed5, Seed6, Seed7, Seed8, NumberOfAssignedPerCacheLineCounts_0, NumberOfAssignedPerCacheLineCounts_1, NumberOfAssignedPerCacheLineCounts_2, NumberOfAssignedPerCacheLineCounts_3, NumberOfAssignedPerCacheLineCounts_4, NumberOfAssignedPerCacheLineCounts_5, NumberOfAssignedPerCacheLineCounts_6, NumberOfAssignedPerCacheLineCounts_7, NumberOfAssignedPerCacheLineCounts_8, NumberOfAssignedPerCacheLineCounts_9, NumberOfAssignedPerCacheLineCounts_10, NumberOfAssignedPerCacheLineCounts_11, NumberOfAssignedPerCacheLineCounts_12, NumberOfAssignedPerCacheLineCounts_13, NumberOfAssignedPerCacheLineCounts_14, NumberOfAssignedPerCacheLineCounts_15, NumberOfAssignedPerCacheLineCounts_16, Slope, Intercept, CorrelationCoefficient, Score, Rank) : 0 +#define EventWriteGraphFoundEvent_AssumeEnabled(KeysFileName, Attempt, SolutionNumber, ElapsedMilliseconds, CoverageType, CoverageValue, CoverageValueAsDouble, StopGraphSolving, IsBest, IsEqual, IsCoverageValueDouble, EqualCount, TotalNumberOfPages, TotalNumberOfLargePages, TotalNumberOfCacheLines, NumberOfUsedPages, NumberOfUsedLargePages, NumberOfUsedCacheLines, NumberOfEmptyPages, NumberOfEmptyLargePages, NumberOfEmptyCacheLines, FirstPageUsed, FirstLargePageUsed, FirstCacheLineUsed, LastPageUsed, LastLargePageUsed, LastCacheLineUsed, TotalNumberOfAssigned, NumberOfKeysWithVerticesMappingToSamePage, NumberOfKeysWithVerticesMappingToSameLargePage, NumberOfKeysWithVerticesMappingToSameCacheLine, MaxGraphTraversalDepth, TotalGraphTraversals, Seed1, Seed2, Seed3, Seed4, Seed5, Seed6, Seed7, Seed8, NumberOfAssignedPerCacheLineCounts_0, NumberOfAssignedPerCacheLineCounts_1, NumberOfAssignedPerCacheLineCounts_2, NumberOfAssignedPerCacheLineCounts_3, NumberOfAssignedPerCacheLineCounts_4, NumberOfAssignedPerCacheLineCounts_5, NumberOfAssignedPerCacheLineCounts_6, NumberOfAssignedPerCacheLineCounts_7, NumberOfAssignedPerCacheLineCounts_8, NumberOfAssignedPerCacheLineCounts_9, NumberOfAssignedPerCacheLineCounts_10, NumberOfAssignedPerCacheLineCounts_11, NumberOfAssignedPerCacheLineCounts_12, NumberOfAssignedPerCacheLineCounts_13, NumberOfAssignedPerCacheLineCounts_14, NumberOfAssignedPerCacheLineCounts_15, NumberOfAssignedPerCacheLineCounts_16, Slope, Intercept, CorrelationCoefficient, Score, Rank) \ + McTemplateK0zixxqqgttttqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqgggxg(&PerfectHashEvents_Context, &GraphFoundEvent, NULL, KeysFileName, Attempt, SolutionNumber, ElapsedMilliseconds, CoverageType, CoverageValue, CoverageValueAsDouble, StopGraphSolving, IsBest, IsEqual, IsCoverageValueDouble, EqualCount, TotalNumberOfPages, TotalNumberOfLargePages, TotalNumberOfCacheLines, NumberOfUsedPages, NumberOfUsedLargePages, NumberOfUsedCacheLines, NumberOfEmptyPages, NumberOfEmptyLargePages, NumberOfEmptyCacheLines, FirstPageUsed, FirstLargePageUsed, FirstCacheLineUsed, LastPageUsed, LastLargePageUsed, LastCacheLineUsed, TotalNumberOfAssigned, NumberOfKeysWithVerticesMappingToSamePage, NumberOfKeysWithVerticesMappingToSameLargePage, NumberOfKeysWithVerticesMappingToSameCacheLine, MaxGraphTraversalDepth, TotalGraphTraversals, Seed1, Seed2, Seed3, Seed4, Seed5, Seed6, Seed7, Seed8, NumberOfAssignedPerCacheLineCounts_0, NumberOfAssignedPerCacheLineCounts_1, NumberOfAssignedPerCacheLineCounts_2, NumberOfAssignedPerCacheLineCounts_3, NumberOfAssignedPerCacheLineCounts_4, NumberOfAssignedPerCacheLineCounts_5, NumberOfAssignedPerCacheLineCounts_6, NumberOfAssignedPerCacheLineCounts_7, NumberOfAssignedPerCacheLineCounts_8, NumberOfAssignedPerCacheLineCounts_9, NumberOfAssignedPerCacheLineCounts_10, NumberOfAssignedPerCacheLineCounts_11, NumberOfAssignedPerCacheLineCounts_12, NumberOfAssignedPerCacheLineCounts_13, NumberOfAssignedPerCacheLineCounts_14, NumberOfAssignedPerCacheLineCounts_15, NumberOfAssignedPerCacheLineCounts_16, Slope, Intercept, CorrelationCoefficient, Score, Rank) // -// Enablement check macro for GraphAssignStart +// Enablement check macro for GraphAssignStartEvent // -#define EventEnabledGraphAssignStart() MCGEN_EVENT_BIT_SET(PerfectHashEnableBits, 4) +#define EventEnabledGraphAssignStartEvent() MCGEN_EVENT_BIT_SET(PerfectHashEnableBits, 4) // -// Event write macros for GraphAssignStart +// Event write macros for GraphAssignStartEvent // -#define EventWriteGraphAssignStart(Activity, KeysFileName, Attempt, NumberOfKeys, NumberOfVertices) \ - MCGEN_EVENT_ENABLED(GraphAssignStart) \ - ? McTemplateK0ziqq(&PerfectHashEvents_Context, &GraphAssignStart, Activity, KeysFileName, Attempt, NumberOfKeys, NumberOfVertices) : 0 -#define EventWriteGraphAssignStart_AssumeEnabled(KeysFileName, Attempt, NumberOfKeys, NumberOfVertices) \ - McTemplateK0ziqq(&PerfectHashEvents_Context, &GraphAssignStart, NULL, KeysFileName, Attempt, NumberOfKeys, NumberOfVertices) +#define EventWriteGraphAssignStartEvent(Activity, KeysFileName, Attempt, NumberOfKeys, NumberOfVertices) \ + MCGEN_EVENT_ENABLED(GraphAssignStartEvent) \ + ? McTemplateK0ziqq(&PerfectHashEvents_Context, &GraphAssignStartEvent, Activity, KeysFileName, Attempt, NumberOfKeys, NumberOfVertices) : 0 +#define EventWriteGraphAssignStartEvent_AssumeEnabled(KeysFileName, Attempt, NumberOfKeys, NumberOfVertices) \ + McTemplateK0ziqq(&PerfectHashEvents_Context, &GraphAssignStartEvent, NULL, KeysFileName, Attempt, NumberOfKeys, NumberOfVertices) // -// Enablement check macro for GraphAssignStop +// Enablement check macro for GraphAssignStopEvent // -#define EventEnabledGraphAssignStop() MCGEN_EVENT_BIT_SET(PerfectHashEnableBits, 4) +#define EventEnabledGraphAssignStopEvent() MCGEN_EVENT_BIT_SET(PerfectHashEnableBits, 4) // -// Event write macros for GraphAssignStop +// Event write macros for GraphAssignStopEvent // -#define EventWriteGraphAssignStop(Activity, KeysFileName, Attempt, NumberOfKeys, NumberOfVertices, NumberOfEmptyVertices, MaxTraversalDepth, TotalTraversals) \ - MCGEN_EVENT_ENABLED(GraphAssignStop) \ - ? McTemplateK0ziqqqqq(&PerfectHashEvents_Context, &GraphAssignStop, Activity, KeysFileName, Attempt, NumberOfKeys, NumberOfVertices, NumberOfEmptyVertices, MaxTraversalDepth, TotalTraversals) : 0 -#define EventWriteGraphAssignStop_AssumeEnabled(KeysFileName, Attempt, NumberOfKeys, NumberOfVertices, NumberOfEmptyVertices, MaxTraversalDepth, TotalTraversals) \ - McTemplateK0ziqqqqq(&PerfectHashEvents_Context, &GraphAssignStop, NULL, KeysFileName, Attempt, NumberOfKeys, NumberOfVertices, NumberOfEmptyVertices, MaxTraversalDepth, TotalTraversals) +#define EventWriteGraphAssignStopEvent(Activity, KeysFileName, Attempt, NumberOfKeys, NumberOfVertices, NumberOfEmptyVertices, MaxTraversalDepth, TotalTraversals) \ + MCGEN_EVENT_ENABLED(GraphAssignStopEvent) \ + ? McTemplateK0ziqqqqq(&PerfectHashEvents_Context, &GraphAssignStopEvent, Activity, KeysFileName, Attempt, NumberOfKeys, NumberOfVertices, NumberOfEmptyVertices, MaxTraversalDepth, TotalTraversals) : 0 +#define EventWriteGraphAssignStopEvent_AssumeEnabled(KeysFileName, Attempt, NumberOfKeys, NumberOfVertices, NumberOfEmptyVertices, MaxTraversalDepth, TotalTraversals) \ + McTemplateK0ziqqqqq(&PerfectHashEvents_Context, &GraphAssignStopEvent, NULL, KeysFileName, Attempt, NumberOfKeys, NumberOfVertices, NumberOfEmptyVertices, MaxTraversalDepth, TotalTraversals) // -// Enablement check macro for RtlGenerateRandomBytesStart +// Enablement check macro for RtlGenerateRandomBytesStartEvent // -#define EventEnabledRtlGenerateRandomBytesStart() MCGEN_EVENT_BIT_SET(PerfectHashEnableBits, 5) +#define EventEnabledRtlGenerateRandomBytesStartEvent() MCGEN_EVENT_BIT_SET(PerfectHashEnableBits, 5) // -// Event write macros for RtlGenerateRandomBytesStart +// Event write macros for RtlGenerateRandomBytesStartEvent // -#define EventWriteRtlGenerateRandomBytesStart(Activity, BytesRequested) \ - MCGEN_EVENT_ENABLED(RtlGenerateRandomBytesStart) \ - ? McTemplateK0q(&PerfectHashEvents_Context, &RtlGenerateRandomBytesStart, Activity, BytesRequested) : 0 -#define EventWriteRtlGenerateRandomBytesStart_AssumeEnabled(BytesRequested) \ - McTemplateK0q(&PerfectHashEvents_Context, &RtlGenerateRandomBytesStart, NULL, BytesRequested) +#define EventWriteRtlGenerateRandomBytesStartEvent(Activity, BytesRequested) \ + MCGEN_EVENT_ENABLED(RtlGenerateRandomBytesStartEvent) \ + ? McTemplateK0q(&PerfectHashEvents_Context, &RtlGenerateRandomBytesStartEvent, Activity, BytesRequested) : 0 +#define EventWriteRtlGenerateRandomBytesStartEvent_AssumeEnabled(BytesRequested) \ + McTemplateK0q(&PerfectHashEvents_Context, &RtlGenerateRandomBytesStartEvent, NULL, BytesRequested) // -// Enablement check macro for RtlGenerateRandomBytesStop +// Enablement check macro for RtlGenerateRandomBytesStopEvent // -#define EventEnabledRtlGenerateRandomBytesStop() MCGEN_EVENT_BIT_SET(PerfectHashEnableBits, 5) +#define EventEnabledRtlGenerateRandomBytesStopEvent() MCGEN_EVENT_BIT_SET(PerfectHashEnableBits, 5) // -// Event write macros for RtlGenerateRandomBytesStop +// Event write macros for RtlGenerateRandomBytesStopEvent // -#define EventWriteRtlGenerateRandomBytesStop(Activity, BytesRequested, Result) \ - MCGEN_EVENT_ENABLED(RtlGenerateRandomBytesStop) \ - ? McTemplateK0qq(&PerfectHashEvents_Context, &RtlGenerateRandomBytesStop, Activity, BytesRequested, Result) : 0 -#define EventWriteRtlGenerateRandomBytesStop_AssumeEnabled(BytesRequested, Result) \ - McTemplateK0qq(&PerfectHashEvents_Context, &RtlGenerateRandomBytesStop, NULL, BytesRequested, Result) +#define EventWriteRtlGenerateRandomBytesStopEvent(Activity, BytesRequested, Result) \ + MCGEN_EVENT_ENABLED(RtlGenerateRandomBytesStopEvent) \ + ? McTemplateK0qq(&PerfectHashEvents_Context, &RtlGenerateRandomBytesStopEvent, Activity, BytesRequested, Result) : 0 +#define EventWriteRtlGenerateRandomBytesStopEvent_AssumeEnabled(BytesRequested, Result) \ + McTemplateK0qq(&PerfectHashEvents_Context, &RtlGenerateRandomBytesStopEvent, NULL, BytesRequested, Result) // -// Enablement check macro for GraphAssignResult +// Enablement check macro for GraphAssignResultEvent // -#define EventEnabledGraphAssignResult() MCGEN_EVENT_BIT_SET(PerfectHashEnableBits, 4) +#define EventEnabledGraphAssignResultEvent() MCGEN_EVENT_BIT_SET(PerfectHashEnableBits, 4) // -// Event write macros for GraphAssignResult +// Event write macros for GraphAssignResultEvent // -#define EventWriteGraphAssignResult(Activity, KeysFileName, Attempt, FunctionVersion, Cycles, Microseconds, NumberOfKeys, NumberOfVertices) \ - MCGEN_EVENT_ENABLED(GraphAssignResult) \ - ? McTemplateK0ziqiiqq(&PerfectHashEvents_Context, &GraphAssignResult, Activity, KeysFileName, Attempt, FunctionVersion, Cycles, Microseconds, NumberOfKeys, NumberOfVertices) : 0 -#define EventWriteGraphAssignResult_AssumeEnabled(KeysFileName, Attempt, FunctionVersion, Cycles, Microseconds, NumberOfKeys, NumberOfVertices) \ - McTemplateK0ziqiiqq(&PerfectHashEvents_Context, &GraphAssignResult, NULL, KeysFileName, Attempt, FunctionVersion, Cycles, Microseconds, NumberOfKeys, NumberOfVertices) +#define EventWriteGraphAssignResultEvent(Activity, KeysFileName, Attempt, FunctionVersion, Cycles, Microseconds, NumberOfKeys, NumberOfVertices) \ + MCGEN_EVENT_ENABLED(GraphAssignResultEvent) \ + ? McTemplateK0ziqiiqq(&PerfectHashEvents_Context, &GraphAssignResultEvent, Activity, KeysFileName, Attempt, FunctionVersion, Cycles, Microseconds, NumberOfKeys, NumberOfVertices) : 0 +#define EventWriteGraphAssignResultEvent_AssumeEnabled(KeysFileName, Attempt, FunctionVersion, Cycles, Microseconds, NumberOfKeys, NumberOfVertices) \ + McTemplateK0ziqiiqq(&PerfectHashEvents_Context, &GraphAssignResultEvent, NULL, KeysFileName, Attempt, FunctionVersion, Cycles, Microseconds, NumberOfKeys, NumberOfVertices) + +// +// Enablement check macro for GraphIsAcyclicEvent +// +#define EventEnabledGraphIsAcyclicEvent() MCGEN_EVENT_BIT_SET(PerfectHashEnableBits, 6) + +// +// Event write macros for GraphIsAcyclicEvent +// +#define EventWriteGraphIsAcyclicEvent(Activity, KeysFileName, Attempt, FunctionVersion, Cycles, Microseconds, NumberOfKeys, NumberOfVertices, IsAcyclic) \ + MCGEN_EVENT_ENABLED(GraphIsAcyclicEvent) \ + ? McTemplateK0ziqiiqqt(&PerfectHashEvents_Context, &GraphIsAcyclicEvent, Activity, KeysFileName, Attempt, FunctionVersion, Cycles, Microseconds, NumberOfKeys, NumberOfVertices, IsAcyclic) : 0 +#define EventWriteGraphIsAcyclicEvent_AssumeEnabled(KeysFileName, Attempt, FunctionVersion, Cycles, Microseconds, NumberOfKeys, NumberOfVertices, IsAcyclic) \ + McTemplateK0ziqiiqqt(&PerfectHashEvents_Context, &GraphIsAcyclicEvent, NULL, KeysFileName, Attempt, FunctionVersion, Cycles, Microseconds, NumberOfKeys, NumberOfVertices, IsAcyclic) #endif // MCGEN_DISABLE_PROVIDER_CODE_GENERATION @@ -934,6 +952,53 @@ McTemplateK0ziqiiqq( } #endif // McTemplateK0ziqiiqq_def +// +//Template from manifest : GraphIsAcyclicTemplate +// +#ifndef McTemplateK0ziqiiqqt_def +#define McTemplateK0ziqiiqqt_def +ETW_INLINE +ULONG +McTemplateK0ziqiiqqt( + _In_ PMCGEN_TRACE_CONTEXT Context, + _In_ PCEVENT_DESCRIPTOR Descriptor, + _In_opt_ const GUID* Activity, + _In_opt_ PCWSTR _Arg0, + _In_ const signed __int64 _Arg1, + _In_ const unsigned int _Arg2, + _In_ const signed __int64 _Arg3, + _In_ const signed __int64 _Arg4, + _In_ const unsigned int _Arg5, + _In_ const unsigned int _Arg6, + _In_ const signed int _Arg7 + ) +{ +#define McTemplateK0ziqiiqqt_ARGCOUNT 8 + + EVENT_DATA_DESCRIPTOR EventData[McTemplateK0ziqiiqqt_ARGCOUNT + 1]; + + EventDataDescCreate(&EventData[1], + (_Arg0 != NULL) ? _Arg0 : L"NULL", + (_Arg0 != NULL) ? (ULONG)((wcslen(_Arg0) + 1) * sizeof(WCHAR)) : (ULONG)sizeof(L"NULL")); + + EventDataDescCreate(&EventData[2],&_Arg1, sizeof(const signed __int64) ); + + EventDataDescCreate(&EventData[3],&_Arg2, sizeof(const unsigned int) ); + + EventDataDescCreate(&EventData[4],&_Arg3, sizeof(const signed __int64) ); + + EventDataDescCreate(&EventData[5],&_Arg4, sizeof(const signed __int64) ); + + EventDataDescCreate(&EventData[6],&_Arg5, sizeof(const unsigned int) ); + + EventDataDescCreate(&EventData[7],&_Arg6, sizeof(const unsigned int) ); + + EventDataDescCreate(&EventData[8],&_Arg7, sizeof(const signed int) ); + + return McGenEventWrite(Context, Descriptor, Activity, McTemplateK0ziqiiqqt_ARGCOUNT + 1, EventData); +} +#endif // McTemplateK0ziqiiqqt_def + // //Template from manifest : GraphAssignStartTemplate // @@ -1016,25 +1081,25 @@ McTemplateK0ziqqqqq( // //Template from manifest : GraphFoundTemplate // -#ifndef McTemplateK0zixqqgttttqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqgggxg_def -#define McTemplateK0zixqqgttttqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqgggxg_def +#ifndef McTemplateK0zixxqqgttttqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqgggxg_def +#define McTemplateK0zixxqqgttttqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqgggxg_def ETW_INLINE ULONG -McTemplateK0zixqqgttttqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqgggxg( +McTemplateK0zixxqqgttttqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqgggxg( _In_ PMCGEN_TRACE_CONTEXT Context, _In_ PCEVENT_DESCRIPTOR Descriptor, _In_opt_ const GUID* Activity, _In_opt_ PCWSTR _Arg0, _In_ const signed __int64 _Arg1, _In_ const unsigned __int64 _Arg2, - _In_ const unsigned int _Arg3, + _In_ const unsigned __int64 _Arg3, _In_ const unsigned int _Arg4, - _In_ const double _Arg5, - _In_ const signed int _Arg6, + _In_ const unsigned int _Arg5, + _In_ const double _Arg6, _In_ const signed int _Arg7, _In_ const signed int _Arg8, _In_ const signed int _Arg9, - _In_ const unsigned int _Arg10, + _In_ const signed int _Arg10, _In_ const unsigned int _Arg11, _In_ const unsigned int _Arg12, _In_ const unsigned int _Arg13, @@ -1081,16 +1146,17 @@ McTemplateK0zixqqgttttqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqgggxg( _In_ const unsigned int _Arg54, _In_ const unsigned int _Arg55, _In_ const unsigned int _Arg56, - _In_ const double _Arg57, + _In_ const unsigned int _Arg57, _In_ const double _Arg58, _In_ const double _Arg59, - _In_ const unsigned __int64 _Arg60, - _In_ const double _Arg61 + _In_ const double _Arg60, + _In_ const unsigned __int64 _Arg61, + _In_ const double _Arg62 ) { -#define McTemplateK0zixqqgttttqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqgggxg_ARGCOUNT 62 +#define McTemplateK0zixxqqgttttqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqgggxg_ARGCOUNT 63 - EVENT_DATA_DESCRIPTOR EventData[McTemplateK0zixqqgttttqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqgggxg_ARGCOUNT + 1]; + EVENT_DATA_DESCRIPTOR EventData[McTemplateK0zixxqqgttttqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqgggxg_ARGCOUNT + 1]; EventDataDescCreate(&EventData[1], (_Arg0 != NULL) ? _Arg0 : L"NULL", @@ -1100,13 +1166,13 @@ McTemplateK0zixqqgttttqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqgggxg( EventDataDescCreate(&EventData[3],&_Arg2, sizeof(const unsigned __int64) ); - EventDataDescCreate(&EventData[4],&_Arg3, sizeof(const unsigned int) ); + EventDataDescCreate(&EventData[4],&_Arg3, sizeof(const unsigned __int64) ); EventDataDescCreate(&EventData[5],&_Arg4, sizeof(const unsigned int) ); - EventDataDescCreate(&EventData[6],&_Arg5, sizeof(const double) ); + EventDataDescCreate(&EventData[6],&_Arg5, sizeof(const unsigned int) ); - EventDataDescCreate(&EventData[7],&_Arg6, sizeof(const signed int) ); + EventDataDescCreate(&EventData[7],&_Arg6, sizeof(const double) ); EventDataDescCreate(&EventData[8],&_Arg7, sizeof(const signed int) ); @@ -1114,7 +1180,7 @@ McTemplateK0zixqqgttttqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqgggxg( EventDataDescCreate(&EventData[10],&_Arg9, sizeof(const signed int) ); - EventDataDescCreate(&EventData[11],&_Arg10, sizeof(const unsigned int) ); + EventDataDescCreate(&EventData[11],&_Arg10, sizeof(const signed int) ); EventDataDescCreate(&EventData[12],&_Arg11, sizeof(const unsigned int) ); @@ -1208,19 +1274,21 @@ McTemplateK0zixqqgttttqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqgggxg( EventDataDescCreate(&EventData[57],&_Arg56, sizeof(const unsigned int) ); - EventDataDescCreate(&EventData[58],&_Arg57, sizeof(const double) ); + EventDataDescCreate(&EventData[58],&_Arg57, sizeof(const unsigned int) ); EventDataDescCreate(&EventData[59],&_Arg58, sizeof(const double) ); EventDataDescCreate(&EventData[60],&_Arg59, sizeof(const double) ); - EventDataDescCreate(&EventData[61],&_Arg60, sizeof(const unsigned __int64) ); + EventDataDescCreate(&EventData[61],&_Arg60, sizeof(const double) ); + + EventDataDescCreate(&EventData[62],&_Arg61, sizeof(const unsigned __int64) ); - EventDataDescCreate(&EventData[62],&_Arg61, sizeof(const double) ); + EventDataDescCreate(&EventData[63],&_Arg62, sizeof(const double) ); - return McGenEventWrite(Context, Descriptor, Activity, McTemplateK0zixqqgttttqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqgggxg_ARGCOUNT + 1, EventData); + return McGenEventWrite(Context, Descriptor, Activity, McTemplateK0zixxqqgttttqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqgggxg_ARGCOUNT + 1, EventData); } -#endif // McTemplateK0zixqqgttttqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqgggxg_def +#endif // McTemplateK0zixxqqgttttqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqgggxg_def // //Template from manifest : GraphAddHashedKeysTemplate @@ -1341,6 +1409,7 @@ McTemplateK0zqqqqiiqqqqqqqq( #define MSG_PerfectHash_event_8_message 0xB0000008L #define MSG_PerfectHash_event_9_message 0xB0000009L #define MSG_PerfectHash_event_10_message 0xB000000AL +#define MSG_PerfectHash_event_11_message 0xB000000BL #define MSG_PerfectHash_event_0_message 0xB0010000L #define MSG_PerfectHash_event_1_message 0xB0010001L #define MSG_PerfectHash_event_2_message 0xB0010002L diff --git a/python/perfecthash/analysis.py b/python/perfecthash/analysis.py index 8f6051c1..abf47a08 100644 --- a/python/perfecthash/analysis.py +++ b/python/perfecthash/analysis.py @@ -503,12 +503,15 @@ ' etw:SessionId,' ' KeysFileName,' ' Attempt,' + ' SolutionNumber,' ' ElapsedMilliseconds,' ' CoverageType,' ' CoverageValue,' + ' CoverageValueAsDouble,' ' StopGraphSolving,' ' IsBest,' ' IsEqual,' + ' IsCoverageValueDouble,' ' EqualCount,' ' TotalNumberOfPages,' ' TotalNumberOfLargePages,' @@ -575,12 +578,15 @@ 'SessionId', 'KeysFileName', 'Attempt', + 'SolutionNumber', 'ElapsedMilliseconds', 'CoverageType', 'CoverageValue', + 'CoverageValueAsDouble', 'StopGraphSolving', 'IsBest', 'IsEqual', + 'IsCoverageValueDouble', 'EqualCount', 'TotalNumberOfPages', 'TotalNumberOfLargePages', @@ -644,12 +650,15 @@ 'ActivityId', 'KeysFileName', 'Attempt', + 'SolutionNumber', 'ElapsedMilliseconds', 'CoverageType', 'CoverageValue', + 'CoverageValueAsDouble', 'StopGraphSolving', 'IsBest', 'IsEqual', + 'IsCoverageValueDouble', 'EqualCount', 'TotalNumberOfPages', 'TotalNumberOfLargePages', @@ -934,6 +943,67 @@ 'Result', ) +# GraphIsAcyclic + +IS_ACYCLIC = 'PerfectHash/IsAcyclic/win:Info' + +IS_ACYCLIC_ETW_HEADER = ( + 'PerfectHash/IsAcyclic/win:Info,' + ' TimeStamp,' + ' Process Name ( PID),' + ' ThreadID,' + ' CPU,' + ' etw:ActivityId,' + ' etw:Related ActivityId,' + ' etw:UserSid,' + ' etw:SessionId,' + ' KeysFileName,' + ' Attempt,' + ' FunctionVersion,' + ' Cycles,' + ' Microseconds,' + ' NumberOfKeys,' + ' NumberOfVertices,' + ' IsAcyclic' +) + +IS_ACYCLIC_CSV_HEADER = ( + 'EventName', + 'TimeStamp', + 'ProcessID', + 'ThreadID', + 'CPU', + 'ActivityId', + 'RelatedActivityId', + 'UserSid', + 'SessionId', + 'KeysFileName', + 'Attempt', + 'FunctionVersion', + 'Cycles', + 'Microseconds', + 'NumberOfKeys', + 'NumberOfVertices', + 'IsAcyclic', +) + +IS_ACYCLIC_CSV_HEADER_SLIM = ( + 'LineNumber', + 'TimeStamp', + 'ProcessID', + 'ThreadID', + 'CPU', + 'ActivityId', + 'KeysFileName', + 'Attempt', + 'FunctionVersion', + 'Cycles', + 'Microseconds', + 'NumberOfKeys', + 'NumberOfVertices', + 'IsAcyclic', +) + # Maps EVENT_NAME_TO_ETW_HEADER = { @@ -945,6 +1015,7 @@ FOUND_NEW_BEST_GRAPH: FOUND_NEW_BEST_GRAPH_ETW_HEADER, FOUND_EQUAL_BEST_GRAPH: FOUND_EQUAL_BEST_GRAPH_ETW_HEADER, FOUND_GRAPH: FOUND_GRAPH_ETW_HEADER, + IS_ACYCLIC: IS_ACYCLIC_ETW_HEADER, } EVENT_NAME_TO_CSV_HEADER = { @@ -961,6 +1032,7 @@ FOUND_NEW_BEST_GRAPH: FOUND_NEW_BEST_GRAPH_CSV_HEADER, FOUND_EQUAL_BEST_GRAPH: FOUND_EQUAL_BEST_GRAPH_CSV_HEADER, FOUND_GRAPH: FOUND_GRAPH_CSV_HEADER, + IS_ACYCLIC: IS_ACYCLIC_CSV_HEADER, } EVENT_NAME_TO_CSV_HEADER_SLIM = { @@ -977,6 +1049,7 @@ FOUND_NEW_BEST_GRAPH: FOUND_NEW_BEST_GRAPH_CSV_HEADER_SLIM, FOUND_EQUAL_BEST_GRAPH: FOUND_EQUAL_BEST_GRAPH_CSV_HEADER_SLIM, FOUND_GRAPH: FOUND_GRAPH_CSV_HEADER_SLIM, + IS_ACYCLIC: IS_ACYCLIC_CSV_HEADER_SLIM, } HAS_SEED_DATA = { @@ -2118,6 +2191,7 @@ def process_xperf_perfecthash_csv(path, out=None): generate_random_bytes_stop = GENERATE_RANDOM_BYTES_STOP cswitch = CSWITCH pmc = PMC + is_acyclic = IS_ACYCLIC assign_io = io.StringIO() generate_random_bytes_io = io.StringIO() @@ -2135,6 +2209,7 @@ def process_xperf_perfecthash_csv(path, out=None): generate_random_bytes_stop: generate_random_bytes_io, cswitch: io.StringIO(), pmc: io.StringIO(), + is_acyclic: io.StringIO(), } paths = { @@ -2150,6 +2225,7 @@ def process_xperf_perfecthash_csv(path, out=None): generate_random_bytes_stop: f'{prefix}_GenerateRandomBytes.csv', cswitch: f'{prefix}_ContextSwitch.csv', pmc: f'{prefix}_Pmc.csv', + is_acyclic: f'{prefix}_IsAcyclic.csv', } counts = { @@ -2165,6 +2241,7 @@ def process_xperf_perfecthash_csv(path, out=None): generate_random_bytes_stop: 0, cswitch: 0, pmc: 0, + is_acyclic: 0, } names = set(counts.keys()) diff --git a/src/PerfectHash/Chm01.c b/src/PerfectHash/Chm01.c index 131b1afa..778aa5ca 100644 --- a/src/PerfectHash/Chm01.c +++ b/src/PerfectHash/Chm01.c @@ -1095,9 +1095,7 @@ Return Value: Context->BestGraph = NULL; LeaveCriticalSection(&Context->BestGraphCriticalSection); - if (!Graph) { - goto Error; - } + ASSERT(Graph != NULL); } // @@ -1570,6 +1568,7 @@ Return Value: { PRTL Rtl; HRESULT Result = S_OK; + ULONG GraphImpl; ULONG NumberOfKeys; USHORT NumberOfBitmaps; PGRAPH_DIMENSIONS Dim; @@ -1583,6 +1582,7 @@ Return Value: ULONGLONG FirstSizeInBytes; ULONGLONG OrderSizeInBytes; ULONGLONG EdgesSizeInBytes; + ULONGLONG Vertices3SizeInBytes; ULONGLONG ValuesSizeInBytes; ULONGLONG AssignedSizeInBytes; ULONGLONG VertexPairsSizeInBytes; @@ -1621,6 +1621,7 @@ Return Value: Rtl = Table->Rtl; Context = Table->Context; + GraphImpl = Table->GraphImpl; MaskFunctionId = Table->MaskFunctionId; GraphInfoOnDisk = Context->GraphInfoOnDisk; TableInfoOnDisk = &GraphInfoOnDisk->TableInfoOnDisk; @@ -1906,34 +1907,57 @@ Return Value: // Calculate the sizes required for each of the arrays. // - EdgesSizeInBytes = ALIGN_UP_YMMWORD( - RTL_ELEMENT_SIZE(GRAPH, Edges) * TotalNumberOfEdges.QuadPart - ); + if (GraphImpl == 1 || GraphImpl == 2) { - NextSizeInBytes = ALIGN_UP_YMMWORD( - RTL_ELEMENT_SIZE(GRAPH, Next) * TotalNumberOfEdges.QuadPart - ); + EdgesSizeInBytes = ALIGN_UP_YMMWORD( + RTL_ELEMENT_SIZE(GRAPH, Edges) * TotalNumberOfEdges.QuadPart + ); + + NextSizeInBytes = ALIGN_UP_YMMWORD( + RTL_ELEMENT_SIZE(GRAPH, Next) * TotalNumberOfEdges.QuadPart + ); + + FirstSizeInBytes = ALIGN_UP_YMMWORD( + RTL_ELEMENT_SIZE(GRAPH, First) * NumberOfVertices.QuadPart + ); + + Vertices3SizeInBytes = 0; + + if (TableCreateFlags.HashAllKeysFirst == FALSE) { + VertexPairsSizeInBytes = 0; + } else { + VertexPairsSizeInBytes = ALIGN_UP_ZMMWORD( + RTL_ELEMENT_SIZE(GRAPH, VertexPairs) * (ULONGLONG)NumberOfKeys + ); + } + + } else { + + ASSERT(GraphImpl == 3); + + EdgesSizeInBytes = 0; + NextSizeInBytes = 0; + FirstSizeInBytes = 0; + + VertexPairsSizeInBytes = ALIGN_UP_YMMWORD( + RTL_ELEMENT_SIZE(GRAPH, Edges3) * NumberOfEdges.QuadPart + ); + + Vertices3SizeInBytes = ALIGN_UP_YMMWORD( + RTL_ELEMENT_SIZE(GRAPH, Vertices3) * NumberOfVertices.QuadPart + ); + + DeletedEdgesBitmapBufferSizeInBytes.QuadPart = 0; + } OrderSizeInBytes = ALIGN_UP_YMMWORD( RTL_ELEMENT_SIZE(GRAPH, Order) * NumberOfEdges.QuadPart ); - FirstSizeInBytes = ALIGN_UP_YMMWORD( - RTL_ELEMENT_SIZE(GRAPH, First) * NumberOfVertices.QuadPart - ); - AssignedSizeInBytes = ALIGN_UP_YMMWORD( RTL_ELEMENT_SIZE(GRAPH, Assigned) * NumberOfVertices.QuadPart ); - if (TableCreateFlags.HashAllKeysFirst == FALSE) { - VertexPairsSizeInBytes = 0; - } else { - VertexPairsSizeInBytes = ALIGN_UP_ZMMWORD( - RTL_ELEMENT_SIZE(GRAPH, VertexPairs) * (ULONGLONG)NumberOfKeys - ); - } - // // Calculate the size required for the values array. This is used as part // of verification, where we essentially do Insert(Key, Key) in combination @@ -2002,6 +2026,7 @@ Return Value: NextSizeInBytes + OrderSizeInBytes + FirstSizeInBytes + + Vertices3SizeInBytes + AssignedSizeInBytes + VertexPairsSizeInBytes + ValuesSizeInBytes + @@ -2059,6 +2084,7 @@ Return Value: Info->NextSizeInBytes = NextSizeInBytes; Info->OrderSizeInBytes = OrderSizeInBytes; Info->FirstSizeInBytes = FirstSizeInBytes; + Info->Vertices3SizeInBytes = Vertices3SizeInBytes; Info->AssignedSizeInBytes = AssignedSizeInBytes; Info->VertexPairsSizeInBytes = VertexPairsSizeInBytes; Info->ValuesSizeInBytes = ValuesSizeInBytes; diff --git a/src/PerfectHash/ExtractArg.c b/src/PerfectHash/ExtractArg.c index 501e4eea..30b00b12 100644 --- a/src/PerfectHash/ExtractArg.c +++ b/src/PerfectHash/ExtractArg.c @@ -933,6 +933,14 @@ Return Value: ADD_PARAM_IF_EQUAL_AND_VALUE_IS_INTEGER(InitialNumberOfTableResizes); + ADD_PARAM_IF_EQUAL_AND_VALUE_IS_INTEGER(MinAttempts); + + ADD_PARAM_IF_EQUAL_AND_VALUE_IS_INTEGER(MaxAttempts); + + ADD_PARAM_IF_EQUAL_AND_VALUE_IS_INTEGER(FixedAttempts); + + ADD_PARAM_IF_EQUAL_AND_VALUE_IS_INTEGER(TargetNumberOfSolutions); + ADD_PARAM_IF_EQUAL_AND_VALUE_IS_INTEGER(BestCoverageAttempts); ADD_PARAM_IF_EQUAL_AND_VALUE_IS_INTEGER(KeySizeInBytes); diff --git a/src/PerfectHash/Graph.c b/src/PerfectHash/Graph.c index 05120a99..347e7c9c 100644 --- a/src/PerfectHash/Graph.c +++ b/src/PerfectHash/Graph.c @@ -15,40 +15,24 @@ Module Name: #include "stdafx.h" #include "PerfectHashEventsPrivate.h" -// -// Helper macro for graph event writing. -// - -#define EVENT_WRITE_GRAPH(Name) \ - EventWriteGraph##Name##Event( \ - &Graph->Activity, \ - Graph->KeysFileName, \ - Edge, \ - NumberOfKeys, \ - Key, \ - Result, \ - Cycles, \ - Microseconds, \ - Graph->Seed1, \ - Graph->Seed2, \ - Graph->Seed3, \ - Graph->Seed4, \ - Graph->Seed5, \ - Graph->Seed6, \ - Graph->Seed7, \ - Graph->Seed8 \ - ) - // // Forward decl. // GRAPH_ADD_KEYS GraphHashKeysThenAdd; +GRAPH_ADD_KEYS GraphAddKeys3; +GRAPH_ADD_KEYS GraphHashKeysThenAdd3; GRAPH_ADD_KEYS GraphAddKeysOriginalSeededHashRoutines; GRAPH_VERIFY GraphVerifyOriginalSeededHashRoutines; GRAPH_CALCULATE_ASSIGNED_MEMORY_COVERAGE GraphCalculateAssignedMemoryCoverage_AVX2; +GRAPH_ASSIGN GraphAssign; GRAPH_ASSIGN GraphAssign2; +GRAPH_ASSIGN GraphAssign3; +GRAPH_IS_ACYCLIC GraphIsAcyclic; +GRAPH_IS_ACYCLIC GraphIsAcyclic3; + +GRAPH_REGISTER_SOLVED GraphRegisterSolvedNoBestCoverage; // // COM scaffolding routines for initialization and rundown. @@ -345,7 +329,8 @@ Return Value: // is acyclic. // - if (!IsGraphAcyclic(Graph)) { + Result = Graph->Vtbl->IsAcyclic(Graph); + if (FAILED(Result)) { // // Failed to create an acyclic graph. @@ -368,6 +353,7 @@ Return Value: // FinishedCount = InterlockedIncrement64(&Context->FinishedCount); + Graph->SolutionNumber = FinishedCount; if (FirstSolvedGraphWins(Context)) { @@ -385,11 +371,14 @@ Return Value: // Perform the assignment step. // - if (Table->GraphImpl == 1) { - GraphAssign(Graph); - } else { - ASSERT(Table->GraphImpl == 2); - GraphAssign2(Graph); + Result = Graph->Vtbl->Assign(Graph); + + // + // Assign() should always succeed. + // + + if (FAILED(Result)) { + PH_RAISE(Result); } // @@ -400,6 +389,8 @@ Return Value: // if (FirstSolvedGraphWins(Context)) { + ASSERT(Context->MinAttempts == 0); + ASSERT(Context->TargetNumberOfSolutions == 0); CONTEXT_END_TIMERS(Solve); SetStopSolving(Context); if (WantsAssignedMemoryCoverage(Graph)) { @@ -413,11 +404,13 @@ Return Value: } // - // If we reach this mode, we're in "find best memory coverage" mode, so, - // register the solved graph then continue solving. + // If we reach this mode, we're either in FindBestMemoryCoverage mode, + // FixedAttempts mode, or we have a target number of solutions to find. // - ASSERT(FindBestMemoryCoverage(Context)); + ASSERT(FindBestMemoryCoverage(Context) || + Context->MinAttempts > 0 || + Context->TargetNumberOfSolutions > 0); // // Calculate memory coverage information if applicable. @@ -450,10 +443,17 @@ Return Value: Coverage->NumberOfCollisionsDuringAssignment = Graph->Collisions; // - // Register the solved graph. We can return this result directly. + // Register the solved graph then return the result directly. // - Result = Graph->Vtbl->RegisterSolved(Graph, NewGraphPointer); + if (FindBestMemoryCoverage(Context)) { + ASSERT(Context->MinAttempts == 0); + Result = Graph->Vtbl->RegisterSolved(Graph, NewGraphPointer); + } else { + ASSERT(Context->MinAttempts > 0 || + Context->TargetNumberOfSolutions > 0); + Result = GraphRegisterSolvedNoBestCoverage(Graph, NewGraphPointer); + } // // Intentional follow-on to End. @@ -772,13 +772,7 @@ Return Value: STOP_GRAPH_COUNTER(AddHashedKeys); - EventWriteGraphAddHashedKeysEvent( - &Graph->Activity, - Graph->KeysFileName, - NumberOfKeys, - Cycles, - Microseconds - ); + EVENT_WRITE_GRAPH_ADD_HASHED_KEYS(); return S_OK; } @@ -1415,6 +1409,8 @@ Return Value: PageSizeBytesProcessed = 0; LargePageSizeBytesProcessed = 0; + Coverage->SolutionNumber = Graph->SolutionNumber; + // // Enumerate the assigned array in cache-line-sized strides. // @@ -1616,6 +1612,8 @@ Return Value: PageSizeBytesProcessed = 0; LargePageSizeBytesProcessed = 0; + Coverage->SolutionNumber = Graph->SolutionNumber; + // // Enumerate the assigned array in cache-line-sized strides. // @@ -2041,76 +2039,9 @@ VerifyMemoryCoverageInvariants( #pragma optimize("", on) // -// Helper macro for emitting graph-found events. Used exclusively by the -// GraphRegisterSolved() routine. +// Helper macro for emitting graph-found events. // -#define EVENT_WRITE_GRAPH_FOUND(Name) \ - EventWriteGraph##Name##( \ - &Graph->Activity, \ - Graph->KeysFileName, \ - Attempt, \ - ElapsedMilliseconds, \ - (ULONG)CoverageType, \ - CoverageValue, \ - CoverageValueAsDouble, \ - (StopGraphSolving != FALSE), \ - (FoundBestGraph != FALSE), \ - (FoundEqualBestGraph != FALSE), \ - (IsCoverageValueDouble != FALSE), \ - EqualCount, \ - Coverage->TotalNumberOfPages, \ - Coverage->TotalNumberOfLargePages, \ - Coverage->TotalNumberOfCacheLines, \ - Coverage->NumberOfUsedPages, \ - Coverage->NumberOfUsedLargePages, \ - Coverage->NumberOfUsedCacheLines, \ - Coverage->NumberOfEmptyPages, \ - Coverage->NumberOfEmptyLargePages, \ - Coverage->NumberOfEmptyCacheLines, \ - Coverage->FirstPageUsed, \ - Coverage->FirstLargePageUsed, \ - Coverage->FirstCacheLineUsed, \ - Coverage->LastPageUsed, \ - Coverage->LastLargePageUsed, \ - Coverage->LastCacheLineUsed, \ - Coverage->TotalNumberOfAssigned, \ - Coverage->NumberOfKeysWithVerticesMappingToSamePage, \ - Coverage->NumberOfKeysWithVerticesMappingToSameLargePage, \ - Coverage->NumberOfKeysWithVerticesMappingToSameCacheLine, \ - Coverage->MaxGraphTraversalDepth, \ - Coverage->TotalGraphTraversals, \ - Graph->Seeds[0], \ - Graph->Seeds[1], \ - Graph->Seeds[2], \ - Graph->Seeds[3], \ - Graph->Seeds[4], \ - Graph->Seeds[5], \ - Graph->Seeds[6], \ - Graph->Seeds[7], \ - Coverage->NumberOfAssignedPerCacheLineCounts[0], \ - Coverage->NumberOfAssignedPerCacheLineCounts[1], \ - Coverage->NumberOfAssignedPerCacheLineCounts[2], \ - Coverage->NumberOfAssignedPerCacheLineCounts[3], \ - Coverage->NumberOfAssignedPerCacheLineCounts[4], \ - Coverage->NumberOfAssignedPerCacheLineCounts[5], \ - Coverage->NumberOfAssignedPerCacheLineCounts[6], \ - Coverage->NumberOfAssignedPerCacheLineCounts[7], \ - Coverage->NumberOfAssignedPerCacheLineCounts[8], \ - Coverage->NumberOfAssignedPerCacheLineCounts[9], \ - Coverage->NumberOfAssignedPerCacheLineCounts[10], \ - Coverage->NumberOfAssignedPerCacheLineCounts[11], \ - Coverage->NumberOfAssignedPerCacheLineCounts[12], \ - Coverage->NumberOfAssignedPerCacheLineCounts[13], \ - Coverage->NumberOfAssignedPerCacheLineCounts[14], \ - Coverage->NumberOfAssignedPerCacheLineCounts[15], \ - Coverage->NumberOfAssignedPerCacheLineCounts[16], \ - Coverage->Slope, \ - Coverage->Intercept, \ - Coverage->CorrelationCoefficient, \ - Coverage->Score, \ - Coverage->Rank \ - ) GRAPH_REGISTER_SOLVED GraphRegisterSolved; @@ -2669,6 +2600,149 @@ Return Value: return Result; } +_Use_decl_annotations_ +HRESULT +GraphRegisterSolvedNoBestCoverage( + PGRAPH Graph, + PGRAPH *NewGraphPointer + ) +/*++ + +Routine Description: + + This is a vastly-simplified version of GraphRegisterSolved() that is called + when we're in FixedAttempts solving mode (which is useful for benchmarking). + Its main job is to mimic the local variables in the aforementioned routine + and call `EVENT_WRITE_GRAPH_FOUND(Found)` in order to ensure an ETW event + is emitted. + + In order to keep all the downstream machinery working (like verification and + table testing), we register the first graph we find as the "best". + +Arguments: + + Graph - Supplies a pointer to the solved graph to register. + + NewGraphPointer - Supplies the address of a variable which will receive the + address of a new graph instance to be used for solving if the routine + returns PH_S_USE_NEW_GRAPH_FOR_SOLVING. + +Return Value: + + PH_S_CONTINUE_GRAPH_SOLVING - Continue graph solving with the current graph. + + PH_S_USE_NEW_GRAPH_FOR_SOLVING - Continue graph solving but use the graph + returned via the NewGraphPointer parameter. + + PH_S_GRAPH_SOLVING_STOPPED - The context indicated that graph solving was + to stop (due to the target number of solutions being found). + +--*/ +{ + HRESULT Result; + PGRAPH SpareGraph = NULL; + BOOLEAN FoundBestGraph = FALSE; + BOOLEAN StopGraphSolving = FALSE; + BOOLEAN FoundEqualBestGraph = FALSE; + BOOLEAN IsCoverageValueDouble = FALSE; + ULONG EqualCount = 0; + ULONG CoverageValue = 0; + DOUBLE CoverageValueAsDouble = 0.0; + LONGLONG Attempt; + ULONGLONG ElapsedMilliseconds; + PPERFECT_HASH_CONTEXT Context; + PASSIGNED_MEMORY_COVERAGE Coverage; + PERFECT_HASH_TABLE_BEST_COVERAGE_TYPE_ID CoverageType; + + // + // Initialize aliases. + // + + Context = Graph->Context; + Coverage = &Graph->AssignedMemoryCoverage; + CoverageType = Context->BestCoverageType; + Attempt = Coverage->Attempt; + ElapsedMilliseconds = GetTickCount64() - Context->StartMilliseconds; + + // + // Indicate continue graph solving by default. + // + + Result = PH_S_CONTINUE_GRAPH_SOLVING; + + // + // Avoid entering the best graph critical section if Context->BestGraph + // already has a value. (We need to suppress SAL for this optimization.) + // + + _No_competing_thread_begin_ + if (Context->BestGraph != NULL) { + goto End; + } + _No_competing_thread_end_ + + // + // Enter the best graph critical section. + // + + EnterCriticalSection(&Context->BestGraphCriticalSection); + + // + // If there is no best graph currently set, proceed with setting it to + // our current graph, then use the spare graph to continue solving. + // + + if (Context->BestGraph == NULL) { + ASSERT(Context->NewBestGraphCount == 0); + SpareGraph = Context->SpareGraph; + ASSERT(SpareGraph != NULL); + ASSERT(IsSpareGraph(SpareGraph)); + SpareGraph->Flags.IsSpare = FALSE; + Context->SpareGraph = NULL; + Context->BestGraph = Graph; + FoundBestGraph = TRUE; + Context->NewBestGraphCount++; + Result = PH_S_USE_NEW_GRAPH_FOR_SOLVING; + } + + // + // Leave the critical section and complete processing. + // + + LeaveCriticalSection(&Context->BestGraphCriticalSection); + +End: + + if (Context->TargetNumberOfSolutions > 0) { + if (Graph->SolutionNumber >= Context->TargetNumberOfSolutions) { + + // + // We've found sufficient solutions; stop solving. + // + + StopGraphSolving = TRUE; + } + } + + if (StopGraphSolving) { + SetStopSolving(Context); + Result = PH_S_STOP_GRAPH_SOLVING; + } else if (FoundBestGraph) { + + // + // We only want to update the new graph pointer if we're using a new + // graph for solving, otherwise, a downstream assertion will trip. + // + + ASSERT(Result == PH_S_USE_NEW_GRAPH_FOR_SOLVING); + ASSERT(SpareGraph != NULL); + *NewGraphPointer = SpareGraph; + } + + EVENT_WRITE_GRAPH_FOUND(Found); + + return Result; +} #ifdef PERFECTHASH_X64_TSX @@ -3190,6 +3264,79 @@ Return Value: Result = S_OK; + // + // Do some more gross vtbl hacking based on graph impl. + // + + if (Graph->Impl) { + + // + // If the impl has already been set and matches the incoming table's, + // skip this initialization. + // + + if (Graph->Impl == Table->GraphImpl) { + goto SkipGraphVtblHackery; + } + } + + Graph->Impl = Table->GraphImpl; + + if (TableCreateFlags.UseOriginalSeededHashRoutines != FALSE) { + + // + // Invariant check: if original seeded hash routines are requested, + // GraphImpl must be 1. + // + + ASSERT(Graph->Impl == 1); + Graph->Vtbl->AddKeys = GraphAddKeysOriginalSeededHashRoutines; + Graph->Vtbl->Verify = GraphVerifyOriginalSeededHashRoutines; + } + + switch (Graph->Impl) { + case 1: + Graph->Vtbl->IsAcyclic = GraphIsAcyclic; + Graph->Vtbl->Assign = GraphAssign; + Graph->Vtbl->AddKeys = ( + (TableCreateFlags.HashAllKeysFirst != FALSE) ? + GraphHashKeysThenAdd : GraphAddKeys + ); + break; + + case 2: + Graph->Vtbl->IsAcyclic = GraphIsAcyclic; + Graph->Vtbl->Assign = GraphAssign2; + Graph->Vtbl->AddKeys = ( + (TableCreateFlags.HashAllKeysFirst != FALSE) ? + GraphHashKeysThenAdd : GraphAddKeys + ); + break; + + case 3: + Graph->Vtbl->IsAcyclic = GraphIsAcyclic3; + Graph->Vtbl->Assign = GraphAssign3; + Graph->Vtbl->AddKeys = ( + (TableCreateFlags.HashAllKeysFirst != FALSE) ? + GraphHashKeysThenAdd3 : GraphAddKeys3 + ); + break; + + default: + PH_RAISE(PH_E_UNREACHABLE_CODE); + break; + } + + // + // Intentional follow-on to SkipGraphVtblHackery. + // + +SkipGraphVtblHackery: + + // + // Do some more gross vtbl hacking based on graph impl. + // + // // Allocate (or reallocate) arrays. // @@ -3218,12 +3365,23 @@ Return Value: goto Error; \ } - ALLOC_ARRAY(Next, PEDGE); - ALLOC_ARRAY(Edges, PEDGE); - ALLOC_ARRAY(First, PVERTEX); ALLOC_ARRAY(Order, PLONG); ALLOC_ARRAY(Assigned, PASSIGNED); + if (Graph->Impl == 1 || Graph->Impl == 2) { + ALLOC_ARRAY(Edges, PEDGE); + ALLOC_ARRAY(Next, PEDGE); + ALLOC_ARRAY(First, PVERTEX); + } else { + ASSERT(Graph->Impl == 3); + ALLOC_ARRAY(Vertices3, PVERTEX3); + + // + // N.B. We don't do `ALLOC_ARRAY(Edges3, PEDGE3);` as it's handled by + // the code block below (via VertexPairs allocation). + // + } + // // If we're hashing all keys first, prepare the vertex pairs array if it // hasn't already been prepared. (This array is sized off the number of @@ -3232,10 +3390,10 @@ Return Value: // above, which grow larger upon each resize event).) // - if (TableCreateFlags.HashAllKeysFirst) { + if (TableCreateFlags.HashAllKeysFirst || Graph->Impl == 3) { - ASSERT(Info->VertexPairsSizeInBytes != 0); VertexPairsSizeInBytes = (SIZE_T)Info->VertexPairsSizeInBytes; + ASSERT(VertexPairsSizeInBytes != 0); if (Graph->VertexPairs == NULL) { @@ -3299,26 +3457,28 @@ Return Value: Graph->AssignedBitmap.SizeOfBitMap = Graph->NumberOfVertices; Graph->IndexBitmap.SizeOfBitMap = Graph->NumberOfVertices; -#define ALLOC_BITMAP_BUFFER(Name) \ - if (!Graph->##Name##.Buffer) { \ - Graph->##Name##.Buffer = (PULONG)( \ - Allocator->Vtbl->Malloc( \ - Allocator, \ - (ULONG_PTR)Info->##Name##BufferSizeInBytes \ - ) \ - ); \ - } else { \ - Graph->##Name##.Buffer = (PULONG)( \ - Allocator->Vtbl->ReAlloc( \ - Allocator, \ - Graph->##Name##.Buffer, \ - (ULONG_PTR)Info->##Name##BufferSizeInBytes \ - ) \ - ); \ - } \ - if (!Graph->##Name##.Buffer) { \ - Result = E_OUTOFMEMORY; \ - goto Error; \ +#define ALLOC_BITMAP_BUFFER(Name) \ + if (Info->##Name##BufferSizeInBytes > 0) { \ + if (!Graph->##Name##.Buffer) { \ + Graph->##Name##.Buffer = (PULONG)( \ + Allocator->Vtbl->Malloc( \ + Allocator, \ + (ULONG_PTR)Info->##Name##BufferSizeInBytes \ + ) \ + ); \ + } else { \ + Graph->##Name##.Buffer = (PULONG)( \ + Allocator->Vtbl->ReAlloc( \ + Allocator, \ + Graph->##Name##.Buffer, \ + (ULONG_PTR)Info->##Name##BufferSizeInBytes \ + ) \ + ); \ + } \ + if (!Graph->##Name##.Buffer) { \ + Result = E_OUTOFMEMORY; \ + goto Error; \ + } \ } ALLOC_BITMAP_BUFFER(DeletedEdgesBitmap); @@ -3550,7 +3710,7 @@ Return Value: Graph->Attempt = InterlockedIncrement64(&Context->Attempts); - if (!Context->FinishedCount && + if ((Context->FinishedCount == 0) && Graph->Attempt - 1 == Context->ResizeTableThreshold) { if (!SetEvent(Context->TryLargerTableSizeEvent)) { @@ -3563,15 +3723,28 @@ Return Value: } // - // Clear the bitmap buffers. + // Check if we're capping maximum attempts; if so, and we've made sufficient + // attempts, indicate stop solving. // -#define ZERO_BITMAP_BUFFER(Name) \ - ASSERT(0 == Info->##Name##BufferSizeInBytes - \ - ((Info->##Name##BufferSizeInBytes >> 3) << 3)); \ - Rtl->RtlZeroMemory((PDWORD64)Graph->##Name##.Buffer, \ - Info->##Name##BufferSizeInBytes) + if (Context->MaxAttempts > 0) { + if (Graph->Attempt - 1 == Context->MaxAttempts) { + SetStopSolving(Context); + return PH_S_MAX_ATTEMPTS_REACHED; + } + } + // + // Clear the bitmap buffers. + // + +#define ZERO_BITMAP_BUFFER(Name) \ + if (Info->##Name##BufferSizeInBytes > 0) { \ + ASSERT(0 == Info->##Name##BufferSizeInBytes - \ + ((Info->##Name##BufferSizeInBytes >> 3) << 3)); \ + Rtl->RtlZeroMemory((PDWORD64)Graph->##Name##.Buffer, \ + Info->##Name##BufferSizeInBytes); \ + } ZERO_BITMAP_BUFFER(DeletedEdgesBitmap); ZERO_BITMAP_BUFFER(VisitedVerticesBitmap); @@ -3582,12 +3755,14 @@ Return Value: // "Empty" all of the nodes. // -#define EMPTY_ARRAY(Name) \ - ASSERT(0 == Info->##Name##SizeInBytes - \ - ((Info->##Name##SizeInBytes >> 3) << 3)); \ - Rtl->RtlFillMemory((PDWORD64)Graph->##Name, \ - Info->##Name##SizeInBytes, \ - (BYTE)~0) +#define EMPTY_ARRAY(Name) \ + if (Info->##Name##SizeInBytes > 0) { \ + ASSERT(0 == Info->##Name##SizeInBytes - \ + ((Info->##Name##SizeInBytes >> 3) << 3)); \ + Rtl->RtlFillMemory((PDWORD64)Graph->##Name, \ + Info->##Name##SizeInBytes, \ + (BYTE)~0); \ + } EMPTY_ARRAY(Next); EMPTY_ARRAY(First); @@ -3597,19 +3772,22 @@ Return Value: // The Order and Assigned arrays get zeroed. // -#define ZERO_ARRAY(Name) \ - ASSERT(0 == Info->##Name##SizeInBytes - \ - ((Info->##Name##SizeInBytes >> 3) << 3)); \ - Rtl->RtlZeroMemory((PDWORD64)Graph->##Name##, \ - Info->##Name##SizeInBytes) +#define ZERO_ARRAY(Name) \ + if (Info->##Name##SizeInBytes > 0) { \ + ASSERT(0 == Info->##Name##SizeInBytes - \ + ((Info->##Name##SizeInBytes >> 3) << 3)); \ + Rtl->RtlZeroMemory((PDWORD64)Graph->##Name##, \ + Info->##Name##SizeInBytes); \ + } ZERO_ARRAY(Order); ZERO_ARRAY(Assigned); + ZERO_ARRAY(Vertices3); Graph->OrderIndex = (LONG)Graph->NumberOfKeys; ASSERT(Graph->OrderIndex > 0); - if (TableCreateFlags.HashAllKeysFirst) { + if (TableCreateFlags.HashAllKeysFirst || Graph->Impl == 3) { ASSERT(Graph->VertexPairs != NULL); @@ -3627,11 +3805,6 @@ Return Value: // behavior is requested but the array is not currently indicating as // write-combined. // - // N.B. We don't need to clear the individual vertex pair array elements - // like we do with the first/next/edge arrays as they have no state - // associated with the notion of being visited or not. (Whereas we - // need to set the first/next/edge arrays to -1 before solving.) - // if (Graph->Flags.WantsWriteCombiningForVertexPairsArray && !Graph->Flags.VertexPairsArrayIsWriteCombined) { @@ -3659,6 +3832,23 @@ Return Value: goto End; } } + + // + // For graph impl 1 and 2, We don't need to clear the individual vertex + // pair array elements like we do with the first/next/edge arrays as + // they have no state associated with the notion of being visited or + // not. (Whereas we need to set the first/next/edge arrays to -1 before + // solving.) + // + + // + // For graph impl 3, the vertex pairs have state, and need to be set to + // -1. + // + + if (Graph->Impl == 3) { + EMPTY_ARRAY(VertexPairs); + } } // diff --git a/src/PerfectHash/Graph.h b/src/PerfectHash/Graph.h index 00c7e1ef..cd158cd3 100644 --- a/src/PerfectHash/Graph.h +++ b/src/PerfectHash/Graph.h @@ -41,9 +41,11 @@ Module Name: typedef ULONG KEY; typedef ULONG EDGE; typedef ULONG VERTEX; +typedef ULONG DEGREE; typedef KEY *PKEY; typedef EDGE *PEDGE; typedef VERTEX *PVERTEX; +typedef DEGREE *PDEGREE; typedef union _VERTEX_PAIR { struct { VERTEX Vertex1; @@ -53,6 +55,38 @@ typedef union _VERTEX_PAIR { ULARGE_INTEGER AsULargeInteger; } VERTEX_PAIR, *PVERTEX_PAIR; +// +// Our third graph implementation uses the following structures. The 3 suffix +// on the EDGE3 and VERTEX3 type names solely represents the version 3 of the +// implementation (and not, for example, a 3-part hypergraph). +// + +typedef union _EDGE3 { + struct { + VERTEX Vertex1; + VERTEX Vertex2; + }; + VERTEX_PAIR AsVertexPair; + ULONGLONG AsULongLong; +} EDGE3, *PEDGE3; + +typedef struct _VERTEX3 { + + // + // The degree of connections for this vertex. + // + + DEGREE Degree; + + // + // All edges for this vertex; an incidence list constructed via XOR'ing all + // edges together (aka "the XOR-trick"). + // + + EDGE Edges; + +} VERTEX3, *PVERTEX3; + // // A core concept of the 2-part hypergraph algorithm for generating a perfect // hash solution is the "assigned" array. The size of this array is equal to @@ -269,7 +303,13 @@ typedef struct _ASSIGNED_MEMORY_COVERAGE { // Pad out to an 8-byte boundary. // - ULONG Padding; + ULONG Padding1; + + // + // The solution number with respect to other graphs that have been solved. + // + + ULONGLONG SolutionNumber; // // Stores Graph->Attempt at the time the memory coverage was captured. @@ -455,10 +495,10 @@ DEFINE_UNUSED_STATE(GRAPH); // // Default version of the graph implementation used (i.e. GraphImp1.c vs -// GraphImpl2.c). +// GraphImpl2.c vs GraphImpl3.c). // -#define DEFAULT_GRAPH_IMPL_VERSION 2 +#define DEFAULT_GRAPH_IMPL_VERSION 3 // // Define the primary dimensions governing the graph size. @@ -621,6 +661,7 @@ typedef struct _GRAPH_INFO { ULONGLONG NextSizeInBytes; ULONGLONG FirstSizeInBytes; ULONGLONG OrderSizeInBytes; + ULONGLONG Vertices3SizeInBytes; ULONGLONG AssignedSizeInBytes; ULONGLONG VertexPairsSizeInBytes; ULONGLONG ValuesSizeInBytes; @@ -805,15 +846,37 @@ HRESULT ); typedef GRAPH_ADD_HASHED_KEYS *PGRAPH_ADD_HASHED_KEYS; +typedef +_Must_inspect_result_ +_Success_(return >= 0) +_Requires_exclusive_lock_held_(Graph->Lock) +HRESULT +(STDAPICALLTYPE GRAPH_IS_ACYCLIC)( + _In_ PGRAPH Graph + ); +typedef GRAPH_IS_ACYCLIC *PGRAPH_IS_ACYCLIC; + +typedef +_Must_inspect_result_ +_Success_(return >= 0) +_Requires_exclusive_lock_held_(Graph->Lock) +HRESULT +(STDAPICALLTYPE GRAPH_ASSIGN)( + _In_ PGRAPH Graph + ); +typedef GRAPH_ASSIGN *PGRAPH_ASSIGN; + typedef struct _GRAPH_VTBL { DECLARE_COMPONENT_VTBL_HEADER(GRAPH); PGRAPH_SET_INFO SetInfo; PGRAPH_ENTER_SOLVING_LOOP EnterSolvingLoop; + PGRAPH_VERIFY Verify; PGRAPH_LOAD_INFO LoadInfo; PGRAPH_RESET Reset; PGRAPH_LOAD_NEW_SEEDS LoadNewSeeds; PGRAPH_SOLVE Solve; - PGRAPH_VERIFY Verify; + PGRAPH_IS_ACYCLIC IsAcyclic; + PGRAPH_ASSIGN Assign; PGRAPH_CALCULATE_ASSIGNED_MEMORY_COVERAGE CalculateAssignedMemoryCoverage; PGRAPH_CALCULATE_ASSIGNED_MEMORY_COVERAGE_FOR_KEYS_SUBSET CalculateAssignedMemoryCoverageForKeysSubset; @@ -873,6 +936,12 @@ typedef struct _Struct_size_bytes_(SizeOfStruct) _GRAPH { ULONGLONG Attempt; + // + // The solution number with respect to other graphs that have been solved. + // + + ULONGLONG SolutionNumber; + // // A localized attempt number that reflects the number of attempts made // by just this thread. @@ -956,10 +1025,10 @@ typedef struct _Struct_size_bytes_(SizeOfStruct) _GRAPH { ULONG NumberOfEmptyVertices; // - // Pad out to an 8-byte boundary. + // Implementation version of this graph instance. // - ULONG Padding1; + ULONG Impl; // // Duplicate the context pointer. (This is also available from Info.) @@ -1029,14 +1098,29 @@ typedef struct _Struct_size_bytes_(SizeOfStruct) _GRAPH { // _Writable_elements_(NumberOfVertices) - PVERTEX Assigned; + PASSIGNED Assigned; // - // Optional array of vertex pairs, indexed by number of keys. + // Array of VERTEX3 elements for the graph impl 3. // - _Writable_elements_(NumberOfKeys) - PVERTEX_PAIR VertexPairs; + _Writable_elements_(NumberOfVertices) + PVERTEX3 Vertices3; + + // + // Graph implementations 1 & 2: this is an optional array of vertex pairs, + // indexed by number of keys. For implementation 3, this will always + // contain the array of vertex pairs, indexed by edge. + // + + _When_(GraphImpl == 1 || GraphImpl == 2, + _Writable_elements_(NumberOfKeys)) + _When_(GraphImpl == 3, + _Writable_elements_(NumberOfEdges)) + union { + PVERTEX_PAIR VertexPairs; + PEDGE3 Edges3; + }; // // Array of values indexed by the offsets in the Assigned array. This @@ -1251,11 +1335,13 @@ extern GRAPH_APPLY_WEIGHTED_SEED_MASKS GraphApplyWeightedSeedMasks; extern GRAPH_SET_INFO GraphSetInfo; extern GRAPH_ENTER_SOLVING_LOOP GraphEnterSolvingLoop; +extern GRAPH_VERIFY GraphVerify; extern GRAPH_LOAD_INFO GraphLoadInfo; -extern GRAPH_LOAD_NEW_SEEDS GraphLoadNewSeeds; extern GRAPH_RESET GraphReset; +extern GRAPH_LOAD_NEW_SEEDS GraphLoadNewSeeds; extern GRAPH_SOLVE GraphSolve; -extern GRAPH_VERIFY GraphVerify; +extern GRAPH_IS_ACYCLIC GraphIsAcyclic; +extern GRAPH_ASSIGN GraphAssign; extern GRAPH_CALCULATE_ASSIGNED_MEMORY_COVERAGE GraphCalculateAssignedMemoryCoverage; extern GRAPH_CALCULATE_ASSIGNED_MEMORY_COVERAGE_FOR_KEYS_SUBSET @@ -1346,4 +1432,28 @@ typedef GRAPH_INFO_ON_DISK *PGRAPH_INFO_ON_DISK; return PH_S_GRAPH_SOLVING_STOPPED; \ } +// +// Define a helper macro for graph event writing. +// + +#define EVENT_WRITE_GRAPH(Name) \ + EventWriteGraph##Name##Event( \ + &Graph->Activity, \ + Graph->KeysFileName, \ + Edge, \ + NumberOfKeys, \ + Key, \ + Result, \ + Cycles, \ + Microseconds, \ + Graph->Seed1, \ + Graph->Seed2, \ + Graph->Seed3, \ + Graph->Seed4, \ + Graph->Seed5, \ + Graph->Seed6, \ + Graph->Seed7, \ + Graph->Seed8 \ + ) + // vim:set ts=8 sw=4 sts=4 tw=80 expandtab : diff --git a/src/PerfectHash/GraphCounters.h b/src/PerfectHash/GraphCounters.h index 60152f4d..3262d71b 100644 --- a/src/PerfectHash/GraphCounters.h +++ b/src/PerfectHash/GraphCounters.h @@ -60,18 +60,21 @@ Module Name: DECL_GRAPH_COUNTER_STRUCT_FIELDS(AddKeys); \ DECL_GRAPH_COUNTER_STRUCT_FIELDS(HashKeys); \ DECL_GRAPH_COUNTER_STRUCT_FIELDS(AddHashedKeys); \ - DECL_GRAPH_COUNTER_STRUCT_FIELDS(Assign) + DECL_GRAPH_COUNTER_STRUCT_FIELDS(Assign); \ + DECL_GRAPH_COUNTER_STRUCT_FIELDS(IsAcyclic) #define RESET_GRAPH_COUNTERS() \ RESET_GRAPH_COUNTER(AddKeys); \ RESET_GRAPH_COUNTER(HashKeys); \ RESET_GRAPH_COUNTER(AddHashedKeys); \ - RESET_GRAPH_COUNTER(Assign) + RESET_GRAPH_COUNTER(Assign); \ + RESET_GRAPH_COUNTER(IsAcyclic) #define COPY_GRAPH_COUNTERS_FROM_GRAPH_TO_TABLE() \ COPY_GRAPH_COUNTER(AddKeys); \ COPY_GRAPH_COUNTER(HashKeys); \ COPY_GRAPH_COUNTER(AddHashedKeys); \ - COPY_GRAPH_COUNTER(Assign) + COPY_GRAPH_COUNTER(Assign); \ + COPY_GRAPH_COUNTER(IsAcyclic) // vim:set ts=8 sw=4 sts=4 tw=80 expandtab : diff --git a/src/PerfectHash/GraphImpl.h b/src/PerfectHash/GraphImpl.h index e1efcb26..0efd3798 100644 --- a/src/PerfectHash/GraphImpl.h +++ b/src/PerfectHash/GraphImpl.h @@ -46,12 +46,4 @@ BOOLEAN typedef IS_GRAPH_ACYCLIC *PIS_GRAPH_ACYCLIC; extern IS_GRAPH_ACYCLIC IsGraphAcyclic; -typedef -VOID -(NTAPI GRAPH_ASSIGN)( - _In_ PGRAPH Graph - ); -typedef GRAPH_ASSIGN *PGRAPH_ASSIGN; -extern GRAPH_ASSIGN GraphAssign; - // vim:set ts=8 sw=4 sts=4 tw=80 expandtab : diff --git a/src/PerfectHash/GraphImpl1.c b/src/PerfectHash/GraphImpl1.c index 446afef2..cfb5926c 100644 --- a/src/PerfectHash/GraphImpl1.c +++ b/src/PerfectHash/GraphImpl1.c @@ -160,6 +160,10 @@ Return Value: ULONG NumberOfEdgesDeleted; PRTL_NUMBER_OF_SET_BITS RtlNumberOfSetBits; + DECL_GRAPH_COUNTER_LOCAL_VARS(); + + START_GRAPH_COUNTER(); + // // Resolve aliases. // @@ -289,14 +293,31 @@ Return Value: } } + STOP_GRAPH_COUNTER(IsAcyclic); + + //EVENT_WRITE_GRAPH_IS_ACYCLIC(); + return IsAcyclic; } +GRAPH_IS_ACYCLIC GraphIsAcyclic; + +_Use_decl_annotations_ +HRESULT +GraphIsAcyclic( + PGRAPH Graph + ) +{ + BOOLEAN Success; + + Success = IsGraphAcyclic(Graph); + return (Success ? S_OK : PH_E_GRAPH_CYCLIC_FAILURE); +} GRAPH_ASSIGN GraphAssign; _Use_decl_annotations_ -VOID +HRESULT GraphAssign( PGRAPH Graph ) @@ -314,7 +335,7 @@ Routine Description: Return Value: - None. + S_OK. --*/ { @@ -332,13 +353,7 @@ Return Value: ASSERT(Graph->Flags.IsAcyclic); - EventWriteGraphAssignStart( - &Graph->Activity, - Graph->KeysFileName, - Graph->Attempt, - Graph->NumberOfKeys, - Graph->NumberOfVertices - ); + EVENT_WRITE_GRAPH_ASSIGN_START(); // // Walk the graph and assign values. @@ -378,29 +393,11 @@ Return Value: STOP_GRAPH_COUNTER(Assign); - EventWriteGraphAssignStop( - &Graph->Activity, - Graph->KeysFileName, - Graph->Attempt, - Graph->NumberOfKeys, - Graph->NumberOfVertices, - Graph->NumberOfEmptyVertices, - Graph->MaximumTraversalDepth, - Graph->TotalTraversals - ); - - EventWriteGraphAssignResult( - &Graph->Activity, - Graph->KeysFileName, - Graph->Attempt, - Graph->Context->Table->GraphImpl, - Cycles, - Microseconds, - Graph->NumberOfKeys, - Graph->NumberOfVertices - ); - - return; + EVENT_WRITE_GRAPH_ASSIGN_STOP(); + + EVENT_WRITE_GRAPH_ASSIGN_RESULT(); + + return S_OK; } // diff --git a/src/PerfectHash/GraphImpl2.c b/src/PerfectHash/GraphImpl2.c index fee4803f..b146d055 100644 --- a/src/PerfectHash/GraphImpl2.c +++ b/src/PerfectHash/GraphImpl2.c @@ -16,7 +16,7 @@ Module Name: I've included the copyright from NetBSD nbperf's nbperf-chm.c* for this reason; thanks Joerg Sonnenberger ! - [*]: https://github.com/tpn/nbperf/blob/master/nbperf-chm.c + [*]: https://github.com/tpn/nbperf/blob/master/v1/nbperf-chm.c --*/ @@ -60,7 +60,7 @@ Module Name: GRAPH_ASSIGN GraphAssign2; _Use_decl_annotations_ -VOID +HRESULT GraphAssign2( PGRAPH Graph ) @@ -113,13 +113,7 @@ Return Value: ASSERT(Graph->Flags.IsAcyclic); - EventWriteGraphAssignStart( - &Graph->Activity, - Graph->KeysFileName, - Graph->Attempt, - Graph->NumberOfKeys, - Graph->NumberOfVertices - ); + EVENT_WRITE_GRAPH_ASSIGN_START(); // // Walk the graph and assign values. @@ -182,29 +176,11 @@ Return Value: STOP_GRAPH_COUNTER(Assign); - EventWriteGraphAssignStop( - &Graph->Activity, - Graph->KeysFileName, - Graph->Attempt, - Graph->NumberOfKeys, - Graph->NumberOfVertices, - Graph->NumberOfEmptyVertices, - 0, // MaximumTraversalDepth - 0 // TotalTraversals - ); - - EventWriteGraphAssignResult( - &Graph->Activity, - Graph->KeysFileName, - Graph->Attempt, - Table->GraphImpl, - Cycles, - Microseconds, - Graph->NumberOfKeys, - Graph->NumberOfVertices - ); - - return; + EVENT_WRITE_GRAPH_ASSIGN_STOP(); + + EVENT_WRITE_GRAPH_ASSIGN_RESULT(); + + return S_OK; } // vim:set ts=8 sw=4 sts=4 tw=80 expandtab : diff --git a/src/PerfectHash/GraphImpl3.c b/src/PerfectHash/GraphImpl3.c new file mode 100644 index 00000000..2a9c81d7 --- /dev/null +++ b/src/PerfectHash/GraphImpl3.c @@ -0,0 +1,621 @@ +/*++ + +Copyright (c) 2018-2021 Trent Nelson + +Module Name: + + GraphImpl3.c + +Abstract: + + This module is our third implementation of the graph module for the perfect + hash library. It is derived from improvements made to NetBSD's nbperf + module in late 2020/early 2021. + + I've included the copyright from NetBSD nbperf's nbperf-chm.c* for this + reason; thanks Joerg Sonnenberger ! + + [*]: https://github.com/tpn/nbperf/blob/master/v2/nbperf-chm.c + +--*/ + +/* $NetBSD: graph2.c,v 1.5 2021/01/07 16:03:08 joerg Exp $ */ +/*- + * Copyright (c) 2009 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Joerg Sonnenberger. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "stdafx.h" +#include "GraphImpl3.h" +#include "PerfectHashEventsPrivate.h" + +// +// Define helper macros. +// + +#define EMPTY ((VERTEX)-1) +#define IsEmpty(Value) ((ULONG)Value == EMPTY) + +// +// When a solution has been found and the assignment step begins, the initial +// value assigned to a vertex is govered by the following macro. +// + +#define INITIAL_ASSIGNMENT_VALUE 0 + +GRAPH_ADD_EDGE GraphAddEdge3; + +_Use_decl_annotations_ +VOID +GraphAddEdge3( + PGRAPH Graph, + EDGE Edge, + VERTEX Vertex1Index, + VERTEX Vertex2Index + ) +/*++ + +Routine Description: + + This routine adds an edge to the hypergraph for two vertices. + +Arguments: + + Graph - Supplies a pointer to the graph for which the edge is to be added. + + Edge - Supplies the edge to add to the graph. + + Vertex1 - Supplies the first vertex. + + Vertex2 - Supplies the second vertex. + +Return Value: + + None. + +--*/ +{ + PVERTEX3 Vertex1; + PVERTEX3 Vertex2; + +#ifdef _DEBUG + // + // Invariant checks: + // + // - Vertex1Index should be less than the number of vertices. + // - Vertex2Index should be less than the number of vertices. + // - Edge should be less than the number of edges. + // - The graph must not have started deletions. + // + + ASSERT(Vertex1Index < Graph->NumberOfVertices); + ASSERT(Vertex2Index < Graph->NumberOfVertices); + ASSERT(Edge < Graph->NumberOfEdges); + ASSERT(!Graph->Flags.Shrinking); +#endif + + // + // Insert the first edge. + // + + Vertex1 = &Graph->Vertices3[Vertex1Index]; + Vertex1->Edges ^= Edge; + ++Vertex1->Degree; + + // + // Insert the second edge. + // + + Vertex2 = &Graph->Vertices3[Vertex2Index]; + Vertex2->Edges ^= Edge; + ++Vertex2->Degree; +} + + +GRAPH_ADD_KEYS GraphAddKeys3; + +_Use_decl_annotations_ +HRESULT +GraphAddKeys3( + PGRAPH Graph, + ULONG NumberOfKeys, + PKEY Keys + ) +/*++ + +Routine Description: + + Add all keys to the hypergraph using the unique seeds to hash each key into + two vertex values, connected by a "hyper-edge". This implementation uses + the newer "Ex" version of the seeded hash routines. + +Arguments: + + Graph - Supplies a pointer to the graph for which the keys will be added. + + NumberOfKeys - Supplies the number of keys. + + Keys - Supplies the base address of the keys array. + +Return Value: + + S_OK - Success. + + PH_E_GRAPH_VERTEX_COLLISION_FAILURE - The graph encountered two vertices + that, when masked, were identical. + +--*/ +{ + KEY Key = 0; + EDGE Edge; + PEDGE Edges; + ULONG Mask; + HRESULT Result; + ULARGE_INTEGER Hash; + PULONGLONG VertexPairs; + PPERFECT_HASH_TABLE Table; + PPERFECT_HASH_TABLE_SEEDED_HASH_EX SeededHashEx; + + DECL_GRAPH_COUNTER_LOCAL_VARS(); + + // + // Initialize aliases. + // + + Table = Graph->Context->Table; + Mask = Table->HashMask; + SeededHashEx = SeededHashExRoutines[Table->HashFunctionId]; + Edges = (PEDGE)Keys; + + // + // Enumerate all keys in the input set, hash them into two unique vertices, + // then add them to the hypergraph. + // + + Result = S_OK; + VertexPairs = (PULONGLONG)Graph->VertexPairs; + + START_GRAPH_COUNTER(); + + for (Edge = 0; Edge < NumberOfKeys; Edge++) { + Key = *Edges++; + + Hash.QuadPart = SeededHashEx(Key, &Graph->FirstSeed, Mask); + + if (Hash.HighPart == Hash.LowPart) { + Result = PH_E_GRAPH_VERTEX_COLLISION_FAILURE; + break; + } + + *VertexPairs++ = Hash.QuadPart; + + // + // Add the edge to the graph connecting these two vertices. + // + + GraphAddEdge3(Graph, Edge, Hash.LowPart, Hash.HighPart); + } + + STOP_GRAPH_COUNTER(AddKeys); + + EVENT_WRITE_GRAPH(AddKeys); + + return Result; +} + +GRAPH_ADD_KEYS GraphHashKeysThenAdd3; + +_Use_decl_annotations_ +HRESULT +GraphHashKeysThenAdd3( + PGRAPH Graph, + ULONG NumberOfKeys, + PKEY Keys + ) +/*++ + +Routine Description: + + This routine is a drop-in replacement for Graph->Vtbl->AddKeys (handled by + GraphInitialize()), and is responsible for hashing all keys into vertices + first, then adding all resulting vertices to the graph. This differs from + the normal GraphAddKeys() behavior, which hashes a key into two vertices + and immediately adds them to the graph via GraphAddEdge(). (This routine + loops over the keys twice; once to construct all the vertices, then again + to add them all to the graph.) + + The motivation behind this routine is to separate out the action of hashing + keys versus adding them to the graph to better analyze performance. + +Arguments: + + Graph - Supplies a pointer to the graph for which the keys will be added. + + NumberOfKeys - Supplies the number of keys. + + Keys - Supplies the base address of the keys array. + +Return Value: + + S_OK - Success. + + PH_E_GRAPH_VERTEX_COLLISION_FAILURE - The graph encountered two vertices + that, when masked, were identical. + + N.B. Unlike GraphAddKeys(), when this code is returned, none of the + vertices will have been added to the graph at this point (versus + having the graph in a partially-constructed state). This has no + impact on the behavior of the graph solving, other than potentially + being faster overall for graphs encountering a lot of collisions + (because the overhead of writing to all the graph's First/Next + arrays will have been avoided). + +--*/ +{ + EDGE Edge; + HRESULT Result; + VERTEX_PAIR VertexPair; + PVERTEX_PAIR VertexPairs; + + DECL_GRAPH_COUNTER_LOCAL_VARS(); + + // + // Attempt to hash the keys first. + // + + Result = GraphHashKeys(Graph, NumberOfKeys, Keys); + if (FAILED(Result)) { + return Result; + } + + // + // No vertex collisions were encountered. All the vertex pairs have been + // written to Graph->VertexPairs, indexed by Edge. Loop through the number + // of edges and add the vertices to the graph. + // + + VertexPairs = Graph->VertexPairs; + + START_GRAPH_COUNTER(); + + for (Edge = 0; Edge < NumberOfKeys; Edge++) { + VertexPair = *(VertexPairs++); + GraphAddEdge3(Graph, Edge, VertexPair.Vertex1, VertexPair.Vertex2); + } + + STOP_GRAPH_COUNTER(AddHashedKeys); + + EVENT_WRITE_GRAPH_ADD_HASHED_KEYS(); + + return S_OK; +} + +VOID +GraphRemoveVertex3( + _In_ PGRAPH Graph, + _In_ VERTEX VertexIndex + ) +{ + EDGE Edge; + PEDGE3 Edge3; + LONG OrderIndex; + PVERTEX3 Vertex; + PVERTEX3 Vertex1; + PVERTEX3 Vertex2; + + Vertex = &Graph->Vertices3[VertexIndex]; + if (Vertex->Degree != 1) { + return; + } + + ASSERT(Vertex->Degree > 0); + + Edge = Vertex->Edges; + Edge3 = &Graph->Edges3[Edge]; + + if (IsEmpty(Edge3->Vertex1)) { + ASSERT(IsEmpty(Edge3->Vertex2)); + return; + } else if (IsEmpty(Edge3->Vertex2)) { + ASSERT(IsEmpty(Edge3->Vertex1)); + return; + } + + Vertex1 = &Graph->Vertices3[Edge3->Vertex1]; + if (Vertex1->Degree >= 1) { + Vertex1->Edges ^= Edge; + --Vertex1->Degree; + } + + Vertex2 = &Graph->Vertices3[Edge3->Vertex2]; + if (Vertex2->Degree >= 1) { + Vertex2->Edges ^= Edge; + --Vertex2->Degree; + } + + Graph->DeletedEdgeCount++; + ASSERT(Graph->DeletedEdgeCount <= Graph->NumberOfEdges); + OrderIndex = --Graph->OrderIndex; + ASSERT(OrderIndex >= 0); + Graph->Order[OrderIndex] = Edge; +} + +GRAPH_IS_ACYCLIC GraphIsAcyclic3; + +_Use_decl_annotations_ +HRESULT +GraphIsAcyclic3( + PGRAPH Graph + ) +/*++ + +Routine Description: + + This routine determines whether or not the graph is acyclic. An acyclic + graph is one where, after deletion of all edges in the graph with vertices + of degree 1, no edges remain. + +Arguments: + + Graph - Supplies a pointer to the graph to operate on. + +Return Value: + + TRUE if the graph is acyclic, FALSE if it's cyclic. + +--*/ +{ + LONG Index; + ULONG EdgeIndex; + VERTEX Vertex; + PEDGE3 OtherEdge; + BOOLEAN IsAcyclic; + ULONG NumberOfKeys; + ULONG NumberOfEdges; + ULONG NumberOfVertices; + ULONG NumberOfEdgesDeleted; + + DECL_GRAPH_COUNTER_LOCAL_VARS(); + + // + // Resolve aliases. + // + + NumberOfKeys = Graph->NumberOfKeys; + NumberOfEdges = Graph->NumberOfEdges; + NumberOfVertices = Graph->NumberOfVertices; + + // + // Invariant check: we should not be shrinking prior to this point, and our + // deleted edge count should be 0. + // + + ASSERT(!Graph->Flags.Shrinking); + ASSERT(Graph->DeletedEdgeCount == 0); + + Graph->OrderIndex = (LONG)NumberOfKeys; + + // + // Toggle the shrinking bit to indicate we've started edge deletion. + // + + Graph->Flags.Shrinking = TRUE; + + // + // Enumerate through all vertices in the graph and attempt to delete those + // connected by edges that have degree 1. + // + + START_GRAPH_COUNTER(); + + for (Vertex = 0; Vertex < NumberOfVertices; Vertex++) { + GraphRemoveVertex3(Graph, Vertex); + } + + for (Index = (LONG)NumberOfKeys; + Graph->OrderIndex > 0 && Index > Graph->OrderIndex; + NOTHING) + { + EdgeIndex = Graph->Order[--Index]; + OtherEdge = &Graph->Edges3[EdgeIndex]; + GraphRemoveVertex3(Graph, OtherEdge->Vertex1); + GraphRemoveVertex3(Graph, OtherEdge->Vertex2); + } + + ASSERT(Graph->OrderIndex >= 0); + + NumberOfEdgesDeleted = Graph->DeletedEdgeCount; + IsAcyclic = (NumberOfKeys == NumberOfEdgesDeleted); + + // + // Invariant check: if we're acyclic, the order index should be zero (as all + // keys were deleted once), greater than zero otherwise. + // + + if (IsAcyclic) { + ASSERT(Graph->OrderIndex == 0); + } else { + ASSERT(Graph->OrderIndex > 0); + } + + // + // Make a note that we're acyclic if applicable in the graph's flags. + // This is checked by GraphAssign() to ensure we only operate on acyclic + // graphs. + // + + if (IsAcyclic) { + + Graph->Flags.IsAcyclic = TRUE; + + } else { + + ULONG HighestDeletedEdges; + PPERFECT_HASH_CONTEXT Context; + + Context = Graph->Info->Context; + + if (NumberOfEdgesDeleted > Context->HighestDeletedEdgesCount) { + + // + // Register as the highest deleted edges count if applicable. + // + + while (TRUE) { + + HighestDeletedEdges = Context->HighestDeletedEdgesCount; + + if (NumberOfEdgesDeleted <= HighestDeletedEdges) { + break; + } + + InterlockedCompareExchange( + (PLONG)&Context->HighestDeletedEdgesCount, + NumberOfEdgesDeleted, + HighestDeletedEdges + ); + + } + } + } + + STOP_GRAPH_COUNTER(IsAcyclic); + + EVENT_WRITE_GRAPH_IS_ACYCLIC(); + + return (IsAcyclic ? S_OK : PH_E_GRAPH_CYCLIC_FAILURE); +} + +GRAPH_ASSIGN GraphAssign3; + +_Use_decl_annotations_ +HRESULT +GraphAssign3( + PGRAPH Graph + ) +/*++ + +Routine Description: + + This routine is called after a graph has determined to be acyclic. It is + responsible for walking the graph and assigning values to edges in order to + complete the perfect hash solution. + +Arguments: + + Graph - Supplies a pointer to the graph to operate on. + +Return Value: + + None. + +--*/ +{ + PEDGE3 Edge3; + ULONG Index; + LONG Order; + ULONG Assigned; + ULONG IndexMask; + VERTEX Vertex1; + VERTEX Vertex2; + ULONG NumberOfKeys; + ULONG NumberOfEdges; + PPERFECT_HASH_TABLE Table; + + DECL_GRAPH_COUNTER_LOCAL_VARS(); + + // + // Initialize aliases. + // + + Table = Graph->Context->Table; + IndexMask = Table->IndexMask; + NumberOfKeys = Graph->NumberOfKeys; + NumberOfEdges = Graph->NumberOfEdges; + + // + // Invariant check: we should only be called on graphs that have already + // been determined to be invariant. + // + + ASSERT(Graph->Flags.IsAcyclic); + + EVENT_WRITE_GRAPH_ASSIGN_START(); + + // + // Walk the graph and assign values. + // + + START_GRAPH_COUNTER(); + + for (Index = 0; Index < NumberOfKeys; Index++) { + + // + // Obtain the edge for the deletion order at this index. + // + + Order = Graph->Order[Index]; + Edge3 = &Graph->Edges3[Order]; + + if (!IsVisitedVertex3(Graph, Edge3->Vertex1)) { + Vertex1 = Edge3->Vertex1; + Vertex2 = Edge3->Vertex2; + ASSERT(Graph->Assigned[Vertex1] == INITIAL_ASSIGNMENT_VALUE); + } else { + Vertex1 = Edge3->Vertex2; + Vertex2 = Edge3->Vertex1; + } + + Assigned = Order - Graph->Assigned[Vertex2]; + if (Assigned >= NumberOfEdges) { + Assigned += NumberOfEdges; + } + + ASSERT(Graph->Assigned[Vertex1] == INITIAL_ASSIGNMENT_VALUE); + Graph->Assigned[Vertex1] = Assigned; + + // + // Set both vertices as visited. + // + + RegisterVertexVisit3(Graph, Vertex1); + RegisterVertexVisit3(Graph, Vertex2); + } + + STOP_GRAPH_COUNTER(Assign); + + EVENT_WRITE_GRAPH_ASSIGN_STOP(); + + EVENT_WRITE_GRAPH_ASSIGN_RESULT(); + + return S_OK; +} + +// vim:set ts=8 sw=4 sts=4 tw=80 expandtab : diff --git a/src/PerfectHash/GraphImpl3.h b/src/PerfectHash/GraphImpl3.h new file mode 100644 index 00000000..266f60d5 --- /dev/null +++ b/src/PerfectHash/GraphImpl3.h @@ -0,0 +1,78 @@ +/*++ + +Copyright (c) 2018-2021 Trent Nelson + +Module Name: + + GraphImpl3.h + +Abstract: + + This is the private header file for the 3rd implementation of graph + functionality for the perfect hash library. + +--*/ + +#include "stdafx.h" + +FORCEINLINE +BOOLEAN +IsVisitedVertex3( + _In_ PGRAPH Graph, + _In_ VERTEX Vertex + ) +{ + return TestGraphBit(VisitedVerticesBitmap, Vertex); +} + +FORCEINLINE +VOID +RegisterVertexVisit3( + _In_ PGRAPH Graph, + _In_ VERTEX Vertex + ) +{ + SetGraphBit(VisitedVerticesBitmap, Vertex); +} + +#if 0 +#ifdef _DEBUG + +FORCEINLINE +VOID +RegisterEdgeDeletion3( + _In_ PGRAPH Graph, + _In_ EDGE Edge + ) +{ + LONG OrderIndex; + //ASSERT(!TestGraphBit(DeletedEdgesBitmap, Edge)); + //SetGraphBit(DeletedEdgesBitmap, Edge); + Graph->DeletedEdgeCount++; + ASSERT(Graph->DeletedEdgeCount <= Graph->NumberOfEdges); + OrderIndex = --Graph->OrderIndex; + ASSERT(OrderIndex >= 0); + Graph->Order[OrderIndex] = Edge; +} + +#else + +FORCEINLINE +VOID +RegisterEdgeDeletion3( + _In_ PGRAPH Graph, + _In_ EDGE Edge + ) +{ + ULONG OrderIndex; + //SetGraphBit(DeletedEdgesBitmap, Edge); + Graph->DeletedEdgeCount++; + OrderIndex = --Graph->OrderIndex; + Graph->Order[OrderIndex] = Edge; +} + +#endif +#endif + + +// vim:set ts=8 sw=4 sts=4 tw=80 expandtab : diff --git a/src/PerfectHash/PerfectHash.vcxproj b/src/PerfectHash/PerfectHash.vcxproj index 24deadf5..59d80e42 100644 --- a/src/PerfectHash/PerfectHash.vcxproj +++ b/src/PerfectHash/PerfectHash.vcxproj @@ -143,6 +143,7 @@ + @@ -226,6 +227,7 @@ + diff --git a/src/PerfectHash/PerfectHash.vcxproj.filters b/src/PerfectHash/PerfectHash.vcxproj.filters index cad17ada..25aaebdd 100644 --- a/src/PerfectHash/PerfectHash.vcxproj.filters +++ b/src/PerfectHash/PerfectHash.vcxproj.filters @@ -310,6 +310,9 @@ Source Files + + Source Files + @@ -603,6 +606,9 @@ Private Header Files + + Private Header Files + diff --git a/src/PerfectHash/PerfectHashConstants.c b/src/PerfectHash/PerfectHashConstants.c index 717a64d8..633e9911 100644 --- a/src/PerfectHash/PerfectHashConstants.c +++ b/src/PerfectHash/PerfectHashConstants.c @@ -1231,18 +1231,20 @@ GRAPH_VTBL GraphInterface = { (PGRAPH_LOCK_SERVER)&ComponentLockServer, &GraphSetInfo, &GraphEnterSolvingLoop, + &GraphVerify, &GraphLoadInfo, &GraphReset, &GraphLoadNewSeeds, &GraphSolve, - &GraphVerify, + &GraphIsAcyclic, + &GraphAssign, &GraphCalculateAssignedMemoryCoverage, &GraphCalculateAssignedMemoryCoverageForKeysSubset, &GraphRegisterSolved, &GraphShouldWeContinueTryingToSolve, &GraphAddKeys, }; -VERIFY_VTBL_SIZE(GRAPH, 12); +VERIFY_VTBL_SIZE(GRAPH, 14); // // Cu diff --git a/src/PerfectHash/PerfectHashContext.c b/src/PerfectHash/PerfectHashContext.c index c50da7ee..6df451c4 100644 --- a/src/PerfectHash/PerfectHashContext.c +++ b/src/PerfectHash/PerfectHashContext.c @@ -871,10 +871,13 @@ Return Value: Context->SolvedContext = NULL; Context->Attempts = 0; + Context->MinAttempts = 0; + Context->MaxAttempts = 0; Context->ResizeLimit = 0; Context->InitialTableSize = 0; Context->StartMilliseconds = 0; Context->ResizeTableThreshold = 0; + Context->TargetNumberOfSolutions = 0; Context->HighestDeletedEdgesCount = 0; Context->NumberOfTableResizeEvents = 0; Context->TotalNumberOfAttemptsWithSmallerTableSizes = 0; diff --git a/src/PerfectHash/PerfectHashContext.h b/src/PerfectHash/PerfectHashContext.h index 81167a15..eb483535 100644 --- a/src/PerfectHash/PerfectHashContext.h +++ b/src/PerfectHash/PerfectHashContext.h @@ -143,6 +143,7 @@ typedef PERFECT_HASH_CONTEXT_STATE *PPERFECT_HASH_CONTEXT_STATE; ) #define SetFirstSolvedGraphWins(Context) \ + ASSERT(Context->MinAttempts == 0); \ Context->State.FirstSolvedGraphWins = TRUE; \ Context->State.FindBestMemoryCoverage = FALSE @@ -416,6 +417,20 @@ typedef struct _Struct_size_bytes_(SizeOfStruct) _PERFECT_HASH_CONTEXT { ULONG InitialResizes; + // + // The following members control the minimum and maximum graph solving + // attempts, and are particularly useful for ensuring a fixed set of + // attempts are made at solving a graph, which is useful during + // benchmarking. Attempt refers to literally that: an attempt. So, it + // includes both failed and successfully-solved graphs. If you want to + // generate a fixed number of solutions, use TargetNumberOfSolutions. + // + + ULONG MinAttempts; + ULONG MaxAttempts; + ULONG TargetNumberOfSolutions; + ULONG Padding9; + // // Maximum number of equal best graphs. When this number is hit, graph // solving will stop, even if the target number of attempts supplied by diff --git a/src/PerfectHash/PerfectHashErrors.dbg b/src/PerfectHash/PerfectHashErrors.dbg index 9dd65e8d..f0c0856f 100644 --- a/src/PerfectHash/PerfectHashErrors.dbg +++ b/src/PerfectHash/PerfectHashErrors.dbg @@ -17,6 +17,7 @@ struct { (HRESULT) PH_S_TABLE_RESIZE_IMMINENT, "PH_S_TABLE_RESIZE_IMMINENT", (HRESULT) PH_S_USE_NEW_GRAPH_FOR_SOLVING, "PH_S_USE_NEW_GRAPH_FOR_SOLVING", (HRESULT) PH_S_NO_KEY_SIZE_EXTRACTED_FROM_FILENAME, "PH_S_NO_KEY_SIZE_EXTRACTED_FROM_FILENAME", + (HRESULT) PH_S_MAX_ATTEMPTS_REACHED, "PH_S_MAX_ATTEMPTS_REACHED", (HRESULT) PH_I_CREATE_TABLE_ROUTINE_RECEIVED_SHUTDOWN_EVENT, "PH_I_CREATE_TABLE_ROUTINE_RECEIVED_SHUTDOWN_EVENT", (HRESULT) PH_I_CREATE_TABLE_ROUTINE_FAILED_TO_FIND_SOLUTION, "PH_I_CREATE_TABLE_ROUTINE_FAILED_TO_FIND_SOLUTION", (HRESULT) PH_I_MAXIMUM_NUMBER_OF_TABLE_RESIZE_EVENTS_REACHED, "PH_I_MAXIMUM_NUMBER_OF_TABLE_RESIZE_EVENTS_REACHED", @@ -348,5 +349,15 @@ struct { (HRESULT) PH_E_RNG_USE_RANDOM_START_SEED_CONFLICTS_WITH_RNG_SEED, "PH_E_RNG_USE_RANDOM_START_SEED_CONFLICTS_WITH_RNG_SEED", (HRESULT) PH_E_RNG_GENERATE_RANDOM_BYTES_INVALID_BUFFER_SIZE, "PH_E_RNG_GENERATE_RANDOM_BYTES_INVALID_BUFFER_SIZE", (HRESULT) PH_E_RNG_NOT_INITIALIZED, "PH_E_RNG_NOT_INITIALIZED", + (HRESULT) PH_E_INVALID_FIXED_ATTEMPTS, "PH_E_INVALID_FIXED_ATTEMPTS", + (HRESULT) PH_E_INVALID_MIN_ATTEMPTS, "PH_E_INVALID_MIN_ATTEMPTS", + (HRESULT) PH_E_INVALID_MAX_ATTEMPTS, "PH_E_INVALID_MAX_ATTEMPTS", + (HRESULT) PH_E_FIXED_ATTEMPTS_CONFLICTS_WITH_MINMAX_ATTEMPTS, "PH_E_FIXED_ATTEMPTS_CONFLICTS_WITH_MINMAX_ATTEMPTS", + (HRESULT) PH_E_MIN_ATTEMPTS_EXCEEDS_MAX_ATTEMPTS, "PH_E_MIN_ATTEMPTS_EXCEEDS_MAX_ATTEMPTS", + (HRESULT) PH_E_FIXED_ATTEMPTS_CONFLICTS_WITH_FIND_BEST_GRAPH, "PH_E_FIXED_ATTEMPTS_CONFLICTS_WITH_FIND_BEST_GRAPH", + (HRESULT) PH_E_MIN_ATTEMPTS_CONFLICTS_WITH_FIND_BEST_GRAPH, "PH_E_MIN_ATTEMPTS_CONFLICTS_WITH_FIND_BEST_GRAPH", + (HRESULT) PH_E_INVALID_TARGET_NUMBER_OF_SOLUTIONS, "PH_E_INVALID_TARGET_NUMBER_OF_SOLUTIONS", + (HRESULT) PH_E_TARGET_NUMBER_OF_SOLUTIONS_CONFLICTS_WITH_FIND_BEST_GRAPH, "PH_E_TARGET_NUMBER_OF_SOLUTIONS_CONFLICTS_WITH_FIND_BEST_GRAPH", + (HRESULT) PH_E_TARGET_NUMBER_OF_SOLUTIONS_EXCEEDS_MIN_ATTEMPTS, "PH_E_TARGET_NUMBER_OF_SOLUTIONS_EXCEEDS_MIN_ATTEMPTS", (HRESULT) 0xFFFFFFFF, NULL }; diff --git a/src/PerfectHash/PerfectHashErrors.mc b/src/PerfectHash/PerfectHashErrors.mc index e12a75e8..073b2fcb 100644 --- a/src/PerfectHash/PerfectHashErrors.mc +++ b/src/PerfectHash/PerfectHashErrors.mc @@ -96,6 +96,15 @@ Language=English No key size extracted from file name. . +MessageId=0x00a +Severity=Success +Facility=ITF +SymbolicName=PH_S_MAX_ATTEMPTS_REACHED +Language=English +Maximum attempts at solving reached. +. + + ; ;//////////////////////////////////////////////////////////////////////////////// ;// PH_SEVERITY_INFORMATIONAL @@ -330,6 +339,8 @@ Table Create Flags: will find a graph that is better (based on the predicate) than when in first graph wins mode. + N.B. See also: --TargetNumberOfSolutions, --FixedAttempts. + --SkipMemoryCoverageInFirstGraphWinsMode Skips calculating memory coverage information when in "first graph wins" @@ -540,11 +551,12 @@ Table Compile Flags: Table Create Parameters: - --GraphImpl=1|2 [default: 2] + --GraphImpl=1|2|3 [default: 3] Selects the backend version of the graph assignment step. Version 1 matches the original CHM algorithm, version 2 is faster and was derived - from NetBSD's nbperf routine. Defaults to version 2. + from NetBSD's nbperf module, version 3 is even faster and was derived + from additional improvements to NetBSD's nbperf module in 2020. --ValueSizeInBytes=4|8 @@ -668,6 +680,18 @@ Table Create Parameters: N.B. Only applies to PerfectHashCreate.exe. + --TargetNumberOfSolutions=N + + Where N is a positive integer and represents a target number of + solutions to find before stopping graph solving. Typically only useful + for benchmarking. + + --FixedAttempts=N + + Where N is a positive integer and represents a fixed number of attempts + that will be made (irrespective of whether or not a solution was found) + before graph solving stops. Typically only useful for benchmarking. + --Seeds= Supplies an optional comma-separated list of up to 8 integers that @@ -3463,3 +3487,83 @@ Language=English An RNG must be initialized before it can be used. . +MessageId=0x3c7 +Severity=Fail +Facility=ITF +SymbolicName=PH_E_INVALID_FIXED_ATTEMPTS +Language=English +Invalid FixedAttempts. +. + +MessageId=0x3c8 +Severity=Fail +Facility=ITF +SymbolicName=PH_E_INVALID_MIN_ATTEMPTS +Language=English +Invalid MinAttempts. +. + +MessageId=0x3c9 +Severity=Fail +Facility=ITF +SymbolicName=PH_E_INVALID_MAX_ATTEMPTS +Language=English +Invalid MaxAttempts. +. + +MessageId=0x3ca +Severity=Fail +Facility=ITF +SymbolicName=PH_E_FIXED_ATTEMPTS_CONFLICTS_WITH_MINMAX_ATTEMPTS +Language=English +FixedAttempts conflicts with MinAttempts/MaxAttempts. +. + +MessageId=0x3cb +Severity=Fail +Facility=ITF +SymbolicName=PH_E_MIN_ATTEMPTS_EXCEEDS_MAX_ATTEMPTS +Language=English +MinAttempts must be less than or equal to MaxAttempts. +. + +MessageId=0x3cc +Severity=Fail +Facility=ITF +SymbolicName=PH_E_FIXED_ATTEMPTS_CONFLICTS_WITH_FIND_BEST_GRAPH +Language=English +FixedAttempts conflicts with FindBestGraph. +. + +MessageId=0x3cd +Severity=Fail +Facility=ITF +SymbolicName=PH_E_MIN_ATTEMPTS_CONFLICTS_WITH_FIND_BEST_GRAPH +Language=English +MinAttempts conflicts with FindBestGraph. +. + +MessageId=0x3ce +Severity=Fail +Facility=ITF +SymbolicName=PH_E_INVALID_TARGET_NUMBER_OF_SOLUTIONS +Language=English +Invalid TargetNumberOfSolutions. +. + +MessageId=0x3cf +Severity=Fail +Facility=ITF +SymbolicName=PH_E_TARGET_NUMBER_OF_SOLUTIONS_CONFLICTS_WITH_FIND_BEST_GRAPH +Language=English +TargetNumberOfSolutions conflicts with FindBestGraph. +. + +MessageId=0x3d0 +Severity=Fail +Facility=ITF +SymbolicName=PH_E_TARGET_NUMBER_OF_SOLUTIONS_EXCEEDS_MIN_ATTEMPTS +Language=English +TargetNumberOfSolutions exceeds MinAttempts. +. + diff --git a/src/PerfectHash/PerfectHashErrorsTEMP.BIN b/src/PerfectHash/PerfectHashErrorsTEMP.BIN index 74da3590..0f6ba429 100644 Binary files a/src/PerfectHash/PerfectHashErrorsTEMP.BIN and b/src/PerfectHash/PerfectHashErrorsTEMP.BIN differ diff --git a/src/PerfectHash/PerfectHashErrors_English.bin b/src/PerfectHash/PerfectHashErrors_English.bin index a99f6358..fedb8d1f 100644 Binary files a/src/PerfectHash/PerfectHashErrors_English.bin and b/src/PerfectHash/PerfectHashErrors_English.bin differ diff --git a/src/PerfectHash/PerfectHashEvents.man b/src/PerfectHash/PerfectHashEvents.man index 5f4fdfd5..9d01994c 100644 --- a/src/PerfectHash/PerfectHashEvents.man +++ b/src/PerfectHash/PerfectHashEvents.man @@ -41,6 +41,7 @@ + @@ -143,6 +154,7 @@ + @@ -153,6 +165,7 @@ + + + @@ -312,6 +337,7 @@ + diff --git a/src/PerfectHash/PerfectHashEventsPrivate.h b/src/PerfectHash/PerfectHashEventsPrivate.h index ec55a8f2..029bb598 100644 --- a/src/PerfectHash/PerfectHashEventsPrivate.h +++ b/src/PerfectHash/PerfectHashEventsPrivate.h @@ -1,6 +1,6 @@ /*++ -Copyright (c) 2020 Trent Nelson +Copyright (c) 2021 Trent Nelson Module Name: @@ -36,4 +36,172 @@ Module Name: #undef RtlZeroMemory #pragma warning(pop) +#define EVENT_WRITE_RTL_RANDOM_BYTES_START(Size) \ + EventWriteRtlGenerateRandomBytesStartEvent( \ + NULL, \ + Size \ + ) + +#define EVENT_WRITE_RTL_RANDOM_BYTES_STOP(Size, Result) \ + EventWriteRtlGenerateRandomBytesStopEvent( \ + NULL, \ + Size, \ + Result \ + ) + +#define EVENT_WRITE_GRAPH(Name) \ + EventWriteGraph##Name##Event( \ + &Graph->Activity, \ + Graph->KeysFileName, \ + Edge, \ + NumberOfKeys, \ + Key, \ + Result, \ + Cycles, \ + Microseconds, \ + Graph->Seed1, \ + Graph->Seed2, \ + Graph->Seed3, \ + Graph->Seed4, \ + Graph->Seed5, \ + Graph->Seed6, \ + Graph->Seed7, \ + Graph->Seed8 \ + ) + +#define EVENT_WRITE_GRAPH_ADD_KEYS() EVENT_WRITE_GRAPH(AddKeys) +#define EVENT_WRITE_GRAPH_HASH_KEYS() EVENT_WRITE_GRAPH(HashKeys) + +#define EVENT_WRITE_GRAPH_HASH_KEYS2() \ + EventWriteGraphHashKeysEvent( \ + &Graph->Activity, \ + Graph->KeysFileName, \ + NumberOfKeys, \ + Cycles, \ + Microseconds \ + ) + +#define EVENT_WRITE_GRAPH_ADD_HASHED_KEYS() \ + EventWriteGraphAddHashedKeysEvent( \ + &Graph->Activity, \ + Graph->KeysFileName, \ + NumberOfKeys, \ + Cycles, \ + Microseconds \ + ) + +#define EVENT_WRITE_GRAPH_IS_ACYCLIC() \ + EventWriteGraphIsAcyclicEvent( \ + &Graph->Activity, \ + Graph->KeysFileName, \ + Graph->Attempt, \ + Graph->Impl, \ + Cycles, \ + Microseconds, \ + Graph->NumberOfKeys, \ + Graph->NumberOfVertices, \ + Graph->Flags.IsAcyclic \ + ) + +#define EVENT_WRITE_GRAPH_ASSIGN_START() \ + EventWriteGraphAssignStartEvent( \ + &Graph->Activity, \ + Graph->KeysFileName, \ + Graph->Attempt, \ + Graph->NumberOfKeys, \ + Graph->NumberOfVertices \ + ) + +#define EVENT_WRITE_GRAPH_ASSIGN_STOP() \ + EventWriteGraphAssignStopEvent( \ + &Graph->Activity, \ + Graph->KeysFileName, \ + Graph->Attempt, \ + Graph->NumberOfKeys, \ + Graph->NumberOfVertices, \ + Graph->NumberOfEmptyVertices, \ + Graph->MaximumTraversalDepth, \ + Graph->TotalTraversals \ + ) + +#define EVENT_WRITE_GRAPH_ASSIGN_RESULT() \ + EventWriteGraphAssignResultEvent( \ + &Graph->Activity, \ + Graph->KeysFileName, \ + Graph->Attempt, \ + Graph->Impl, \ + Cycles, \ + Microseconds, \ + Graph->NumberOfKeys, \ + Graph->NumberOfVertices \ + ) + +#define EVENT_WRITE_GRAPH_FOUND(Name) \ + EventWriteGraph##Name##Event( \ + &Graph->Activity, \ + Graph->KeysFileName, \ + Attempt, \ + Graph->SolutionNumber, \ + ElapsedMilliseconds, \ + (ULONG)CoverageType, \ + CoverageValue, \ + CoverageValueAsDouble, \ + (StopGraphSolving != FALSE), \ + (FoundBestGraph != FALSE), \ + (FoundEqualBestGraph != FALSE), \ + (IsCoverageValueDouble != FALSE), \ + EqualCount, \ + Coverage->TotalNumberOfPages, \ + Coverage->TotalNumberOfLargePages, \ + Coverage->TotalNumberOfCacheLines, \ + Coverage->NumberOfUsedPages, \ + Coverage->NumberOfUsedLargePages, \ + Coverage->NumberOfUsedCacheLines, \ + Coverage->NumberOfEmptyPages, \ + Coverage->NumberOfEmptyLargePages, \ + Coverage->NumberOfEmptyCacheLines, \ + Coverage->FirstPageUsed, \ + Coverage->FirstLargePageUsed, \ + Coverage->FirstCacheLineUsed, \ + Coverage->LastPageUsed, \ + Coverage->LastLargePageUsed, \ + Coverage->LastCacheLineUsed, \ + Coverage->TotalNumberOfAssigned, \ + Coverage->NumberOfKeysWithVerticesMappingToSamePage, \ + Coverage->NumberOfKeysWithVerticesMappingToSameLargePage, \ + Coverage->NumberOfKeysWithVerticesMappingToSameCacheLine, \ + Coverage->MaxGraphTraversalDepth, \ + Coverage->TotalGraphTraversals, \ + Graph->Seeds[0], \ + Graph->Seeds[1], \ + Graph->Seeds[2], \ + Graph->Seeds[3], \ + Graph->Seeds[4], \ + Graph->Seeds[5], \ + Graph->Seeds[6], \ + Graph->Seeds[7], \ + Coverage->NumberOfAssignedPerCacheLineCounts[0], \ + Coverage->NumberOfAssignedPerCacheLineCounts[1], \ + Coverage->NumberOfAssignedPerCacheLineCounts[2], \ + Coverage->NumberOfAssignedPerCacheLineCounts[3], \ + Coverage->NumberOfAssignedPerCacheLineCounts[4], \ + Coverage->NumberOfAssignedPerCacheLineCounts[5], \ + Coverage->NumberOfAssignedPerCacheLineCounts[6], \ + Coverage->NumberOfAssignedPerCacheLineCounts[7], \ + Coverage->NumberOfAssignedPerCacheLineCounts[8], \ + Coverage->NumberOfAssignedPerCacheLineCounts[9], \ + Coverage->NumberOfAssignedPerCacheLineCounts[10], \ + Coverage->NumberOfAssignedPerCacheLineCounts[11], \ + Coverage->NumberOfAssignedPerCacheLineCounts[12], \ + Coverage->NumberOfAssignedPerCacheLineCounts[13], \ + Coverage->NumberOfAssignedPerCacheLineCounts[14], \ + Coverage->NumberOfAssignedPerCacheLineCounts[15], \ + Coverage->NumberOfAssignedPerCacheLineCounts[16], \ + Coverage->Slope, \ + Coverage->Intercept, \ + Coverage->CorrelationCoefficient, \ + Coverage->Score, \ + Coverage->Rank \ + ) + // vim:set ts=8 sw=4 sts=4 tw=80 expandtab : diff --git a/src/PerfectHash/PerfectHashTableCreate.c b/src/PerfectHash/PerfectHashTableCreate.c index caaaf7ef..e9574594 100644 --- a/src/PerfectHash/PerfectHashTableCreate.c +++ b/src/PerfectHash/PerfectHashTableCreate.c @@ -553,7 +553,12 @@ Return Value: ULONG Index; ULONG Count; ULONG GraphImpl; + ULONG FixedAttempts; HRESULT Result = S_OK; + BOOLEAN SawMinAttempts = FALSE; + BOOLEAN SawMaxAttempts = FALSE; + BOOLEAN SawFixedAttempts = FALSE; + BOOLEAN SawTargetNumberOfSolutions = FALSE; BOOLEAN SawResizeLimit = FALSE; BOOLEAN SawInitialResizes = FALSE; BOOLEAN SawResizeThreshold = FALSE; @@ -577,6 +582,7 @@ Return Value: Param = TableCreateParams->Params; GraphImpl = DEFAULT_GRAPH_IMPL_VERSION; + FixedAttempts = 0; if (Count == 0) { if (Param != NULL) { @@ -612,6 +618,26 @@ Return Value: SawInitialResizes = TRUE; break; + case TableCreateParameterMinAttemptsId: + Context->MinAttempts = Param->AsULong; + SawMinAttempts = TRUE; + break; + + case TableCreateParameterMaxAttemptsId: + Context->MaxAttempts = Param->AsULong; + SawMaxAttempts = TRUE; + break; + + case TableCreateParameterFixedAttemptsId: + FixedAttempts = Param->AsULong; + SawFixedAttempts = TRUE; + break; + + case TableCreateParameterTargetNumberOfSolutionsId: + Context->TargetNumberOfSolutions = Param->AsULong; + SawTargetNumberOfSolutions = TRUE; + break; + case TableCreateParameterBestCoverageAttemptsId: Context->BestCoverageAttempts = Param->AsULongLong; break; @@ -800,14 +826,109 @@ Return Value: Result = PH_E_INITIAL_RESIZES_EXCEEDS_MAX_RESIZES; goto Error; } + } + + // + // Validate min/max/fixed attempts. + // + + if (SawFixedAttempts) { + if (FixedAttempts == 0) { + Result = PH_E_INVALID_FIXED_ATTEMPTS; + goto Error; + } + + if (Table->TableCreateFlags.FindBestGraph != FALSE) { + Result = PH_E_FIXED_ATTEMPTS_CONFLICTS_WITH_FIND_BEST_GRAPH; + goto Error; + }; + + // + // --MinAttempts or --MaxAttempts with --FixedAttempts doesn't make + // sense. + // + + if (SawMinAttempts || SawMaxAttempts) { + Result = PH_E_FIXED_ATTEMPTS_CONFLICTS_WITH_MINMAX_ATTEMPTS; + } + + // + // N.B. There's no Context->FixedAttempts; we just use the Min/Max + // members to box the desired number of attempts. + // + + Context->MinAttempts = FixedAttempts; + Context->MaxAttempts = FixedAttempts; + + } + + if (SawMinAttempts) { + + if (Context->MinAttempts == 0) { + Result = PH_E_INVALID_MIN_ATTEMPTS; + goto Error; + } + + if (Table->TableCreateFlags.FindBestGraph != FALSE) { + Result = PH_E_MIN_ATTEMPTS_CONFLICTS_WITH_FIND_BEST_GRAPH; + goto Error; + }; + + // + // If we didn't see MaxAttempts, default it to MinAttempts. (This + // makes more sense than, say, reaching min attempts then switching + // into FirstGraphWins mode.) + // + + if (!SawMaxAttempts) { + Context->MaxAttempts = Context->MinAttempts; + } else { + if (Context->MaxAttempts < Context->MinAttempts) { + Result = PH_E_MIN_ATTEMPTS_EXCEEDS_MAX_ATTEMPTS; + goto Error; + } + } + } + + if (SawMaxAttempts) { + if (Context->MaxAttempts == 0) { + Result = PH_E_INVALID_MAX_ATTEMPTS; + goto Error; + } + } + + if (SawTargetNumberOfSolutions) { + + if (Context->TargetNumberOfSolutions == 0) { + Result = PH_E_INVALID_TARGET_NUMBER_OF_SOLUTIONS; + goto Error; + } + + if (SawMinAttempts) { + if (Context->MinAttempts > Context->TargetNumberOfSolutions) { + Result = PH_E_TARGET_NUMBER_OF_SOLUTIONS_EXCEEDS_MIN_ATTEMPTS; + goto Error; + } + } + } + + if (Context->MinAttempts > 0 || + Context->MaxAttempts > 0 || + Context->TargetNumberOfSolutions > 0) + { + // + // We don't want to stop solving after the first solution is found, so + // clear the applicable flag. + // + Context->State.FirstSolvedGraphWins = FALSE; } // // Validate GraphImpl. // - if (GraphImpl != 1 && GraphImpl != 2) { + if (GraphImpl != 1 && GraphImpl != 2 && GraphImpl != 3) { Result = PH_E_INVALID_GRAPH_IMPL; goto Error; } diff --git a/src/PerfectHash/PerfectHashTableHashEx.c b/src/PerfectHash/PerfectHashTableHashEx.c index 30aa0b59..bfdecf86 100644 --- a/src/PerfectHash/PerfectHashTableHashEx.c +++ b/src/PerfectHash/PerfectHashTableHashEx.c @@ -1825,8 +1825,8 @@ Return Value: // Calculate the individual hash parts. // - Vertex1 = DownsizedKey * Seed1; - Vertex2 = DownsizedKey * Seed2; + Vertex1 = (ULONG)(((ULONGLONG)DownsizedKey * (ULONGLONG)Seed1) >> 32); + Vertex2 = (ULONG)(((ULONGLONG)DownsizedKey * (ULONGLONG)Seed2) >> 32); Result.LowPart = (Vertex1 & Mask); Result.HighPart = (Vertex2 & Mask); diff --git a/src/PerfectHash/RtlRandom.c b/src/PerfectHash/RtlRandom.c index 93a4053d..5302f190 100644 --- a/src/PerfectHash/RtlRandom.c +++ b/src/PerfectHash/RtlRandom.c @@ -75,7 +75,7 @@ Return Value: // Argument validation complete. Continue. // - EventWriteRtlGenerateRandomBytesStart(NULL, SizeOfBufferInBytes); + EVENT_WRITE_RTL_RANDOM_BYTES_START(SizeOfBufferInBytes); ASSERT(Rtl->CryptProv != 0); if (!CryptGenRandom(Rtl->CryptProv, SizeOfBufferInBytes, Buffer)) { @@ -85,7 +85,7 @@ Return Value: Result = S_OK; } - EventWriteRtlGenerateRandomBytesStop(NULL, SizeOfBufferInBytes, Result); + EVENT_WRITE_RTL_RANDOM_BYTES_STOP(SizeOfBufferInBytes, Result); return Result; } diff --git a/src/PerfectHash/run-wevtutil.bat b/src/PerfectHash/run-wevtutil.bat new file mode 100644 index 00000000..79ed6722 --- /dev/null +++ b/src/PerfectHash/run-wevtutil.bat @@ -0,0 +1,2 @@ +wevtutil um %cd%\PerfectHashEvents.man +wevtutil im %cd%\PerfectHashEvents.man