Arcane  v3.14.10.0
Documentation développeur
Chargement...
Recherche...
Aucune correspondance
TestHashTable.cc
1// -*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
2//-----------------------------------------------------------------------------
3// Copyright 2000-2024 CEA (www.cea.fr) IFPEN (www.ifpenergiesnouvelles.com)
4// See the top-level COPYRIGHT file for details.
5// SPDX-License-Identifier: Apache-2.0
6//-----------------------------------------------------------------------------
7
8#include <gtest/gtest.h>
9
10#include "arcane/utils/HashTableMap.h"
11#include "arcane/utils/String.h"
12#include "arcane/utils/PlatformUtils.h"
13#include "arcane/utils/HashTableMap2.h"
14
15#include <chrono>
16#include <unordered_map>
17
18/*---------------------------------------------------------------------------*/
19/*---------------------------------------------------------------------------*/
20
21using namespace Arcane;
22
23/*
24 ThatClass& operator=(const ThatClass& from)
25 Data* lookup(KeyTypeConstRef id)
26 ValueType& lookupValue(KeyTypeConstRef id)
27 Data* lookupAdd(KeyTypeConstRef id, const ValueType& value, bool& is_add)
28 Data* lookupAdd(KeyTypeConstRef id)
29 void nocheckAdd(KeyTypeConstRef id, const ValueType& value)
30
31 */
33{
34 {
36
37 ASSERT_EQ(hash1.count(), 0);
38 hash1.add(25, "Test1");
39
40 ASSERT_EQ(hash1.count(), 1);
41
42 hash1.add(32, "Test2");
43 ASSERT_EQ(hash1.count(), 2);
44
45 hash1.add(32, "Test3");
46 ASSERT_EQ(hash1.count(), 2);
47
48 ASSERT_TRUE(hash1.hasKey(32));
49 ASSERT_FALSE(hash1.hasKey(47));
50
51 ASSERT_EQ(hash1[32], "Test3");
52 ASSERT_EQ(hash1[25], "Test1");
53
54 hash1.remove(32);
55 ASSERT_FALSE(hash1.hasKey(32));
56 ASSERT_EQ(hash1.count(), 1);
57
58 hash1.add(32, "Test4");
59 ASSERT_EQ(hash1.count(), 2);
60 ASSERT_EQ(hash1[32], "Test4");
61
62 hash1.clear();
63 ASSERT_EQ(hash1.count(), 0);
64 }
65 {
66 HashTableMapT<Int64, Int32> hash2(1050, true);
67 int n = 1000;
68 for (int i = 0; i < n; ++i)
69 hash2.add((i + 1), (i + 1) * 10);
70 ASSERT_EQ(hash2.count(), n);
71
72 hash2.clear();
73 ASSERT_EQ(hash2.count(), 0);
74 int n2 = 2000;
75 for (int i = 0; i < n2; ++i)
76 hash2.add((i + 1), (i + 1) * 10);
77 ASSERT_EQ(hash2.count(), n2);
78
79 hash2.resize(3000, true);
80 ASSERT_EQ(hash2.count(), n2);
81 for (int i = 0; i < n2; ++i)
82 ASSERT_EQ(hash2[i + 1], (i + 1) * 10);
83
84 hash2.rehash();
85 ASSERT_EQ(hash2.count(), n2);
86 for (int i = 0; i < n2; ++i)
87 ASSERT_EQ(hash2[i + 1], (i + 1) * 10);
88
90 hash3 = hash2;
91 ASSERT_EQ(hash3.count(), n2);
92 for (int i = 0; i < n2; ++i)
93 ASSERT_EQ(hash3[i + 1], (i + 1) * 10);
94
95 {
96 int nx = 2000000;
98 std::cout << "Test Hash n=" << nx << "\n";
99 for (int i = 0; i < nx; ++i)
100 hash2.add((i + 1), (i + 1) * 5);
101 std::cout << "MEM=" << platform::getMemoryUsed() << "\n";
102 }
103 }
104}
105
106Int64 _getRealTimeUS()
107{
108 auto x = std::chrono::high_resolution_clock::now();
109 // Converti la valeur en microsecondes.
110 auto y = std::chrono::time_point_cast<std::chrono::microseconds>(x);
111 return static_cast<Int64>(y.time_since_epoch().count());
112}
113
114template <typename Key, typename Value>
116{
117 public:
118
119 using Data = typename Arcane::HashTableMapT<Key, Value>::Data;
120 using value_type = std::pair<Key, Value>;
121
122 public:
123
125 : m_map(100, true)
126 {}
127
128 public:
129
130 void insert(std::pair<Key, Value> v)
131 {
132 m_map.add(v.first, v.second);
133 }
134 void clear() { m_map.clear(); }
135 const Data* end() const { return nullptr; }
136 const Data* find(const Key& k) const
137 {
138 return m_map.lookup(k);
139 }
140 void erase(const Data* d)
141 {
142 if (d) {
143 Data* dd = const_cast<Data*>(d);
144 Key v = dd->key();
145 m_map.remove(v);
146 }
147 }
148 size_t size() const { return m_map.count(); }
149 template <typename Lambda> void eachValue(const Lambda& v)
150 {
151 m_map.eachValue(v);
152 }
153
154 private:
155
157};
158
159template <bool HasIter, typename HashType> void
160_addMultiple(const char* name, HashType& map_instance, int nb_key)
161{
162 using value_type = typename HashType::value_type;
163 std::cout << "ADD_MULTIPLE name=" << name << "\n";
164 map_instance.clear();
165
166 // Teste l'ajout
167 Int64 t0 = _getRealTimeUS();
168 for (Int32 i = 0; i < nb_key; i++) {
169 Int32 value = (i + 1) * 5;
170 map_instance.insert(value_type(i, value));
171 }
172 Int64 t1 = _getRealTimeUS();
173 std::cout << "ADD_TIME=" << (t1 - t0) << "\n";
174
175 // Teste le find
176 int nb_found = 0;
177 auto map_end = map_instance.end();
178 for (Int32 i = (2 * nb_key - 1); i >= 0; i -= 2) {
179 if (map_instance.find(i) != map_end)
180 ++nb_found;
181 }
182 Int64 t2 = _getRealTimeUS();
183 std::cout << "FIND_TIME=" << (t2 - t1) << " nb_found=" << nb_found << "\n";
185 {
186 Int64 total = 0;
187 if constexpr (HasIter) {
188 auto iter_begin = map_instance.begin();
189 auto iter_end = map_instance.end();
190 for (; iter_begin != iter_end; ++iter_begin)
191 total += iter_begin->second;
192 }
193 else {
194 map_instance.eachValue([&](Int32 v) {
195 total += v;
196 });
197 }
198 Int64 t3 = _getRealTimeUS();
200 Int64 expected_total = 5 * ((i64_nb_key) * (i64_nb_key + 1) / 2);
201
202 std::cout << "ITER_TIME=" << (t3 - t2) << " total=" << total << " T2=" << expected_total << "\n";
204 }
205
206 // Teste la suppression
207 Int64 t5 = _getRealTimeUS();
208 for (Int32 i = nb_key - 1; i >= 0; i -= 2) {
209 auto x = map_instance.find(i);
210 if (x != map_instance.end())
211 map_instance.erase(x);
212 }
213 Int64 t6 = _getRealTimeUS();
214 std::cout << "ERASE_TIME=" << (t6 - t5) << " remaining_size=" << map_instance.size() << "\n";
215 ASSERT_EQ(map_instance.size(), nb_key / 2);
216 std::cout << "MEM (MB)=" << static_cast<Int64>(platform::getMemoryUsed() / 1000000.0) << "\n";
217}
218
219int num_keys = 100000;
220
222{
223 std::unordered_map<Int64, Int32> std_map;
224 _addMultiple<true>("std::unordered_map", std_map, num_keys);
225}
226
228{
230 _addMultiple<false>("ArcaneLegacyMap", arcane_map, num_keys);
231}
232
234{
236 _addMultiple<true>("ArcaneHashMap2", arcane_map, num_keys);
237}
238
240{
241 std::cout << "STRUCT_SIZE=" << sizeof(impl::HashTableMap2<Int64, Int32>) << "\n";
243 arcane_map.add(5, 23);
244 arcane_map.add(29, 12);
245 arcane_map.add(97, 3);
246 ASSERT_EQ(arcane_map.size(), 3);
247
249 ASSERT_EQ(arcane_map2.size(), 0);
250
252 ASSERT_EQ(arcane_map2.size(), arcane_map.size());
253 ASSERT_EQ(arcane_map2[5], 23);
254 ASSERT_EQ(arcane_map2[29], 12);
255 ASSERT_EQ(arcane_map2[97], 3);
257
259 arcane_map3.clone(arcane_map);
261
262 arcane_map3.clear();
263 ASSERT_EQ(arcane_map3.size(), 0);
264}
265
266/*---------------------------------------------------------------------------*/
267/*---------------------------------------------------------------------------*/
#define ASSERT_FALSE(condition)
Vérifie que condition est faux.
Definition Assertion.h:138
#define ASSERT_TRUE(condition)
Vérifie que condition est vrai.
Definition Assertion.h:126
Lecteur des fichiers de maillage via la bibliothèque LIMA.
Definition Lima.cc:120
Implementation of std::unordered_map.
-*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-