Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .devcontainer/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ RUN apt update && \
clang-format \
clangd \
jq \
ccache \
memtier-benchmark && \
# Update certificates
update-ca-certificates && \
Expand Down
29 changes: 25 additions & 4 deletions .github/workflows/integration_tests-asan.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,20 +30,41 @@ jobs:

# Build the Docker image from the Dockerfile in your repo
- name: Build Docker Image
run: docker build -t presubmit-image -f .devcontainer/Dockerfile .
run: |
echo "::group::Docker Build"
DOCKER_START=$(date +%s)
docker build -t presubmit-image -f .devcontainer/Dockerfile .
DOCKER_END=$(date +%s)
echo "::endgroup::"
echo "[TIMING] Docker Image Build: $((DOCKER_END - DOCKER_START))s"

- name: Restore ccache
uses: actions/cache@v4
with:
path: .ccache
key: ccache-integration-asan-${{ github.ref }}-${{ github.sha }}
restore-keys: |
ccache-integration-asan-${{ github.ref }}-
ccache-integration-asan-

- name: Run Integration Tests
- name: Build and Run Integration Tests (ASAN)
id: test-run
timeout-minutes: 140
continue-on-error: true
run: |
mkdir test-results
mkdir -p test-results .ccache
echo "[TIMING] Build+Integration Tests (ASAN) started at $(date)"
TEST_START=$(date +%s)
docker run --privileged --rm \
--mount type=bind,source="$(pwd)/test-results",target=/workspace/test-results \
-v "$(pwd):/workspace" \
--user "ubuntu:ubuntu" \
-e CCACHE_DIR=/workspace/.ccache \
-e CCACHE_MAXSIZE=1G \
presubmit-image \
sudo ci/build_ubuntu.sh --run-integration-tests --asan --integration-output=/workspace/test-results
sudo -E ci/build_ubuntu.sh --run-integration-tests --asan --integration-output=/workspace/test-results
TEST_END=$(date +%s)
echo "[TIMING] Build+Integration Tests (ASAN) completed in $((TEST_END - TEST_START))s"

- name: Update Test Results Permissions
if: always()
Expand Down
29 changes: 25 additions & 4 deletions .github/workflows/integration_tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,20 +30,41 @@ jobs:

# Build the Docker image from the Dockerfile in your repo
- name: Build Docker Image
run: docker build -t presubmit-image -f .devcontainer/Dockerfile .
run: |
echo "::group::Docker Build"
DOCKER_START=$(date +%s)
docker build -t presubmit-image -f .devcontainer/Dockerfile .
DOCKER_END=$(date +%s)
echo "::endgroup::"
echo "[TIMING] Docker Image Build: $((DOCKER_END - DOCKER_START))s"

- name: Restore ccache
uses: actions/cache@v4
with:
path: .ccache
key: ccache-integration-${{ github.ref }}-${{ github.sha }}
restore-keys: |
ccache-integration-${{ github.ref }}-
ccache-integration-

- name: Run Integration Tests
- name: Build and Run Integration Tests
id: test-run
timeout-minutes: 140
continue-on-error: true
run: |
mkdir test-results
mkdir -p test-results .ccache
echo "[TIMING] Build+Integration Tests started at $(date)"
TEST_START=$(date +%s)
docker run --privileged --rm \
--mount type=bind,source="$(pwd)/test-results",target=/workspace/test-results \
-v "$(pwd):/workspace" \
--user "ubuntu:ubuntu" \
-e CCACHE_DIR=/workspace/.ccache \
-e CCACHE_MAXSIZE=1G \
presubmit-image \
sudo ci/build_ubuntu.sh --run-integration-tests --integration-output=/workspace/test-results
sudo -E ci/build_ubuntu.sh --run-integration-tests --integration-output=/workspace/test-results
TEST_END=$(date +%s)
echo "[TIMING] Build+Integration Tests completed in $((TEST_END - TEST_START))s"

- name: Update Test Results Permissions
if: always()
Expand Down
8 changes: 6 additions & 2 deletions .github/workflows/macos.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ jobs:
- name: Checkout Code
uses: actions/checkout@v3

# Set up Docker to build and run the container
- name: Build Code
run: ./build.sh
run: |
echo "[TIMING] macOS Build started at $(date)"
BUILD_START=$(date +%s)
./build.sh
BUILD_END=$(date +%s)
echo "[TIMING] macOS Build completed in $((BUILD_END - BUILD_START))s"
29 changes: 25 additions & 4 deletions .github/workflows/unittests-asan.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,19 +30,40 @@ jobs:

# Build the Docker image from the Dockerfile in your repo
- name: Build Docker Image
run: docker build -t presubmit-image -f .devcontainer/Dockerfile .
run: |
echo "::group::Docker Build"
DOCKER_START=$(date +%s)
docker build -t presubmit-image -f .devcontainer/Dockerfile .
DOCKER_END=$(date +%s)
echo "::endgroup::"
echo "[TIMING] Docker Image Build: $((DOCKER_END - DOCKER_START))s"

- name: Restore ccache
uses: actions/cache@v4
with:
path: .ccache
key: ccache-unittests-asan-${{ github.ref }}-${{ github.sha }}
restore-keys: |
ccache-unittests-asan-${{ github.ref }}-
ccache-unittests-asan-

- name: Run Tests ASAN
- name: Build and Run Unit Tests (ASAN)
id: test-run
continue-on-error: true
run: |
mkdir test-results
mkdir -p test-results .ccache
echo "[TIMING] Build+Test (ASAN) started at $(date)"
TEST_START=$(date +%s)
docker run --privileged --rm \
--mount type=bind,source="$(pwd)/test-results",target=/workspace/test-results \
-v "$(pwd):/workspace" \
--user "ubuntu:ubuntu" \
-e CCACHE_DIR=/workspace/.ccache \
-e CCACHE_MAXSIZE=1G \
presubmit-image \
sudo ci/build_ubuntu.sh --run-tests --asan --unittest-output=/workspace/test-results
sudo -E ci/build_ubuntu.sh --run-tests --asan --unittest-output=/workspace/test-results
TEST_END=$(date +%s)
echo "[TIMING] Build+Test (ASAN) completed in $((TEST_END - TEST_START))s"

- name: Update Test Results Permissions
if: always()
Expand Down
29 changes: 25 additions & 4 deletions .github/workflows/unittests-tsan.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,19 +30,40 @@ jobs:

# Build the Docker image from the Dockerfile in your repo
- name: Build Docker Image
run: docker build -t presubmit-image -f .devcontainer/Dockerfile .
run: |
echo "::group::Docker Build"
DOCKER_START=$(date +%s)
docker build -t presubmit-image -f .devcontainer/Dockerfile .
DOCKER_END=$(date +%s)
echo "::endgroup::"
echo "[TIMING] Docker Image Build: $((DOCKER_END - DOCKER_START))s"

- name: Restore ccache
uses: actions/cache@v4
with:
path: .ccache
key: ccache-unittests-tsan-${{ github.ref }}-${{ github.sha }}
restore-keys: |
ccache-unittests-tsan-${{ github.ref }}-
ccache-unittests-tsan-

- name: Run Tests TSAN
- name: Build and Run Unit Tests (TSAN)
id: test-run
continue-on-error: true
run: |
mkdir test-results
mkdir -p test-results .ccache
echo "[TIMING] Build+Test (TSAN) started at $(date)"
TEST_START=$(date +%s)
docker run --privileged --rm \
--mount type=bind,source="$(pwd)/test-results",target=/workspace/test-results \
-v "$(pwd):/workspace" \
--user "ubuntu:ubuntu" \
-e CCACHE_DIR=/workspace/.ccache \
-e CCACHE_MAXSIZE=1G \
presubmit-image \
sudo ci/build_ubuntu.sh --run-tests --tsan --unittest-output=/workspace/test-results
sudo -E ci/build_ubuntu.sh --run-tests --tsan --unittest-output=/workspace/test-results
TEST_END=$(date +%s)
echo "[TIMING] Build+Test (TSAN) completed in $((TEST_END - TEST_START))s"

- name: Update Test Results Permissions
if: always()
Expand Down
29 changes: 25 additions & 4 deletions .github/workflows/unittests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,19 +30,40 @@ jobs:

# Build the Docker image from the Dockerfile in your repo
- name: Build Docker Image
run: docker build -t presubmit-image -f .devcontainer/Dockerfile .
run: |
echo "::group::Docker Build"
DOCKER_START=$(date +%s)
docker build -t presubmit-image -f .devcontainer/Dockerfile .
DOCKER_END=$(date +%s)
echo "::endgroup::"
echo "[TIMING] Docker Image Build: $((DOCKER_END - DOCKER_START))s"

- name: Restore ccache
uses: actions/cache@v4
with:
path: .ccache
key: ccache-unittests-${{ github.ref }}-${{ github.sha }}
restore-keys: |
ccache-unittests-${{ github.ref }}-
ccache-unittests-

- name: Run Tests
- name: Build and Run Unit Tests
id: test-run
continue-on-error: true
run: |
mkdir test-results
mkdir -p test-results .ccache
echo "[TIMING] Build+Test started at $(date)"
TEST_START=$(date +%s)
docker run --privileged --rm \
--mount type=bind,source="$(pwd)/test-results",target=/workspace/test-results \
-v "$(pwd):/workspace" \
-e CCACHE_DIR=/workspace/.ccache \
-e CCACHE_MAXSIZE=1G \
--user "ubuntu:ubuntu" \
presubmit-image \
sudo ci/build_ubuntu.sh --run-tests --unittest-output=/workspace/test-results
sudo -E ci/build_ubuntu.sh --run-tests --unittest-output=/workspace/test-results
TEST_END=$(date +%s)
echo "[TIMING] Build+Test completed in $((TEST_END - TEST_START))s"

- name: Update Test Results Permissions
if: always()
Expand Down
8 changes: 8 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,14 @@ project(
LANGUAGES C CXX)
list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake/Modules/")

# Use ccache to speed up incremental builds if available
find_program(CCACHE_FOUND ccache)
if(CCACHE_FOUND)
message(STATUS "Using ccache: ${CCACHE_FOUND}")
set(CMAKE_C_COMPILER_LAUNCHER ccache)
set(CMAKE_CXX_COMPILER_LAUNCHER ccache)
endif()

# This project can only compile macOS / Linux, we can use the UNIX predefined
# variable to test this
if(NOT UNIX)
Expand Down
51 changes: 51 additions & 0 deletions build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,43 @@ export SAN_BUILD
export ROOT_DIR
. "${ROOT_DIR}/scripts/common.rc"

# ── Build Timing Instrumentation ──────────────────────────────────────────────
# Tracks wall-clock time for each build phase so we can identify bottlenecks.
declare -A _PHASE_TIMES 2>/dev/null || true
_BUILD_PHASES_LOG=""

function timing_start() {
local phase_name="$1"
eval "_PHASE_START_${phase_name//[- ]/_}=$(date +%s)"
printf "${BLUE}[TIMING]${RESET} ▶ ${phase_name} started\n"
}

function timing_end() {
local phase_name="$1"
local var_name="_PHASE_START_${phase_name//[- ]/_}"
local start_time=${!var_name}
local end_time=$(date +%s)
local elapsed=$((end_time - start_time))
local minutes=$((elapsed / 60))
local seconds=$((elapsed % 60))
printf "${BLUE}[TIMING]${RESET} ■ ${phase_name} completed in ${GREEN}${minutes}m ${seconds}s${RESET} (${elapsed}s)\n"
_BUILD_PHASES_LOG="${_BUILD_PHASES_LOG} ${phase_name}: ${minutes}m ${seconds}s (${elapsed}s)\n"
}

function timing_summary() {
if [ -n "${_BUILD_PHASES_LOG}" ]; then
printf "\n${BOLD_PINK}═══════════════════════════════════════${RESET}\n"
printf "${BOLD_PINK} BUILD TIMING SUMMARY${RESET}\n"
printf "${BOLD_PINK}═══════════════════════════════════════${RESET}\n"
printf "${_BUILD_PHASES_LOG}"
printf "${BOLD_PINK}───────────────────────────────────────${RESET}\n"
printf " Total build time: ${GREEN}${BUILD_RUNTIME}s${RESET}\n"
printf " Total test time: ${GREEN}${TEST_RUNTIME}s${RESET}\n"
printf "${BOLD_PINK}═══════════════════════════════════════${RESET}\n\n"
fi
}
# ──────────────────────────────────────────────────────────────────────────────

if [[ "${CMAKE_GENERATOR}" == "Ninja" ]]; then
BUILD_TOOL="ninja"
else
Expand Down Expand Up @@ -444,14 +481,20 @@ check_tools
START_TIME=$(date +%s)

# Build ICU dependencies before configuring cmake
timing_start "ICU_Build"
build_icu_if_needed
timing_end "ICU_Build"

if [[ "${RUN_CMAKE}" == "yes" ]] || [[ "${FORCE_CMAKE}" == "yes" ]]; then
timing_start "CMake_Configure"
configure
timing_end "CMake_Configure"
fi

if [[ "${RUN_BUILD}" == "yes" ]]; then
timing_start "Ninja_Build"
build
timing_end "Ninja_Build"
fi

END_TIME=$(date +%s)
Expand All @@ -464,6 +507,7 @@ if [[ "${SAN_BUILD}" != "no" ]]; then
fi

if [[ "${RUN_TEST}" == "all" ]]; then
timing_start "Unit_Tests"
rm -f "${TEST_OUTPUT_FILE}"
CURRENT_TEST_OUTPUT_FILE="${BUILD_DIR}/current_test.out"
while read -r test; do
Expand All @@ -476,7 +520,9 @@ if [[ "${RUN_TEST}" == "all" ]]; then
done < <(find "${TESTS_DIR}" -name "*_test" -type f)
rm -f "${CURRENT_TEST_OUTPUT_FILE}"
print_test_summary
timing_end "Unit_Tests"
elif [ ! -z "${RUN_TEST}" ]; then
timing_start "Unit_Tests"
rm -f "${TEST_OUTPUT_FILE}"
CURRENT_TEST_OUTPUT_FILE="${BUILD_DIR}/current_test.out"
echo "==> Running executable: ${TESTS_DIR}/${RUN_TEST}" >> "${TEST_OUTPUT_FILE}"
Expand All @@ -486,7 +532,9 @@ elif [ ! -z "${RUN_TEST}" ]; then
("${TESTS_DIR}/${RUN_TEST}" --gtest_brief=1 > "${CURRENT_TEST_OUTPUT_FILE}" 2>&1 && cat "${CURRENT_TEST_OUTPUT_FILE}" >> "${TEST_OUTPUT_FILE}" && print_test_ok) || { cat "${CURRENT_TEST_OUTPUT_FILE}" >> "${TEST_OUTPUT_FILE}"; print_test_error_and_exit; }
rm -f "${CURRENT_TEST_OUTPUT_FILE}"
print_test_summary
timing_end "Unit_Tests"
elif [[ "${INTEGRATION_TEST}" == "yes" ]]; then
timing_start "Integration_Tests"
if [ ! -z "${TEST_PATTERN}" ]; then
echo ""
LOG_WARNING " ** TEST_PATTERN is found, skipping Abseil based integration tests **"
Expand Down Expand Up @@ -523,8 +571,11 @@ elif [[ "${INTEGRATION_TEST}" == "yes" ]]; then
# Run will run ASan or normal tests based on the environment variable SAN_BUILD
./run.sh
popd >/dev/null
timing_end "Integration_Tests"
fi

END_TIME=$(date +%s)
TEST_RUNTIME=$((END_TIME - START_TIME))

timing_summary
exit ${EXIT_CODE}
23 changes: 23 additions & 0 deletions ci/build_ubuntu.sh
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,29 @@ trap cleanup EXIT

cd ${CI_DIR}

CI_TOTAL_START=$(date +%s)

LOG_INFO "[TIMING] ▶ Prepare Environment started"
PREPARE_START=$(date +%s)
prepare_env
PREPARE_END=$(date +%s)
LOG_INFO "[TIMING] ■ Prepare Environment completed in $((PREPARE_END - PREPARE_START))s"

LOG_INFO "[TIMING] ▶ Build and Run Tests started"
BUILD_TEST_START=$(date +%s)
build_and_run_tests
BUILD_TEST_END=$(date +%s)
LOG_INFO "[TIMING] ■ Build and Run Tests completed in $((BUILD_TEST_END - BUILD_TEST_START))s"

CI_TOTAL_END=$(date +%s)
CI_TOTAL=$((CI_TOTAL_END - CI_TOTAL_START))

LOG_INFO "═══════════════════════════════════════"
LOG_INFO " CI TIMING SUMMARY"
LOG_INFO "═══════════════════════════════════════"
LOG_INFO " Prepare Environment: $((PREPARE_END - PREPARE_START))s"
LOG_INFO " Build and Run Tests: $((BUILD_TEST_END - BUILD_TEST_START))s"
LOG_INFO " ─────────────────────────────────────"
LOG_INFO " CI Total: ${CI_TOTAL}s"
LOG_INFO "═══════════════════════════════════════"

Loading