зеркало из https://github.com/mozilla/pjs.git
integrate test framework with graph server, new page set, and add linux support b=368720 r=rhelmer p=anodelman p=bhearsum
This commit is contained in:
Родитель
0e07922d3a
Коммит
b259289c31
|
@ -1,9 +1,100 @@
|
|||
PREREQUISITES:
You'll need to download some software onto your Windows machine before running
these performance tests:
|
||||
* Python 2.4
The scripts all run from Python 2.4. You will need the windows version
|
||||
(not the cygwin version). You can download it here:
http://www.python.org/ftp/python/2.4/python-2.4.msi
|
||||
PREREQUISITES:
|
||||
You'll need to download some software onto your Windows machine before running
|
||||
these performance tests:
|
||||
|
||||
* Python 2.4
|
||||
The scripts all run from Python 2.4. You will need the windows version
|
||||
(not the cygwin version). You can download it here:
|
||||
http://www.python.org/ftp/python/2.4/python-2.4.msi
|
||||
|
||||
Make sure to correctly set the path to python in the paths.py file.
|
||||
After you download and install Python 2.4, you'll need to install
some extensions:
|
||||
* Python Win32 Extensions
These extensions provide some support for process management and
performance monitoring.
http://prdownloads.sourceforge.net/pywin32/pywin32-208.win32-py2.4.exe?download
|
||||
* Numerical Python:
This is required by Matplotlib.
http://prdownloads.sourceforge.net/numpy/Numeric-24.2.win32-py2.4.exe?download
|
||||
* Matplotlib
This library is used to plot the graphs of performance characteristics
of Firefox during the page load test.
http://prdownloads.sourceforge.net/matplotlib/matplotlib-0.87.3.win32-py2.4.exe?download
* PySyc
This is used for reading/writing config files in YAML.
http://pyyaml.org/download/pysyck/PySyck-0.61.2.win32-py2.4.exe
* Cygwin
For some reason, we can't get output from Firefox unless it's wrapped in a
Cygwin sh shell. So we use cygwin for that, and to sync between Firefox
runs. Download it here:
http://www.cygwin.com/setup.exe
Make sure to correctly set the path to Cygwin in the paths.py file.
* msvcp71.dll
You need a copy of this file to run Python with all the libraries. If you have
Visual Studio 2003 installed, you've already got it.
SETUP:
|
||||
1. Make sure the prerequisites, above, are installed.
2. Copy this entire directory and all subdirectories onto your local disk
3. Edit the paths.py file to set the paths to Cygwin, Firefox, etc. on your
machine.
4. Create a YAML config file with info about the profiles you want to test.
It should look something like this:
# Filename will be appended to the timestamp in the report filename.
# Use letters and underscores only
filename: slowmachine
# The title of the report
title: 1 GHz Celeron
# Name of profile to test
Test profile 1:
# Path to Firefox to test
firefox: C:\Program Files\Mozilla Firefox 2 Beta 1\firefox.exe
# Preferences to set in the test (use "preferences : {}" for no prefs)
preferences:
javascript.options.showInConsole : true
xpinstall.enabled : true
# Extensions to install in test (use "extensions: {}" for none)
extensions:
# Need quotes around guid because of curly braces
"{12345678-1234-1234-1234-abcd12345678}" : c:\path\to\unzipped\xpi
foo@sample.com : c:\path\to\other\unzipped\xpi
5. Run run_tests.py with the name of your config file as an argument. You can use
a space-separated list of config files, to generate a report of startup and page load times. The
report will be placed in the REPORTS_DIR directory you specified in
paths.py.
DIRECTORY STRUCTURE:
page_load_test/
This directory contains the JavaScript files and html data files for the
page load test. The page load test opens a new window and cycles through
loading each html file, timing each load.
startup_test/
This directory contains the JavaScript to run the startup test. It
measures how long it takes Firefox to start up.
base_profile/
This directory contains the base profile used for testing. A copy of
this profile is made for each testing profile, and extensions or prefs
are added according to the test_configs array in run_tests.py. For the
page load test to run correctly, the hostperm.1 file must be set to allow
scheme:file uris to open in new windows, and the pref to force a window
to open in a tab must not be set. The dom.allow_scripts_to_close_windows
pref should also be set to true. The browser.shell.checkDefaultBrowser
pref should be set to false.
run_tests.py, paths.py
These files should be configured to run the test on different machines,
with different extensions or preferences. See setup above.
|
||||
|
||||
After you download and install Python 2.4, you'll need to install
|
||||
some extensions:
|
||||
|
||||
* Python Win32 Extensions
|
||||
These extensions provide some support for process management and
|
||||
performance monitoring.
|
||||
http://prdownloads.sourceforge.net/pywin32/pywin32-208.win32-py2.4.exe?download
|
||||
|
||||
* Apache HTTP Server
|
||||
Found at http://httpd.apache.org/
|
||||
The page cycler works on a local Apache server. After installing Apache simply place
|
||||
the page_load_test/ directory into htdocs/ directory of Apache (found on most systems
|
||||
at c:\Program Files\Apache Software Foundation\Apache2.2\htdocs)
|
||||
|
||||
1. Make sure the prerequisites, above, are installed.
|
||||
2. Copy this entire directory and all subdirectories onto your local disk
|
||||
3. Edit the config.py file to set the paths to Cygwin, Firefox, etc. on your
|
||||
machine.
|
||||
4. Create a YAML config file with info about the profiles you want to test.
|
||||
NOTE: You should set the preferences network.proxy.type:1, network.proxy.http:localhost and
|
||||
network.proxy.http_port:80 - these settings ensure that the browser will only
|
||||
contact local web pages and will not attempt to pull information from the live web,
|
||||
this is important for collecting consistant testing results.
|
||||
It should look something like this:
|
||||
|
||||
# Filename will be appended to the timestamp in the report filename.
|
||||
# Use letters and underscores only
|
||||
filename: testfilename
|
||||
|
||||
# The title of the report
|
||||
title: testtitle
|
||||
|
||||
# Name of profile to test
|
||||
Test profile 1:
|
||||
# Path to Firefox to test
|
||||
firefox: C:\cygwin\tmp\test\firefox\firefox\firefox.exe
|
||||
|
||||
branch: testbranch
|
||||
|
||||
branchid: testbranchid
|
||||
|
||||
profile_path: C:\win32\base_profile
|
||||
|
||||
# Preferences to set in the test (use "preferences : {}" for no prefs)
|
||||
preferences :
|
||||
browser.shell.checkDefaultBrowser : false
|
||||
dom.allow_scripts_to_close_windows : true
|
||||
dom.disable_open_during_load: false
|
||||
browser.dom.window.dump.enabled: true
|
||||
network.proxy.type : 1
|
||||
network.proxy.http : localhost
|
||||
network.proxy.http_port : 80
|
||||
|
||||
# Extensions to install in test (use "extensions: {}" for none)
|
||||
extensions :
|
||||
# Need quotes around guid because of curly braces
|
||||
"{12345678-1234-1234-1234-abcd12345678}" : c:\path\to\unzipped\xpi
|
||||
foo@sample.com : c:\path\to\other\unzipped\xpi
|
||||
|
||||
5. Provide a pages/ directory
|
||||
The page_load_test/ relies upon having a pages directory that includes the web pages
|
||||
to be cycled through. Each directory in pages/ should be a given web page.
|
||||
The parray.js file needs to be edited to reflect the list of index pages of the web pages
|
||||
that are to be tested - it is currently full of a sample list.
|
||||
|
||||
6. Run "python run_tests.py" with the name of your config file as an argument. You can use
|
||||
a space-separated list of config files, to generate a report of startup and page load times.
|
||||
|
||||
DIRECTORY STRUCTURE:
|
||||
page_load_test/
|
||||
This directory contains the JavaScript files and html data files for the
|
||||
page load test. The page load test opens a new window and cycles through
|
||||
loading each html file, timing each load.
|
||||
startup_test/
|
||||
This directory contains the JavaScript to run the startup test. It
|
||||
measures how long it takes Firefox to start up.
|
||||
base_profile/
|
||||
This directory contains the base profile used for testing. A copy of
|
||||
this profile is made for each testing profile, and extensions or prefs
|
||||
are added according to the test_configs array in run_tests.py. For the
|
||||
page load test to run correctly, the hostperm.1 file must be set to allow
|
||||
scheme:file uris to open in new windows, and the pref to force a window
|
||||
to open in a tab must not be set. The dom.allow_scripts_to_close_windows
|
||||
pref should also be set to true. The browser.shell.checkDefaultBrowser
|
||||
pref should be set to false.
|
||||
config.py
|
||||
This file should be configured to run the test on different machines,
|
||||
with different extensions or preferences. See setup above.
|
||||
|
||||
|
|
35
testing/performance/talos/paths.py → testing/performance/talos/config.py
Executable file → Normal file
35
testing/performance/talos/paths.py → testing/performance/talos/config.py
Executable file → Normal file
|
@ -1,5 +1,3 @@
|
|||
#!c:/Python24/python.exe
|
||||
#
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
|
@ -21,6 +19,7 @@
|
|||
#
|
||||
# Contributor(s):
|
||||
# Annie Sullivan <annie.sullivan@gmail.com> (original author)
|
||||
# Alice Nodelman <anodelman@mozilla.com>
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
|
@ -43,6 +42,8 @@
|
|||
__author__ = 'annie.sullivan@gmail.com (Annie Sullivan)'
|
||||
|
||||
|
||||
OS = r'win32'
|
||||
|
||||
"""For some reason, can only get output from dump() in Firefox if
|
||||
it's run through cygwin bash. So here's the path to cygwin.
|
||||
"""
|
||||
|
@ -56,16 +57,38 @@ SYNC = r'c:\cygwin\bin\sync'
|
|||
urls with scheme:file to open in new windows, and the preference to open
|
||||
new windows in a tab should be off.
|
||||
"""
|
||||
BASE_PROFILE_DIR = r'C:\extension_perf_testing\base_profile'
|
||||
BASE_PROFILE_DIR = r'C:\win32\base_profile'
|
||||
|
||||
"""The directory the generated reports go into."""
|
||||
REPORTS_DIR = r'c:\extension_perf_reports'
|
||||
|
||||
"""The path to the file url to load when initializing a new profile"""
|
||||
INIT_URL = 'file:///c:/mozilla/testing/performance/win32/initialize.html'
|
||||
INIT_URL = 'file:///c:/win32/initialize.html'
|
||||
|
||||
"""The path to the file url to load for startup test (Ts)"""
|
||||
TS_URL = 'file:///c:/mozilla/testing/performance/win32/startup_test/startup_test.html?begin='
|
||||
TS_URL = 'file:///c:/win32/startup_test/startup_test.html?begin='
|
||||
|
||||
"""Number of times to run startup test (Ts)"""
|
||||
TS_NUM_RUNS = 5
|
||||
|
||||
"""The path to the file url to load for page load test (Tp)"""
|
||||
TP_URL = 'file:///c:/mozilla/testing/performance/win32/page_load_test/cycler.html'
|
||||
TP_URL = 'http://localhost/page_load_test/framecycler.html'
|
||||
|
||||
"""Number of times the page load test (Tp) loads each page in the test."""
|
||||
TP_NUM_CYCLES = 5
|
||||
|
||||
"""Resolution of counter sample data for page load test (Tp), in seconds
|
||||
(For example, if TP_RESOLUTION=1, sample counters every 1 second"""
|
||||
TP_RESOLUTION = 1
|
||||
|
||||
"""Run page load test.
|
||||
For possible values of counters argument on Windows, see
|
||||
http://technet2.microsoft.com/WindowsServer/en/Library/86b5d116-6fb3-427b-af8c-9077162125fe1033.mspx?mfr=true
|
||||
Possible values on Linux:
|
||||
'Private Bytes', '% Processor Time', 'RSS'
|
||||
"""
|
||||
|
||||
COUNTERS = ['Private Bytes', 'Working Set', '% Processor Time']
|
||||
|
||||
"""URL for the results server"""
|
||||
RESULTS_SERVER = 'graphserver.url.here'
|
|
@ -1,5 +1,3 @@
|
|||
#!c:/Python24/python.exe
|
||||
#
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
|
@ -42,63 +40,18 @@
|
|||
__author__ = 'annie.sullivan@gmail.com (Annie Sullivan)'
|
||||
|
||||
|
||||
import msvcrt
|
||||
|
||||
import os
|
||||
import re
|
||||
import time
|
||||
import win32api
|
||||
import win32file
|
||||
import win32pdhutil
|
||||
import win32pipe
|
||||
|
||||
import paths
|
||||
import config
|
||||
|
||||
if config.OS == "linux":
|
||||
from ffprocess_linux import *
|
||||
elif config.OS == "win32":
|
||||
from ffprocess_win32 import *
|
||||
|
||||
def GetCygwinPath(dos_path):
|
||||
"""Helper function to get the Cygwin path from a dos path.
|
||||
Used to generate a Firefox command line piped through the
|
||||
Cygwin bash shell
|
||||
|
||||
Args:
|
||||
dos_path: String containing the dos path
|
||||
|
||||
Returns:
|
||||
String containing the cygwin path
|
||||
"""
|
||||
|
||||
# Convert the path to a cygwin path. Assumes the path starts with
|
||||
# /cygdrive/driveletter
|
||||
cygwin_path = '/' + dos_path[3:] # Remove 'C:\'
|
||||
cygwin_path = cygwin_path.replace('\\', '/') # Backslashes->slashes
|
||||
cygwin_path = cygwin_path.replace(' ', '\\ ') # Escape spaces
|
||||
cygwin_path = '/cygdrive/' + dos_path[0] + cygwin_path # Add drive letter
|
||||
return cygwin_path
|
||||
|
||||
|
||||
def GenerateFirefoxCommandLine(firefox_path, profile_dir, url):
|
||||
"""Generates the command line for a process to run Firefox, wrapped
|
||||
by cygwin so that we can read the output from dump() statements.
|
||||
|
||||
Args:
|
||||
firefox_path: String containing the path to the firefox exe to use
|
||||
profile_dir: String containing the directory of the profile to run Firefox in
|
||||
url: String containing url to start with.
|
||||
"""
|
||||
|
||||
profile_arg = ''
|
||||
if profile_dir:
|
||||
profile_dir = profile_dir.replace('\\', '\\\\\\')
|
||||
profile_arg = '-profile %s' % profile_dir
|
||||
|
||||
url_arg = ''
|
||||
if url:
|
||||
url_arg = '-url %s' % url
|
||||
|
||||
cmd = '%s "%s %s %s"' % (paths.CYGWIN,
|
||||
GetCygwinPath(firefox_path),
|
||||
profile_arg,
|
||||
url_arg)
|
||||
return cmd
|
||||
|
||||
|
||||
def SyncAndSleep():
|
||||
|
@ -106,84 +59,10 @@ def SyncAndSleep():
|
|||
Otherwise "Firefox is already running.." errors occur
|
||||
"""
|
||||
|
||||
os.spawnl(os.P_WAIT, paths.SYNC)
|
||||
os.spawnl(os.P_WAIT, config.SYNC)
|
||||
time.sleep(3)
|
||||
|
||||
|
||||
def TerminateProcess(pid):
|
||||
"""Helper function to terminate a process, given the pid
|
||||
|
||||
Args:
|
||||
pid: integer process id of the process to terminate.
|
||||
"""
|
||||
|
||||
PROCESS_TERMINATE = 1
|
||||
handle = win32api.OpenProcess(PROCESS_TERMINATE, False, pid)
|
||||
win32api.TerminateProcess(handle, -1)
|
||||
win32api.CloseHandle(handle)
|
||||
|
||||
|
||||
def ProcessesWithNameExist(process_name):
|
||||
"""Returns true if there are any processes running with the
|
||||
given name. Useful to check whether a Firefox process is still running
|
||||
|
||||
Args:
|
||||
process_name: String containing the process name, i.e. "firefox"
|
||||
|
||||
Returns:
|
||||
True if any processes with that name are running, False otherwise.
|
||||
"""
|
||||
|
||||
try:
|
||||
pids = win32pdhutil.FindPerformanceAttributesByName(process_name, counter="ID Process")
|
||||
return len(pids) > 0
|
||||
except:
|
||||
# Might get an exception if there are no instances of the process running.
|
||||
return False
|
||||
|
||||
|
||||
def TerminateAllProcesses(process_name):
|
||||
"""Helper function to terminate all processes with the given process name
|
||||
|
||||
Args:
|
||||
process_name: String containing the process name, i.e. "firefox"
|
||||
"""
|
||||
|
||||
# Get all the process ids of running instances of this process, and terminate them.
|
||||
try:
|
||||
pids = win32pdhutil.FindPerformanceAttributesByName(process_name, counter="ID Process")
|
||||
for pid in pids:
|
||||
TerminateProcess(pid)
|
||||
except:
|
||||
# Might get an exception if there are no instances of the process running.
|
||||
pass
|
||||
|
||||
|
||||
def NonBlockingReadProcessOutput(handle):
|
||||
"""Does a non-blocking read from the output of the process
|
||||
with the given handle.
|
||||
|
||||
Args:
|
||||
handle: The process handle returned from os.popen()
|
||||
|
||||
Returns:
|
||||
A tuple (bytes, output) containing the number of output
|
||||
bytes read, and the actual output.
|
||||
"""
|
||||
|
||||
output = ""
|
||||
|
||||
try:
|
||||
osfhandle = msvcrt.get_osfhandle(handle.fileno())
|
||||
(read, num_avail, num_message) = win32pipe.PeekNamedPipe(osfhandle, 0)
|
||||
if num_avail > 0:
|
||||
(error_code, output) = win32file.ReadFile(osfhandle, num_avail, None)
|
||||
|
||||
return (num_avail, output)
|
||||
except:
|
||||
return (0, output)
|
||||
|
||||
|
||||
def RunProcessAndWaitForOutput(command, process_name, output_regex, timeout):
|
||||
"""Runs the given process and waits for the output that matches the given
|
||||
regular expression. Stops if the process exits early or times out.
|
||||
|
|
|
@ -0,0 +1,167 @@
|
|||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public License Version
|
||||
# 1.1 (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.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
# for the specific language governing rights and limitations under the
|
||||
# License.
|
||||
#
|
||||
# The Original Code is standalone Firefox Windows performance test.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Google Inc.
|
||||
# Portions created by the Initial Developer are Copyright (C) 2006
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
# Annie Sullivan <annie.sullivan@gmail.com> (original author)
|
||||
# Ben Hearsum <bhearsum@wittydomain.com> (OS independence)
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
import subprocess
|
||||
import signal
|
||||
import os
|
||||
from select import select
|
||||
|
||||
|
||||
def GenerateFirefoxCommandLine(firefox_path, profile_dir, url):
|
||||
"""Generates the command line for a process to run Firefox, wrapped
|
||||
by cygwin so that we can read the output from dump() statements.
|
||||
|
||||
Args:
|
||||
firefox_path: String containing the path to the firefox exe to use
|
||||
profile_dir: String containing the directory of the profile to run Firefox in
|
||||
url: String containing url to start with.
|
||||
"""
|
||||
|
||||
profile_arg = ''
|
||||
if profile_dir:
|
||||
profile_arg = '-profile %s' % profile_dir
|
||||
|
||||
url_arg = ''
|
||||
if url:
|
||||
url_arg = '-url %s' % url
|
||||
|
||||
cmd = '%s %s %s' % (firefox_path,
|
||||
profile_arg,
|
||||
url_arg)
|
||||
return cmd
|
||||
|
||||
|
||||
def GetPidsByName(process_name):
|
||||
"""Searches for processes containing a given string.
|
||||
This function is UNIX specific.
|
||||
|
||||
Args:
|
||||
process_name: The string to be searched for
|
||||
|
||||
Returns:
|
||||
A list of PIDs containing the string. An empty list is returned if none are
|
||||
found.
|
||||
"""
|
||||
|
||||
matchingPids = []
|
||||
|
||||
command = ['ps', 'ax']
|
||||
handle = subprocess.Popen(command, stdout=subprocess.PIPE)
|
||||
|
||||
# wait for the process to terminate
|
||||
handle.wait()
|
||||
data = handle.stdout.read()
|
||||
|
||||
# find all matching processes and add them to the list
|
||||
for line in data.splitlines():
|
||||
if line.find(process_name) >= 0:
|
||||
# splits by whitespace, the first one should be the pid
|
||||
pid = int(line.split()[0])
|
||||
matchingPids.append(pid)
|
||||
|
||||
return matchingPids
|
||||
|
||||
|
||||
def ProcessesWithNameExist(process_name):
|
||||
"""Returns true if there are any processes running with the
|
||||
given name. Useful to check whether a Firefox process is still running
|
||||
|
||||
Args:
|
||||
process_name: String containing the process name, i.e. "firefox"
|
||||
|
||||
Returns:
|
||||
True if any processes with that name are running, False otherwise.
|
||||
"""
|
||||
|
||||
pids = GetPidsByName(process_name)
|
||||
return len(pids) > 0
|
||||
|
||||
|
||||
def TerminateProcess(pid):
|
||||
"""Helper function to terminate a process, given the pid
|
||||
|
||||
Args:
|
||||
pid: integer process id of the process to terminate.
|
||||
"""
|
||||
|
||||
os.kill(pid, signal.SIGTERM)
|
||||
|
||||
|
||||
def TerminateAllProcesses(process_name):
|
||||
"""Helper function to terminate all processes with the given process name
|
||||
|
||||
Args:
|
||||
process_name: String containing the process name, i.e. "firefox"
|
||||
"""
|
||||
|
||||
# Get all the process ids of running instances of this process,
|
||||
# and terminate them
|
||||
pids = GetPidsByName(process_name)
|
||||
for pid in pids:
|
||||
TerminateProcess(pid)
|
||||
|
||||
|
||||
def NonBlockingReadProcessOutput(handle):
|
||||
"""Does a non-blocking read from the output of the process
|
||||
with the given handle.
|
||||
|
||||
Args:
|
||||
handle: The process handle returned from os.popen()
|
||||
|
||||
Returns:
|
||||
A tuple (bytes, output) containing the number of output
|
||||
bytes read, and the actual output.
|
||||
"""
|
||||
|
||||
output = ""
|
||||
num_avail = 0
|
||||
|
||||
# check for data
|
||||
# select() does not seem to work well with pipes.
|
||||
# after data is available once it *always* thinks there is data available
|
||||
# readline() will continue to return an empty string however
|
||||
# so we can use this behavior to work around the problem
|
||||
while select([handle], [], [], 0)[0]:
|
||||
line = handle.readline()
|
||||
if line:
|
||||
output += line
|
||||
else:
|
||||
break
|
||||
# this statement is true for encodings that have 1byte/char
|
||||
num_avail = len(output)
|
||||
|
||||
return (num_avail, output)
|
|
@ -0,0 +1,165 @@
|
|||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public License Version
|
||||
# 1.1 (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.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
# for the specific language governing rights and limitations under the
|
||||
# License.
|
||||
#
|
||||
# The Original Code is standalone Firefox Windows performance test.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Google Inc.
|
||||
# Portions created by the Initial Developer are Copyright (C) 2006
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
# Annie Sullivan <annie.sullivan@gmail.com> (original author)
|
||||
# Ben Hearsum <bhearsum@wittydomain.com> (OS independence)
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
import win32api
|
||||
import win32file
|
||||
import win32pdhutil
|
||||
import win32pipe
|
||||
import msvcrt
|
||||
|
||||
import config
|
||||
|
||||
|
||||
def GetCygwinPath(dos_path):
|
||||
"""Helper function to get the Cygwin path from a dos path.
|
||||
Used to generate a Firefox command line piped through the
|
||||
Cygwin bash shell
|
||||
|
||||
Args:
|
||||
dos_path: String containing the dos path
|
||||
|
||||
Returns:
|
||||
String containing the cygwin path
|
||||
"""
|
||||
|
||||
# Convert the path to a cygwin path. Assumes the path starts with
|
||||
# /cygdrive/driveletter
|
||||
cygwin_path = '/' + dos_path[3:] # Remove 'C:\'
|
||||
cygwin_path = cygwin_path.replace('\\', '/') # Backslashes->slashes
|
||||
cygwin_path = cygwin_path.replace(' ', '\\ ') # Escape spaces
|
||||
cygwin_path = '/cygdrive/' + dos_path[0] + cygwin_path # Add drive letter
|
||||
return cygwin_path
|
||||
|
||||
|
||||
def GenerateFirefoxCommandLine(firefox_path, profile_dir, url):
|
||||
"""Generates the command line for a process to run Firefox, wrapped
|
||||
by cygwin so that we can read the output from dump() statements.
|
||||
|
||||
Args:
|
||||
firefox_path: String containing the path to the firefox exe to use
|
||||
profile_dir: String containing the directory of the profile to run Firefox in
|
||||
url: String containing url to start with.
|
||||
"""
|
||||
|
||||
profile_arg = ''
|
||||
if profile_dir:
|
||||
profile_dir = profile_dir.replace('\\', '\\\\\\')
|
||||
profile_arg = '-profile %s' % profile_dir
|
||||
|
||||
url_arg = ''
|
||||
if url:
|
||||
url_arg = '-url %s' % url
|
||||
|
||||
cmd = '%s "%s %s %s"' % (config.CYGWIN,
|
||||
GetCygwinPath(firefox_path),
|
||||
profile_arg,
|
||||
url_arg)
|
||||
return cmd
|
||||
|
||||
|
||||
def TerminateProcess(pid):
|
||||
"""Helper function to terminate a process, given the pid
|
||||
|
||||
Args:
|
||||
pid: integer process id of the process to terminate.
|
||||
"""
|
||||
|
||||
PROCESS_TERMINATE = 1
|
||||
handle = win32api.OpenProcess(PROCESS_TERMINATE, False, pid)
|
||||
win32api.TerminateProcess(handle, -1)
|
||||
win32api.CloseHandle(handle)
|
||||
|
||||
|
||||
def ProcessesWithNameExist(process_name):
|
||||
"""Returns true if there are any processes running with the
|
||||
given name. Useful to check whether a Firefox process is still running
|
||||
|
||||
Args:
|
||||
process_name: String containing the process name, i.e. "firefox"
|
||||
|
||||
Returns:
|
||||
True if any processes with that name are running, False otherwise.
|
||||
"""
|
||||
|
||||
try:
|
||||
pids = win32pdhutil.FindPerformanceAttributesByName(process_name, counter="ID Process")
|
||||
return len(pids) > 0
|
||||
except:
|
||||
# Might get an exception if there are no instances of the process running.
|
||||
return False
|
||||
|
||||
|
||||
def TerminateAllProcesses(process_name):
|
||||
"""Helper function to terminate all processes with the given process name
|
||||
|
||||
Args:
|
||||
process_name: String containing the process name, i.e. "firefox"
|
||||
"""
|
||||
|
||||
# Get all the process ids of running instances of this process, and terminate them.
|
||||
try:
|
||||
pids = win32pdhutil.FindPerformanceAttributesByName(process_name, counter="ID Process")
|
||||
for pid in pids:
|
||||
TerminateProcess(pid)
|
||||
except:
|
||||
# Might get an exception if there are no instances of the process running.
|
||||
pass
|
||||
|
||||
|
||||
def NonBlockingReadProcessOutput(handle):
|
||||
"""Does a non-blocking read from the output of the process
|
||||
with the given handle.
|
||||
|
||||
Args:
|
||||
handle: The process handle returned from os.popen()
|
||||
|
||||
Returns:
|
||||
A tuple (bytes, output) containing the number of output
|
||||
bytes read, and the actual output.
|
||||
"""
|
||||
|
||||
output = ""
|
||||
|
||||
try:
|
||||
osfhandle = msvcrt.get_osfhandle(handle.fileno())
|
||||
(read, num_avail, num_message) = win32pipe.PeekNamedPipe(osfhandle, 0)
|
||||
if num_avail > 0:
|
||||
(error_code, output) = win32file.ReadFile(osfhandle, num_avail, None)
|
||||
|
||||
return (num_avail, output)
|
||||
except:
|
||||
return (0, output)
|
|
@ -1,5 +1,3 @@
|
|||
#!c:/Python24/python.exe
|
||||
#
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
|
@ -55,7 +53,12 @@ import tempfile
|
|||
import time
|
||||
|
||||
import ffprocess
|
||||
import paths
|
||||
import config
|
||||
|
||||
if config.OS is "linux":
|
||||
from ffprofile_linux import *
|
||||
elif config.OS is "win32":
|
||||
from ffprofile_win32 import *
|
||||
|
||||
|
||||
def PrefString(name, value, newline):
|
||||
|
@ -81,20 +84,6 @@ def PrefString(name, value, newline):
|
|||
return 'user_pref("%s", %s);%s' % (name, out_value, newline)
|
||||
|
||||
|
||||
def MakeDirectoryContentsWritable(dirname):
|
||||
"""Recursively makes all the contents of a directory writable.
|
||||
Uses os.chmod(filename, 0777), which works on Windows.
|
||||
|
||||
Args:
|
||||
dirname: Name of the directory to make contents writable.
|
||||
"""
|
||||
|
||||
for (root, dirs, files) in os.walk(dirname):
|
||||
os.chmod(root, 0777)
|
||||
for filename in files:
|
||||
os.chmod(os.path.join(root, filename), 0777)
|
||||
|
||||
|
||||
def CreateTempProfileDir(source_profile, prefs, extensions):
|
||||
"""Creates a temporary profile directory from the source profile directory
|
||||
and adds the given prefs and links to extensions.
|
||||
|
@ -149,7 +138,7 @@ def InitializeNewProfile(firefox_path, profile_dir):
|
|||
"""
|
||||
|
||||
# Run Firefox with the new profile directory
|
||||
cmd = ffprocess.GenerateFirefoxCommandLine(firefox_path, profile_dir, paths.INIT_URL)
|
||||
cmd = ffprocess.GenerateFirefoxCommandLine(firefox_path, profile_dir, config.INIT_URL)
|
||||
handle = os.popen(cmd)
|
||||
|
||||
# Wait for Firefox to shut down and restart with the new profile,
|
||||
|
|
|
@ -0,0 +1,51 @@
|
|||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public License Version
|
||||
# 1.1 (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.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
# for the specific language governing rights and limitations under the
|
||||
# License.
|
||||
#
|
||||
# The Original Code is standalone Firefox Windows performance test.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Google Inc.
|
||||
# Portions created by the Initial Developer are Copyright (C) 2006
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
# Annie Sullivan <annie.sullivan@gmail.com> (original author)
|
||||
# Ben Hearsum <bhearsum@wittydomain.com> (OS independence)
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
import os
|
||||
|
||||
def MakeDirectoryContentsWritable(dirname):
|
||||
"""Recursively makes all the contents of a directory writable.
|
||||
Uses os.chmod(filename, 0755).
|
||||
|
||||
Args:
|
||||
dirname: Name of the directory to make contents writable.
|
||||
"""
|
||||
|
||||
for (root, dirs, files) in os.walk(dirname):
|
||||
os.chmod(root, 0755)
|
||||
for filename in files:
|
||||
os.chmod(os.path.join(root, filename), 0755)
|
|
@ -0,0 +1,51 @@
|
|||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public License Version
|
||||
# 1.1 (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.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
# for the specific language governing rights and limitations under the
|
||||
# License.
|
||||
#
|
||||
# The Original Code is standalone Firefox Windows performance test.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Google Inc.
|
||||
# Portions created by the Initial Developer are Copyright (C) 2006
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
# Annie Sullivan <annie.sullivan@gmail.com> (original author)
|
||||
# Ben Hearsum <bhearsum@wittydomain.com> (OS independence)
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
import os
|
||||
|
||||
def MakeDirectoryContentsWritable(dirname):
|
||||
"""Recursively makes all the contents of a directory writable.
|
||||
Uses os.chmod(filename, 0777), which works on Windows.
|
||||
|
||||
Args:
|
||||
dirname: Name of the directory to make contents writable.
|
||||
"""
|
||||
|
||||
for (root, dirs, files) in os.walk(dirname):
|
||||
os.chmod(root, 0777)
|
||||
for filename in files:
|
||||
os.chmod(os.path.join(root, filename), 0777)
|
166
testing/performance/talos/page_load_test/cycler.html → testing/performance/talos/page_load_test/framecycler.html
Executable file → Normal file
166
testing/performance/talos/page_load_test/cycler.html → testing/performance/talos/page_load_test/framecycler.html
Executable file → Normal file
|
@ -1,54 +1,6 @@
|
|||
<!-- ***** BEGIN LICENSE BLOCK *****
|
||||
- Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
-
|
||||
- The contents of this file are subject to the Mozilla Public License Version
|
||||
- 1.1 (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.mozilla.org/MPL/
|
||||
-
|
||||
- Software distributed under the License is distributed on an "AS IS" basis,
|
||||
- WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
- for the specific language governing rights and limitations under the
|
||||
- License.
|
||||
-
|
||||
- The Original Code is JavaScript local page load test.
|
||||
-
|
||||
- The Initial Developer of the Original Code is
|
||||
- Google Inc.
|
||||
- Portions created by the Initial Developer are Copyright (C) 1999
|
||||
- the Initial Developer. All Rights Reserved.
|
||||
-
|
||||
- Contributor(s):
|
||||
- Darin Fisher <darin@meer.net>
|
||||
- Annie Sullivan <annie.sullivan@gmail.com>
|
||||
-
|
||||
- Alternatively, the contents of this file may be used under the terms of
|
||||
- either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
- the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
- in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
- of those above. If you wish to allow use of your version of this file only
|
||||
- under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
- use your version of this file under the terms of the MPL, indicate your
|
||||
- decision by deleting the provisions above and replace them with the notice
|
||||
- and other provisions required by the LGPL or the GPL. If you do not delete
|
||||
- the provisions above, a recipient may use your version of this file under
|
||||
- the terms of any one of the MPL, the GPL or the LGPL.
|
||||
-
|
||||
- ***** END LICENSE BLOCK ***** -->
|
||||
|
||||
<html>
|
||||
<script language="Javascript" type="text/javascript" src="parray.js"></script>
|
||||
<script>
|
||||
var win = null;
|
||||
var pages = [
|
||||
"bugzilla.mozilla.org/",
|
||||
"lxr.mozilla.org/",
|
||||
"vanilla-page/",
|
||||
];
|
||||
var pages_i18n = [
|
||||
"bugzilla.mozilla.org/",
|
||||
"lxr.mozilla.org/",
|
||||
"vanilla-page/",
|
||||
];
|
||||
|
||||
var NUM_PAGES;
|
||||
var NUM_CYCLES;
|
||||
|
@ -111,6 +63,18 @@
|
|||
sum = sum + ary[i];
|
||||
}
|
||||
|
||||
// median
|
||||
sorted_ary = ary.concat();
|
||||
sorted_ary.sort();
|
||||
// remove longest run
|
||||
sorted_ary.pop();
|
||||
if (sorted_ary.length%2) {
|
||||
r.median = sorted_ary[(sorted_ary.length-1)/2];
|
||||
}else{
|
||||
var n = Math.floor(sorted_ary.length / 2);
|
||||
r.median = (sorted_ary[n] + sorted_ary[n + 1]) / 2;
|
||||
}
|
||||
|
||||
// ignore max value when computing mean and stddev
|
||||
r.mean = (sum - r.max) / (ary.length - 1);
|
||||
|
||||
|
@ -135,17 +99,62 @@
|
|||
return td;
|
||||
}
|
||||
|
||||
function loadReport() {
|
||||
win.addEventListener("load", showReport, true);
|
||||
var baseUri = document.location.href.substr(0, document.location.href.lastIndexOf('/') + 1);
|
||||
win.document.location = baseUri + "report.html";
|
||||
function dumpReport() {
|
||||
var all = new Array();
|
||||
var counter = 0;
|
||||
|
||||
for (var i = 0; i < timeVals.length; ++i) {
|
||||
for (var j = 0; j < timeVals[i].length; ++j) {
|
||||
all[counter] = timeVals[i][j];
|
||||
++counter;
|
||||
}
|
||||
}
|
||||
|
||||
// avg and avg median are cumulative for all the pages
|
||||
var avgs = new Array();
|
||||
var medians = new Array();
|
||||
for (var i = 0; i < timeVals.length; ++i) {
|
||||
avgs[i] = getArrayStats(timeVals[i]).mean;
|
||||
medians[i] = getArrayStats(timeVals[i]).median;
|
||||
}
|
||||
var avg = getArrayStats(avgs).mean;
|
||||
var avgmed = getArrayStats(medians).mean;
|
||||
var rstring = "__start_page_load_report";
|
||||
|
||||
var r = getArrayStats(all);
|
||||
//dump(
|
||||
// "(tinderbox dropping follows)\n"+
|
||||
// "_x_x_mozilla_page_load,"+avgmed+","+r.max+","+r.min+"\n"+
|
||||
// "_x_x_mozilla_page_load_details,avgmedian|"+avgmed+"|average|"+avg.toFixed(2)+"|minimum|"+r.min+"|maximum|"+r.max+"|stddev|"+r.stdd.toFixed(2)+":"
|
||||
//);
|
||||
|
||||
for (var i = 0; i < timeVals.length; ++i) {
|
||||
r = getArrayStats(timeVals[i]);
|
||||
fields = pages[i].split('/');
|
||||
rstring += "page:" + fields[5] + ":" + r.median.toFixed(2) + "\n";
|
||||
//dump(
|
||||
// '|'+
|
||||
// i+';'+
|
||||
// pages[i]+';'+
|
||||
// r.median+';'+
|
||||
// r.mean+';'+
|
||||
// r.min+';'+
|
||||
// r.max
|
||||
//);
|
||||
for (var j = 0; j < timeVals[i].length; ++j) {
|
||||
//dump(
|
||||
// ';'+timeVals[i][j]
|
||||
//);
|
||||
}
|
||||
}
|
||||
rstring += "__end_page_load_report";
|
||||
//alert(rstring);
|
||||
dump(rstring);
|
||||
}
|
||||
|
||||
function showReport() {
|
||||
var doc = win.document;
|
||||
var doc = frames["content"].document;
|
||||
var tbody = doc.getElementById("tbody");
|
||||
var sum_mean = 0;
|
||||
var sum_stdd = 0;
|
||||
for (var i = 0; i < timeVals.length; ++i) {
|
||||
var tr = doc.createElement("TR");
|
||||
|
||||
|
@ -156,9 +165,7 @@
|
|||
appendTableCol(tr, r.max.toFixed(2));
|
||||
appendTableCol(tr, r.mean.toFixed(2));
|
||||
appendTableCol(tr, r.stdd.toFixed(2));
|
||||
sum_mean += r.mean;
|
||||
sum_stdd += r.stdd;
|
||||
//appendTableCol(tr, r.chi2.toFixed(2));
|
||||
appendTableCol(tr, r.median.toFixed(2));
|
||||
|
||||
for (var j = 0; j < timeVals[i].length; ++j) {
|
||||
var tv = timeVals[i][j];
|
||||
|
@ -169,24 +176,23 @@
|
|||
|
||||
tbody.appendChild(tr);
|
||||
}
|
||||
dump("__start_page_load_report\n");
|
||||
dump("mean: " + sum_mean.toFixed(2) + "\n");
|
||||
dump("stdd: " + sum_stdd.toFixed(2) + "\n");
|
||||
dump("__end_page_load_report\n");
|
||||
win.close()
|
||||
window.close()
|
||||
}
|
||||
|
||||
function loadPage(i) {
|
||||
tstart = new Date();
|
||||
win.addEventListener("load", winLoad, true);
|
||||
win.document.location = "base/" + pages[i] + "index.html";
|
||||
frames["content"].document.location = pages[i];
|
||||
}
|
||||
|
||||
function winLoad() {
|
||||
function frameLoad() {
|
||||
if (cycle == NUM_CYCLES) {
|
||||
showReport();
|
||||
dumpReport();
|
||||
window.close();
|
||||
return;
|
||||
}
|
||||
|
||||
var tend = new Date();
|
||||
var href = win.document.location.href;
|
||||
var href = frames["content"].document.location.href;
|
||||
if (href == "about:blank")
|
||||
return;
|
||||
var tdelta = tend - tstart;
|
||||
|
@ -195,35 +201,31 @@
|
|||
|
||||
var text = (cycle + 1) + ', ' + (index + 1) + ', ' + fields[fields.length - 2] + ", " + tdelta;
|
||||
|
||||
var body = document.body;
|
||||
var doc = frames["header"].document;
|
||||
var body = doc.body;
|
||||
while (body.firstChild)
|
||||
body.removeChild(body.firstChild);
|
||||
body.appendChild(document.createTextNode(text));
|
||||
body.appendChild(doc.createTextNode(text));
|
||||
|
||||
if (++index == NUM_PAGES) {
|
||||
index = 0;
|
||||
if (++cycle == NUM_CYCLES) {
|
||||
// display summary
|
||||
try {
|
||||
win.removeEventListener("load", winLoad, true);
|
||||
} catch (e) { alert("displaying summary, caught " + e); }
|
||||
win.document.location = "about:blank";
|
||||
window.setTimeout(loadReport, 500);
|
||||
frames["content"].document.location = "report.html";
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
win.removeEventListener("load", winLoad, true);
|
||||
} catch (e) { alert("Displaying page " + index + " caught " + e); }
|
||||
win.document.location = "about:blank";
|
||||
window.setTimeout("loadPage(" + index + ")", 500);
|
||||
}
|
||||
|
||||
function init() {
|
||||
win = window.open("about:blank", "Page Load Test");
|
||||
window.resizeTo(800, 800);
|
||||
window.setTimeout("loadPage(" + index + ")", 500);
|
||||
}
|
||||
</script>
|
||||
<body onload="init();"></body>
|
||||
<frameset rows="40,*" onload="init()">
|
||||
<frame name="header" src="header.html">
|
||||
<frame name="content" src="" onload="frameLoad()">
|
||||
</frameset>
|
||||
</html>
|
|
@ -0,0 +1,398 @@
|
|||
pages = [
|
||||
"http://localhost/page_load_test/pages/www.yahoo.com/www.yahoo.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.msn.com/www.msn.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.google.com/www.google.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.baidu.com/www.baidu.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.myspace.com/www.myspace.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.qq.com/www.qq.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.live.com/www.live.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.ebay.com/www.ebay.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.wikipedia.org/www.wikipedia.org/index.html",
|
||||
"http://localhost/page_load_test/pages/www.163.com/www.163.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.microsoft.com/www.microsoft.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.blogger.com/www.blogger.com/start.html",
|
||||
"http://localhost/page_load_test/pages/www.yahoo.com.cn/cn.yahoo.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.amazon.com/www.amazon.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.google.co.uk/www.google.co.uk/index.html",
|
||||
"http://localhost/page_load_test/pages/www.taobao.com/www.taobao.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.google.de/www.google.de/index.html",
|
||||
"http://localhost/page_load_test/pages/www.google.co.jp/www.google.co.jp/index.html",
|
||||
"http://localhost/page_load_test/pages/www.wretch.cc/www.wretch.cc/index.html",
|
||||
"http://localhost/page_load_test/pages/www.google.com.br/www.google.com.br/index.html",
|
||||
"http://localhost/page_load_test/pages/www.bbc.co.uk/www.bbc.co.uk/index.html",
|
||||
"http://localhost/page_load_test/pages/www.uol.com.br/www.uol.com.br/index.html",
|
||||
"http://localhost/page_load_test/pages/www.fotolog.net/www.fotolog.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.passport.net/accountservices.passport.net/ppnetworkhome.srf@vv=450&lc=1033.html",
|
||||
"http://localhost/page_load_test/pages/www.craigslist.org/sfbay.craigslist.org/index.html",
|
||||
"http://localhost/page_load_test/pages/www.cnn.com/www.cnn.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.google.com.mx/www.google.com.mx/index.html",
|
||||
"http://localhost/page_load_test/pages/www.imdb.com/www.imdb.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.flickr.com/www.flickr.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.mail.ru/www.mail.ru/index.html",
|
||||
"http://localhost/page_load_test/pages/www.xanga.com/www.xanga.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.aol.com/www.aol.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.google.es/www.google.es/index.html",
|
||||
"http://localhost/page_load_test/pages/www.yandex.ru/www.yandex.ru/index.html",
|
||||
"http://localhost/page_load_test/pages/www.google.co.in/www.google.co.in/index.html",
|
||||
//"http://localhost/page_load_test/pages/www.discuss.com.hk/www.discuss.com.hk/index.html",
|
||||
"http://localhost/page_load_test/pages/www.ebay.co.uk/www.ebay.co.uk/index.html",
|
||||
"http://localhost/page_load_test/pages/www.mixi.jp/mixi.jp/index.html",
|
||||
"http://localhost/page_load_test/pages/www.naver.com/www.naver.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.friendster.com/www.friendster.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.google.fr/www.google.fr/index.html",
|
||||
"http://localhost/page_load_test/pages/www.facebook.com/www.facebook.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.google.pl/www.google.pl/index.html",
|
||||
"http://localhost/page_load_test/pages/www.google.ca/www.google.ca/index.html",
|
||||
"http://localhost/page_load_test/pages/www.google.com.tr/www.google.com.tr/index.html",
|
||||
"http://localhost/page_load_test/pages/www.onet.pl/www.onet.pl/index.html",
|
||||
"http://localhost/page_load_test/pages/www.google.cl/www.google.cl/index.html",
|
||||
"http://localhost/page_load_test/pages/www.pchome.com.tw/www.pchome.com.tw/index.html",
|
||||
"http://localhost/page_load_test/pages/www.terra.com.br/www.terra.com.br/capa/index.html",
|
||||
"http://localhost/page_load_test/pages/www.imageshack.us/www.imageshack.us/index.html",
|
||||
"http://localhost/page_load_test/pages/www.google.com.sa/www.google.com.sa/index.html",
|
||||
"http://localhost/page_load_test/pages/www.rakuten.co.jp/www.rakuten.co.jp/index.html",
|
||||
"http://localhost/page_load_test/pages/www.geocities.com/geocities.yahoo.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.vnet.cn/www.vnet.cn/default.aspx.html",
|
||||
"http://localhost/page_load_test/pages/www.ebay.de/www.ebay.de/index.html",
|
||||
"http://localhost/page_load_test/pages/www.uwants.com/www.uwants.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.rediff.com/www.rediff.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.photobucket.com/photobucket.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.soso.com/www.soso.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.google.com.ar/www.google.com.ar/index.html",
|
||||
"http://localhost/page_load_test/pages/www.adultfriendfinder.com/www.adultfriendfinder.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.apple.com/www.apple.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.livedoor.com/www.livedoor.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.sogou.com/www.sogou.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.google.cn/www.google.cn/index.html",
|
||||
"http://localhost/page_load_test/pages/www.newsgroup.la/www.newsgroup.la/index.html",
|
||||
"http://localhost/page_load_test/pages/www.chinaren.com/www.chinaren.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.sourceforge.net/sourceforge.net/index.php.html",
|
||||
"http://localhost/page_load_test/pages/www.digg.com/www.digg.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.126.com/www.126.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.daum.net/www.daum.net/index.html",
|
||||
"http://localhost/page_load_test/pages/www.xinhuanet.com/www.xinhuanet.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.about.com/www.about.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.nate.com/www.nate.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.rambler.ru/www.rambler.ru/index.html",
|
||||
"http://localhost/page_load_test/pages/www.google.it/www.google.it/index.html",
|
||||
"http://localhost/page_load_test/pages/www.comcast.net/www.comcast.net/index.html",
|
||||
"http://localhost/page_load_test/pages/www.badongo.com/www.badongo.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.free.fr/www.free.fr/index.html",
|
||||
"http://localhost/page_load_test/pages/www.3721.com/www.3721.com/wlsm/index.htm.html",
|
||||
"http://localhost/page_load_test/pages/www.ebay.com.cn/www.ebay.com.cn/index.html",
|
||||
"http://localhost/page_load_test/pages/www.hinet.net/www.hinet.net/index.html",
|
||||
"http://localhost/page_load_test/pages/www.statcounter.com/www.statcounter.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.adobe.com/www.adobe.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.google.com.au/www.google.com.au/index.html",
|
||||
"http://localhost/page_load_test/pages/www.mop.com/www.mop.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.ig.com.br/www.ig.com.br/index.html",
|
||||
"http://localhost/page_load_test/pages/www.starware.com/www.starware.com/2.0.0.0/index.html",
|
||||
"http://localhost/page_load_test/pages/www.google.co.il/www.google.co.il/index.html",
|
||||
//"http://localhost/page_load_test/pages/www.hkjc.com/www.hkjc.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.china.com/www.china.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.dell.com/www.dell.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.51.com/www.51.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.digitalpoint.com/www.digitalpoint.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.flurl.com/www.flurl.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.goo.ne.jp/www.goo.ne.jp/index.html",
|
||||
"http://localhost/page_load_test/pages/www.atnext.com/www.atnext.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.download.com/www.download.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.cnnic.cn/www.cnnic.cn/index.html",
|
||||
"http://localhost/page_load_test/pages/www.cmfu.com/www.cmfu.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.mediaplex.com/www.mediaplex.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.googlesyndication.com/www.googlesyndication.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.mapquest.com/www.mapquest.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.globo.com/www.globo.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.weather.com/www.weather.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.imagevenue.com/www.imagevenue.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.overture.com/www.content.overture.com/d/index.html",
|
||||
"http://localhost/page_load_test/pages/www.theplanet.com/www.theplanet.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.icio.us/",
|
||||
"http://localhost/page_load_test/pages/www.pconline.com.cn/www.pconline.com.cn/index.html",
|
||||
"http://localhost/page_load_test/pages/www.mywebsearch.com/search.mywebsearch.com/mywebsearch/default.jhtml.html",
|
||||
"http://localhost/page_load_test/pages/www.sendspace.com/www.sendspace.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.typepad.com/www.typepad.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.amazon.co.jp/www.amazon.co.jp/index.html",
|
||||
"http://localhost/page_load_test/pages/www.infoseek.co.jp/www.infoseek.co.jp/index.html",
|
||||
"http://localhost/page_load_test/pages/www.21cn.com/www.21cn.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.gamer.com.tw/www.gamer.com.tw/index.html",
|
||||
"http://localhost/page_load_test/pages/www.tianya.cn/www.tianya.cn/index.html",
|
||||
"http://localhost/page_load_test/pages/www.google.com.eg/www.google.com.eg/index.html",
|
||||
"http://localhost/page_load_test/pages/www.deviantart.com/www.deviantart.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.metacafe.com/www.metacafe.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.265.com/www.265.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.google.com.tw/www.google.com.tw/index.html",
|
||||
"http://localhost/page_load_test/pages/www.match.com/www.match.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.php.net/www.php.net/index.html",
|
||||
"http://localhost/page_load_test/pages/www.spiegel.de/www.spiegel.de/index.html",
|
||||
"http://localhost/page_load_test/pages/www.neopets.com/www.neopets.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.phoenixtv.com/www.phoenixtv.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.hp.com/www.hp.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.google.nl/www.google.nl/index.html",
|
||||
"http://localhost/page_load_test/pages/www.nifty.com/www.nifty.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.sina.com.hk/www.sina.com.hk/index.html",
|
||||
"http://localhost/page_load_test/pages/www.sexyono.com/www.sexyono.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.paipai.com/www.paipai.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.amazon.co.uk/www.amazon.co.uk/index.html",
|
||||
"http://localhost/page_load_test/pages/www.chinahr.com/www.chinahr.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.tripod.com/www.tripod.lycos.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.google.co.ve/www.google.co.ve/index.html",
|
||||
"http://localhost/page_load_test/pages/www.yam.com/www.yam.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.google.com.pe/www.google.com.pe/index.html",
|
||||
"http://localhost/page_load_test/pages/www.reference.com/www.reference.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.maktoob.com/www.maktoob.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.wordpress.com/wordpress.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.gmx.net/www.gmx.net/index.html",
|
||||
"http://localhost/page_load_test/pages/www.google.com.co/www.google.com.co/index.html",
|
||||
"http://localhost/page_load_test/pages/www.sexuploader.com/www.megarotic.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.webs-tv.net/www.webs-tv.net/index.html",
|
||||
"http://localhost/page_load_test/pages/www.narod.ru/narod.yandex.ru/index.html",
|
||||
"http://localhost/page_load_test/pages/www.aebn.net/www.aebn.net/index.html",
|
||||
"http://localhost/page_load_test/pages/www.mozilla.com/www.mozilla.com/en-US/index.html",
|
||||
"http://localhost/page_load_test/pages/www.invisionfree.com/www.invisionfree.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.gamespot.com/www.gamespot.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.nastydollars.com/www.nastydollars.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.wefong.com/www.wefong.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.homeway.com.cn/www.hexun.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.rapidshare.com/www.rapidshare.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.vnexpress.net/www.vnexpress.net/Vietnam/Home/index.html",
|
||||
"http://localhost/page_load_test/pages/www.ask.com/www.ask.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.uusee.com/www.uusee.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.linkedin.com/www.linkedin.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.yesky.com/www.yesky.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.information.com/www.information.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.msn.com.br/br.msn.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.51job.com/www.51job.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.people.com.cn/www.people.com.cn/index.html",
|
||||
"http://localhost/page_load_test/pages/www.verycd.com/www.verycd.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.sportsline.com/www.sportsline.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.youthwant.com.tw/www.youthwant.com.tw/index.html",
|
||||
"http://localhost/page_load_test/pages/www.skyblog.com/www.skyblog.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.technorati.com/www.technorati.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.google.co.th/www.google.co.th/index.html",
|
||||
"http://localhost/page_load_test/pages/www.google.com.vn/www.google.com.vn/index.html",
|
||||
"http://localhost/page_load_test/pages/www.hatena.ne.jp/www.hatena.ne.jp/index.html",
|
||||
"http://localhost/page_load_test/pages/www.yourfilehost.com/www.yourfilehost.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.amazon.de/www.amazon.de/index.html",
|
||||
"http://localhost/page_load_test/pages/www.chinamobile.com/www.chinamobile.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.centrum.cz/www.centrum.cz/index.html",
|
||||
"http://localhost/page_load_test/pages/www.flogao.com.br/www.flogao.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.myway.com/www.myway.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.xuite.net/www.xuite.net/index.html",
|
||||
"http://localhost/page_load_test/pages/www.msn.com.cn/cn.msn.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.kooora.com/www.kooora.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.godaddy.com/www.godaddy.com/gdshop/default.asp.html",
|
||||
"http://localhost/page_load_test/pages/www.google.com.sg/www.google.com.sg/index.html",
|
||||
"http://localhost/page_load_test/pages/www.4399.com/www.4399.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.earthlink.net/www.earthlink.net/index.html",
|
||||
"http://localhost/page_load_test/pages/www.torrentspy.com/www.torrentspy.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.pornotube.com/www.pornotube.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.aweber.com/www.aweber.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.slashdot.org/slashdot.org/index.html",
|
||||
"http://localhost/page_load_test/pages/www.2ch.net/www.2ch.net/index.html",
|
||||
"http://localhost/page_load_test/pages/www.ev1servers.net/www.ev1servers.net/index.html",
|
||||
"http://localhost/page_load_test/pages/www.webshots.com/www.webshots.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.webmasterworld.com/www.webmasterworld.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.google.se/www.google.se/index.html",
|
||||
"http://localhost/page_load_test/pages/www.biglobe.ne.jp/www.biglobe.ne.jp/index.html",
|
||||
"http://localhost/page_load_test/pages/www.domaintools.com/www.domaintools.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.mininova.org/www.mininova.org/index.html",
|
||||
"http://localhost/page_load_test/pages/www.elmundo.es/www.elmundo.es/index.html",
|
||||
"http://localhost/page_load_test/pages/www.google.ro/www.google.ro/index.html",
|
||||
"http://localhost/page_load_test/pages/www.google.ae/www.google.ae/index.html",
|
||||
"http://localhost/page_load_test/pages/www.clubbox.co.kr/www.clubbox.co.kr/index.html",
|
||||
"http://localhost/page_load_test/pages/www.w3.org/www.w3.org/index.html",
|
||||
"http://localhost/page_load_test/pages/www.qihoo.com/www.qihoo.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.google.ru/www.google.ru/index.html",
|
||||
"http://localhost/page_load_test/pages/www.miniclip.com/www.miniclip.com/games/en/index.html",
|
||||
"http://localhost/page_load_test/pages/www.milliyet.com.tr/www.milliyet.com.tr/2006/12/05/index.html",
|
||||
"http://localhost/page_load_test/pages/www.google.com.my/www.google.com.my/index.html",
|
||||
"http://localhost/page_load_test/pages/www.bebo.com/www.bebo.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.dmm.co.jp/www.dmm.co.jp/index.html",
|
||||
"http://localhost/page_load_test/pages/www.orange.fr/www.orange.fr/index.html",
|
||||
"http://localhost/page_load_test/pages/www.bta.net.cn/www.bta.net.cn/index.html",
|
||||
"http://localhost/page_load_test/pages/www.istockphoto.com/www.istockphoto.com/index.php.html",
|
||||
"http://localhost/page_load_test/pages/www.qianlong.com/www.qianlong.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.ebay.com.au/www.ebay.com.au/index.html",
|
||||
"http://localhost/page_load_test/pages/www.chinaz.com/www.chinaz.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.adbrite.com/www.adbrite.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.sitepoint.com/www.sitepoint.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.zhongsou.com/www.zhongsou.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.ups.com/www.ups.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.wwe.com/www.wwe.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.netflix.com/www.netflix.com/Register.html",
|
||||
"http://localhost/page_load_test/pages/www.target.com/www.target.com/gp/homepage.html",
|
||||
"http://localhost/page_load_test/pages/www.it.com.cn/www.it.com.cn/index.html",
|
||||
"http://localhost/page_load_test/pages/www.washingtonpost.com/www.washingtonpost.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.usps.com/www.usps.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.iask.com/www.iask.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.google.com.hk/www.google.com.hk/index.html",
|
||||
"http://localhost/page_load_test/pages/www.ibm.com/www.ibm.com/us/index.html",
|
||||
"http://localhost/page_load_test/pages/www.google.gr/www.google.gr/index.html",
|
||||
"http://localhost/page_load_test/pages/www.6park.com/www.6park.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.sex141.com/www.sex141.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.excite.co.jp/www.excite.co.jp/index.html",
|
||||
"http://localhost/page_load_test/pages/www.sakura.ne.jp/www.sakura.ne.jp/index.html",
|
||||
"http://localhost/page_load_test/pages/www.icq.com/www.icq.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.bangbros1.com/www.bangbros1.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.answers.com/www.answers.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.foxsports.com/msn.foxsports.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.clickbank.com/www.clickbank.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.skype.com/www.skype.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.mofile.com/tv.mofile.com/cn/index/main.do.html",
|
||||
"http://localhost/page_load_test/pages/www.mlb.com/mlb.mlb.com/NASApp/mlb/index.jsp.html",
|
||||
"http://localhost/page_load_test/pages/www.89.com/www.89.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.nba.com/www.nba.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.pornaccess.com/www.pornaccess.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.imagefap.com/www.imagefap.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.pcpop.com/www.pcpop.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.hurriyet.com.tr/www.hurriyet.com.tr/anasayfa/index.html",
|
||||
"http://localhost/page_load_test/pages/www.t-online.de/www.t-online.de/index.html",
|
||||
"http://localhost/page_load_test/pages/www.google.pt/www.google.pt/index.html",
|
||||
"http://localhost/page_load_test/pages/www.no-ip.com/www.no-ip.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.ocn.ne.jp/www.ocn.ne.jp/index.html",
|
||||
"http://localhost/page_load_test/pages/www.it168.com/www.it168.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.seesaa.net/tag.seesaa.jp/index.html",
|
||||
"http://localhost/page_load_test/pages/www.nih.gov/www.nih.gov/index.html",
|
||||
"http://localhost/page_load_test/pages/www.raaga.com/www.raaga.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.lide.cz/www.lide.cz/index.html",
|
||||
"http://localhost/page_load_test/pages/www.indiatimes.com/in.indiatimes.com/usdefault.cms.html",
|
||||
"http://localhost/page_load_test/pages/www.doubleclick.com/www.doubleclick.com/us/index.html",
|
||||
"http://localhost/page_load_test/pages/www.reuters.com/today.reuters.com/news/home.aspx.html",
|
||||
"http://localhost/page_load_test/pages/www.dantri.com.vn/www19.dantri.com.vn/news/index.html",
|
||||
"http://localhost/page_load_test/pages/www.fotka.pl/www.fotka.pl/index.html",
|
||||
"http://localhost/page_load_test/pages/www.miarroba.com/miarroba.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.readnovel.com/www.readnovel.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.hawaaworld.com/www.hawaaworld.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.expedia.com/www.expedia.com/Default.asp@CCheck=1&.html",
|
||||
"http://localhost/page_load_test/pages/www.msn.co.uk/uk.msn.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.104.com.tw/www.104.com.tw/index.html",
|
||||
"http://localhost/page_load_test/pages/www.eastmoney.com/www.eastmoney.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.fares.net/www.fares.net/index.html",
|
||||
"http://localhost/page_load_test/pages/www.zhaopin.com/www.zhaopin.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.clarin.com/www.clarin.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.dreamwiz.com/www.dreamwiz.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.ameblo.jp/www.ameba.jp/index.html",
|
||||
"http://localhost/page_load_test/pages/www.dailymotion.com/www.dailymotion.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.ikea.com/www.ikea.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.constantcontact.com/www.constantcontact.com/index.jsp.html",
|
||||
"http://localhost/page_load_test/pages/www.mainichi-msn.co.jp/www.mainichi-msn.co.jp/index.html",
|
||||
"http://localhost/page_load_test/pages/www.xnxx.com/www.xnxx.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.dnsstuff.com/www.dnsstuff.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.tigerdirect.com/www.tigerdirect.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.nikkei.co.jp/www.nikkei.co.jp/index.html",
|
||||
"http://localhost/page_load_test/pages/www.liveinternet.ru/www.liveinternet.ru/index.html",
|
||||
"http://localhost/page_load_test/pages/www.forbes.com/www.forbes.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.linksynergy.com/",
|
||||
"http://localhost/page_load_test/pages/www.yousendit.com/www.yousendit.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.6rb.com/www.6rb.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.nfl.com/www.nfl.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.bestbuy.com/www.bestbuy.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.iwiw.hu/www.iwiw.hu/pages/user/login.jsp.html",
|
||||
"http://localhost/page_load_test/pages/www.aim.com/www.aim.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.zaobao.com/www.zaobao.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.gamefaqs.com/www.gamefaqs.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.whenu.com/www.whenu.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.pogo.com/www.pogo.com/home/home.do@sls=2&site=pogo.html",
|
||||
"http://localhost/page_load_test/pages/www.online.sh.cn/www.online.sh.cn/index.html",
|
||||
"http://localhost/page_load_test/pages/www.sanook.com/www.sanook.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.blog.cz/blog.cz/index.html",
|
||||
"http://localhost/page_load_test/pages/www.feedburner.com/www.feedburner.com/fb/a/home.html",
|
||||
"http://localhost/page_load_test/pages/www.msn.ca/sympatico.msn.ca/index.html",
|
||||
"http://localhost/page_load_test/pages/www.libero.it/www.libero.it/index.html",
|
||||
"http://localhost/page_load_test/pages/72.14.235.104/72.14.235.104/index.html",
|
||||
"http://localhost/page_load_test/pages/www.excite.com/www.excite.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.leo.org/www.leo.org/index.html",
|
||||
"http://localhost/page_load_test/pages/www.ebay.fr/www.ebay.fr/index.html",
|
||||
"http://localhost/page_load_test/pages/www.ctrip.com/www.ctrip.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.last.fm/www.last.fm/index.html",
|
||||
"http://localhost/page_load_test/pages/www.gamebase.com.tw/www.gamebase.com.tw/index.html",
|
||||
"http://localhost/page_load_test/pages/www.ebay.ca/www.ebay.ca/index.html",
|
||||
"http://localhost/page_load_test/pages/www.yimg.com/",
|
||||
"http://localhost/page_load_test/pages/www.vietnamnet.vn/www.vietnamnet.vn/index.html",
|
||||
"http://localhost/page_load_test/pages/www.uploading.com/www.uploading.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.sapo.pt/www.sapo.pt/index.html",
|
||||
"http://localhost/page_load_test/pages/www.usatoday.com/www.usatoday.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.pplive.com/www.pplive.com/zh-cn/index.html",
|
||||
"http://localhost/page_load_test/pages/www.multiply.com/multiply.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.jobsdb.com/www.jobsdb.com/default.htm@58518.html",
|
||||
"http://localhost/page_load_test/pages/www.4399.net/www.4399.net/index.html",
|
||||
"http://localhost/page_load_test/pages/www.ynet.com/www.ynet.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.google.ch/www.google.ch/index.html",
|
||||
"http://localhost/page_load_test/pages/www.mac.com/www.apple.com/dotmac/index.html",
|
||||
"http://localhost/page_load_test/pages/www.joomla.org/www.joomla.org/index.html",
|
||||
"http://localhost/page_load_test/pages/www.dyndns.org/www.dyndns.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.voyeurweb.com/www.voyeurweb.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.wuhan.net.cn/www.wuhan.net.cn/index.html",
|
||||
"http://localhost/page_load_test/pages/www.piczo.com/www.piczo.com/index.html@cr=4&rfm=y.html",
|
||||
"http://localhost/page_load_test/pages/www.google.be/www.google.be/index.html",
|
||||
"http://localhost/page_load_test/pages/www.panet.co.il/www.panet.co.il/index.html",
|
||||
"http://localhost/page_load_test/pages/www.google.co.ma/www.google.co.ma/index.html",
|
||||
"http://localhost/page_load_test/pages/72.14.221.104/72.14.221.104/index.html",
|
||||
"http://localhost/page_load_test/pages/www.msn.com.tw/tw.msn.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.wangyou.com/www.wangyou.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.6arab.com/www.6arab.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.wordpress.org/wordpress.org/index.html",
|
||||
"http://localhost/page_load_test/pages/www.onlinedown.net/www.onlinedown.net/index.html",
|
||||
"http://localhost/page_load_test/pages/www.drudgereport.com/www.drudgereport.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.joyo.com/www.joyo.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.skycn.com/www.skycn.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.zedo.com/www.zedo.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.i-part.com.cn/www.i-part.com.cn/index.html",
|
||||
"http://localhost/page_load_test/pages/www.w3schools.com/www.w3schools.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.payserve.com/www.payserve.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.macromedia.com/www.adobe.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.usercash.com/www.usercash.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.51.la/www.51.la/index.html",
|
||||
"http://localhost/page_load_test/pages/www.chinacars.com/www.chinacars.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.cj.com/www.cj.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.isohunt.com/www.isohunt.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.engadget.com/www.engadget.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.nikkansports.com/www.nikkansports.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.fedex.com/www.fedex.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.mobile.de/www.mobile.de/index.html",
|
||||
"http://localhost/page_load_test/pages/www.cams.com/www.cams.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.kinghost.com/www.kinghost.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.made-in-china.com/www.made-in-china.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.24h.com.vn/www14.24h.com.vn/index.php.html",
|
||||
"http://localhost/page_load_test/pages/www.sxc.hu/www.sxc.hu/index.html",
|
||||
"http://localhost/page_load_test/pages/www.tv.com/www.tv.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.nextag.com/www.nextag.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.jrj.com.cn/www.jrj.com.cn/index.html",
|
||||
"http://localhost/page_load_test/pages/www.msn.es/es.msn.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.terra.com.ar/www.terra.com.ar/index.html",
|
||||
"http://localhost/page_load_test/pages/www.wikimedia.org/www.wikimedia.org/index.html",
|
||||
"http://localhost/page_load_test/pages/www.google.lt/www.google.lt/index.html",
|
||||
"http://localhost/page_load_test/pages/www.aftonbladet.se/www.aftonbladet.se/index.html",
|
||||
"http://localhost/page_load_test/pages/72.14.209.104/72.14.209.104/index.html",
|
||||
"http://localhost/page_load_test/pages/www.xrea.com/www.xrea.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.mysql.com/www.mysql.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.overstock.com/www.overstock.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.sitemeter.com/www.sitemeter.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.yok.com/www.yok.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.met-art.com/www.met-art.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.sun.com/www.sun.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.tripadvisor.com/www.tripadvisor.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.gc.ca/www.gc.ca/index.html",
|
||||
"http://localhost/page_load_test/pages/www.realtor.com/www.realtor.com/Default.asp@poe=realtor.html",
|
||||
"http://localhost/page_load_test/pages/www.spoluzaci.cz/www.spoluzaci.cz/index.html",
|
||||
"http://localhost/page_load_test/pages/www.netscape.com/www.netscape.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.asahi.com/www.asahi.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.fanfiction.net/www.fanfiction.net/index.html",
|
||||
"http://localhost/page_load_test/pages/www.msn.com.hk/www.msn.com.hk/Default.asp.html",
|
||||
"http://localhost/page_load_test/pages/www.travelocity.com/www.travelocity.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.ninemsn.com.au/ninemsn.com.au/index.html",
|
||||
"http://localhost/page_load_test/pages/www.stumbleupon.com/www.stumbleupon.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.cafepress.com/www.cafepress.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.livejasmin.com/www.2.livejasmin.com/index.php.html",
|
||||
"http://localhost/page_load_test/pages/www.ezinearticles.com/www.ezinearticles.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.pricegrabber.com/www.pricegrabber.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.sina.com/www.sina.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.lycos.com/www.lycos.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.apache.org/www.apache.org/index.html",
|
||||
"http://localhost/page_load_test/pages/www.ringo.com/www.ringo.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.videosz.com/www.videosz.com/index.html",
|
||||
"http://localhost/page_load_test/pages/www.fotop.net/www.fotop.net/index.html",
|
||||
"http://localhost/page_load_test/pages/www.fatwallet.com/www.fatwallet.com/index.html",
|
||||
];
|
||||
pages_i18n = pages;
|
|
@ -0,0 +1,48 @@
|
|||
#http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/146306
|
||||
import httplib, mimetypes
|
||||
|
||||
def post_multipart(host, selector, fields, files):
|
||||
"""
|
||||
Post fields and files to an http host as multipart/form-data.
|
||||
fields is a sequence of (name, value) elements for regular form fields.
|
||||
files is a sequence of (name, filename, value) elements for data to be uploaded as files
|
||||
Return the server's response page.
|
||||
"""
|
||||
content_type, body = encode_multipart_formdata(fields, files)
|
||||
h = httplib.HTTP(host)
|
||||
h.putrequest('POST', selector)
|
||||
h.putheader('content-type', content_type)
|
||||
h.putheader('content-length', str(len(body)))
|
||||
h.endheaders()
|
||||
h.send(body)
|
||||
errcode, errmsg, headers = h.getreply()
|
||||
return h.file.read()
|
||||
|
||||
def encode_multipart_formdata(fields, files):
|
||||
"""
|
||||
fields is a sequence of (name, value) elements for regular form fields.
|
||||
files is a sequence of (name, filename, value) elements for data to be uploaded as files
|
||||
Return (content_type, body) ready for httplib.HTTP instance
|
||||
"""
|
||||
BOUNDARY = '----------ThIs_Is_tHe_bouNdaRY_$'
|
||||
CRLF = '\r\n'
|
||||
L = []
|
||||
for (key, value) in fields:
|
||||
L.append('--' + BOUNDARY)
|
||||
L.append('Content-Disposition: form-data; name="%s"' % key)
|
||||
L.append('')
|
||||
L.append(value)
|
||||
for (key, filename, value) in files:
|
||||
L.append('--' + BOUNDARY)
|
||||
L.append('Content-Disposition: form-data; name="%s"; filename="%s"' % (key, filename))
|
||||
L.append('Content-Type: %s' % get_content_type(filename))
|
||||
L.append('')
|
||||
L.append(value)
|
||||
L.append('--' + BOUNDARY + '--')
|
||||
L.append('')
|
||||
body = CRLF.join(L)
|
||||
content_type = 'multipart/form-data; boundary=%s' % BOUNDARY
|
||||
return content_type, body
|
||||
|
||||
def get_content_type(filename):
|
||||
return mimetypes.guess_type(filename)[0] or 'application/octet-stream'
|
|
@ -1,234 +0,0 @@
|
|||
#!c:/Python24/python.exe
|
||||
#
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public License Version
|
||||
# 1.1 (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.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
# for the specific language governing rights and limitations under the
|
||||
# License.
|
||||
#
|
||||
# The Original Code is standalone Firefox Windows performance test.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Google Inc.
|
||||
# Portions created by the Initial Developer are Copyright (C) 2006
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
# Annie Sullivan <annie.sullivan@gmail.com> (original author)
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
"""Writes a report with the results of the Ts (startup) and Tp (page load) tests.
|
||||
|
||||
The report contains the mean startup time for each profile and the standard
|
||||
deviation, the sum of page load times and the standard deviation, and a graph
|
||||
of each performance counter measured during the page load test.
|
||||
"""
|
||||
|
||||
__author__ = 'annie.sullivan@gmail.com (Annie Sullivan)'
|
||||
|
||||
|
||||
import csv
|
||||
import math
|
||||
import matplotlib.mlab
|
||||
import os
|
||||
import pylab
|
||||
import re
|
||||
import time
|
||||
|
||||
import paths
|
||||
|
||||
|
||||
def MakeArray(start, len, step):
|
||||
"""Helper function to create an array for an axis to plot counter data.
|
||||
|
||||
Args:
|
||||
start: The first value in the array
|
||||
len: The length of the array
|
||||
step: The difference between values in the array
|
||||
|
||||
Returns:
|
||||
An array starting at start, with len values each step apart.
|
||||
"""
|
||||
|
||||
count = start
|
||||
end = start + (len * step)
|
||||
array = []
|
||||
while count < end:
|
||||
array.append(count)
|
||||
count += step
|
||||
|
||||
return array
|
||||
|
||||
|
||||
def GetPlottableData(counter_name, data):
|
||||
"""Some counters should be displayed as a moving average, or
|
||||
may need other adjustment to be plotted. This function
|
||||
makes adjustments to the data based on counter name.
|
||||
|
||||
Args:
|
||||
counter_name: The name of the counter, i.e 'Working Set'
|
||||
data: The original data collected from the counter
|
||||
|
||||
Returns:
|
||||
data array adjusted based on counter name.
|
||||
"""
|
||||
|
||||
if counter_name == '% Processor Time':
|
||||
# Use a moving average for % processor time
|
||||
return matplotlib.mlab.movavg(data, 5)
|
||||
if counter_name == 'Working Set' or counter_name == 'Private Bytes':
|
||||
# Change the scale from bytes to megabytes for working set
|
||||
return [float(x) / 1000000 for x in data]
|
||||
|
||||
# No change for other counters
|
||||
return data
|
||||
|
||||
|
||||
def GenerateReport(title, filename, configurations, ts_times, tp_times, tp_counters, tp_resolution):
|
||||
""" Generates a report file in html using the given data
|
||||
|
||||
Args:
|
||||
title: Title of the report
|
||||
filename: Filename of the report, before the timestamp
|
||||
configurations: Array of strings, containing the name of
|
||||
each configuration tested.
|
||||
ts_times: Array of arrays of ts startup times for each configuration.
|
||||
tp_times: Array of page load times for each configuration tested.
|
||||
tp_counters: Array of counter data for page load configurations
|
||||
|
||||
Returns:
|
||||
filename of html report.
|
||||
"""
|
||||
|
||||
# Make sure the reports/ and reports/graphs/ directories exist
|
||||
graphs_subdir = os.path.join(paths.REPORTS_DIR, 'graphs')
|
||||
if not os.path.exists(graphs_subdir):
|
||||
os.makedirs(graphs_subdir) # Will create parent directories
|
||||
|
||||
# Create html report file
|
||||
localtime = time.localtime()
|
||||
timestamp = int(time.mktime(localtime))
|
||||
report_filename = os.path.join(paths.REPORTS_DIR, filename + "_" + str(timestamp) + ".html")
|
||||
report = open(report_filename, 'w')
|
||||
report.write('<html><head><title>Performance Report for %s, %s</title></head>\n' %
|
||||
(title, time.strftime('%m-%d-%y')))
|
||||
report.write('<body>\n')
|
||||
report.write('<h1>%s, %s</h1>' % (title, time.strftime('%m-%d-%y')))
|
||||
|
||||
# Write out TS data
|
||||
report.write('<p><h2>Startup Test (Ts) Results</h2>\n')
|
||||
report.write('<table border="1" cellpadding="5" cellspacing="0">\n')
|
||||
report.write('<tr>')
|
||||
report.write('<th>Profile Tested</th>')
|
||||
report.write('<th>Mean</th>')
|
||||
report.write('<th>Standard Deviation</th></tr>\n')
|
||||
ts_csv_filename = os.path.join(paths.REPORTS_DIR, filename + "_" + str(timestamp) + '_ts.csv')
|
||||
ts_csv_file = open(ts_csv_filename, 'wb')
|
||||
ts_csv = csv.writer(ts_csv_file)
|
||||
for i in range (0, len(configurations)):
|
||||
# Calculate mean
|
||||
mean = 0
|
||||
for ts_time in ts_times[i]:
|
||||
mean += float(ts_time)
|
||||
mean = mean / len(ts_times[i])
|
||||
|
||||
# Calculate standard deviation
|
||||
stdd = 0
|
||||
for ts_time in ts_times[i]:
|
||||
stdd += (float(ts_time) - mean) * (float(ts_time) - mean)
|
||||
stdd = stdd / len(ts_times[i])
|
||||
stdd = math.sqrt(stdd)
|
||||
|
||||
report.write('<tr><td>%s</td><td>%f</td><td>%f</td></tr>\n' %
|
||||
(configurations[i], mean, stdd))
|
||||
ts_csv.writerow([configurations[i], mean, stdd])
|
||||
report.write('</table></p>\n')
|
||||
ts_csv_file.close()
|
||||
|
||||
# Write out TP data
|
||||
report.write('<p><h2>Page Load Test (Tp) Results</h2>\n')
|
||||
report.write('<table border="1" cellpadding="5" cellspacing="0">\n')
|
||||
report.write('<tr>')
|
||||
report.write('<th>Profile Tested</th>')
|
||||
report.write('<th>Sum of mean times</th>')
|
||||
report.write('<th>Sum of Standard Deviations</th></tr>\n')
|
||||
tp_csv_filename = os.path.join(paths.REPORTS_DIR, filename + "_" + str(timestamp) + '_tp.csv')
|
||||
tp_csv_file = open(tp_csv_filename, 'wb')
|
||||
tp_csv = csv.writer(tp_csv_file)
|
||||
|
||||
# Write out TP data
|
||||
for i in range (0, len(tp_times)):
|
||||
(tmp1, mean, tmp2, stdd) = tp_times[i].split()
|
||||
report.write('<tr><td>%s</td><td>%f</td><td>%f</td></tr>\n' %
|
||||
(configurations[i], float(mean), float(stdd)))
|
||||
tp_csv.writerow([configurations[i], float(mean), float(stdd)])
|
||||
report.write('</table></p>\n')
|
||||
tp_csv_file.close()
|
||||
|
||||
# Write out counter data from TP tests
|
||||
report.write('<p><h2>Performance Data</h2></p>\n')
|
||||
|
||||
# Write out graph of performance for each counter
|
||||
colors = ['r-', 'g-', 'b-', 'y-', 'c-', 'm-']
|
||||
nonchar = re.compile('[\W]*')
|
||||
if len(tp_counters) > 0:
|
||||
counter_names = []
|
||||
for counter in tp_counters[0]:
|
||||
counter_names.append(counter)
|
||||
for counter_name in counter_names:
|
||||
|
||||
# Create a new figure for this counter
|
||||
pylab.clf()
|
||||
|
||||
# Label the figure, and the x/y axes
|
||||
pylab.title(counter_name)
|
||||
pylab.ylabel(counter_name)
|
||||
pylab.xlabel("Time")
|
||||
|
||||
# Draw a line for each counter in a different color on the graph
|
||||
current_color = 0
|
||||
line_handles = [] # Save the handle of each line for the legend
|
||||
for count_data in tp_counters:
|
||||
data = GetPlottableData(counter_name, count_data[counter_name])
|
||||
times = MakeArray(0, len(data), tp_resolution)
|
||||
handle = pylab.plot(times, data, colors[current_color])
|
||||
line_handles.append(handle)
|
||||
current_color = (current_color + 1) % len(colors)
|
||||
|
||||
# Draw a legend in the upper right corner
|
||||
legend = pylab.legend(line_handles, configurations, 'upper right')
|
||||
ltext = legend.get_texts()
|
||||
pylab.setp(ltext, fontsize='small') # legend text is too large by default
|
||||
|
||||
# Save the graph and link to it from html.
|
||||
image_name = os.path.join(graphs_subdir,
|
||||
filename + "_" + str(timestamp) + nonchar.sub('', counter_name) + '.png')
|
||||
pylab.savefig(image_name)
|
||||
img_src = image_name[len(paths.REPORTS_DIR) : ]
|
||||
if img_src.startswith('\\'):
|
||||
img_src = img_src[1 : ]
|
||||
img_src = img_src.replace('\\', '/')
|
||||
report.write('<p><img src="%s" alt="%s"></p>\n' % (img_src, counter_name))
|
||||
|
||||
report.write('</body></html>\n')
|
||||
|
||||
return report_filename
|
|
@ -1,5 +1,3 @@
|
|||
#!c:/Python24/python.exe
|
||||
#
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
|
@ -21,6 +19,7 @@
|
|||
#
|
||||
# Contributor(s):
|
||||
# Annie Sullivan <annie.sullivan@gmail.com> (original author)
|
||||
# Alice Nodelman <anodelman@mozilla.com>
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
|
@ -52,23 +51,38 @@ __author__ = 'annie.sullivan@gmail.com (Annie Sullivan)'
|
|||
import time
|
||||
import syck
|
||||
import sys
|
||||
import urllib
|
||||
import tempfile
|
||||
import os
|
||||
import string
|
||||
import socket
|
||||
socket.setdefaulttimeout(480)
|
||||
|
||||
import report
|
||||
import paths
|
||||
import config
|
||||
import tp
|
||||
import ts
|
||||
import post_file
|
||||
|
||||
|
||||
# Number of times to run startup test (Ts)
|
||||
TS_NUM_RUNS = 5
|
||||
|
||||
# Number of times the page load test (Tp) loads each page in the test.
|
||||
TP_NUM_CYCLES = 7
|
||||
|
||||
# Resolution of counter sample data for page load test (Tp), in seconds
|
||||
# (For example, if TP_RESOLUTION=1, sample counters every 1 second
|
||||
TP_RESOLUTION = 1
|
||||
def shortNames(name):
|
||||
if name == "tp_loadtime":
|
||||
return "tp_l"
|
||||
elif name == "tp_Percent Processor Time":
|
||||
return "tp_%cpu"
|
||||
elif name == "tp_Working Set":
|
||||
return "tp_memset"
|
||||
elif name == "tp_Private Bytes":
|
||||
return "tp_pbytes"
|
||||
else:
|
||||
return name
|
||||
|
||||
def process_Request(post):
|
||||
str = ""
|
||||
lines = post.split('\n')
|
||||
for line in lines:
|
||||
if line.find("RETURN:") > -1:
|
||||
str += line.rsplit(":")[3] + ":" + shortNames(line.rsplit(":")[1]) + ":" + line.rsplit(":")[2] + '\n'
|
||||
return str
|
||||
|
||||
def test_file(filename):
|
||||
"""Runs the Ts and Tp tests on the given config file and generates a report.
|
||||
|
@ -81,45 +95,134 @@ def test_file(filename):
|
|||
test_names = []
|
||||
title = ''
|
||||
filename_prefix = ''
|
||||
testdate = ''
|
||||
|
||||
# Read in the profile info from the YAML config file
|
||||
config_file = open(filename, 'r')
|
||||
# some versions of syck take a file, while others take a string
|
||||
try:
|
||||
yaml = syck.load(config_file)
|
||||
except:
|
||||
yaml = syck.load("".join(config_file.readlines()))
|
||||
config_file.close()
|
||||
for item in yaml:
|
||||
if item == 'title':
|
||||
title = yaml[item]
|
||||
elif item == 'filename':
|
||||
filename_prefix = yaml[item]
|
||||
elif item == 'testdate':
|
||||
testdate = yaml[item]
|
||||
else:
|
||||
new_config = [yaml[item]['preferences'],
|
||||
yaml[item]['extensions'],
|
||||
yaml[item]['firefox']]
|
||||
yaml[item]['firefox'],
|
||||
yaml[item]['branch'],
|
||||
yaml[item]['branchid'],
|
||||
yaml[item]['profile_path']]
|
||||
test_configs.append(new_config)
|
||||
test_names.append(item)
|
||||
config_file.close()
|
||||
|
||||
print test_configs
|
||||
sys.stdout.flush()
|
||||
if (testdate != ''):
|
||||
date = int(time.mktime(time.strptime(testdate, '%a, %d %b %Y %H:%M:%S GMT')))
|
||||
else:
|
||||
date = int(time.time()) #TODO get this into own file
|
||||
print "using testdate: %d" % date
|
||||
print "actual date: %d" % int(time.time())
|
||||
|
||||
|
||||
# Run startup time test
|
||||
ts_times = ts.RunStartupTests(paths.BASE_PROFILE_DIR,
|
||||
test_configs,
|
||||
TS_NUM_RUNS)
|
||||
ts_times = ts.RunStartupTests(test_configs,
|
||||
config.TS_NUM_RUNS)
|
||||
|
||||
# Run page load test. For possible values of counters argument, see
|
||||
# http://technet2.microsoft.com/WindowsServer/en/Library/86b5d116-6fb3-427b-af8c-9077162125fe1033.mspx?mfr=true
|
||||
(tp_times, tp_counters) = tp.RunPltTests(paths.BASE_PROFILE_DIR,
|
||||
test_configs,
|
||||
TP_NUM_CYCLES,
|
||||
['Private Bytes', 'Working Set', '% Processor Time'],
|
||||
TP_RESOLUTION)
|
||||
print "finished ts"
|
||||
sys.stdout.flush()
|
||||
|
||||
# Generate a report of the results.
|
||||
report.GenerateReport(title,
|
||||
filename_prefix,
|
||||
test_names,
|
||||
ts_times,
|
||||
tp_times,
|
||||
tp_counters,
|
||||
TP_RESOLUTION)
|
||||
(r_strings, tp_times, tp_counters) = tp.RunPltTests(test_configs,
|
||||
config.TP_NUM_CYCLES,
|
||||
config.COUNTERS,
|
||||
config.TP_RESOLUTION)
|
||||
|
||||
print "finished tp"
|
||||
sys.stdout.flush()
|
||||
|
||||
|
||||
#TODO: place this in its own file
|
||||
#send results to the graph server
|
||||
# each line of the string is of the format page:page_name:page_loadtime\n
|
||||
tbox = title
|
||||
url_format = "http://%s/%s"
|
||||
link_format= "<a href = \"%s\">%s</a>"
|
||||
#value, testname, tbox, timeval, date, branch, branchid, type, data
|
||||
result_format = "%.2f,%s,%s,%d,%d,%s,%s,%s,%s,\n"
|
||||
result_format2 = "%.2f,%s,%s,%d,%d,%s,%s,%s,\n"
|
||||
filename = tempfile.mktemp()
|
||||
tmpf = open(filename, "w")
|
||||
|
||||
testname = "ts"
|
||||
print "formating results for: ts"
|
||||
print "# of values: %d" % len(ts_times)
|
||||
for index in range(len(ts_times)):
|
||||
i = 0
|
||||
for tstime in ts_times[index]:
|
||||
tmpf.write(result_format % (float(tstime), testname, tbox, i, date, test_configs[index][3], test_configs[index][4], "discrete", "ms"))
|
||||
i = i+1
|
||||
|
||||
testname = "tp"
|
||||
for index in range(len(r_strings)):
|
||||
r_strings[index].strip('\n')
|
||||
page_results = r_strings[index].splitlines()
|
||||
i = 0
|
||||
print "formating results for: loadtime"
|
||||
print "# of values: %d" % len(page_results)
|
||||
for mypage in page_results:
|
||||
r = mypage.split(':')
|
||||
tmpf.write(result_format % (float(r[2]), testname + "_loadtime", tbox, i, date, test_configs[index][3], test_configs[index][4], "discrete", r[1]))
|
||||
i = i+1
|
||||
|
||||
for index in range(len(tp_counters)):
|
||||
for count_type in config.COUNTERS:
|
||||
i = 0
|
||||
print "formating results for: " + count_type
|
||||
print "# of values: %d" % len(tp_counters[index][count_type])
|
||||
for value in tp_counters[index][count_type]:
|
||||
tmpf.write(result_format2 % (float(value), testname + "_" + count_type.replace("%", "Percent"), tbox, i, date, test_configs[index][3], test_configs[index][4], "discrete"))
|
||||
i = i+1
|
||||
|
||||
|
||||
print "finished formating results"
|
||||
tmpf.flush()
|
||||
tmpf.close()
|
||||
tmpf = open(filename, "r")
|
||||
file_data = tmpf.read()
|
||||
while True:
|
||||
try:
|
||||
ret = post_file.post_multipart(config.RESULTS_SERVER, '/bulk.cgi', [("key", "value")], [("filename", filename, file_data)
|
||||
])
|
||||
except IOError:
|
||||
print "IOError"
|
||||
else:
|
||||
break
|
||||
print "completed sending results"
|
||||
links = process_Request(ret)
|
||||
tmpf.close()
|
||||
os.remove(filename)
|
||||
|
||||
lines = links.split('\n')
|
||||
for line in lines:
|
||||
if line == "":
|
||||
continue
|
||||
values = line.split(":")
|
||||
linkName = values[1]
|
||||
if float(values[2]) > 0:
|
||||
linkName += "_T: " + values[2]
|
||||
else:
|
||||
linkName += "_1"
|
||||
url = url_format % (config.RESULTS_SERVER, values[0],)
|
||||
link = link_format % (url, linkName,)
|
||||
print "RETURN: " + link
|
||||
|
||||
|
||||
if __name__=='__main__':
|
||||
|
|
|
@ -1,36 +1,32 @@
|
|||
# This is a sample configuration file to show how to run the Windows
|
||||
# performance tests.
|
||||
# Filename will be appended to the timestamp in the report filename.
|
||||
# Use letters and underscores only
|
||||
filename: testfilename
|
||||
|
||||
# The title of the html report
|
||||
title: Windows 2000, 1Ghz Celeron, 256MB Ram
|
||||
# The title of the report
|
||||
title: testtitle
|
||||
|
||||
# Text to append to the filename (should only contain letters, numbers,
|
||||
# and underscores)
|
||||
filename: win2k_lowmem
|
||||
# Name of profile to test
|
||||
Test profile 1:
|
||||
# Path to Firefox to test
|
||||
firefox: C:\cygwin\tmp\test\firefox\firefox\firefox.exe
|
||||
|
||||
# Profiles to test. Each of these can have different extensions installed,
|
||||
# different prefs set, and different paths to firefox.
|
||||
branch: testbranch
|
||||
|
||||
Firefox 1.5:
|
||||
# Path to Firefox executable to test:
|
||||
firefox: "C:\\Program Files\\Mozilla Firefox\\firefox.exe"
|
||||
branchid: testbranchid
|
||||
|
||||
# No preferences beyond the defaults
|
||||
preferences: {}
|
||||
profile_path: C:\win32\base_profile
|
||||
|
||||
# No extensions installed
|
||||
extensions: {}
|
||||
# Preferences to set in the test (use "preferences : {}" for no prefs)
|
||||
preferences :
|
||||
browser.shell.checkDefaultBrowser : false
|
||||
dom.allow_scripts_to_close_windows : true
|
||||
dom.disable_open_during_load: false
|
||||
browser.dom.window.dump.enabled: true
|
||||
network.proxy.type : 1
|
||||
network.proxy.http : localhost
|
||||
network.proxy.http_port : 80
|
||||
|
||||
Firefox 2.0 beta 1:
|
||||
# Path to Firefox executable to test:
|
||||
firefox: "C:\\Program Files\Mozilla Firefox 2 Beta 1\\firefox.exe"
|
||||
# Extensions to install in test (use "extensions: {}" for none)
|
||||
#extensions:
|
||||
extensions : {}
|
||||
|
||||
# Turn on prefs to enable safe browsing with no remote lookups
|
||||
# As an example of a string pref, make the selected search eBay
|
||||
preferences:
|
||||
browser.safebrowsing.enabled: true
|
||||
browser.safebrowsing.remoteLookups: false
|
||||
browser.search.selectedEngine: "eBay"
|
||||
|
||||
# No extensions
|
||||
extensions: {}
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
-
|
||||
- Contributor(s):
|
||||
- Annie Sullivan <annie.sullivan@gmail.com>
|
||||
- Alice Nodelman <anodelman@mozilla.com>
|
||||
-
|
||||
- Alternatively, the contents of this file may be used under the terms of
|
||||
- either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
|
@ -43,7 +44,6 @@
|
|||
dump('\n\n__startuptime,' + startupTime + '\n\n');
|
||||
}
|
||||
window.close();
|
||||
}
|
||||
">
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
#!c:/Python24/python.exe
|
||||
#
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
|
@ -21,6 +19,7 @@
|
|||
#
|
||||
# Contributor(s):
|
||||
# Annie Sullivan <annie.sullivan@gmail.com> (original author)
|
||||
# Ben Hearsum <bhearsum@wittydomain.com> (OS independence)
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
|
@ -54,12 +53,16 @@ import os
|
|||
import re
|
||||
import shutil
|
||||
import time
|
||||
import win32pdh
|
||||
import win32pdhutil
|
||||
import sys
|
||||
|
||||
import ffprocess
|
||||
import ffprofile
|
||||
import paths
|
||||
import config
|
||||
|
||||
if config.OS == "linux":
|
||||
from tp_linux import *
|
||||
elif config.OS == "win32":
|
||||
from tp_win32 import *
|
||||
|
||||
|
||||
# Regular expression to get stats for page load test (Tp)
|
||||
|
@ -67,66 +70,7 @@ TP_REGEX = re.compile('__start_page_load_report(.*)__end_page_load_report',
|
|||
re.DOTALL | re.MULTILINE)
|
||||
|
||||
|
||||
def AddCounter(counter_name):
|
||||
"""Adds a pdh query and counter of the given name to Firefox.
|
||||
|
||||
Args: counter_name: The name of the counter to add, i.e. "% Processor Time"
|
||||
|
||||
Returns:
|
||||
(query handle, counter handle)
|
||||
"""
|
||||
|
||||
path = win32pdh.MakeCounterPath( (None,
|
||||
'process',
|
||||
'firefox',
|
||||
None,
|
||||
-1,
|
||||
counter_name) )
|
||||
hq = win32pdh.OpenQuery()
|
||||
try:
|
||||
hc = win32pdh.AddCounter(hq, path)
|
||||
except:
|
||||
win32pdh.CloseQuery(hq)
|
||||
return hq, hc
|
||||
|
||||
|
||||
def CleanupCounter(hq, hc):
|
||||
"""Cleans up a counter after it is no longer needed.
|
||||
|
||||
Args:
|
||||
hq: handle to the query for the counter
|
||||
hc: handle to the counter
|
||||
"""
|
||||
|
||||
try:
|
||||
win32pdh.RemoveCounter(hc)
|
||||
win32pdh.CloseQuery(hq)
|
||||
except:
|
||||
# Sometimes we get unexpected win32 errors. Not much can be done.
|
||||
pass
|
||||
|
||||
|
||||
def GetCounterValue(hq, hc):
|
||||
"""Returns the current value of the given counter
|
||||
|
||||
Args:
|
||||
hq: Handle of the query for the counter
|
||||
hc: Handle of the counter
|
||||
|
||||
Returns:
|
||||
The current value of the counter
|
||||
"""
|
||||
|
||||
try:
|
||||
win32pdh.CollectQueryData(hq)
|
||||
type, val = win32pdh.GetFormattedCounterValue(hc, win32pdh.PDH_FMT_LONG)
|
||||
return val
|
||||
except:
|
||||
return None
|
||||
|
||||
|
||||
def RunPltTests(source_profile_dir,
|
||||
profile_configs,
|
||||
def RunPltTests(profile_configs,
|
||||
num_cycles,
|
||||
counters,
|
||||
resolution):
|
||||
|
@ -134,7 +78,6 @@ def RunPltTests(source_profile_dir,
|
|||
base diectory and list of configuations.
|
||||
|
||||
Args:
|
||||
source_profile_dir: Full path to base directory to copy profile from.
|
||||
profile_configs: Array of configuration options for each profile.
|
||||
These are of the format:
|
||||
[{prefname:prevalue,prefname2:prefvalue2},
|
||||
|
@ -156,35 +99,42 @@ def RunPltTests(source_profile_dir,
|
|||
|
||||
counter_data = []
|
||||
plt_results = []
|
||||
for config in profile_configs:
|
||||
results_string = []
|
||||
for pconfig in profile_configs:
|
||||
print "in tp"
|
||||
print pconfig
|
||||
sys.stdout.flush()
|
||||
rstring = ""
|
||||
# Create the new profile
|
||||
profile_dir = ffprofile.CreateTempProfileDir(source_profile_dir,
|
||||
config[0],
|
||||
config[1])
|
||||
|
||||
profile_dir = ffprofile.CreateTempProfileDir(pconfig[5],
|
||||
pconfig[0],
|
||||
pconfig[1])
|
||||
print "created profile"
|
||||
# Run Firefox once with new profile so initializing it doesn't cause
|
||||
# a performance hit, and the second Firefox that gets created is properly
|
||||
# terminated.
|
||||
ffprofile.InitializeNewProfile(config[2], profile_dir)
|
||||
ffprofile.InitializeNewProfile(pconfig[2], profile_dir)
|
||||
print "initialized firefox"
|
||||
sys.stdout.flush()
|
||||
ffprocess.SyncAndSleep()
|
||||
|
||||
# Run the plt test for this profile
|
||||
timeout = 300
|
||||
timeout = 10000
|
||||
total_time = 0
|
||||
output = ''
|
||||
url = paths.TP_URL + '?cycles=' + str(num_cycles)
|
||||
command_line = ffprocess.GenerateFirefoxCommandLine(config[2], profile_dir, url)
|
||||
url = config.TP_URL + '?cycles=' + str(num_cycles)
|
||||
command_line = ffprocess.GenerateFirefoxCommandLine(pconfig[2], profile_dir, url)
|
||||
handle = os.popen(command_line)
|
||||
# PDH might need to be "refreshed" if it has been queried while
|
||||
# Firefox is closed.
|
||||
win32pdh.EnumObjects(None, None, 0, 1)
|
||||
# give firefox a chance to open
|
||||
time.sleep(1)
|
||||
|
||||
cm = CounterManager("firefox", counters)
|
||||
|
||||
cm.startMonitor()
|
||||
|
||||
# Initialize counts
|
||||
counts = {}
|
||||
counter_handles = {}
|
||||
for counter in counters:
|
||||
counts[counter] = []
|
||||
counter_handles[counter] = AddCounter(counter)
|
||||
|
||||
while total_time < timeout:
|
||||
|
||||
|
@ -194,11 +144,9 @@ def RunPltTests(source_profile_dir,
|
|||
|
||||
# Get the output from all the possible counters
|
||||
for count_type in counters:
|
||||
val = GetCounterValue(counter_handles[count_type][0],
|
||||
counter_handles[count_type][1])
|
||||
val = cm.getCounterValue(count_type)
|
||||
|
||||
if (val):
|
||||
# Sometimes the first sample can be None, or PLT test will have
|
||||
# closed Firefox by this point. Only count real values.
|
||||
counts[count_type].append(val)
|
||||
|
||||
# Check to see if page load times were outputted
|
||||
|
@ -206,12 +154,13 @@ def RunPltTests(source_profile_dir,
|
|||
output += current_output
|
||||
match = TP_REGEX.search(output)
|
||||
if match:
|
||||
rstring += match.group(1)
|
||||
plt_results.append(match.group(1))
|
||||
break;
|
||||
break
|
||||
|
||||
# Cleanup counters
|
||||
for counter in counters:
|
||||
CleanupCounter(counter_handles[counter][0], counter_handles[counter][1])
|
||||
cm.stopMonitor()
|
||||
|
||||
print "got tp results from browser"
|
||||
|
||||
# Firefox should have exited cleanly, but close it if it doesn't
|
||||
# after 2 seconds.
|
||||
|
@ -226,5 +175,6 @@ def RunPltTests(source_profile_dir,
|
|||
shutil.rmtree(profile_dir)
|
||||
|
||||
counter_data.append(counts)
|
||||
results_string.append(rstring)
|
||||
|
||||
return (plt_results, counter_data)
|
||||
return (results_string, plt_results, counter_data)
|
||||
|
|
|
@ -0,0 +1,261 @@
|
|||
#!/usr/bin/env python
|
||||
#
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public License Version
|
||||
# 1.1 (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.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
# for the specific language governing rights and limitations under the
|
||||
# License.
|
||||
#
|
||||
# The Original Code is standalone Firefox Windows performance test.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Google Inc.
|
||||
# Portions created by the Initial Developer are Copyright (C) 2006
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
# Annie Sullivan <annie.sullivan@gmail.com> (original author)
|
||||
# Ben Hearsum <bhearsum@wittydomain.com> (ported to linux)
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
"""A set of functions to run the Tp test.
|
||||
|
||||
The Tp test measures page load times in Firefox. It does this with a
|
||||
JavaScript script that opens a new window and cycles through page loads
|
||||
from the local disk, timing each one. The script dumps the sum of the
|
||||
mean times to open each page, and the standard deviation, to standard out.
|
||||
We can also measure performance attributes during the test. See below for
|
||||
what can be monitored
|
||||
"""
|
||||
|
||||
__author__ = 'annie.sullivan@gmail.com (Annie Sullivan)'
|
||||
|
||||
|
||||
import os
|
||||
import time
|
||||
import threading
|
||||
|
||||
import ffprocess
|
||||
|
||||
def GetPrivateBytes(pid):
|
||||
"""Calculate the amount of private, writeable memory allocated to a process.
|
||||
This code was adapted from 'pmap.c', part of the procps project.
|
||||
"""
|
||||
mapfile = '/proc/%s/maps' % pid
|
||||
maps = open(mapfile)
|
||||
|
||||
private = 0
|
||||
|
||||
for line in maps:
|
||||
# split up
|
||||
(range,line) = line.split(" ", 1)
|
||||
|
||||
(start,end) = range.split("-")
|
||||
flags = line.split(" ", 1)[0]
|
||||
|
||||
size = int(end, 16) - int(start, 16)
|
||||
|
||||
if flags.find("p") >= 0:
|
||||
if flags.find("w") >= 0:
|
||||
private += size
|
||||
|
||||
return private
|
||||
|
||||
|
||||
def GetResidentSize(pid):
|
||||
"""Retrieve the current resident memory for a given process"""
|
||||
# for some reason /proc/PID/stat doesn't give accurate information
|
||||
# so we use status instead
|
||||
file = '/proc/%s/status' % pid
|
||||
|
||||
status = open(file)
|
||||
|
||||
for line in status:
|
||||
if line.find("VmRSS") >= 0:
|
||||
return int(line.split()[1]) * 1024
|
||||
|
||||
|
||||
def GetCpuTime(pid, sampleTime=1):
|
||||
"""Calculates the percent of time a process spent executing
|
||||
This function samples /proc/PID/status at a rate of 20samples/sec to
|
||||
check whether a process is active or idle.
|
||||
|
||||
Args:
|
||||
pid: The PID of process to calculate time for
|
||||
sampleTime: The length of time to monitor the process for. If this
|
||||
argument is unspecified or 0 it will be monitored until
|
||||
it terminates
|
||||
Returns:
|
||||
A percent of time a PID was idle (between 0.00 and 100.00)
|
||||
"""
|
||||
file = '/proc/%s/status' % pid
|
||||
|
||||
sampleInterval = .05
|
||||
totalSamples = (1 / sampleInterval) * sampleTime
|
||||
|
||||
states = []
|
||||
|
||||
while os.path.exists(file):
|
||||
status = open(file)
|
||||
|
||||
for line in status:
|
||||
if line.find("State") >= 0:
|
||||
states.append(line.split()[1])
|
||||
|
||||
# check to see if we've reached the maximum number of samples
|
||||
if totalSamples != 0 and len(states) >= totalSamples:
|
||||
break;
|
||||
|
||||
time.sleep(sampleInterval);
|
||||
|
||||
# non-idle cpu time = active cpu time / total cpu time
|
||||
# ex: 10 total cycles, 8 idle cycles, 2 active cycles
|
||||
# non-idle cpu time = 2 / 10
|
||||
# non-idle cpu time = .2 (20%)
|
||||
try:
|
||||
activeCpuTime = float(states.count("R")) / float(len(states))
|
||||
except ZeroDivisionError:
|
||||
activeCpuTime = -1
|
||||
|
||||
return float("%.2lf" % (activeCpuTime * 100))
|
||||
|
||||
|
||||
counterDict = {}
|
||||
counterDict["Private Bytes"] = GetPrivateBytes
|
||||
counterDict["RSS"] = GetResidentSize
|
||||
counterDict["% Processor Time"] = GetCpuTime
|
||||
|
||||
class CounterManager(threading.Thread):
|
||||
"""This class manages the monitoring of a process with any number of
|
||||
counters.
|
||||
|
||||
A counter can be any function that takes an argument of one pid and
|
||||
returns a piece of data about that process.
|
||||
Some examples are: CalcCPUTime, GetResidentSize, and GetPrivateBytes
|
||||
"""
|
||||
|
||||
pollInterval = .25
|
||||
|
||||
def __init__(self, process, counters=None):
|
||||
"""Args:
|
||||
counters: A list of counters to monitor. Any counters whose name does
|
||||
not match a key in 'counterDict' will be ignored.
|
||||
"""
|
||||
self.allCounters = {}
|
||||
self.registeredCounters = {}
|
||||
self.process = process
|
||||
self.runThread = False
|
||||
self.pid = -1
|
||||
|
||||
self._loadCounters()
|
||||
self.registerCounters(counters)
|
||||
|
||||
threading.Thread.__init__(self)
|
||||
|
||||
def _loadCounters(self):
|
||||
"""Loads all of the counters defined in the counterDict"""
|
||||
for counter in counterDict.keys():
|
||||
self.allCounters[counter] = counterDict[counter]
|
||||
|
||||
def registerCounters(self, counters):
|
||||
"""Registers a list of counters that will be monitoring.
|
||||
Only counters whose names are found in allCounters will be added
|
||||
"""
|
||||
for counter in counters:
|
||||
if counter in self.allCounters:
|
||||
self.registeredCounters[counter] = \
|
||||
[self.allCounters[counter], []]
|
||||
|
||||
def unregisterCounters(self, counters):
|
||||
"""Unregister a list of counters.
|
||||
Only counters whose names are found in registeredCounters will be
|
||||
paid attention to
|
||||
"""
|
||||
for counter in counters:
|
||||
if counter in self.registeredCounters:
|
||||
del self.registeredCounters[counter]
|
||||
|
||||
def getRegisteredCounters(self):
|
||||
"""Returns a list of the registered counters."""
|
||||
return keys(self.registeredCounters)
|
||||
|
||||
def getCounterValue(self, counterName):
|
||||
"""Returns the last value of the counter 'counterName'"""
|
||||
try:
|
||||
if counterName is "% Processor Time":
|
||||
return self._getCounterAverage(counterName)
|
||||
else:
|
||||
return self.registeredCounters[counterName][1][-1]
|
||||
except:
|
||||
return None
|
||||
|
||||
def _getCounterAverage(self, counterName):
|
||||
"""Returns the average value of the counter 'counterName'"""
|
||||
try:
|
||||
total = 0
|
||||
for v in self.registeredCounters[counterName][1]:
|
||||
total += v
|
||||
return total / len(self.registeredCounters[counterName][1])
|
||||
except:
|
||||
return None
|
||||
|
||||
def getProcess(self):
|
||||
"""Returns the process currently associated with this CounterManager"""
|
||||
return self.process
|
||||
|
||||
def startMonitor(self):
|
||||
"""Starts the monitoring process.
|
||||
Throws an exception if any error occurs
|
||||
"""
|
||||
# TODO: make this function less ugly
|
||||
try:
|
||||
# the last process is the useful one
|
||||
self.pid = ffprocess.GetPidsByName(self.process)[-1]
|
||||
os.stat('/proc/%s' % self.pid)
|
||||
self.runThread = True
|
||||
self.start()
|
||||
except:
|
||||
raise
|
||||
|
||||
def stopMonitor(self):
|
||||
"""Stops the monitor"""
|
||||
# TODO: should probably wait until we know run() is completely stopped
|
||||
# before setting self.pid to None. Use a lock?
|
||||
self.runThread = False
|
||||
|
||||
def run(self):
|
||||
"""Performs the actual monitoring of the process. Will keep running
|
||||
until stopMonitor() is called
|
||||
"""
|
||||
while self.runThread:
|
||||
for counter in self.registeredCounters.keys():
|
||||
# counter[0] is a function that gets the current value for
|
||||
# a counter
|
||||
# counter[1] is a list of recorded values
|
||||
try:
|
||||
self.registeredCounters[counter][1].append(
|
||||
self.registeredCounters[counter][0](self.pid))
|
||||
except:
|
||||
# if a counter throws an exception, remove it
|
||||
self.unregisterCounters([counter])
|
||||
|
||||
time.sleep(self.pollInterval)
|
|
@ -0,0 +1,98 @@
|
|||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public License Version
|
||||
# 1.1 (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.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
# for the specific language governing rights and limitations under the
|
||||
# License.
|
||||
#
|
||||
# The Original Code is standalone Firefox Windows performance test.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Google Inc.
|
||||
# Portions created by the Initial Developer are Copyright (C) 2006
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
# Annie Sullivan <annie.sullivan@gmail.com> (original author)
|
||||
# Ben Hearsum <bhearsum@wittydomain.com> (OS independence)
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
|
||||
import win32pdh
|
||||
import win32pdhutil
|
||||
|
||||
|
||||
class CounterManager:
|
||||
|
||||
def __init__(self, process, counters=None):
|
||||
self.process = process
|
||||
self.registeredCounters = {}
|
||||
self.registerCounters(counters)
|
||||
# PDH might need to be "refreshed" if it has been queried while Firefox
|
||||
# is closed
|
||||
win32pdh.EnumObjects(None, None, 0, 1)
|
||||
|
||||
def registerCounters(self, counters):
|
||||
for counter in counters:
|
||||
self.registeredCounters[counter] = []
|
||||
|
||||
def unregisterCounters(self, counters):
|
||||
for counter in counters:
|
||||
if counter in self.registeredCounters:
|
||||
del self.registeredCounters[counter]
|
||||
|
||||
def getRegisteredCounters(self):
|
||||
return keys(self.registeredCounters)
|
||||
|
||||
def getCounterValue(self, counter):
|
||||
hq = self.registeredCounters[counter][0]
|
||||
hc = self.registeredCounters[counter][1]
|
||||
try:
|
||||
win32pdh.CollectQueryData(hq)
|
||||
type, val = win32pdh.GetFormattedCounterValue(hc, win32pdh.PDH_FMT_LONG)
|
||||
return val
|
||||
except:
|
||||
return None
|
||||
|
||||
def getProcess(self):
|
||||
return self.process
|
||||
|
||||
def startMonitor(self):
|
||||
# PDH might need to be "refreshed" if it has been queried while Firefox
|
||||
# is closed
|
||||
win32pdh.EnumObjects(None, None, 0, 1)
|
||||
|
||||
for counter in self.registeredCounters:
|
||||
path = win32pdh.MakeCounterPath((None, 'process', self.process,
|
||||
None, -1, counter))
|
||||
hq = win32pdh.OpenQuery()
|
||||
try:
|
||||
hc = win32pdh.AddCounter(hq, path)
|
||||
except:
|
||||
win32pdh.CloseQuery(hq)
|
||||
|
||||
self.registeredCounters[counter] = [hq, hc]
|
||||
|
||||
def stopMonitor(self):
|
||||
for counter in self.registeredCounters:
|
||||
win32pdh.RemoveCounter(self.registeredCounters[counter][1])
|
||||
win32pdh.CloseQuery(self.registeredCounters[counter][0])
|
||||
self.registeredCounters.clear()
|
|
@ -1,5 +1,3 @@
|
|||
#!c:/Python24/python.exe
|
||||
#
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
|
@ -21,6 +19,7 @@
|
|||
#
|
||||
# Contributor(s):
|
||||
# Annie Sullivan <annie.sullivan@gmail.com> (original author)
|
||||
# Alice Nodelman <anodelman@mozilla.com>
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
|
@ -55,7 +54,7 @@ import time
|
|||
|
||||
import ffprocess
|
||||
import ffprofile
|
||||
import paths
|
||||
import config
|
||||
|
||||
|
||||
# Regular expression to get the time for startup test (Ts)
|
||||
|
@ -96,7 +95,7 @@ def RunStartupTest(firefox_path, profile_dir, num_runs, timeout):
|
|||
# Create a command line that passes in the url of the startup test
|
||||
# with the current time as the begin_time argument
|
||||
time_arg = int(time.time() * 1000)
|
||||
url = paths.TS_URL + str(time_arg)
|
||||
url = config.TS_URL + str(time_arg)
|
||||
command_line = ffprocess.GenerateFirefoxCommandLine(firefox_path, profile_dir, url)
|
||||
(match, timed_out) = ffprocess.RunProcessAndWaitForOutput(command_line,
|
||||
'firefox',
|
||||
|
@ -110,12 +109,11 @@ def RunStartupTest(firefox_path, profile_dir, num_runs, timeout):
|
|||
return startup_times
|
||||
|
||||
|
||||
def RunStartupTests(source_profile_dir, profile_configs, num_runs):
|
||||
def RunStartupTests(profile_configs, num_runs):
|
||||
"""Runs the startup tests with profiles created from the
|
||||
given base profile directory and list of configurations.
|
||||
|
||||
Args:
|
||||
source_profile_dir: Full path to base directory to copy profile from.
|
||||
profile_configs: Array of configuration options for each profile.
|
||||
These are of the format:
|
||||
[{prefname:prevalue,prefname2:prefvalue2},{extensionguid:path_to_extension}],[{prefname...
|
||||
|
@ -128,7 +126,7 @@ def RunStartupTests(source_profile_dir, profile_configs, num_runs):
|
|||
all_times = []
|
||||
for config in profile_configs:
|
||||
# Create the new profile
|
||||
profile_dir = ffprofile.CreateTempProfileDir(source_profile_dir,
|
||||
profile_dir = ffprofile.CreateTempProfileDir(config[5],
|
||||
config[0],
|
||||
config[1])
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче