blob: f8dadd25f23880743cd88d8264953877eb23e227 [file]
/*
* 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 "../framework/test_framework.hpp"
#include <thread>
#include <atomic>
namespace opendal::test {
class OpenDALBenchmarkTest : public BenchmarkTest {
protected:
void SetUp() override {
BenchmarkTest::SetUp();
}
};
// Benchmark write operations
OPENDAL_TEST_F(OpenDALBenchmarkTest, BenchmarkWriteOperations) {
std::vector<size_t> sizes = {1024, 10240, 102400, 1024*1024}; // 1KB, 10KB, 100KB, 1MB
for (auto size : sizes) {
auto content = random_string(size);
benchmark_operation(
"Write " + std::to_string(size) + " bytes",
[&]() {
auto path = random_path();
op_.write(path, content);
},
10 // iterations
);
}
}
// Benchmark read operations
OPENDAL_TEST_F(OpenDALBenchmarkTest, BenchmarkReadOperations) {
std::vector<size_t> sizes = {1024, 10240, 102400, 1024*1024}; // 1KB, 10KB, 100KB, 1MB
for (auto size : sizes) {
auto content = random_string(size);
auto path = random_path();
// Pre-write the file
op_.write(path, content);
benchmark_operation(
"Read " + std::to_string(size) + " bytes",
[&]() {
auto result = op_.read(path);
// Verify size to ensure read actually happened
EXPECT_EQ(result.size(), size);
},
10 // iterations
);
}
}
// Benchmark exists operations
OPENDAL_TEST_F(OpenDALBenchmarkTest, BenchmarkExistsOperations) {
auto path = random_path();
auto content = random_string(1024);
// Create the file
op_.write(path, content);
benchmark_operation(
"Exists check",
[&]() {
bool exists = op_.exists(path);
EXPECT_TRUE(exists);
},
10 // iterations
);
}
// Benchmark list operations
OPENDAL_TEST_F(OpenDALBenchmarkTest, BenchmarkListOperations) {
auto dir_path = random_dir_path();
// Create directory with files
op_.create_dir(dir_path);
for (int i = 0; i < 100; ++i) {
auto file_path = dir_path + "file_" + std::to_string(i) + ".txt";
op_.write(file_path, random_string(100));
}
benchmark_operation(
"List directory with 100 files",
[&]() {
auto entries = op_.list(dir_path);
EXPECT_EQ(entries.size(), 101); // 100 files + 1 directory
},
10 // iterations
);
}
// Benchmark delete operations
OPENDAL_TEST_F(OpenDALBenchmarkTest, BenchmarkDeleteOperations) {
benchmark_operation(
"Delete operations",
[&]() {
auto path = random_path();
auto content = random_string(1024);
// Create and delete file
op_.write(path, content);
op_.remove(path);
},
10 // iterations
);
}
// Benchmark create directory operations
OPENDAL_TEST_F(OpenDALBenchmarkTest, BenchmarkCreateDirOperations) {
benchmark_operation(
"Create directory operations",
[&]() {
auto dir_path = random_dir_path();
op_.create_dir(dir_path);
},
10 // iterations
);
}
// Benchmark stat operations
OPENDAL_TEST_F(OpenDALBenchmarkTest, BenchmarkStatOperations) {
auto path = random_path();
auto content = random_string(1024);
// Create the file
op_.write(path, content);
benchmark_operation(
"Stat operations",
[&]() {
auto metadata = op_.stat(path);
EXPECT_EQ(metadata.type, opendal::EntryMode::FILE);
EXPECT_EQ(metadata.content_length, content.size());
},
10 // iterations
);
}
// Benchmark reader operations
OPENDAL_TEST_F(OpenDALBenchmarkTest, BenchmarkReaderOperations) {
auto path = random_path();
const size_t file_size = 1024 * 1024; // 1MB
auto content = random_string(file_size);
// Create the file
op_.write(path, content);
benchmark_operation(
"Reader sequential read",
[&]() {
auto reader = op_.reader(path);
const size_t chunk_size = 4096; // 4KB chunks
std::string buffer(chunk_size, 0);
for (size_t offset = 0; offset < file_size; offset += chunk_size) {
reader.seek(offset, std::ios::beg);
size_t read_size = std::min(chunk_size, file_size - offset);
reader.read(buffer.data(), read_size);
}
},
10 // iterations
);
}
// Benchmark concurrent operations
OPENDAL_TEST_F(OpenDALBenchmarkTest, BenchmarkConcurrentOperations) {
const int num_threads = 10;
const int operations_per_thread = 100;
auto start_time = std::chrono::high_resolution_clock::now();
std::vector<std::thread> threads;
std::atomic<int> completed_operations{0};
for (int t = 0; t < num_threads; ++t) {
threads.emplace_back([&, t]() {
for (int i = 0; i < operations_per_thread; ++i) {
auto path = random_path();
auto content = random_string(1024);
// Write, read, delete cycle
op_.write(path, content);
auto result = op_.read(path);
op_.remove(path);
completed_operations++;
}
});
}
for (auto& thread : threads) {
thread.join();
}
auto end_time = std::chrono::high_resolution_clock::now();
auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(end_time - start_time);
int total_operations = num_threads * operations_per_thread * 3; // write + read + delete
double ops_per_sec = (total_operations * 1000.0) / duration.count();
std::cout << "Concurrent benchmark results:" << std::endl;
std::cout << " Threads: " << num_threads << std::endl;
std::cout << " Total operations: " << total_operations << std::endl;
std::cout << " Duration: " << duration.count() << " ms" << std::endl;
std::cout << " Operations per second: " << ops_per_sec << std::endl;
EXPECT_EQ(completed_operations, num_threads * operations_per_thread);
}
// Benchmark memory usage patterns
OPENDAL_TEST_F(OpenDALBenchmarkTest, BenchmarkMemoryUsage) {
// Test with different file sizes to understand memory usage
std::vector<size_t> sizes = {1024, 102400, 1024*1024, 10*1024*1024}; // 1KB to 10MB
for (auto size : sizes) {
auto path = random_path();
auto content = random_string(size);
timer_.start();
// Write and read back to measure memory allocation patterns
op_.write(path, content);
auto result = op_.read(path);
timer_.stop();
EXPECT_EQ(result.size(), size);
std::cout << "Memory usage test - Size: " << (size / 1024) << " KB, "
<< "Time: " << timer_.elapsed_ms() << " ms" << std::endl;
// Cleanup
op_.remove(path);
}
}
} // namespace opendal::test