blob: 0525085bdbff85cb054d0f9a848a0621fe489c31 [file] [log] [blame]
// 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 <cstdint>
#include <functional>
#include <memory>
#include <string>
#include <utility>
#include <vector>
#include <glog/logging.h>
#include <gtest/gtest.h>
#include "kudu/integration-tests/cluster_itest_util.h"
#include "kudu/integration-tests/external_mini_cluster-itest-base.h"
#include "kudu/integration-tests/test_workload.h"
#include "kudu/mini-cluster/external_mini_cluster.h"
#include "kudu/util/metrics.h"
#include "kudu/util/monotime.h"
#include "kudu/util/status.h"
#include "kudu/util/test_macros.h"
#include "kudu/util/test_util.h"
using std::string;
using std::vector;
METRIC_DECLARE_entity(server);
METRIC_DECLARE_gauge_uint64(generic_current_allocated_bytes);
METRIC_DECLARE_gauge_uint64(tcmalloc_pageheap_free_bytes);
namespace kudu {
using cluster::ExternalMiniClusterOptions;
using cluster::ExternalTabletServer;
namespace {
void GetOverheadRatio(ExternalTabletServer* ets, double* ratio) {
CHECK(ratio);
int64_t generic_current_allocated_bytes = 0;
int64_t tcmalloc_pageheap_free_bytes = 0;
ASSERT_OK(itest::GetTsCounterValue(ets, &METRIC_generic_current_allocated_bytes,
&generic_current_allocated_bytes));
ASSERT_OK(itest::GetTsCounterValue(ets, &METRIC_tcmalloc_pageheap_free_bytes,
&tcmalloc_pageheap_free_bytes));
ASSERT_GT(generic_current_allocated_bytes, 0);
ASSERT_GE(tcmalloc_pageheap_free_bytes, 0);
*ratio = static_cast<double>(tcmalloc_pageheap_free_bytes) / generic_current_allocated_bytes;
}
} // namespace
class MemoryGcITest : public ExternalMiniClusterITestBase {
};
TEST_F(MemoryGcITest, TestPeriodicGc) {
vector<string> ts_flags;
// Set GC interval seconds short enough, so the test case could complete sooner.
ts_flags.emplace_back("--gc_tcmalloc_memory_interval_seconds=5");
// Disable tcmalloc memory GC by memory tracker, but periodical tcmalloc memory
// GC is still enabled.
ts_flags.emplace_back("--disable_tcmalloc_gc_by_memory_tracker_for_testing=true");
ExternalMiniClusterOptions opts;
opts.extra_tserver_flags = std::move(ts_flags);
opts.num_tablet_servers = 3;
NO_FATALS(StartClusterWithOpts(opts));
// Disable periodical tcmalloc memory GC for tserver-0 and tserver-2.
ASSERT_OK(cluster_->SetFlag(cluster_->tablet_server(0),
"gc_tcmalloc_memory_interval_seconds", "0"));
ASSERT_OK(cluster_->SetFlag(cluster_->tablet_server(1),
"gc_tcmalloc_memory_interval_seconds", "1"));
ASSERT_OK(cluster_->SetFlag(cluster_->tablet_server(2),
"gc_tcmalloc_memory_interval_seconds", "0"));
// Write some data for scan later.
{
TestWorkload workload(cluster_.get());
workload.set_num_tablets(60);
workload.set_num_replicas(1);
workload.set_num_write_threads(4);
workload.set_write_batch_size(10);
workload.set_payload_bytes(1024);
workload.Setup();
workload.Start();
ASSERT_EVENTUALLY([&]() {
ASSERT_GE(workload.rows_inserted(), 30000);
});
workload.StopAndJoin();
}
// Start scan, then more memory will be allocated by tcmalloc.
{
TestWorkload workload(cluster_.get());
workload.set_num_write_threads(0);
workload.set_num_read_threads(8);
workload.Setup();
workload.Start();
// Sleep a long time to ensure memory consumed more.
SleepFor(MonoDelta::FromSeconds(8));
workload.StopAndJoin();
}
// Check result.
ASSERT_EVENTUALLY([&]() {
NO_FATALS(
double ratio;
GetOverheadRatio(cluster_->tablet_server(0), &ratio);
ASSERT_GE(ratio, 0.1) << "tserver-0";
GetOverheadRatio(cluster_->tablet_server(1), &ratio);
ASSERT_LE(ratio, 0.1) << "tserver-1";
GetOverheadRatio(cluster_->tablet_server(2), &ratio);
ASSERT_GE(ratio, 0.1) << "tserver-2";
);
});
}
} // namespace kudu