| #!/bin/bash |
| # |
| # Copyright 2012 Google Inc. |
| # |
| # Licensed 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. |
| # |
| # Note: this script is not yet usable outside Google, because it depends on a |
| # corpus database that we can't open source. It should be possible to create a |
| # db with a combination of mod_pagespeed's slurping and a headless browser, but |
| # we don't currently have a script or instructions on how to do this. |
| # TODO(jefftk): resolve this |
| # |
| # This script runs a mod_pagespeed load-test. The typical |
| # configuration is to run this on your development workstation and |
| # mps_generate_load.sh will be run (via ssh) on a different machine |
| # (localhost by default, for single-machine runs). |
| # |
| # Usage: scripts/mps_load_test.sh |
| # [-start_apache_then_exit] |
| # [-custom_so mod_pagespeed.so] |
| # [-custom_so24 mod_pagespeed_ap24.so] |
| # [-user_agent user_agent_string] |
| # [-chrome] |
| # [-memcached|-redis] |
| # [-ipro_preserve] |
| # [-purging] |
| # [-inline_unauthorized_resources] |
| # [-ssl] |
| # [-debug] |
| # [corpus_file.tar.bz2] |
| # |
| # Note: Order of supplied command line parameters matters for correct working. |
| # |
| # corpus_file.tar.bz2 is mandatory on the first run and ignored on later runs. |
| # The extracted version is stored in the directory specified by $corpus (see |
| # below) between runs. |
| # |
| # Example of user_agent_string: Chrome/23.0.1271.17 |
| # Saying '-chrome' is equivalent to saying 'give me a recent version of Chrome, |
| # which needs to be updated by editing this script. |
| # |
| # If the 'machine name' argument is "localhost" then: |
| # - you will not be prompted for your ssh password |
| # - your machine will be unusable for a little while |
| # - your results may be more consistent |
| # |
| # This scripts prompts you for your su password if it needs to set your |
| # /proc/sys/net/ipv4/tcp_tw_recycle file to contain a "1". |
| |
| set -e # exit script if any command returns an error |
| set -u # exit the script if any variable is uninitialized |
| |
| this_dir=$(dirname "${BASH_SOURCE[0]}") |
| cd "$this_dir/.." |
| src="$PWD" |
| |
| gen_load="$src/devel/mps_generate_load.sh" |
| corpus="$HOME/pagespeed-loadtest-corpus" |
| |
| start_apache_then_exit=0 |
| |
| # Check if we are asked for an external cache (e.g memcached or redis) but |
| # don't have a port configured first, as we need to re-launch ourselves using |
| # run_program_with_EXTCACHE.sh, so we don't want to mess up $@. |
| for argument in "$@"; do |
| if [ "$argument" = "-memcached" -a -z "${MEMCACHED_PORT+x}" ]; then |
| exec "$src/install/run_program_with_memcached.sh" \ |
| "$src/devel/mps_load_test.sh" "$@" |
| elif [ "$argument" = "-redis" -a -z "${REDIS_PORT+x}" ]; then |
| exec "$src/install/run_program_with_redis.sh" \ |
| "$src/devel/mps_load_test.sh" "$@" |
| fi |
| done |
| |
| if [[ $# -ge 1 && "$1" = "-start_apache_then_exit" ]]; then |
| start_apache_then_exit=1 |
| shift |
| fi |
| |
| custom_so= |
| if [[ $# -ge 2 && "$1" = "-custom_so" ]]; then |
| custom_so=$2 |
| shift 2 |
| fi |
| |
| custom_so24= |
| if [[ $# -ge 2 && "$1" = "-custom_so24" ]]; then |
| custom_so24=$2 |
| shift 2 |
| fi |
| |
| if [[ $# -ge 1 && "$1" = "-chrome" ]]; then |
| export USER_AGENT_FLAG="--user_agent Chrome/47.0.2526.80" |
| shift |
| elif [[ $# -ge 2 && "$1" = "-user_agent" ]]; then |
| export USER_AGENT_FLAG="--user_agent $2" |
| shift 2 |
| else |
| export USER_AGENT_FLAG= |
| fi |
| |
| if [[ $# -ge 1 && "$1" = "-memcached" ]]; then |
| echo "Using memcached on port $MEMCACHED_PORT" |
| shift |
| export MEMCACHED=1 |
| export REDIS=0 |
| cache_stat_prefix="memcache" |
| elif [[ $# -ge 1 && "$1" = "-redis" ]]; then |
| echo Using redis on port "$REDIS_PORT" |
| shift |
| export MEMCACHED=0 |
| export REDIS=1 |
| cache_stat_prefix="redis" |
| else |
| export MEMCACHED=0 |
| export REDIS=0 |
| cache_stat_prefix="file_cache_" |
| fi |
| |
| if [[ $# -ge 1 && "$1" = "-ipro_preserve" ]]; then |
| shift |
| export IPRO_PRESERVE=1 |
| export EXTRA_URL_FLAGS=--ipro_preserve |
| else |
| export IPRO_PRESERVE=0 |
| export EXTRA_URL_FLAGS= |
| fi |
| |
| if [[ $# -ge 1 && "$1" = "-purging" ]]; then |
| shift |
| export PURGING=1 |
| else |
| export PURGING=0 |
| fi |
| |
| if [[ $# -ge 1 && "$1" = "-inline_unauthorized_resources" ]]; then |
| shift |
| export IUR=1 |
| else |
| export IUR=0 |
| fi |
| |
| if [[ $# -ge 1 && "$1" = "-ssl" ]]; then |
| shift |
| export EXTRA_FETCH_FLAGS=--ssl |
| else |
| export EXTRA_FETCH_FLAGS= |
| fi |
| |
| if [[ $# -ge 1 && "$1" = "-debug" ]]; then |
| shift |
| compile_mode="Debug" |
| else |
| compile_mode="OptDebug" |
| fi |
| |
| if [ $# -ge 2 ]; then |
| echo "Unknown arguments: $@" |
| exit 1 |
| fi |
| |
| if [ ! -d "$corpus" ] && [ $# -ne 1 ]; then |
| echo "Invalid arguments: corpus required" |
| exit 1 |
| fi |
| |
| if [ -d "$corpus" ] && [ $# -ne 0 ]; then |
| echo "Warning: using already extracted corpus instead of $1" |
| fi |
| |
| # If an 'su' password is required, then get it before going off and compiling |
| # stuff. |
| "$src/devel/turn_on_timewait_recyling.sh" |
| |
| if [ -d /var/run/pagespeed/ ]; then |
| rm -rf /var/run/pagespeed/* |
| else |
| sudo mkdir -p /var/run/pagespeed |
| sudo chown "$USER" /var/run/pagespeed |
| fi |
| |
| # Only ssh (and warn user that they will need a password) if using a separate |
| # host for load generation. |
| cmd="$gen_load $EXTRA_URL_FLAGS $EXTRA_FETCH_FLAGS $USER_AGENT_FLAG" |
| |
| APACHE_DEBUG_ROOT=${APACHE_DEBUG_ROOT:-$HOME/apache2} |
| |
| echo Checking whether we have the corpus available. |
| if [ ! -d "$corpus" ]; then |
| corpus_src="$1" |
| echo "Copying corpus files from $corpus_src" |
| mkdir -p "$corpus" |
| cd "$corpus" |
| tar xjf "$corpus_src" |
| fi |
| |
| cd "$src/devel" |
| |
| # Build a version of mod_pagespeed with all optimizations enabled, but with |
| # a build that includes DCHECKs. |
| make -j8 CONF=$compile_mode apache_trace_stress_test_server \ |
| DUMP_DIR="$corpus" \ |
| APACHE_DEBUG_ROOT="${APACHE_DEBUG_ROOT}" \ |
| MOD_PAGESPEED_CACHE=/var/run/pagespeed/cache |
| |
| # If a custom .so got specified, install it. |
| if [[ -n "$custom_so" ]]; then |
| install -c "$custom_so" "$APACHE_DEBUG_ROOT/modules/mod_pagespeed.so" |
| fi |
| |
| if [[ -n "$custom_so24" ]]; then |
| install -c "$custom_so24" "$APACHE_DEBUG_ROOT/modules/mod_pagespeed_ap24.so" |
| fi |
| |
| # Restart apache for any hand-specified .so or alternative binary |
| if [[ -n "$custom_so" || -n "$custom_so24" ]]; then |
| make apache_debug_stop |
| make apache_debug_start |
| fi |
| |
| if [[ "$start_apache_then_exit" = 1 ]]; then |
| exit 0 |
| fi |
| |
| stop_crash_scraper="/tmp/stop_crash_scraper" |
| error_log="$APACHE_DEBUG_ROOT/logs/error_log" |
| rm -f "$stop_crash_scraper" |
| |
| echo starting test ... |
| "$src/devel/scrape_error_log_for_crashes.sh" \ |
| "$error_log" "$stop_crash_scraper" & |
| echo "$cmd ..." |
| $cmd |
| touch "$stop_crash_scraper" |
| |
| # Print some interesting statistics from the server |
| statsfile=/tmp/mps_load_test_stats.$$ |
| wget -q -O $statsfile http://localhost:8080/mod_pagespeed_global_statistics |
| grep "$cache_stat_prefix" $statsfile | grep -v onchange= |
| grep shm $statsfile |
| grep dropped $statsfile |
| grep cache_batcher $statsfile |
| grep rewrite_cached_output_missed_deadline $statsfile |
| grep bytes_saved $statsfile |
| grep serf $statsfile |
| grep queued-fetch-count $statsfile |
| grep page_load_count $statsfile |
| grep 404_count $statsfile |
| grep file_cache_bytes_freed_in_cleanup $statsfile |
| grep file_cache_cleanups $statsfile |
| grep file_cache_write_errors $statsfile |
| grep image_webp_rewrites $statsfile |
| egrep "num_css|num_js" $statsfile |
| rm -f $statsfile |
| |
| set +e |
| echo 'egrep "exit signal|CRASH" $error_log' |
| egrep "exit signal|CRASH" $error_log |
| if [ $? = 0 ]; then |
| echo "*** $error_log has dangerous looking errors. Please investigate." |
| exit 1 |
| else |
| echo "No deaths reported in $error_log -- ship it." |
| fi |
| |
| if [ "$MEMCACHED" = "1" -o "$REDIS" = "1" ]; then |
| date |
| echo -n Sleeping 5 seconds before killing external cache server to let |
| echo -n outstanding writes quiesce... |
| sleep 5 |
| echo "done" |
| fi |