blob: 47687b0b893c1a72f4fe2229cf2177df81e599cf [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 <pegasus/error.h>
#include <rocksdb/env.h>
#include <rocksdb/statistics.h>
#include <s2/s1angle.h>
#include <s2/s2latlng.h>
#include <s2/s2latlng_rect.h>
#include <s2/s2testing.h>
#include <stdint.h>
#include <atomic>
#include <iostream>
#include <list>
#include <memory>
#include <string>
#include "geo/lib/geo_client.h"
#include "geo/lib/latlng_codec.h"
#include "utils/env.h"
#include "utils/errors.h"
#include "utils/fmt_logging.h"
#include "utils/string_conv.h"
#include "utils/synchronize.h"
static const int data_count = 10000;
int main(int argc, char **argv)
{
if (argc < 7) {
std::cerr << "USAGE: " << argv[0] << " <cluster_name> <app_name> <geo_app_name> <radius> "
"<test_count> <max_level> [gen_data]"
<< std::endl;
return -1;
}
std::string cluster_name = argv[1];
std::string app_name = argv[2];
std::string geo_app_name = argv[3];
double radius = 0.0;
if (!dsn::buf2double(argv[4], radius)) {
std::cerr << "radius is invalid: " << argv[4] << std::endl;
return -1;
}
int test_count = 2000;
if (!dsn::buf2int32(argv[5], test_count)) {
std::cerr << "test_count is invalid: " << argv[5] << std::endl;
return -1;
}
int max_level = 16;
if (!dsn::buf2int32(argv[6], max_level)) {
std::cerr << "max_level is invalid: " << argv[6] << std::endl;
return -1;
}
bool gen_data = false;
if (argc >= 8) {
if (!dsn::buf2bool(argv[7], gen_data)) {
std::cerr << "gen_data is invalid: " << argv[7] << std::endl;
return -1;
}
}
// TODO(yingchun): the benchmark can not exit normally, we need to fix it later.
pegasus::geo::geo_client my_geo(
"config.ini", cluster_name.c_str(), app_name.c_str(), geo_app_name.c_str());
auto err = my_geo.set_max_level(max_level);
if (!err.is_ok()) {
std::cerr << "set_max_level failed, err: " << err << std::endl;
return -1;
}
// cover beijing 5th ring road
S2LatLngRect rect(S2LatLng::FromDegrees(39.810151, 116.194511),
S2LatLng::FromDegrees(40.028697, 116.535087));
// generate data for test
if (gen_data) {
const pegasus::geo::latlng_codec &codec = my_geo.get_codec();
for (int i = 0; i < data_count; ++i) {
std::string value;
S2LatLng latlng(S2Testing::SamplePoint(rect));
bool ok = codec.encode_to_value(latlng.lat().degrees(), latlng.lng().degrees(), value);
CHECK(ok, "");
int ret = my_geo.set(std::to_string(i), "", value, 1000);
if (ret != pegasus::PERR_OK) {
std::cerr << "set data failed. error=" << ret << std::endl;
}
}
}
enum class histogram_type : uint32_t
{
LATENCY,
RESULT_COUNT
};
auto statistics = rocksdb::CreateDBStatistics();
rocksdb::Env *env = dsn::utils::PegasusEnv(dsn::utils::FileDataType::kSensitive);
uint64_t start = env->NowNanos();
std::atomic<uint64_t> count(test_count);
dsn::utils::notify_event get_completed;
// test search_radial by lat & lng
for (int i = 0; i < test_count; ++i) {
S2LatLng latlng(S2Testing::SamplePoint(rect));
uint64_t start_nanos = env->NowNanos();
my_geo.async_search_radial(
latlng.lat().degrees(),
latlng.lng().degrees(),
radius,
-1,
pegasus::geo::geo_client::SortType::random,
500,
[&, start_nanos](int error_code, std::list<pegasus::geo::SearchResult> &&results) {
statistics->measureTime(static_cast<uint32_t>(histogram_type::LATENCY),
env->NowNanos() - start_nanos);
statistics->measureTime(static_cast<uint32_t>(histogram_type::RESULT_COUNT),
results.size());
uint64_t left = count.fetch_sub(1);
if (left == 1) {
get_completed.notify();
}
});
}
std::cout << "get_completed.wait" << std::endl;
get_completed.wait();
uint64_t end = env->NowNanos();
std::cout << "start time: " << start << ", end time: " << end
<< ", QPS: " << test_count / ((end - start) / 1e9) << std::endl;
std::cout << "latency_histogram: " << std::endl;
std::cout << statistics->getHistogramString(static_cast<uint32_t>(histogram_type::LATENCY))
<< std::endl;
std::cout << "result_count_histogram: " << std::endl;
std::cout << statistics->getHistogramString(static_cast<uint32_t>(histogram_type::RESULT_COUNT))
<< std::endl;
return 0;
}