| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | /* | ||
| 2 | * Copyright (c) 2000-2022 Inria | ||
| 3 | * All rights reserved. | ||
| 4 | * | ||
| 5 | * Redistribution and use in source and binary forms, with or without | ||
| 6 | * modification, are permitted provided that the following conditions are met: | ||
| 7 | * | ||
| 8 | * * Redistributions of source code must retain the above copyright notice, | ||
| 9 | * this list of conditions and the following disclaimer. | ||
| 10 | * * Redistributions in binary form must reproduce the above copyright notice, | ||
| 11 | * this list of conditions and the following disclaimer in the documentation | ||
| 12 | * and/or other materials provided with the distribution. | ||
| 13 | * * Neither the name of the ALICE Project-Team nor the names of its | ||
| 14 | * contributors may be used to endorse or promote products derived from this | ||
| 15 | * software without specific prior written permission. | ||
| 16 | * | ||
| 17 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
| 18 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
| 19 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
| 20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE | ||
| 21 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
| 22 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
| 23 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
| 24 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||
| 25 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
| 26 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
| 27 | * POSSIBILITY OF SUCH DAMAGE. | ||
| 28 | * | ||
| 29 | * Contact: Bruno Levy | ||
| 30 | * | ||
| 31 | * https://www.inria.fr/fr/bruno-levy | ||
| 32 | * | ||
| 33 | * Inria, | ||
| 34 | * Domaine de Voluceau, | ||
| 35 | * 78150 Le Chesnay - Rocquencourt | ||
| 36 | * FRANCE | ||
| 37 | * | ||
| 38 | */ | ||
| 39 | |||
| 40 | #include <geogram/basic/packed_arrays.h> | ||
| 41 | #include <geogram/basic/logger.h> | ||
| 42 | #include <geogram/basic/string.h> | ||
| 43 | |||
| 44 | namespace { | ||
| 45 | |||
| 46 | using namespace GEO; | ||
| 47 | |||
| 48 | /** | ||
| 49 | * \brief Computes a percentage of a reference value | ||
| 50 | * \param[in] num the value to compute the percentage of | ||
| 51 | * \param[in] denom the reference value | ||
| 52 | * \return a formatted string that contains the \p num and its percentage | ||
| 53 | * of \p denom | ||
| 54 | */ | ||
| 55 | ✗ | std::string percent_str(index_t num, index_t denom) { | |
| 56 | ✗ | if(denom == 0) { | |
| 57 | ✗ | return String::to_string(num); | |
| 58 | } | ||
| 59 | ✗ | double x = double(num) / double(denom) * 100.0; | |
| 60 | ✗ | return String::to_string(num) + "(" + String::to_string(x) + "%)"; | |
| 61 | } | ||
| 62 | } | ||
| 63 | |||
| 64 | namespace GEO { | ||
| 65 | |||
| 66 | 76 | PackedArrays::PackedArrays() { | |
| 67 | 76 | nb_arrays_ = 0; | |
| 68 | 76 | Z1_block_size_ = 0; | |
| 69 | 76 | Z1_stride_ = 0; | |
| 70 | 76 | Z1_ = nullptr; | |
| 71 | 76 | ZV_ = nullptr; | |
| 72 | 76 | thread_safe_ = false; | |
| 73 | 76 | } | |
| 74 | |||
| 75 | ✗ | void PackedArrays::show_stats() { | |
| 76 | ✗ | index_t nb_items_in_Z1 = 0; | |
| 77 | ✗ | index_t nb_items_in_ZV = 0; | |
| 78 | ✗ | index_t nb_arrays_in_ZV = 0; | |
| 79 | ✗ | index_t nb_items = 0; | |
| 80 | ✗ | for(index_t i = 0; i < nb_arrays_; i++) { | |
| 81 | ✗ | index_t sz = array_size(i); | |
| 82 | ✗ | nb_items += sz; | |
| 83 | ✗ | if(sz > Z1_block_size_) { | |
| 84 | ✗ | nb_items_in_ZV += (sz - Z1_block_size_); | |
| 85 | ✗ | nb_arrays_in_ZV++; | |
| 86 | } | ||
| 87 | ✗ | nb_items_in_Z1 += std::min(sz, Z1_block_size_); | |
| 88 | } | ||
| 89 | |||
| 90 | ✗ | Logger::out("PArrays") | |
| 91 | ✗ | << "stats (nb_arrays=" << nb_arrays_ | |
| 92 | ✗ | << ", Z1 block size=" << Z1_block_size_ << ") " | |
| 93 | ✗ | << (static_mode() ? "static" : "dynamic") | |
| 94 | ✗ | << std::endl; | |
| 95 | |||
| 96 | ✗ | index_t Z1_total = nb_arrays_ * Z1_block_size_; | |
| 97 | |||
| 98 | ✗ | Logger::out("PArrays") | |
| 99 | << "Z1 filling:" | ||
| 100 | ✗ | << percent_str(nb_items_in_Z1, Z1_total) << std::endl; | |
| 101 | |||
| 102 | ✗ | if(!static_mode()) { | |
| 103 | ✗ | Logger::out("PArrays") | |
| 104 | ✗ | << "arrays in ZV:" << percent_str(nb_arrays_in_ZV, nb_arrays_) | |
| 105 | ✗ | << std::endl; | |
| 106 | ✗ | Logger::out("PArrays") | |
| 107 | ✗ | << "items in Z1:" << percent_str(nb_items_in_Z1, nb_items) | |
| 108 | ✗ | << std::endl; | |
| 109 | ✗ | Logger::out("PArrays") | |
| 110 | ✗ | << "items in ZV:" << percent_str(nb_items_in_ZV, nb_items) | |
| 111 | ✗ | << std::endl; | |
| 112 | } | ||
| 113 | ✗ | } | |
| 114 | |||
| 115 | 76 | PackedArrays::~PackedArrays() { | |
| 116 | 76 | clear(); | |
| 117 | 76 | } | |
| 118 | |||
| 119 | 140 | void PackedArrays::clear() { | |
| 120 |
2/2✓ Branch 0 taken 64 times.
✓ Branch 1 taken 76 times.
|
140 | if(ZV_ != nullptr) { |
| 121 |
2/2✓ Branch 0 taken 68860 times.
✓ Branch 1 taken 64 times.
|
68924 | for(index_t i = 0; i < nb_arrays_; i++) { |
| 122 | 68860 | free(ZV_[i]); | |
| 123 | } | ||
| 124 | 64 | free(ZV_); | |
| 125 | 64 | ZV_ = nullptr; | |
| 126 | } | ||
| 127 | 140 | nb_arrays_ = 0; | |
| 128 | 140 | Z1_block_size_ = 0; | |
| 129 | 140 | Z1_stride_ = 0; | |
| 130 | 140 | free(Z1_); | |
| 131 | 140 | Z1_ = nullptr; | |
| 132 | 140 | } | |
| 133 | |||
| 134 | 65 | void PackedArrays::set_thread_safe(bool x) { | |
| 135 | 65 | thread_safe_ = x; | |
| 136 |
1/2✓ Branch 0 taken 65 times.
✗ Branch 1 not taken.
|
65 | if(x) { |
| 137 | 65 | Z1_spinlocks_.resize(nb_arrays_); | |
| 138 | } else { | ||
| 139 | ✗ | Z1_spinlocks_.clear(); | |
| 140 | } | ||
| 141 | 65 | } | |
| 142 | |||
| 143 | 64 | void PackedArrays::init( | |
| 144 | index_t nb_arrays, | ||
| 145 | index_t Z1_block_size, | ||
| 146 | bool static_mode | ||
| 147 | ) { | ||
| 148 | 64 | clear(); | |
| 149 | 64 | nb_arrays_ = nb_arrays; | |
| 150 | 64 | Z1_block_size_ = Z1_block_size; | |
| 151 | 64 | Z1_stride_ = Z1_block_size_ + 1; // +1 for storing array size. | |
| 152 | 64 | Z1_ = (index_t*) calloc( | |
| 153 | 64 | nb_arrays_, sizeof(index_t) * Z1_stride_ | |
| 154 | ); | ||
| 155 |
1/2✓ Branch 0 taken 64 times.
✗ Branch 1 not taken.
|
64 | if(!static_mode) { |
| 156 | 64 | ZV_ = (index_t**) calloc( | |
| 157 | 64 | nb_arrays_, sizeof(index_t*) | |
| 158 | ); | ||
| 159 | } | ||
| 160 |
1/2✓ Branch 0 taken 64 times.
✗ Branch 1 not taken.
|
64 | if(thread_safe_) { |
| 161 | 64 | Z1_spinlocks_.resize(nb_arrays_); | |
| 162 | } | ||
| 163 | 64 | } | |
| 164 | |||
| 165 | 3972079 | void PackedArrays::get_array( | |
| 166 | index_t array_index, index_t* array, bool lock | ||
| 167 | ) const { | ||
| 168 |
1/6✗ Branch 0 not taken.
✓ Branch 1 taken 3972079 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
|
3972079 | geo_debug_assert(array_index < nb_arrays_); |
| 169 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3972079 times.
|
3972079 | if(lock) { |
| 170 | ✗ | lock_array(array_index); | |
| 171 | } | ||
| 172 | 3972079 | const index_t* array_base = Z1_ + array_index * Z1_stride_; | |
| 173 | 3972079 | index_t array_size = *array_base; | |
| 174 | 3972079 | index_t nb = array_size; | |
| 175 | 3972079 | array_base++; | |
| 176 | 3972079 | index_t nb_in_block = std::min(nb, Z1_block_size_); | |
| 177 | 3972079 | Memory::copy(array, array_base, sizeof(index_t) * nb_in_block); | |
| 178 |
2/2✓ Branch 0 taken 644443 times.
✓ Branch 1 taken 3327636 times.
|
3972079 | if(nb > nb_in_block) { |
| 179 | 644443 | nb -= nb_in_block; | |
| 180 | 644443 | array += nb_in_block; | |
| 181 | 644443 | array_base = ZV_[array_index]; | |
| 182 | 644443 | Memory::copy(array, array_base, sizeof(index_t) * nb); | |
| 183 | } | ||
| 184 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3972079 times.
|
3972079 | if(lock) { |
| 185 | ✗ | unlock_array(array_index); | |
| 186 | } | ||
| 187 | 3972079 | } | |
| 188 | |||
| 189 | 1287599 | void PackedArrays::set_array( | |
| 190 | index_t array_index, | ||
| 191 | index_t array_size, const index_t* array, | ||
| 192 | bool lock | ||
| 193 | ) { | ||
| 194 |
1/6✗ Branch 0 not taken.
✓ Branch 1 taken 1287599 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
|
1287599 | geo_debug_assert(array_index < nb_arrays_); |
| 195 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1287599 times.
|
1287599 | if(lock) { |
| 196 | ✗ | lock_array(array_index); | |
| 197 | } | ||
| 198 | 1287599 | index_t* array_base = Z1_ + array_index * Z1_stride_; | |
| 199 | 1287599 | index_t old_array_size = *array_base; | |
| 200 | 1287599 | array_base++; | |
| 201 |
2/2✓ Branch 0 taken 33027 times.
✓ Branch 1 taken 1254572 times.
|
1287599 | if(array_size != old_array_size) { |
| 202 |
1/2✓ Branch 1 taken 33027 times.
✗ Branch 2 not taken.
|
33027 | resize_array(array_index, array_size, false); |
| 203 | } | ||
| 204 | 1287599 | index_t nb = array_size; | |
| 205 | 1287599 | index_t nb_in_block = std::min(nb, Z1_block_size_); | |
| 206 | 1287599 | Memory::copy(array_base, array, sizeof(index_t) * nb_in_block); | |
| 207 |
2/2✓ Branch 0 taken 67006 times.
✓ Branch 1 taken 1220593 times.
|
1287599 | if(nb > nb_in_block) { |
| 208 | 67006 | nb -= nb_in_block; | |
| 209 | 67006 | array += nb_in_block; | |
| 210 | 67006 | array_base = ZV_[array_index]; | |
| 211 | 67006 | Memory::copy(array_base, array, sizeof(index_t) * nb); | |
| 212 | } | ||
| 213 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1287599 times.
|
1287599 | if(lock) { |
| 214 | ✗ | unlock_array(array_index); | |
| 215 | } | ||
| 216 | 1287599 | } | |
| 217 | |||
| 218 | 101887 | void PackedArrays::resize_array( | |
| 219 | index_t array_index, index_t array_size, bool lock | ||
| 220 | ) { | ||
| 221 |
1/6✗ Branch 0 not taken.
✓ Branch 1 taken 101887 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
|
101887 | geo_debug_assert(array_index < nb_arrays_); |
| 222 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 101887 times.
|
101887 | if(lock) { |
| 223 | ✗ | lock_array(array_index); | |
| 224 | } | ||
| 225 | 101887 | index_t* array_base = Z1_ + array_index * Z1_stride_; | |
| 226 | 101887 | index_t old_array_size = *array_base; | |
| 227 |
1/2✓ Branch 0 taken 101887 times.
✗ Branch 1 not taken.
|
101887 | if(old_array_size != array_size) { |
| 228 | 101887 | *array_base = array_size; | |
| 229 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 101887 times.
|
101887 | if(static_mode()) { |
| 230 | ✗ | geo_assert(array_size <= Z1_block_size_); | |
| 231 | } else { | ||
| 232 | 69048 | index_t nb_in_ZV = | |
| 233 |
2/2✓ Branch 0 taken 32839 times.
✓ Branch 1 taken 69048 times.
|
101887 | (array_size > Z1_block_size_) ? |
| 234 | 32839 | array_size - Z1_block_size_ : 0; | |
| 235 | 101887 | ZV_[array_index] = (index_t*) realloc( | |
| 236 | 101887 | ZV_[array_index], sizeof(index_t) * nb_in_ZV | |
| 237 | ); | ||
| 238 | } | ||
| 239 | } | ||
| 240 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 101887 times.
|
101887 | if(lock) { |
| 241 | ✗ | unlock_array(array_index); | |
| 242 | } | ||
| 243 | 101887 | } | |
| 244 | } | ||
| 245 |