blob: 53130865cd35c6aa0e831cc4bc5390f1695735e8 [file] [log] [blame]
#!/bin/bash
# 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.
set -e
export ENABLE_FORY_DEBUG_OUTPUT=0
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
cd "$SCRIPT_DIR"
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color
# Default values
JOBS=16
DATA=""
SERIALIZER=""
DEBUG_BUILD=false
DURATION=""
# Parse arguments
usage() {
echo "Usage: $0 [OPTIONS]"
echo ""
echo "Build and run C++ benchmarks"
echo ""
echo "Options:"
echo " --data <struct|sample|mediacontent|structlist|samplelist|mediacontentlist>"
echo " Filter benchmark by data type"
echo " --serializer <fory|protobuf|msgpack>"
echo " Filter benchmark by serializer"
echo " --duration <seconds> Minimum time to run each benchmark (e.g., 10, 30)"
echo " --debug Build with debug symbols and low optimization for profiling"
echo " --help Show this help message"
echo ""
echo "Examples:"
echo " $0 # Run all benchmarks"
echo " $0 --data struct # Run only Struct benchmarks"
echo " $0 --serializer fory # Run only Fory benchmarks"
echo " $0 --serializer msgpack # Run only Msgpack benchmarks"
echo " $0 --data struct --serializer fory"
echo " $0 --duration 10 # Run each benchmark for at least 10 seconds"
echo " $0 --debug # Build for profiling (visible function names in flamegraph)"
echo ""
echo "For profiling/flamegraph, use: ./profile.sh"
exit 0
}
while [[ $# -gt 0 ]]; do
case $1 in
--data)
DATA="$2"
shift 2
;;
--serializer)
SERIALIZER="$2"
shift 2
;;
--duration)
DURATION="$2"
shift 2
;;
--debug)
DEBUG_BUILD=true
shift
;;
--help|-h)
usage
;;
*)
echo -e "${RED}Unknown option: $1${NC}"
usage
;;
esac
done
# Build benchmark filter
FILTER=""
DATA_PATTERN=""
SERIALIZER_PATTERN=""
if [[ -n "$DATA" ]]; then
DATA_LOWER="$(echo "$DATA" | tr '[:upper:]' '[:lower:]')"
case "$DATA_LOWER" in
struct)
DATA_PATTERN="Struct"
;;
sample)
DATA_PATTERN="Sample"
;;
mediacontent)
DATA_PATTERN="MediaContent"
;;
structlist)
DATA_PATTERN="StructList"
;;
samplelist)
DATA_PATTERN="SampleList"
;;
mediacontentlist)
DATA_PATTERN="MediaContentList"
;;
*)
echo -e "${RED}Unknown data type: $DATA${NC}"
echo "Expected one of: struct, sample, mediacontent, structlist, samplelist, mediacontentlist"
exit 1
;;
esac
fi
if [[ -n "$SERIALIZER" ]]; then
SERIALIZER_LOWER="$(echo "$SERIALIZER" | tr '[:upper:]' '[:lower:]')"
case "$SERIALIZER_LOWER" in
fory)
SERIALIZER_PATTERN="Fory"
;;
protobuf)
SERIALIZER_PATTERN="Protobuf"
;;
msgpack)
SERIALIZER_PATTERN="Msgpack"
;;
*)
echo -e "${RED}Unknown serializer: $SERIALIZER${NC}"
echo "Expected one of: fory, protobuf, msgpack"
exit 1
;;
esac
fi
if [[ -n "$SERIALIZER_PATTERN" && -n "$DATA_PATTERN" ]]; then
FILTER="^BM_${SERIALIZER_PATTERN}_${DATA_PATTERN}_(Serialize|Deserialize)$"
elif [[ -n "$SERIALIZER_PATTERN" ]]; then
FILTER="^BM_${SERIALIZER_PATTERN}_"
elif [[ -n "$DATA_PATTERN" ]]; then
FILTER="^BM_.*_${DATA_PATTERN}_(Serialize|Deserialize)$"
fi
echo -e "${GREEN}=== Fory C++ Benchmark ===${NC}"
echo ""
# Step 1: Build
echo -e "${YELLOW}[1/3] Building benchmark...${NC}"
mkdir -p build
cd build
if [[ "$DEBUG_BUILD" == true ]]; then
echo -e "${YELLOW}Building with debug symbols for profiling...${NC}"
# Detect OS for platform-specific flags
OS_TYPE="$(uname -s)"
if [[ "$OS_TYPE" == "Darwin" ]]; then
# macOS: Use -gfull for complete debug info, -fno-omit-frame-pointer for stack traces
cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo \
-DCMAKE_CXX_FLAGS="-O1 -gfull -fno-inline -fno-omit-frame-pointer -fno-optimize-sibling-calls" ..
else
# Linux
cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo \
-DCMAKE_CXX_FLAGS="-O1 -g -fno-inline -fno-omit-frame-pointer" ..
fi
else
cmake -DCMAKE_BUILD_TYPE=Release ..
fi
cmake --build . -j"$JOBS"
echo -e "${GREEN}Build complete!${NC}"
echo ""
# Step 2: Run benchmark
echo -e "${YELLOW}[2/3] Running benchmark...${NC}"
BENCH_ARGS="--benchmark_format=json --benchmark_out=benchmark_results.json"
if [[ -n "$DURATION" ]]; then
BENCH_ARGS="$BENCH_ARGS --benchmark_min_time=${DURATION}s"
echo -e "Duration: ${DURATION}s per benchmark"
fi
if [[ -n "$FILTER" ]]; then
BENCH_ARGS="$BENCH_ARGS --benchmark_filter=$FILTER"
echo -e "Filter: ${FILTER}"
fi
./fory_benchmark $BENCH_ARGS
echo -e "${GREEN}Benchmark complete!${NC}"
echo ""
# Step 3: Generate report
echo -e "${YELLOW}[3/3] Generating report...${NC}"
cd "$SCRIPT_DIR"
# Check for Python dependencies
if ! python3 -c "import matplotlib" 2>/dev/null; then
echo -e "${YELLOW}Installing required Python packages...${NC}"
pip3 install matplotlib numpy psutil
fi
python3 benchmark_report.py --json-file build/benchmark_results.json --output-dir report
echo ""
echo -e "${GREEN}=== All done! ===${NC}"
echo -e "Report generated at: ${SCRIPT_DIR}/report/REPORT.md"
echo -e "Plots saved in: ${SCRIPT_DIR}/report/"
echo ""
echo -e "For profiling/flamegraph, run: ${YELLOW}./profile.sh --help${NC}"