[llvm] fd4aeba - Revert "[ADT] add ConcurrentHashtable class."

Alexey Lapshin via llvm-commits llvm-commits at lists.llvm.org
Thu Mar 23 06:43:35 PDT 2023


Author: Alexey Lapshin
Date: 2023-03-23T14:42:40+01:00
New Revision: fd4aeba307ca30da00a8db21a200cc9afcef63c6

URL: https://github.com/llvm/llvm-project/commit/fd4aeba307ca30da00a8db21a200cc9afcef63c6
DIFF: https://github.com/llvm/llvm-project/commit/fd4aeba307ca30da00a8db21a200cc9afcef63c6.diff

LOG: Revert "[ADT] add ConcurrentHashtable class."

This reverts commit 8482b238062ed7263facea9490f67119e00a037a.

Added: 
    

Modified: 
    llvm/unittests/ADT/CMakeLists.txt

Removed: 
    llvm/include/llvm/ADT/ConcurrentHashtable.h
    llvm/unittests/ADT/ConcurrentHashtableTest.cpp


################################################################################
diff  --git a/llvm/include/llvm/ADT/ConcurrentHashtable.h b/llvm/include/llvm/ADT/ConcurrentHashtable.h
deleted file mode 100644
index 56344ab9b8411..0000000000000
--- a/llvm/include/llvm/ADT/ConcurrentHashtable.h
+++ /dev/null
@@ -1,395 +0,0 @@
-//===- ConcurrentHashtable.h ------------------------------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_ADT_CONCURRENTHASHTABLE_H
-#define LLVM_ADT_CONCURRENTHASHTABLE_H
-
-#include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/Hashing.h"
-#include "llvm/ADT/PointerIntPair.h"
-#include "llvm/ADT/STLExtras.h"
-#include "llvm/ADT/SmallVector.h"
-#include "llvm/Support/Allocator.h"
-#include "llvm/Support/Debug.h"
-#include "llvm/Support/Parallel.h"
-#include "llvm/Support/WithColor.h"
-#include "llvm/Support/xxhash.h"
-#include <atomic>
-#include <cstddef>
-#include <iomanip>
-#include <mutex>
-#include <sstream>
-#include <type_traits>
-
-namespace llvm {
-
-/// ConcurrentHashTable - is a resizeable concurrent hashtable.
-/// The number of resizings limited up to x2^32. This hashtable is
-/// useful to have efficient access to aggregate data(like strings,
-/// type descriptors...) and to keep only single copy of such
-/// an aggregate. The hashtable allows only concurrent insertions:
-///
-/// KeyDataTy* = insert ( const KeyTy& );
-///
-/// Data structure:
-///
-/// Inserted value KeyTy is mapped to 64-bit hash value ->
-///
-///          [------- 64-bit Hash value --------]
-///          [  StartEntryIndex ][ Bucket Index ]
-///                    |                |
-///              points to the     points to
-///              first probe       the bucket.
-///              position inside
-///              bucket entries
-///
-/// After initialization, all buckets have an initial size. During insertions,
-/// buckets might be extended to contain more entries. Each bucket can be
-/// independently resized and rehashed(no need to lock the whole table).
-/// Different buckets may have 
diff erent sizes. If the single bucket is full
-/// then the bucket is resized.
-///
-/// BucketsArray keeps all buckets. Each bucket keeps an array of Entries
-/// (pointers to KeyDataTy) and another array of entries hashes:
-///
-/// BucketsArray[BucketIdx].Hashes[EntryIdx]:
-/// BucketsArray[BucketIdx].Entries[EntryIdx]:
-///
-/// [Bucket 0].Hashes -> [uint32_t][uint32_t]
-/// [Bucket 0].Entries -> [KeyDataTy*][KeyDataTy*]
-///
-/// [Bucket 1].Hashes -> [uint32_t][uint32_t][uint32_t][uint32_t]
-/// [Bucket 1].Entries -> [KeyDataTy*][KeyDataTy*][KeyDataTy*][KeyDataTy*]
-///                      .........................
-/// [Bucket N].Hashes -> [uint32_t][uint32_t][uint32_t]
-/// [Bucket N].Entries -> [KeyDataTy*][KeyDataTy*][KeyDataTy*]
-///
-/// ConcurrentHashTableByPtr uses an external thread-safe allocator to allocate
-/// KeyDataTy items.
-
-template <typename KeyTy, typename KeyDataTy, typename AllocatorTy>
-class ConcurrentHashTableInfoByPtr {
-public:
-  /// \returns Hash value for the specified \p Key.
-  static inline uint64_t getHashValue(const KeyTy &Key) {
-    return xxHash64(Key);
-  }
-
-  /// \returns true if both \p LHS and \p RHS are equal.
-  static inline bool isEqual(const KeyTy &LHS, const KeyTy &RHS) {
-    return LHS == RHS;
-  }
-
-  /// \returns key for the specified \p KeyData.
-  static inline const KeyTy &getKey(const KeyDataTy &KeyData) {
-    return KeyData.getKey();
-  }
-
-  /// \returns newly created object of KeyDataTy type.
-  static inline KeyDataTy *create(const KeyTy &Key, AllocatorTy &Allocator) {
-    return KeyDataTy::create(Key, Allocator);
-  }
-};
-
-template <typename KeyTy, typename KeyDataTy, typename AllocatorTy,
-          typename Info =
-              ConcurrentHashTableInfoByPtr<KeyTy, KeyDataTy, AllocatorTy>>
-class ConcurrentHashTableByPtr {
-public:
-  ConcurrentHashTableByPtr(
-      AllocatorTy &Allocator, size_t EstimatedSize = 100000,
-      size_t ThreadsNum = parallel::strategy.compute_thread_count(),
-      size_t InitialNumberOfBuckets = 128)
-      : MultiThreadAllocator(Allocator) {
-    assert((ThreadsNum > 0) && "ThreadsNum must be greater than 0");
-    assert((InitialNumberOfBuckets > 0) &&
-           "InitialNumberOfBuckets must be greater than 0");
-
-    constexpr size_t UINT64_BitsNum = sizeof(uint64_t) * 8;
-    constexpr size_t UINT32_BitsNum = sizeof(uint32_t) * 8;
-
-    NumberOfBuckets = ThreadsNum;
-
-    // Calculate number of buckets.
-    if (ThreadsNum > 1) {
-      NumberOfBuckets *= InitialNumberOfBuckets;
-      NumberOfBuckets *= std::max(
-          1,
-          countr_zero(PowerOf2Ceil(EstimatedSize / InitialNumberOfBuckets)) >>
-              2);
-    }
-    NumberOfBuckets = PowerOf2Ceil(NumberOfBuckets);
-
-    // Allocate buckets.
-    BucketsArray = std::make_unique<Bucket[]>(NumberOfBuckets);
-
-    InitialBucketSize = EstimatedSize / NumberOfBuckets;
-    InitialBucketSize = std::max((size_t)1, InitialBucketSize);
-    InitialBucketSize = PowerOf2Ceil(InitialBucketSize);
-
-    // Initialize each bucket.
-    for (size_t Idx = 0; Idx < NumberOfBuckets; Idx++) {
-      HashesPtr Hashes = new ExtHashBitsTy[InitialBucketSize];
-      memset(Hashes, 0, sizeof(ExtHashBitsTy) * InitialBucketSize);
-
-      DataPtr Entries = new EntryDataTy[InitialBucketSize];
-      memset(Entries, 0, sizeof(EntryDataTy) * InitialBucketSize);
-
-      BucketsArray[Idx].Size = InitialBucketSize;
-      BucketsArray[Idx].Hashes = Hashes;
-      BucketsArray[Idx].Entries = Entries;
-    }
-
-    // Calculate masks.
-    HashMask = NumberOfBuckets - 1;
-
-    size_t LeadingZerosNumber = countl_zero(HashMask);
-    HashBitsNum = UINT64_BitsNum - LeadingZerosNumber;
-
-    // We keep only high 32-bits of hash value. So bucket size cannot
-    // exceed 2^32. Bucket size is always power of two.
-    MaxBucketSize = 1Ull << (std::min(UINT32_BitsNum, LeadingZerosNumber));
-
-    // Calculate mask for extended hash bits.
-    ExtHashMask = (NumberOfBuckets * MaxBucketSize) - 1;
-  }
-
-  virtual ~ConcurrentHashTableByPtr() {
-    // Deallocate buckets.
-    for (size_t Idx = 0; Idx < NumberOfBuckets; Idx++) {
-      delete[] BucketsArray[Idx].Hashes;
-      delete[] BucketsArray[Idx].Entries;
-    }
-  }
-
-  /// Insert new value \p NewValue or return already existing entry.
-  ///
-  /// \returns entry and "true" if an entry is just inserted or
-  /// "false" if an entry already exists.
-  std::pair<KeyDataTy *, bool> insert(const KeyTy &NewValue) {
-    // Calculate bucket index.
-    uint64_t Hash = Info::getHashValue(NewValue);
-    Bucket &CurBucket = BucketsArray[getBucketIdx(Hash)];
-    uint32_t ExtHashBits = getExtHashBits(Hash);
-
-    // Lock bucket.
-    CurBucket.Guard.lock();
-
-    HashesPtr BucketHashes = CurBucket.Hashes;
-    DataPtr BucketEntries = CurBucket.Entries;
-    size_t CurEntryIdx = getStartIdx(ExtHashBits, CurBucket.Size);
-
-    while (true) {
-      uint32_t CurEntryHashBits = BucketHashes[CurEntryIdx];
-
-      if (CurEntryHashBits == 0 && BucketEntries[CurEntryIdx] == nullptr) {
-        // Found empty slot. Insert data.
-        KeyDataTy *NewData = Info::create(NewValue, MultiThreadAllocator);
-        BucketEntries[CurEntryIdx] = NewData;
-        BucketHashes[CurEntryIdx] = ExtHashBits;
-
-        CurBucket.NumberOfEntries++;
-        RehashBucket(CurBucket);
-
-        CurBucket.Guard.unlock();
-
-        return {NewData, true};
-      }
-
-      if (CurEntryHashBits == ExtHashBits) {
-        // Hash matched. Check value for equality.
-        KeyDataTy *EntryData = BucketEntries[CurEntryIdx];
-        if (Info::isEqual(Info::getKey(*EntryData), NewValue)) {
-          // Already existed entry matched with inserted data is found.
-          CurBucket.Guard.unlock();
-
-          return {EntryData, false};
-        }
-      }
-
-      CurEntryIdx++;
-      CurEntryIdx &= (CurBucket.Size - 1);
-    }
-
-    llvm_unreachable("Insertion error.");
-    return {};
-  }
-
-  /// Print information about current state of hash table structures.
-  void printStatistic(raw_ostream &OS) {
-    OS << "\n--- HashTable statistic:\n";
-    OS << "\nNumber of buckets = " << NumberOfBuckets;
-    OS << "\nInitial bucket size = " << InitialBucketSize;
-
-    uint64_t NumberOfNonEmptyBuckets = 0;
-    uint64_t NumberOfEntriesPlusEmpty = 0;
-    uint64_t OverallNumberOfEntries = 0;
-    uint64_t OverallSize = sizeof(*this) + NumberOfBuckets * sizeof(Bucket);
-
-    DenseMap<size_t, size_t> BucketSizesMap;
-
-    // For each bucket...
-    for (size_t Idx = 0; Idx < NumberOfBuckets; Idx++) {
-      Bucket &CurBucket = BucketsArray[Idx];
-
-      BucketSizesMap[CurBucket.Size]++;
-
-      if (CurBucket.NumberOfEntries != 0)
-        NumberOfNonEmptyBuckets++;
-      NumberOfEntriesPlusEmpty += CurBucket.Size;
-      OverallNumberOfEntries += CurBucket.NumberOfEntries;
-      OverallSize +=
-          (sizeof(ExtHashBitsTy) + sizeof(EntryDataTy)) * CurBucket.Size;
-    }
-
-    OS << "\nOverall number of entries = " << OverallNumberOfEntries;
-    OS << "\nOverall number of non empty buckets = " << NumberOfNonEmptyBuckets;
-    for (auto &BucketSize : BucketSizesMap)
-      OS << "\n Number of buckets with size " << BucketSize.first << ": "
-         << BucketSize.second;
-
-    std::stringstream stream;
-    stream << std::fixed << std::setprecision(2)
-           << ((float)OverallNumberOfEntries / (float)NumberOfEntriesPlusEmpty);
-    std::string str = stream.str();
-
-    OS << "\nLoad factor = " << str;
-    OS << "\nOverall allocated size = " << OverallSize;
-  }
-
-protected:
-  using ExtHashBitsTy = uint32_t;
-  using EntryDataTy = KeyDataTy *;
-
-  using HashesPtr = ExtHashBitsTy *;
-  using DataPtr = EntryDataTy *;
-
-  // Bucket structure. Keeps bucket data.
-  struct Bucket {
-    Bucket() = default;
-
-    // Size of bucket.
-    uint32_t Size = 0;
-
-    // Number of non-null entries.
-    size_t NumberOfEntries = 0;
-
-    // Hashes for [Size] entries.
-    HashesPtr Hashes = nullptr;
-
-    // [Size] entries.
-    DataPtr Entries = nullptr;
-
-    // Mutex for this bucket.
-    std::mutex Guard;
-  };
-
-  // Reallocate and rehash bucket if this is full enough.
-  void RehashBucket(Bucket &CurBucket) {
-    assert((CurBucket.Size > 0) && "Uninitialised bucket");
-    if (CurBucket.NumberOfEntries < CurBucket.Size * 0.9)
-      return;
-
-    if (CurBucket.Size >= MaxBucketSize)
-      report_fatal_error("ConcurrentHashTable is full");
-
-    size_t NewBucketSize = CurBucket.Size << 1;
-    assert((NewBucketSize <= MaxBucketSize) && "New bucket size is too big");
-    assert((CurBucket.Size < NewBucketSize) &&
-           "New bucket size less than size of current bucket");
-
-    // Store old entries & hashes arrays.
-    HashesPtr SrcHashes = CurBucket.Hashes;
-    DataPtr SrcEntries = CurBucket.Entries;
-
-    // Allocate new entries&hashes arrays.
-    HashesPtr DestHashes = new ExtHashBitsTy[NewBucketSize];
-    memset(DestHashes, 0, sizeof(ExtHashBitsTy) * NewBucketSize);
-
-    DataPtr DestEntries = new EntryDataTy[NewBucketSize];
-    memset(DestEntries, 0, sizeof(EntryDataTy) * NewBucketSize);
-
-    // For each entry in source arrays...
-    for (size_t CurSrcEntryIdx = 0; CurSrcEntryIdx < CurBucket.Size;
-         CurSrcEntryIdx++) {
-      uint32_t CurSrcEntryHashBits = SrcHashes[CurSrcEntryIdx];
-
-      // Check for null entry.
-      if (CurSrcEntryHashBits == 0 && SrcEntries[CurSrcEntryIdx] == nullptr)
-        continue;
-
-      size_t StartDestIdx = getStartIdx(CurSrcEntryHashBits, NewBucketSize);
-
-      // Insert non-null entry into the new arrays.
-      while (true) {
-        uint32_t CurDestEntryHashBits = DestHashes[StartDestIdx];
-
-        if (CurDestEntryHashBits == 0 && DestEntries[StartDestIdx] == nullptr) {
-          // Found empty slot. Insert data.
-          DestHashes[StartDestIdx] = CurSrcEntryHashBits;
-          DestEntries[StartDestIdx] = SrcEntries[CurSrcEntryIdx];
-          break;
-        }
-
-        StartDestIdx++;
-        StartDestIdx = StartDestIdx & (NewBucketSize - 1);
-      }
-    }
-
-    // Update bucket fields.
-    CurBucket.Hashes = DestHashes;
-    CurBucket.Entries = DestEntries;
-    CurBucket.Size = NewBucketSize;
-
-    // Delete old bucket entries.
-    if (SrcHashes != nullptr)
-      delete[] SrcHashes;
-    if (SrcEntries != nullptr)
-      delete[] SrcEntries;
-  }
-
-  size_t getBucketIdx(hash_code Hash) { return Hash & HashMask; }
-
-  uint32_t getExtHashBits(uint64_t Hash) {
-    return (Hash & ExtHashMask) >> HashBitsNum;
-  }
-
-  size_t getStartIdx(uint32_t ExtHashBits, size_t BucketSize) {
-    assert((BucketSize > 0) && "Empty bucket");
-
-    return ExtHashBits & (BucketSize - 1);
-  }
-
-  // Number of bits in hash mask.
-  uint64_t HashBitsNum = 0;
-
-  // Hash mask.
-  uint64_t HashMask = 0;
-
-  // Hash mask for the extended hash bits.
-  uint64_t ExtHashMask = 0;
-
-  // The maximal bucket size.
-  size_t MaxBucketSize = 0;
-
-  // Initial size of bucket.
-  size_t InitialBucketSize = 0;
-
-  // The number of buckets.
-  size_t NumberOfBuckets = 0;
-
-  // Array of buckets.
-  std::unique_ptr<Bucket[]> BucketsArray;
-
-  // Used for allocating KeyDataTy values.
-  AllocatorTy &MultiThreadAllocator;
-};
-
-} // end namespace llvm
-
-#endif // LLVM_ADT_CONCURRENTHASHTABLE_H

diff  --git a/llvm/unittests/ADT/CMakeLists.txt b/llvm/unittests/ADT/CMakeLists.txt
index c5190255ba773..900294d4216ee 100644
--- a/llvm/unittests/ADT/CMakeLists.txt
+++ b/llvm/unittests/ADT/CMakeLists.txt
@@ -17,7 +17,6 @@ add_llvm_unittest(ADTTests
   BumpPtrListTest.cpp
   CoalescingBitVectorTest.cpp
   CombinationGeneratorTest.cpp
-  ConcurrentHashtableTest.cpp
   DAGDeltaAlgorithmTest.cpp
   DeltaAlgorithmTest.cpp
   DenseMapTest.cpp

diff  --git a/llvm/unittests/ADT/ConcurrentHashtableTest.cpp b/llvm/unittests/ADT/ConcurrentHashtableTest.cpp
deleted file mode 100644
index c4faece251790..0000000000000
--- a/llvm/unittests/ADT/ConcurrentHashtableTest.cpp
+++ /dev/null
@@ -1,279 +0,0 @@
-//===- ConcurrentHashtableTest.cpp ----------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/ADT/ConcurrentHashtable.h"
-#include "llvm/Support/Debug.h"
-#include "llvm/Support/FormatVariadic.h"
-#include "llvm/Support/Parallel.h"
-#include "gtest/gtest.h"
-#include <limits>
-#include <random>
-#include <vector>
-using namespace llvm;
-
-namespace {
-class String {
-public:
-  String() {}
-  const std::string &getKey() const { return Data; }
-
-  template <typename AllocatorTy>
-  static String *create(const std::string &Num, AllocatorTy &Allocator) {
-    String *Result = Allocator.template Allocate<String>();
-    new (Result) String(Num);
-    return Result;
-  }
-
-protected:
-  String(const std::string &Num) { Data += Num; }
-
-  std::string Data;
-  std::array<char, 0x20> ExtraData;
-};
-
-static LLVM_THREAD_LOCAL BumpPtrAllocator ThreadLocalAllocator;
-class PerThreadAllocator : public AllocatorBase<PerThreadAllocator> {
-public:
-  inline LLVM_ATTRIBUTE_RETURNS_NONNULL void *Allocate(size_t Size,
-                                                       size_t Alignment) {
-    return ThreadLocalAllocator.Allocate(Size, Align(Alignment));
-  }
-  inline size_t getBytesAllocated() const {
-    return ThreadLocalAllocator.getBytesAllocated();
-  }
-
-  // Pull in base class overloads.
-  using AllocatorBase<PerThreadAllocator>::Allocate;
-} Allocator;
-
-TEST(ConcurrentHashTableTest, AddStringEntries) {
-  ConcurrentHashTableByPtr<
-      std::string, String, PerThreadAllocator,
-      ConcurrentHashTableInfoByPtr<std::string, String, PerThreadAllocator>>
-      HashTable(Allocator, 10);
-
-  size_t AllocatedBytesAtStart = Allocator.getBytesAllocated();
-  std::pair<String *, bool> res1 = HashTable.insert("1");
-  // Check entry is inserted.
-  EXPECT_TRUE(res1.first->getKey() == "1");
-  EXPECT_TRUE(res1.second);
-
-  std::pair<String *, bool> res2 = HashTable.insert("2");
-  // Check old entry is still valid.
-  EXPECT_TRUE(res1.first->getKey() == "1");
-  // Check new entry is inserted.
-  EXPECT_TRUE(res2.first->getKey() == "2");
-  EXPECT_TRUE(res2.second);
-  // Check new and old entries use 
diff erent memory.
-  EXPECT_TRUE(res1.first != res2.first);
-
-  std::pair<String *, bool> res3 = HashTable.insert("3");
-  // Check one more entry is inserted.
-  EXPECT_TRUE(res3.first->getKey() == "3");
-  EXPECT_TRUE(res3.second);
-
-  std::pair<String *, bool> res4 = HashTable.insert("1");
-  // Check duplicated entry is inserted.
-  EXPECT_TRUE(res4.first->getKey() == "1");
-  EXPECT_FALSE(res4.second);
-  // Check duplicated entry uses the same memory.
-  EXPECT_TRUE(res1.first == res4.first);
-
-  // Check first entry is still valid.
-  EXPECT_TRUE(res1.first->getKey() == "1");
-
-  // Check data was allocated by allocator.
-  EXPECT_TRUE(Allocator.getBytesAllocated() > AllocatedBytesAtStart);
-
-  // Check statistic.
-  std::string StatisticString;
-  raw_string_ostream StatisticStream(StatisticString);
-  HashTable.printStatistic(StatisticStream);
-
-  EXPECT_TRUE(StatisticString.find("Overall number of entries = 3\n") !=
-              std::string::npos);
-}
-
-TEST(ConcurrentHashTableTest, AddStringMultiplueEntries) {
-  const size_t NumElements = 10000;
-  ConcurrentHashTableByPtr<
-      std::string, String, PerThreadAllocator,
-      ConcurrentHashTableInfoByPtr<std::string, String, PerThreadAllocator>>
-      HashTable(Allocator);
-
-  // Check insertion.
-  for (size_t I = 0; I < NumElements; I++) {
-    size_t AllocatedBytesAtStart = Allocator.getBytesAllocated();
-    std::string StringForElement = formatv("{0}", I);
-    std::pair<String *, bool> Entry = HashTable.insert(StringForElement);
-    EXPECT_TRUE(Entry.second);
-    EXPECT_TRUE(Entry.first->getKey() == StringForElement);
-    EXPECT_TRUE(Allocator.getBytesAllocated() > AllocatedBytesAtStart);
-  }
-
-  std::string StatisticString;
-  raw_string_ostream StatisticStream(StatisticString);
-  HashTable.printStatistic(StatisticStream);
-
-  // Verifying that the table contains exactly the number of elements we
-  // inserted.
-  EXPECT_TRUE(StatisticString.find("Overall number of entries = 10000\n") !=
-              std::string::npos);
-
-  // Check insertion of duplicates.
-  for (size_t I = 0; I < NumElements; I++) {
-    size_t AllocatedBytesAtStart = Allocator.getBytesAllocated();
-    std::string StringForElement = formatv("{0}", I);
-    std::pair<String *, bool> Entry = HashTable.insert(StringForElement);
-    EXPECT_FALSE(Entry.second);
-    EXPECT_TRUE(Entry.first->getKey() == StringForElement);
-    // Check no additional bytes were allocated for duplicate.
-    EXPECT_TRUE(Allocator.getBytesAllocated() == AllocatedBytesAtStart);
-  }
-
-  // Check statistic.
-  // Verifying that the table contains exactly the number of elements we
-  // inserted.
-  EXPECT_TRUE(StatisticString.find("Overall number of entries = 10000\n") !=
-              std::string::npos);
-}
-
-TEST(ConcurrentHashTableTest, AddStringMultiplueEntriesWithResize) {
-  // Number of elements exceeds original size, thus hashtable should be resized.
-  const size_t NumElements = 20000;
-  ConcurrentHashTableByPtr<
-      std::string, String, PerThreadAllocator,
-      ConcurrentHashTableInfoByPtr<std::string, String, PerThreadAllocator>>
-      HashTable(Allocator, 100);
-
-  // Check insertion.
-  for (size_t I = 0; I < NumElements; I++) {
-    size_t AllocatedBytesAtStart = Allocator.getBytesAllocated();
-    std::string StringForElement = formatv("{0} {1}", I, I + 100);
-    std::pair<String *, bool> Entry = HashTable.insert(StringForElement);
-    EXPECT_TRUE(Entry.second);
-    EXPECT_TRUE(Entry.first->getKey() == StringForElement);
-    EXPECT_TRUE(Allocator.getBytesAllocated() > AllocatedBytesAtStart);
-  }
-
-  std::string StatisticString;
-  raw_string_ostream StatisticStream(StatisticString);
-  HashTable.printStatistic(StatisticStream);
-
-  // Verifying that the table contains exactly the number of elements we
-  // inserted.
-  EXPECT_TRUE(StatisticString.find("Overall number of entries = 20000\n") !=
-              std::string::npos);
-
-  // Check insertion of duplicates.
-  for (size_t I = 0; I < NumElements; I++) {
-    size_t AllocatedBytesAtStart = Allocator.getBytesAllocated();
-    std::string StringForElement = formatv("{0} {1}", I, I + 100);
-    std::pair<String *, bool> Entry = HashTable.insert(StringForElement);
-    EXPECT_FALSE(Entry.second);
-    EXPECT_TRUE(Entry.first->getKey() == StringForElement);
-    // Check no additional bytes were allocated for duplicate.
-    EXPECT_TRUE(Allocator.getBytesAllocated() == AllocatedBytesAtStart);
-  }
-
-  // Check statistic.
-  // Verifying that the table contains exactly the number of elements we
-  // inserted.
-  EXPECT_TRUE(StatisticString.find("Overall number of entries = 20000\n") !=
-              std::string::npos);
-}
-
-TEST(ConcurrentHashTableTest, AddStringEntriesParallel) {
-  const size_t NumElements = 10000;
-  ConcurrentHashTableByPtr<
-      std::string, String, PerThreadAllocator,
-      ConcurrentHashTableInfoByPtr<std::string, String, PerThreadAllocator>>
-      HashTable(Allocator);
-
-  // Check parallel insertion.
-  parallelFor(0, NumElements, [&](size_t I) {
-    size_t AllocatedBytesAtStart = Allocator.getBytesAllocated();
-    std::string StringForElement = formatv("{0}", I);
-    std::pair<String *, bool> Entry = HashTable.insert(StringForElement);
-    EXPECT_TRUE(Entry.second);
-    EXPECT_TRUE(Entry.first->getKey() == StringForElement);
-    EXPECT_TRUE(Allocator.getBytesAllocated() > AllocatedBytesAtStart);
-  });
-
-  std::string StatisticString;
-  raw_string_ostream StatisticStream(StatisticString);
-  HashTable.printStatistic(StatisticStream);
-
-  // Verifying that the table contains exactly the number of elements we
-  // inserted.
-  EXPECT_TRUE(StatisticString.find("Overall number of entries = 10000\n") !=
-              std::string::npos);
-
-  // Check parallel insertion of duplicates.
-  parallelFor(0, NumElements, [&](size_t I) {
-    size_t AllocatedBytesAtStart = Allocator.getBytesAllocated();
-    std::string StringForElement = formatv("{0}", I);
-    std::pair<String *, bool> Entry = HashTable.insert(StringForElement);
-    EXPECT_FALSE(Entry.second);
-    EXPECT_TRUE(Entry.first->getKey() == StringForElement);
-    // Check no additional bytes were allocated for duplicate.
-    EXPECT_TRUE(Allocator.getBytesAllocated() == AllocatedBytesAtStart);
-  });
-
-  // Check statistic.
-  // Verifying that the table contains exactly the number of elements we
-  // inserted.
-  EXPECT_TRUE(StatisticString.find("Overall number of entries = 10000\n") !=
-              std::string::npos);
-}
-
-TEST(ConcurrentHashTableTest, AddStringEntriesParallelWithResize) {
-  const size_t NumElements = 20000;
-  ConcurrentHashTableByPtr<
-      std::string, String, PerThreadAllocator,
-      ConcurrentHashTableInfoByPtr<std::string, String, PerThreadAllocator>>
-      HashTable(Allocator, 100);
-
-  // Check parallel insertion.
-  parallelFor(0, NumElements, [&](size_t I) {
-    size_t AllocatedBytesAtStart = Allocator.getBytesAllocated();
-    std::string StringForElement = formatv("{0}", I);
-    std::pair<String *, bool> Entry = HashTable.insert(StringForElement);
-    EXPECT_TRUE(Entry.second);
-    EXPECT_TRUE(Entry.first->getKey() == StringForElement);
-    EXPECT_TRUE(Allocator.getBytesAllocated() > AllocatedBytesAtStart);
-  });
-
-  std::string StatisticString;
-  raw_string_ostream StatisticStream(StatisticString);
-  HashTable.printStatistic(StatisticStream);
-
-  // Verifying that the table contains exactly the number of elements we
-  // inserted.
-  EXPECT_TRUE(StatisticString.find("Overall number of entries = 20000\n") !=
-              std::string::npos);
-
-  // Check parallel insertion of duplicates.
-  parallelFor(0, NumElements, [&](size_t I) {
-    size_t AllocatedBytesAtStart = Allocator.getBytesAllocated();
-    std::string StringForElement = formatv("{0}", I);
-    std::pair<String *, bool> Entry = HashTable.insert(StringForElement);
-    EXPECT_FALSE(Entry.second);
-    EXPECT_TRUE(Entry.first->getKey() == StringForElement);
-    // Check no additional bytes were allocated for duplicate.
-    EXPECT_TRUE(Allocator.getBytesAllocated() == AllocatedBytesAtStart);
-  });
-
-  // Check statistic.
-  // Verifying that the table contains exactly the number of elements we
-  // inserted.
-  EXPECT_TRUE(StatisticString.find("Overall number of entries = 20000\n") !=
-              std::string::npos);
-}
-
-} // namespace


        


More information about the llvm-commits mailing list