| /** |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| **/ |
| |
| #include <numa.h> |
| |
| #include <cstddef> |
| #include <memory> |
| |
| #include "catalog/NUMAPlacementScheme.hpp" |
| #include "catalog/PartitionSchemeHeader.hpp" |
| #include "storage/StorageBlockInfo.hpp" |
| |
| #include "gtest/gtest.h" |
| |
| namespace quickstep { |
| |
| // Test to check if the number of NUMA nodes in the system |
| // is the same as the number of NUMA nodes as reported by |
| // the NUMAPlacementScheme. |
| TEST(NUMAPlacementSchemeTest, CheckNumNUMANodes) { |
| // Number of partitions in the Catalog Relation. |
| std::size_t num_partitions = 4; |
| |
| // Create a NUMAPlacementScheme object with the num_partitions. |
| std::unique_ptr<NUMAPlacementScheme> placement_scheme( |
| new NUMAPlacementScheme(num_partitions)); |
| |
| // Get the number of NUMA nodes in the system. |
| const std::size_t num_numa_nodes = numa_num_configured_nodes(); |
| |
| // Check if the number of NUMA nodes in NUMAPlacementScheme and that returned |
| // from the system are the same. |
| EXPECT_EQ(num_numa_nodes, placement_scheme->getNumNUMANodes()); |
| } |
| |
| // Test to check if the partitions are assigned the available NUMA nodes in a |
| // round-robin manner. |
| TEST(NUMAPlacementSchemeTest, CheckNUMANodesAssignment) { |
| // Number of partitions in the Catalog Relation. |
| std::size_t num_partitions = 64; |
| |
| // Create a NUMAPlacementScheme object with the num_partitions. |
| std::unique_ptr<NUMAPlacementScheme> placement_scheme( |
| new NUMAPlacementScheme(num_partitions)); |
| |
| // Check that the partitions are assigned to the NUMA nodes in a |
| // round-robbin manner. Partition 0 should be assigned to NUMA node 0, |
| // partition 1 should be assigned to NUMA node 1, and so on. Partition n |
| // should be assigned to NUMA node n modulus number_of_NUMA_nodes. |
| for (std::size_t part_num = 0; |
| part_num < num_partitions; |
| ++part_num) { |
| EXPECT_EQ(static_cast<int>(part_num % placement_scheme->getNumNUMANodes()), |
| placement_scheme->getNUMANodeForPartition(part_num)); |
| } |
| } |
| |
| // Test the serialization and deserialization of NUMAPlacementScheme object. |
| TEST(NUMAPlacementSchemeTest, NUMAPlacementSchemeSerializationTest) { |
| // Number of blocks in the Catalog Relation. |
| constexpr int kNumBlocks = 10; |
| |
| // Number of partitions in the Catalog Relation. |
| std::size_t num_partitions = 64; |
| |
| // Create a HashPartitionSchemeHeader object with 64 partitions and attribute |
| // 0 as the partitioning attribute. |
| std::unique_ptr<PartitionSchemeHeader> partition_scheme_header( |
| new HashPartitionSchemeHeader(num_partitions, { 0 })); |
| |
| // Create a NUMAPlacementScheme object with the num_partitions. |
| std::unique_ptr<NUMAPlacementScheme> placement_scheme( |
| new NUMAPlacementScheme(num_partitions)); |
| |
| // Add some entries into block to NUMA node map. |
| for (block_id block = 0; block < kNumBlocks; ++block) { |
| placement_scheme->addBlockToNUMANodeMap( |
| block, block % placement_scheme->getNumNUMANodes()); |
| } |
| |
| // Check if the BlockToNUMANodeMap has exactly the same entries that we just |
| // inserted.. |
| for (block_id block = 0; block < kNumBlocks; ++block) { |
| EXPECT_EQ(static_cast<int>(block % placement_scheme->getNumNUMANodes()), |
| placement_scheme->getNUMANodeForBlock(block)); |
| } |
| |
| // Create a new placement scheme object from the protobuf version of the |
| // previously created placement scheme object. Note that serialization is done |
| // using getProto() and deserialization is done using |
| // ReconstructFromProto() methods, respectively. |
| std::unique_ptr<NUMAPlacementScheme> placement_scheme_from_proto; |
| placement_scheme_from_proto.reset( |
| NUMAPlacementScheme::ReconstructFromProto( |
| placement_scheme->getProto(), partition_scheme_header->getNumPartitions())); |
| |
| // Check if the number of NUMA nodes is the same in both the placement scheme |
| // objects. |
| EXPECT_EQ(placement_scheme->getNumNUMANodes(), |
| placement_scheme_from_proto->getNumNUMANodes()); |
| |
| // Check if the mapping between the partitions to the NUMA nodes is the same |
| // in both the placement scheme objects. |
| for (std::size_t part_id = 0; part_id < num_partitions; ++part_id) { |
| EXPECT_EQ(placement_scheme->getNUMANodeForPartition(part_id), |
| placement_scheme_from_proto->getNUMANodeForPartition(part_id)); |
| } |
| |
| // Check if the entries in the block to NUMA node map are the same in both the |
| // placement scheme objects. |
| for (block_id block = 0; block < kNumBlocks; ++block) { |
| EXPECT_EQ(placement_scheme->getNUMANodeForBlock(block), |
| placement_scheme_from_proto->getNUMANodeForBlock(block)); |
| } |
| } |
| |
| } // namespace quickstep |