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:
rhelmer@mozilla.com 2007-05-04 15:13:40 -07:00
Родитель 0e07922d3a
Коммит b259289c31
21 изменённых файлов: 1691 добавлений и 655 удалений

Просмотреть файл

@ -1,9 +1,100 @@
PREREQUISITES: You'll need to download some software onto your Windows machine before running these performance tests: PREREQUISITES:
* Python 2.4 The scripts all run from Python 2.4. You will need the windows version You'll need to download some software onto your Windows machine before running
(not the cygwin version). You can download it here: http://www.python.org/ftp/python/2.4/python-2.4.msi 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. 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 After you download and install Python 2.4, you'll need to install
* Numerical Python: This is required by Matplotlib. http://prdownloads.sourceforge.net/numpy/Numeric-24.2.win32-py2.4.exe?download some extensions:
* 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. * 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.

Просмотреть файл

@ -1,5 +1,3 @@
#!c:/Python24/python.exe
#
# ***** BEGIN LICENSE BLOCK ***** # ***** BEGIN LICENSE BLOCK *****
# Version: MPL 1.1/GPL 2.0/LGPL 2.1 # Version: MPL 1.1/GPL 2.0/LGPL 2.1
# #
@ -21,6 +19,7 @@
# #
# Contributor(s): # Contributor(s):
# Annie Sullivan <annie.sullivan@gmail.com> (original author) # 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 # 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 # either the GNU General Public License Version 2 or later (the "GPL"), or
@ -43,6 +42,8 @@
__author__ = 'annie.sullivan@gmail.com (Annie Sullivan)' __author__ = 'annie.sullivan@gmail.com (Annie Sullivan)'
OS = r'win32'
"""For some reason, can only get output from dump() in Firefox if """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. 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 urls with scheme:file to open in new windows, and the preference to open
new windows in a tab should be off. 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.""" """The directory the generated reports go into."""
REPORTS_DIR = r'c:\extension_perf_reports' REPORTS_DIR = r'c:\extension_perf_reports'
"""The path to the file url to load when initializing a new profile""" """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)""" """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)""" """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 ***** # ***** BEGIN LICENSE BLOCK *****
# Version: MPL 1.1/GPL 2.0/LGPL 2.1 # Version: MPL 1.1/GPL 2.0/LGPL 2.1
# #
@ -42,63 +40,18 @@
__author__ = 'annie.sullivan@gmail.com (Annie Sullivan)' __author__ = 'annie.sullivan@gmail.com (Annie Sullivan)'
import msvcrt
import os import os
import re import re
import time 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(): def SyncAndSleep():
@ -106,84 +59,10 @@ def SyncAndSleep():
Otherwise "Firefox is already running.." errors occur Otherwise "Firefox is already running.." errors occur
""" """
os.spawnl(os.P_WAIT, paths.SYNC) os.spawnl(os.P_WAIT, config.SYNC)
time.sleep(3) 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): def RunProcessAndWaitForOutput(command, process_name, output_regex, timeout):
"""Runs the given process and waits for the output that matches the given """Runs the given process and waits for the output that matches the given
regular expression. Stops if the process exits early or times out. 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 ***** # ***** BEGIN LICENSE BLOCK *****
# Version: MPL 1.1/GPL 2.0/LGPL 2.1 # Version: MPL 1.1/GPL 2.0/LGPL 2.1
# #
@ -55,7 +53,12 @@ import tempfile
import time import time
import ffprocess 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): def PrefString(name, value, newline):
@ -81,20 +84,6 @@ def PrefString(name, value, newline):
return 'user_pref("%s", %s);%s' % (name, out_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): def CreateTempProfileDir(source_profile, prefs, extensions):
"""Creates a temporary profile directory from the source profile directory """Creates a temporary profile directory from the source profile directory
and adds the given prefs and links to extensions. 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 # 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) handle = os.popen(cmd)
# Wait for Firefox to shut down and restart with the new profile, # 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)

Просмотреть файл

@ -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> <html>
<script language="Javascript" type="text/javascript" src="parray.js"></script>
<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_PAGES;
var NUM_CYCLES; var NUM_CYCLES;
@ -111,6 +63,18 @@
sum = sum + ary[i]; 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 // ignore max value when computing mean and stddev
r.mean = (sum - r.max) / (ary.length - 1); r.mean = (sum - r.max) / (ary.length - 1);
@ -135,17 +99,62 @@
return td; return td;
} }
function loadReport() { function dumpReport() {
win.addEventListener("load", showReport, true); var all = new Array();
var baseUri = document.location.href.substr(0, document.location.href.lastIndexOf('/') + 1); var counter = 0;
win.document.location = baseUri + "report.html";
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() { function showReport() {
var doc = win.document; var doc = frames["content"].document;
var tbody = doc.getElementById("tbody"); var tbody = doc.getElementById("tbody");
var sum_mean = 0;
var sum_stdd = 0;
for (var i = 0; i < timeVals.length; ++i) { for (var i = 0; i < timeVals.length; ++i) {
var tr = doc.createElement("TR"); var tr = doc.createElement("TR");
@ -156,9 +165,7 @@
appendTableCol(tr, r.max.toFixed(2)); appendTableCol(tr, r.max.toFixed(2));
appendTableCol(tr, r.mean.toFixed(2)); appendTableCol(tr, r.mean.toFixed(2));
appendTableCol(tr, r.stdd.toFixed(2)); appendTableCol(tr, r.stdd.toFixed(2));
sum_mean += r.mean; appendTableCol(tr, r.median.toFixed(2));
sum_stdd += r.stdd;
//appendTableCol(tr, r.chi2.toFixed(2));
for (var j = 0; j < timeVals[i].length; ++j) { for (var j = 0; j < timeVals[i].length; ++j) {
var tv = timeVals[i][j]; var tv = timeVals[i][j];
@ -169,24 +176,23 @@
tbody.appendChild(tr); 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) { function loadPage(i) {
tstart = new Date(); tstart = new Date();
win.addEventListener("load", winLoad, true); frames["content"].document.location = pages[i];
win.document.location = "base/" + pages[i] + "index.html";
} }
function winLoad() { function frameLoad() {
if (cycle == NUM_CYCLES) {
showReport();
dumpReport();
window.close();
return;
}
var tend = new Date(); var tend = new Date();
var href = win.document.location.href; var href = frames["content"].document.location.href;
if (href == "about:blank") if (href == "about:blank")
return; return;
var tdelta = tend - tstart; var tdelta = tend - tstart;
@ -195,35 +201,31 @@
var text = (cycle + 1) + ', ' + (index + 1) + ', ' + fields[fields.length - 2] + ", " + tdelta; 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) while (body.firstChild)
body.removeChild(body.firstChild); body.removeChild(body.firstChild);
body.appendChild(document.createTextNode(text)); body.appendChild(doc.createTextNode(text));
if (++index == NUM_PAGES) { if (++index == NUM_PAGES) {
index = 0; index = 0;
if (++cycle == NUM_CYCLES) { if (++cycle == NUM_CYCLES) {
// display summary // display summary
try { frames["content"].document.location = "report.html";
win.removeEventListener("load", winLoad, true);
} catch (e) { alert("displaying summary, caught " + e); }
win.document.location = "about:blank";
window.setTimeout(loadReport, 500);
return; 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); window.setTimeout("loadPage(" + index + ")", 500);
} }
function init() { function init() {
win = window.open("about:blank", "Page Load Test"); window.resizeTo(800, 800);
window.setTimeout("loadPage(" + index + ")", 500); window.setTimeout("loadPage(" + index + ")", 500);
} }
</script> </script>
<body onload="init();"></body> <frameset rows="40,*" onload="init()">
<frame name="header" src="header.html">
<frame name="content" src="" onload="frameLoad()">
</frameset>
</html> </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 ***** # ***** BEGIN LICENSE BLOCK *****
# Version: MPL 1.1/GPL 2.0/LGPL 2.1 # Version: MPL 1.1/GPL 2.0/LGPL 2.1
# #
@ -21,6 +19,7 @@
# #
# Contributor(s): # Contributor(s):
# Annie Sullivan <annie.sullivan@gmail.com> (original author) # 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 # 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 # 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 time
import syck import syck
import sys import sys
import urllib
import tempfile
import os
import string
import socket
socket.setdefaulttimeout(480)
import report import config
import paths
import tp import tp
import ts import ts
import post_file
# Number of times to run startup test (Ts) def shortNames(name):
TS_NUM_RUNS = 5 if name == "tp_loadtime":
return "tp_l"
# Number of times the page load test (Tp) loads each page in the test. elif name == "tp_Percent Processor Time":
TP_NUM_CYCLES = 7 return "tp_%cpu"
elif name == "tp_Working Set":
# Resolution of counter sample data for page load test (Tp), in seconds return "tp_memset"
# (For example, if TP_RESOLUTION=1, sample counters every 1 second elif name == "tp_Private Bytes":
TP_RESOLUTION = 1 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): def test_file(filename):
"""Runs the Ts and Tp tests on the given config file and generates a report. """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 = [] test_names = []
title = '' title = ''
filename_prefix = '' filename_prefix = ''
testdate = ''
# Read in the profile info from the YAML config file # Read in the profile info from the YAML config file
config_file = open(filename, 'r') config_file = open(filename, 'r')
# some versions of syck take a file, while others take a string
try:
yaml = syck.load(config_file) yaml = syck.load(config_file)
except:
yaml = syck.load("".join(config_file.readlines()))
config_file.close() config_file.close()
for item in yaml: for item in yaml:
if item == 'title': if item == 'title':
title = yaml[item] title = yaml[item]
elif item == 'filename': elif item == 'filename':
filename_prefix = yaml[item] filename_prefix = yaml[item]
elif item == 'testdate':
testdate = yaml[item]
else: else:
new_config = [yaml[item]['preferences'], new_config = [yaml[item]['preferences'],
yaml[item]['extensions'], 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_configs.append(new_config)
test_names.append(item) test_names.append(item)
config_file.close() 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 # Run startup time test
ts_times = ts.RunStartupTests(paths.BASE_PROFILE_DIR, ts_times = ts.RunStartupTests(test_configs,
test_configs, config.TS_NUM_RUNS)
TS_NUM_RUNS)
# Run page load test. For possible values of counters argument, see print "finished ts"
# http://technet2.microsoft.com/WindowsServer/en/Library/86b5d116-6fb3-427b-af8c-9077162125fe1033.mspx?mfr=true sys.stdout.flush()
(tp_times, tp_counters) = tp.RunPltTests(paths.BASE_PROFILE_DIR,
test_configs,
TP_NUM_CYCLES,
['Private Bytes', 'Working Set', '% Processor Time'],
TP_RESOLUTION)
# Generate a report of the results. (r_strings, tp_times, tp_counters) = tp.RunPltTests(test_configs,
report.GenerateReport(title, config.TP_NUM_CYCLES,
filename_prefix, config.COUNTERS,
test_names, config.TP_RESOLUTION)
ts_times,
tp_times, print "finished tp"
tp_counters, sys.stdout.flush()
TP_RESOLUTION)
#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__': if __name__=='__main__':

Просмотреть файл

@ -1,36 +1,32 @@
# This is a sample configuration file to show how to run the Windows # Filename will be appended to the timestamp in the report filename.
# performance tests. # Use letters and underscores only
filename: testfilename
# The title of the html report # The title of the report
title: Windows 2000, 1Ghz Celeron, 256MB Ram title: testtitle
# Text to append to the filename (should only contain letters, numbers, # Name of profile to test
# and underscores) Test profile 1:
filename: win2k_lowmem # 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, branch: testbranch
# different prefs set, and different paths to firefox.
Firefox 1.5: branchid: testbranchid
# Path to Firefox executable to test:
firefox: "C:\\Program Files\\Mozilla Firefox\\firefox.exe"
# No preferences beyond the defaults profile_path: C:\win32\base_profile
preferences: {}
# No extensions installed # Preferences to set in the test (use "preferences : {}" for no prefs)
extensions: {} 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: # Extensions to install in test (use "extensions: {}" for none)
# Path to Firefox executable to test: #extensions:
firefox: "C:\\Program Files\Mozilla Firefox 2 Beta 1\\firefox.exe" 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): - Contributor(s):
- Annie Sullivan <annie.sullivan@gmail.com> - Annie Sullivan <annie.sullivan@gmail.com>
- Alice Nodelman <anodelman@mozilla.com>
- -
- Alternatively, the contents of this file may be used under the terms of - 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 - either the GNU General Public License Version 2 or later (the "GPL"), or
@ -43,7 +44,6 @@
dump('\n\n__startuptime,' + startupTime + '\n\n'); dump('\n\n__startuptime,' + startupTime + '\n\n');
} }
window.close(); window.close();
}
"> ">
</body> </body>
</html> </html>

Просмотреть файл

@ -1,5 +1,3 @@
#!c:/Python24/python.exe
#
# ***** BEGIN LICENSE BLOCK ***** # ***** BEGIN LICENSE BLOCK *****
# Version: MPL 1.1/GPL 2.0/LGPL 2.1 # Version: MPL 1.1/GPL 2.0/LGPL 2.1
# #
@ -21,6 +19,7 @@
# #
# Contributor(s): # Contributor(s):
# Annie Sullivan <annie.sullivan@gmail.com> (original author) # 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 # 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 # either the GNU General Public License Version 2 or later (the "GPL"), or
@ -54,12 +53,16 @@ import os
import re import re
import shutil import shutil
import time import time
import win32pdh import sys
import win32pdhutil
import ffprocess import ffprocess
import ffprofile 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) # 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) re.DOTALL | re.MULTILINE)
def AddCounter(counter_name): def RunPltTests(profile_configs,
"""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,
num_cycles, num_cycles,
counters, counters,
resolution): resolution):
@ -134,7 +78,6 @@ def RunPltTests(source_profile_dir,
base diectory and list of configuations. base diectory and list of configuations.
Args: Args:
source_profile_dir: Full path to base directory to copy profile from.
profile_configs: Array of configuration options for each profile. profile_configs: Array of configuration options for each profile.
These are of the format: These are of the format:
[{prefname:prevalue,prefname2:prefvalue2}, [{prefname:prevalue,prefname2:prefvalue2},
@ -156,35 +99,42 @@ def RunPltTests(source_profile_dir,
counter_data = [] counter_data = []
plt_results = [] 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 # Create the new profile
profile_dir = ffprofile.CreateTempProfileDir(source_profile_dir, profile_dir = ffprofile.CreateTempProfileDir(pconfig[5],
config[0], pconfig[0],
config[1]) pconfig[1])
print "created profile"
# Run Firefox once with new profile so initializing it doesn't cause # Run Firefox once with new profile so initializing it doesn't cause
# a performance hit, and the second Firefox that gets created is properly # a performance hit, and the second Firefox that gets created is properly
# terminated. # terminated.
ffprofile.InitializeNewProfile(config[2], profile_dir) ffprofile.InitializeNewProfile(pconfig[2], profile_dir)
print "initialized firefox"
sys.stdout.flush()
ffprocess.SyncAndSleep() ffprocess.SyncAndSleep()
# Run the plt test for this profile # Run the plt test for this profile
timeout = 300 timeout = 10000
total_time = 0 total_time = 0
output = '' output = ''
url = paths.TP_URL + '?cycles=' + str(num_cycles) url = config.TP_URL + '?cycles=' + str(num_cycles)
command_line = ffprocess.GenerateFirefoxCommandLine(config[2], profile_dir, url) command_line = ffprocess.GenerateFirefoxCommandLine(pconfig[2], profile_dir, url)
handle = os.popen(command_line) handle = os.popen(command_line)
# PDH might need to be "refreshed" if it has been queried while # give firefox a chance to open
# Firefox is closed. time.sleep(1)
win32pdh.EnumObjects(None, None, 0, 1)
cm = CounterManager("firefox", counters)
cm.startMonitor()
# Initialize counts
counts = {} counts = {}
counter_handles = {}
for counter in counters: for counter in counters:
counts[counter] = [] counts[counter] = []
counter_handles[counter] = AddCounter(counter)
while total_time < timeout: while total_time < timeout:
@ -194,11 +144,9 @@ def RunPltTests(source_profile_dir,
# Get the output from all the possible counters # Get the output from all the possible counters
for count_type in counters: for count_type in counters:
val = GetCounterValue(counter_handles[count_type][0], val = cm.getCounterValue(count_type)
counter_handles[count_type][1])
if (val): 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) counts[count_type].append(val)
# Check to see if page load times were outputted # Check to see if page load times were outputted
@ -206,12 +154,13 @@ def RunPltTests(source_profile_dir,
output += current_output output += current_output
match = TP_REGEX.search(output) match = TP_REGEX.search(output)
if match: if match:
rstring += match.group(1)
plt_results.append(match.group(1)) plt_results.append(match.group(1))
break; break
# Cleanup counters cm.stopMonitor()
for counter in counters:
CleanupCounter(counter_handles[counter][0], counter_handles[counter][1]) print "got tp results from browser"
# Firefox should have exited cleanly, but close it if it doesn't # Firefox should have exited cleanly, but close it if it doesn't
# after 2 seconds. # after 2 seconds.
@ -226,5 +175,6 @@ def RunPltTests(source_profile_dir,
shutil.rmtree(profile_dir) shutil.rmtree(profile_dir)
counter_data.append(counts) 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 ***** # ***** BEGIN LICENSE BLOCK *****
# Version: MPL 1.1/GPL 2.0/LGPL 2.1 # Version: MPL 1.1/GPL 2.0/LGPL 2.1
# #
@ -21,6 +19,7 @@
# #
# Contributor(s): # Contributor(s):
# Annie Sullivan <annie.sullivan@gmail.com> (original author) # 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 # 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 # either the GNU General Public License Version 2 or later (the "GPL"), or
@ -55,7 +54,7 @@ import time
import ffprocess import ffprocess
import ffprofile import ffprofile
import paths import config
# Regular expression to get the time for startup test (Ts) # 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 # Create a command line that passes in the url of the startup test
# with the current time as the begin_time argument # with the current time as the begin_time argument
time_arg = int(time.time() * 1000) 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) command_line = ffprocess.GenerateFirefoxCommandLine(firefox_path, profile_dir, url)
(match, timed_out) = ffprocess.RunProcessAndWaitForOutput(command_line, (match, timed_out) = ffprocess.RunProcessAndWaitForOutput(command_line,
'firefox', 'firefox',
@ -110,12 +109,11 @@ def RunStartupTest(firefox_path, profile_dir, num_runs, timeout):
return startup_times 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 """Runs the startup tests with profiles created from the
given base profile directory and list of configurations. given base profile directory and list of configurations.
Args: Args:
source_profile_dir: Full path to base directory to copy profile from.
profile_configs: Array of configuration options for each profile. profile_configs: Array of configuration options for each profile.
These are of the format: These are of the format:
[{prefname:prevalue,prefname2:prefvalue2},{extensionguid:path_to_extension}],[{prefname... [{prefname:prevalue,prefname2:prefvalue2},{extensionguid:path_to_extension}],[{prefname...
@ -128,7 +126,7 @@ def RunStartupTests(source_profile_dir, profile_configs, num_runs):
all_times = [] all_times = []
for config in profile_configs: for config in profile_configs:
# Create the new profile # Create the new profile
profile_dir = ffprofile.CreateTempProfileDir(source_profile_dir, profile_dir = ffprofile.CreateTempProfileDir(config[5],
config[0], config[0],
config[1]) config[1])