mysql5/mysql-5.7.27/unittest/gunit/opt_costmodel-t.cc

200 lines
6.8 KiB
C++

/*
Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software Foundation,
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */
// First include (the generated) my_config.h, to get correct platform defines.
#include "my_config.h"
#include <gtest/gtest.h>
#include "opt_costmodel.h"
#include "opt_costconstantcache.h"
#include "fake_table.h"
#include "test_utils.h"
namespace costmodel_unittest {
using my_testing::Server_initializer;
class CostModelTest : public ::testing::Test
{
protected:
virtual void SetUp()
{
// Add a storage engine to the hton2plugin array.
// This is needed for the cost model to add cost constants
// for the storage engine
LEX_STRING engine_name= {C_STRING_WITH_LEN("InnoDB")};
hton2plugin[0]= new st_plugin_int();
hton2plugin[0]->name= engine_name;
initializer.SetUp();
}
virtual void TearDown()
{
initializer.TearDown();
delete hton2plugin[0];
hton2plugin[0]= NULL;
}
THD *thd() { return initializer.thd(); }
Server_initializer initializer;
};
/*
Tests for temporary tables that are not dependent on hard coded cost
constants.
*/
void test_tmptable_cost(const Cost_model_server *cm,
Cost_model_server::enum_tmptable_type tmp_table_type)
{
const uint rows= 3;
// Cost of inserting and reading data in a temporary table
EXPECT_EQ(cm->tmptable_readwrite_cost(tmp_table_type, rows, rows),
rows * cm->tmptable_readwrite_cost(tmp_table_type, 1.0, 1.0));
}
/*
Test the Cost_model_server interface.
*/
TEST_F(CostModelTest, CostModelServer)
{
const uint rows= 3;
// Create and initialize the server cost model
Cost_model_server cm;
cm.init();
// Create and initialize a cost constant object that will be used
// for verifying default values for cost constants
const Server_cost_constants default_server_cost;
// Test row evaluate cost
EXPECT_EQ(cm.row_evaluate_cost(1.0), default_server_cost.row_evaluate_cost());
EXPECT_EQ(cm.row_evaluate_cost(rows),
rows * cm.row_evaluate_cost(1.0));
// Test key compare cost
EXPECT_EQ(cm.key_compare_cost(1.0), default_server_cost.key_compare_cost());
EXPECT_EQ(cm.key_compare_cost(rows), rows * cm.key_compare_cost(1.0));
// Cost of creating a tempoary table without inserting data into it
EXPECT_EQ(cm.tmptable_create_cost(Cost_model_server::MEMORY_TMPTABLE),
default_server_cost.memory_temptable_create_cost());
EXPECT_EQ(cm.tmptable_create_cost(Cost_model_server::DISK_TMPTABLE),
default_server_cost.disk_temptable_create_cost());
// Cost of inserting one row in a temporary table
EXPECT_EQ(cm.tmptable_readwrite_cost(Cost_model_server::MEMORY_TMPTABLE,
1.0, 0.0),
default_server_cost.memory_temptable_row_cost());
EXPECT_EQ(cm.tmptable_readwrite_cost(Cost_model_server::DISK_TMPTABLE,
1.0, 0.0),
default_server_cost.disk_temptable_row_cost());
// Cost of reading one row in a temporary table
EXPECT_EQ(cm.tmptable_readwrite_cost(Cost_model_server::MEMORY_TMPTABLE,
0.0, 1.0),
default_server_cost.memory_temptable_row_cost());
EXPECT_EQ(cm.tmptable_readwrite_cost(Cost_model_server::DISK_TMPTABLE,
0.0, 1.0),
default_server_cost.disk_temptable_row_cost());
// Tests for temporary tables that are independent of cost constants
test_tmptable_cost(&cm, Cost_model_server::MEMORY_TMPTABLE);
test_tmptable_cost(&cm, Cost_model_server::DISK_TMPTABLE);
}
/*
Test the Cost_model_table interface.
*/
TEST_F(CostModelTest, CostModelTable)
{
const uint rows= 3;
const double blocks= 4.0;
const uint key= 0;
// A table is needed in order to initialize the table cost model
Fake_TABLE table(1, false);
// Create and initialize a cost model table object
Cost_model_server cost_model_server;
cost_model_server.init();
Cost_model_table cm;
cm.init(&cost_model_server, &table);
// Create and initialize a cost constant object that will be used
// for verifying default values for cost constants
const Server_cost_constants default_server_cost;
const SE_cost_constants default_engine_cost;
// Test row evaluate cost
EXPECT_EQ(cm.row_evaluate_cost(1.0), default_server_cost.row_evaluate_cost());
EXPECT_EQ(cm.row_evaluate_cost(rows),
rows * cm.row_evaluate_cost(1.0));
// Test key compare cost
EXPECT_EQ(cm.key_compare_cost(1.0), default_server_cost.key_compare_cost());
EXPECT_EQ(cm.key_compare_cost(rows),
rows * cm.key_compare_cost(1.0));
// Test io block read cost
EXPECT_EQ(cm.io_block_read_cost(1.0),
default_engine_cost.io_block_read_cost());
EXPECT_EQ(cm.io_block_read_cost(blocks),
blocks * cm.io_block_read_cost(1.0));
// Test page_read_cost() with table in memory buffer
EXPECT_EQ(cm.page_read_cost(1.0),
default_engine_cost.memory_block_read_cost());
EXPECT_EQ(cm.page_read_cost(blocks),
blocks * cm.page_read_cost(1.0));
// Test page_read_cost() with table data on disk
table.file->stats.table_in_mem_estimate= 0.0; // Table is on disk
EXPECT_EQ(cm.page_read_cost(1.0),
default_engine_cost.io_block_read_cost());
EXPECT_EQ(cm.page_read_cost(blocks),
blocks * cm.page_read_cost(1.0));
// Test page_read_cost_index() with index data in memory
table.key_info[key].set_in_memory_estimate(1.0); // Index is in memory
EXPECT_EQ(cm.page_read_cost_index(key, 1.0),
default_engine_cost.memory_block_read_cost());
EXPECT_EQ(cm.page_read_cost_index(key, blocks),
blocks * cm.page_read_cost_index(key, 1.0));
// Test page_read_oost_index() with index data on disk
table.key_info[key].set_in_memory_estimate(0.0); // Index is on disk
EXPECT_EQ(cm.page_read_cost_index(key, 1.0),
default_engine_cost.io_block_read_cost());
EXPECT_EQ(cm.page_read_cost_index(key, blocks),
blocks * cm.page_read_cost_index(key, 1.0));
// Test disk seek base cost
EXPECT_EQ(cm.disk_seek_base_cost(),
DISK_SEEK_BASE_COST * cm.io_block_read_cost(1.0));
// Test disk seek cost
EXPECT_GT(cm.disk_seek_cost(2.0), cm.disk_seek_cost(1.0));
}
}