Skip to content

Commit 34cb791

Browse files
[#12763] DocDB: Adding PGO build types: prof_gen and prof_use.
Summary: Added build types for generating and using profile for profile guided optimizations with clang. Added forced profile dumping to tserver with prof_gen build. For performance comparison of `release+lto` vs `prof_use+lto` the profile was collected with CassandraKeyValue app. Then CassandraKeyValue, CassandraTransactionalKeyValue and CassandraUniqueSecondaryIndex were run 9 times each. Comparing the average of 9 runs of the average of the first 30 read ops/sec. Parameters for all apps: --num_unique_keys 1000000 --num_threads_read 128 --num_threads_write 4 --nouuid --num_writes 10000 --num_reads 10000000 ``` app | release | prof_use | prof_use/release | ops/sec | ops/sec | CassandraKeyValue | 43348.1 | 45550.8 | 1.051 CassandraTransactionalKeyValue | 28487.5 | 29574.7 | 1.038 CassandraUniqueSecondaryIndex | 39259.1 | 42316.8 | 1.078 ``` Test Plan: Run builds and yb-sample-apps Reviewers: dfelsing, mbautin Reviewed By: dfelsing, mbautin Subscribers: dfelsing, mbautin, bogdan Differential Revision: https://phabricator.dev.yugabyte.com/D18258
1 parent 25e488d commit 34cb791

File tree

5 files changed

+108
-9
lines changed

5 files changed

+108
-9
lines changed

CMakeLists.txt

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -582,6 +582,23 @@ if ("${YB_BUILD_TYPE}" MATCHES "^(asan|tsan)$")
582582
endif()
583583

584584
set(BUILD_SHARED_LIBS ON)
585+
if ("${YB_BUILD_TYPE}" STREQUAL "prof_gen")
586+
ADD_CXX_FLAGS("-fprofile-instr-generate -DYB_PROFGEN")
587+
endif ()
588+
589+
if ("${YB_BUILD_TYPE}" STREQUAL "prof_use")
590+
if (NOT YB_PGO_DATA_PATH)
591+
message (SEND_ERROR "Pgo data path is not set.")
592+
endif()
593+
ADD_CXX_FLAGS("-fprofile-instr-use=${YB_PGO_DATA_PATH}")
594+
# Even with the fresh profile data we might get warnings like
595+
# warning: Function control flow change detected (hash mismatch)
596+
# [-Wbackend-plugin]
597+
# Silencing it for now.
598+
ADD_CXX_FLAGS("-Wno-backend-plugin")
599+
ADD_CXX_FLAGS("-Wno-profile-instr-unprofiled")
600+
ADD_CXX_FLAGS("-Wno-profile-instr-out-of-date")
601+
endif ()
585602

586603
# Position independent code is only necessary when producing shared objects.
587604
ADD_CXX_FLAGS(-fPIC)

build-support/common-build-env.sh

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,8 @@ readonly -a VALID_BUILD_TYPES=(
159159
tsan
160160
tsan_slow
161161
pvs
162+
prof_gen
163+
prof_use
162164
)
163165
make_regex_from_list VALID_BUILD_TYPES "${VALID_BUILD_TYPES[@]}"
164166

@@ -344,7 +346,7 @@ decide_whether_to_use_linuxbrew() {
344346
fi
345347
elif [[ -n ${YB_LINUXBREW_DIR:-} ||
346348
( ${YB_COMPILER_TYPE} =~ ^clang[0-9]+$ &&
347-
$build_type == "release" &&
349+
$build_type =~ ^(release|prof_(gen|use))$ &&
348350
"$( uname -m )" == "x86_64" ) ]]; then
349351
YB_USE_LINUXBREW=1
350352
fi
@@ -643,6 +645,9 @@ set_cmake_build_type_and_compiler_type() {
643645
tsan_slow)
644646
cmake_build_type=debug
645647
;;
648+
prof_gen|prof_use)
649+
cmake_build_type=release
650+
;;
646651
*)
647652
cmake_build_type=$build_type
648653
esac
@@ -655,11 +660,16 @@ set_cmake_build_type_and_compiler_type() {
655660
readonly YB_COMPILER_TYPE
656661
export YB_COMPILER_TYPE
657662

658-
if [[ $build_type =~ ^asan|tsan|tsan_slow$ && $YB_COMPILER_TYPE == gcc* ]]; then
663+
if [[ $build_type =~ ^(asan|tsan|tsan_slow)$ && $YB_COMPILER_TYPE == gcc* ]]; then
659664
fatal "Build type $build_type not supported with compiler type $YB_COMPILER_TYPE." \
660665
"Sanitizers are only supported with Clang."
661666
fi
662667

668+
if [[ $build_type =~ ^(prof_gen|prof_use)$ && $YB_COMPILER_TYPE == gcc* ]]; then
669+
fatal "Build type $build_type not supported with compiler type $YB_COMPILER_TYPE." \
670+
"PGO works only with Clang for now."
671+
fi
672+
663673
# We need to set CMAKE_C_COMPILER and CMAKE_CXX_COMPILER outside of CMake. We used to do that from
664674
# CMakeLists.txt, and got into an infinite loop where CMake kept saying:
665675
#

build-support/tserver_lto.sh

Lines changed: 31 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,39 @@
55
activate_virtualenv
66
set_pythonpath
77

8+
# usage:
9+
# for release build : ./tserver_lto.sh
10+
# for prof_gen build : ./tserver_lto.sh prof_gen
11+
# for prof_use build : ./tserver_lto.sh prof_use path/to/pgo/data
12+
13+
if [[ $# -gt 0 ]]; then
14+
build_type=$1
15+
validate_build_type "$build_type"
16+
shift
17+
if [[ $build_type == "prof_use" ]]; then
18+
expect_num_args 1 "$@"
19+
pgo_data_path="$1"
20+
shift
21+
fi
22+
else
23+
build_type="release"
24+
fi
25+
826
if [[ $( uname -m ) == "x86_64" ]]; then
9-
build_root_basename=release-clang12-linuxbrew-full-lto-ninja
27+
build_root_basename="$build_type-clang13-linuxbrew-full-lto-ninja"
1028
else
11-
build_root_basename=release-clang12-full-lto-ninja
29+
build_root_basename="$build_type-clang12-full-lto-ninja"
30+
fi
31+
32+
dep_graph_cmd=(
33+
"${YB_SRC_ROOT}/python/yb/dependency_graph.py"
34+
"--build-root=${YB_SRC_ROOT}/build/${build_root_basename}"
35+
"--file-regex=^.*/yb-tserver$"
36+
)
37+
if [[ $build_type == "prof_use" ]]; then
38+
dep_graph_cmd+=( "--build-args=--pgo-data-path ${pgo_data_path}" )
1239
fi
40+
dep_graph_cmd+=( link-whole-program "$@" )
1341

1442
set -x
15-
"$YB_SRC_ROOT/python/yb/dependency_graph.py" \
16-
--build-root "$YB_SRC_ROOT/build/${build_root_basename}" \
17-
--file-regex "^.*/yb-tserver$" \
18-
link-whole-program \
19-
"$@"
43+
"${dep_graph_cmd[@]}"

src/yb/tserver/tablet_server_main.cc

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,13 @@
7575

7676
#include "yb/tserver/server_main_util.h"
7777

78+
#if defined(YB_PROFGEN) && defined(__clang__)
79+
extern "C" int __llvm_profile_write_file(void);
80+
extern "C" void __llvm_profile_set_filename(const char *);
81+
extern "C" void __llvm_profile_reset_counters();
82+
#endif
83+
84+
7885
using namespace std::placeholders;
7986

8087
using yb::redisserver::RedisServer;
@@ -159,6 +166,18 @@ void SetProxyAddresses() {
159166
SetProxyAddress(&FLAGS_pgsql_proxy_bind_address, "YSQL", PgProcessConf::kDefaultPort);
160167
}
161168

169+
#if defined(YB_PROFGEN) && defined(__clang__)
170+
// Force profile dumping
171+
void PeriodicDumpLLVMProfileFile() {
172+
__llvm_profile_set_filename("tserver-%p-%m.profraw");
173+
while (true) {
174+
__llvm_profile_write_file();
175+
__llvm_profile_reset_counters();
176+
SleepFor(MonoDelta::FromSeconds(60));
177+
}
178+
}
179+
#endif
180+
162181
int TabletServerMain(int argc, char** argv) {
163182
#ifndef NDEBUG
164183
HybridTime::TEST_SetPrettyToString(true);
@@ -274,6 +293,13 @@ int TabletServerMain(int argc, char** argv) {
274293
LOG(INFO) << "Redis server successfully started.";
275294
}
276295

296+
#if defined(YB_PROFGEN) && defined(__clang__)
297+
// TODO After the TODO below is fixed the call of
298+
// PeriodicDumpLLVMProfileFile can be moved to the infinite while loop
299+
// at the end of the function.
300+
std::thread llvm_profile_dump_thread(PeriodicDumpLLVMProfileFile);
301+
#endif
302+
277303
// TODO(neil): After CQL server is starting, it blocks this thread from moving on.
278304
// This should be fixed such that all processes or service by tablet server are treated equally
279305
// by using different threads for each process.
@@ -310,6 +336,11 @@ int TabletServerMain(int argc, char** argv) {
310336
SleepFor(MonoDelta::FromSeconds(60));
311337
}
312338

339+
#if defined(YB_PROFGEN) && defined(__clang__)
340+
// Currently unreachable
341+
llvm_profile_dump_thread.join();
342+
#endif
343+
313344
return 0;
314345
}
315346

yb_build.sh

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -720,6 +720,7 @@ java_only=false
720720
cmake_only=false
721721
run_python_tests=false
722722
cmake_extra_args=""
723+
pgo_data_path=""
723724
predefined_build_root=""
724725
java_test_name=""
725726
show_report=true
@@ -1041,6 +1042,14 @@ while [[ $# -gt 0 ]]; do
10411042
cmake_extra_args+=$2
10421043
shift
10431044
;;
1045+
--pgo-data-path)
1046+
ensure_option_has_arg "$@"
1047+
pgo_data_path=$(realpath "$2")
1048+
shift
1049+
if [[ ! -f $pgo_data_path ]]; then
1050+
fatal "Profile data file doesn't exist: $pgo_data_path"
1051+
fi
1052+
;;
10441053
--make-ninja-extra-args)
10451054
ensure_option_has_arg "$@"
10461055
if [[ -n $make_ninja_extra_args ]]; then
@@ -1354,6 +1363,10 @@ if ! "$build_java" && "$resolve_java_dependencies"; then
13541363
fatal "--resolve-java-dependencies is not allowed if not building Java code"
13551364
fi
13561365

1366+
if [[ $build_type == "prof_use" ]] && [[ $pgo_data_path == "" ]]; then
1367+
fatal "Please set --pgo-data-path path/to/pgo/data"
1368+
fi
1369+
13571370
# End of post-processing and validating command-line arguments.
13581371

13591372
# -------------------------------------------------------------------------------------------------
@@ -1524,6 +1537,10 @@ if "$no_tcmalloc"; then
15241537
cmake_opts+=( -DYB_TCMALLOC_ENABLED=0 )
15251538
fi
15261539

1540+
if [[ $pgo_data_path != "" ]]; then
1541+
cmake_opts+=( "-DYB_PGO_DATA_PATH=$pgo_data_path" )
1542+
fi
1543+
15271544
detect_num_cpus_and_set_make_parallelism
15281545
if "$build_cxx"; then
15291546
log "Using make parallelism of $YB_MAKE_PARALLELISM" \

0 commit comments

Comments
 (0)