Firefox/Projects/Startup Time Improvements: Difference between revisions

From MozillaWiki
Jump to navigation Jump to search
No edit summary
 
(96 intermediate revisions by 10 users not shown)
Line 1: Line 1:
__NOTOC__
= Overview =
= Overview =
'''Sprint lead:''' Dietrich Ayala <br/>
'''Sprinters:''' Ryan Flint, Drew Willcoxon, David Dahl <br/>
'''Concurrent work:''' Vlad Vukićević, Taras Glek


'''Description:''' Investigate areas for improving startup time of the Mozilla platform, find & fix issues that help Fennec and WinCE.
'''Description:''' Improve startup time of Firefox and Fennec on all operating systems and platforms, including mobile devices.


'''Phase 1: Exploration''' 7/13 - 7/24, Achieve visibility into the performance-related problem areas during browser startup, and to use that visibility to create actionable bugs, creating a clear development path to move forward on.
'''Project lead:''' <br/>
'''Project members:''' Taras Glek,  Ben Hsieh, Steve Fink, Michael Wu, Shawn Wilsher


'''Phase 2: Seek and Destroy''' 7/27 - 8/7, More research into causes of I/O usage, and evaluation of approaches for large-scale mitigation. Fix bugs in which a resolution path is already clear, and that would provide a human-noticeable win in Fennec or WinCe. For areas not immediately fixable, file bugs and ensure that the relevant people are aware of the problem, and work to get those bugs with potentially big wins prioritized.
'''Bugs:''' [http://tinyurl.com/ygbnzmd Open] | [http://tinyurl.com/yjp8d6w Fixed] | [http://bit.ly/5t9fA9 Fixed in 3.6]


= Bug visibility =
'''Results''': [http://graphs.mozilla.org/dashboard/snapshot/ Performance Snapshot] (snapshot numbers for last 7 days, and version comparisons)


We've been using "[ts]" in the whiteboard field for our newly filed bugs as well as pre-existing.
'''Graphs:''' [http://bit.ly/5fjmP9 Windows XP] | [http://bit.ly/8FjKvj Windows Vista] | [http://bit.ly/7aHx3r Mac Leopard] | [http://bit.ly/8wUHGs Linux]
* [https://bugzilla.mozilla.org/buglist.cgi?quicksearch=sw%3A%5Bts%5D ts bugs].


;Meta bugs
'''Status:''' [http://autonome.wordpress.com/tag/startup/ Weekly status updates]
* {{bug|459117}} Fennec performance meta bug
 
* {{bug|447581}} Startup meta bug
=Active Projects=
* {{bug|479078}} Startup research meta bug
<onlyinclude>
* {{bug|7251}} very old startup meta bug
{|border="1" cellspacing="0" cellpadding="2"
!Estimated win
!Bug #
!Summary
!Owner
!Status
!Notes
|-
|~10%
|[[Firefox/Projects/2010Q3_Dirty_Startup_Reduction|"Dirty Profile" Startup Reduction]]
|Constant startup relative to profile size
|Shawn Wilsher
|
|
|-
|significant
|{{bug|558200}}
|Extension profiler platform api
|Steve Fink
|
| There is an easy way to provide feedback to extension developers to help them figure out why their extension is misbehaving. We need to implement that ASAP, so typical firefox installs(with lots of extensions) can be fast
|}
</onlyinclude>
 
=Help Wanted/Onhold=
{|border="1" cellspacing="0" cellpadding="2"
!Estimated win
!Bug #
!Summary
!Owner
!Status
!Notes
|-
|~8%
|{{bug|561842}}
|Fold libraries into libxul
|Ted Mielczarek
|
|proof of concept done
|-
|up to 40%
|{{bug|531406}}
|Optimize code locality in binaries. Working on enabling pgo atm.
|Taras Glek
|
|Linux almost done, need to figure out integration. Windows proof of concept needs work.
See [http://blog.mozilla.com/tglek/2010/02/19/teaching-ld-to-optimize-binaries-for-startup/ blog post] for more details. Taras and Ehsan working on Windows locality improvements ({{bug|553721}}).
|-
|~10%
|{{bug|512584}}
|Fast paths for Cc/Ci
|
|
|Confirmed win. Unfortunately this approach touches a lot of sensitive code, might be easier to port js to not use Cc/Ci
|-
|TBD
|{{bug|513149}} {{bug|553456}}
|Speed up CSS parsing
|Zack Weinberg
|
|
|-
|significant
|{{bug|559663}}
|Measuring IOPs
|
|
|Our current infrastructure does not measure cold startup effectively, it should.
|
|-
|TBD
|{{bug|569629}}
|Get rid of static initializers
|
|
|These slowdown library loading, cause a lot of pagefaults on gcc platforms.
|}
 
 
Other efforts:
* {{bug|514083}} HFS+ compression on Mac OSX 10.6
 
'''Measurement & Testing Projects'''
* cold startup testing
** {{bug|532965}} - fix Mac cold startup test
** {{bug|522807}} - make windows cold startup test
 
* dirty profile testing
** {{bug|527596}} - dirty Tp
** {{bug|FILEME}} - test an all-dirty profile
 
=Future Projects=


= Instrumentation =
* {{bug|523146}} - micro-benchmarking test framework
* {{bug|522375}} - built-in startup measurement


== Create an easily accessible timeline of the startup path (David, Vlad) ==
* {{bug|509755}} - put modules into a jar
* '''Status''': in progress
* {{bug|FILEME}} - [https://bugzilla.mozilla.org/show_bug.cgi?id=279839#c29 string pool for jsxpcom]
* '''Usage''': [https://wiki.mozilla.org/Firefox/Sprints/Startup_Time_Improvements/StartupPatchUsage#Quick_Start steps here]
* taking advantage of tracing
* '''Results'''
** figure out where we're not tracing in the startup log
** [http://blog.mozilla.com/dmandelin/2009/02/26/tracevis-performance-visualization-for-tracemonkey/ dmandelin's blog post]
** traceviz ({{bug|497999}})
* timeline of the startup path (David, Vlad)
** Status: incomplete (held up on hangs, nspr changes)
** [https://wiki.mozilla.org/Firefox/Sprints/Startup_Time_Improvements/StartupPatchUsage#Quick_Start docs]
** {{bug|480735}} instrumentation
** {{bug|480735}} instrumentation
** {{bug|503605}} visualization
** {{bug|503605}} visualization ([http://mozilla.ddahl.com/startup/timeline-similie.html Simile timeline], [http://people.mozilla.org/~dietrich/ddahl_sample_output.txt raw log])
** Example output: [http://mozilla.ddahl.com/startup/timeline-similie.html Simile timeline]
** Example output: [http://people.mozilla.org/~dietrich/ddahl_sample_output.txt raw log]


== Mine the Ts DTrace viz/logs (Drew) ==
=Inactive Projects=
* '''Status''': complete, moved on to filesystem operations below
* '''Results'''
** It's my conclusion that (cold) startup is heavily I/O-bound.  Something like 90% of cold startup time is spent in page faults and other I/O syscalls, especially read, getattrlist, and stat.  And the majority of time spent after Firefox actually gets up and running is in XBL and CSS.  Any improvements that ignore these observations will therefore be marginal IMO.
* '''Bugs'''
** {{bug|504858}} - Investigate delaying initialization of bookmarks toolbar
** {{bug|504872}} - Investigate further delaying initialization of the search bar
** I think these two bugs aren't worth pursuing.  As Gavin comments in them, the latency I noticed is due to unavoidable things like XBL attachment and flushing layout.  Moreover, they contribute very, very little to startup time.


== Log and mine filesystem operations during startup (Ryan, Drew) ==
* {{bug|507101}} - combining js components
* '''Status''': in progress
* minification
* '''Todo'''
** {{bug|524858}} - minify js
** maybe write a new dtrace script for targeting offenders
** {{bug|513132}} - minify css
* '''Results'''
** {{bug|523479}} - minify extension's contents
** checking out Xperf and others for Windows work
* Mine the Ts DTrace viz/logs (Drew)
** Status: complete, moved on to filesystem operations below
** Results
*** cold startup is heavily I/O-bound. 90% of cold startup time is spent in page faults and other I/O syscalls, especially read, getattrlist, and stat.
*** majority of time spent after Firefox actually gets up and running is in XBL and CSS.
* Log and mine filesystem operations during startup (Ryan, Drew)
** Status: complete, bugs filed for egregious offenders
** Results
*** checking out Xperf and others for Windows work
*** investigating dtrace timing/FS cache issues on OS X
*** investigating dtrace timing/FS cache issues on OS X
**** Instruments appears to have the same issues
**** Instruments appears to have the same issues
*** Simple JS file exec script has yielded [https://bugzilla.mozilla.org/buglist.cgi?bug_id=504513 some results]
*** Simple JS file exec script has yielded [https://bugzilla.mozilla.org/buglist.cgi?bug_id=504513 some results]
** [[Firefox/Projects/Startup_Time_Improvements/adw_notes|Drew's notes]]
** References
** [[Firefox/Projects/Startup_Time_Improvements/joelr_notes|Joel's notes]]
*** [http://boomswaggerboom.wordpress.com/2009/06/24/firefox-for-mac-os-x-and-filesystem-related-system-calls/ Josh Aas's post on filesystem calls]
* '''References'''
*** [http://blog.mozilla.com/tglek/2009/07/01/python-gdb-logging-file-io/ Taras' post] on using GDB for logging
** [http://boomswaggerboom.wordpress.com/2009/06/24/firefox-for-mac-os-x-and-filesystem-related-system-calls/ Josh Aas's post]
*** [[Firefox/Projects/Startup_Time_Improvements/IO_Scratchpad]]
** [http://blog.mozilla.com/tglek/2009/07/01/python-gdb-logging-file-io/ Taras' post] on using GDB for logging
*** [[Firefox/Projects/Startup_Time_Improvements/adw_notes|Drew's notes]]
** [[Firefox/Projects/Startup_Time_Improvements/IO_Scratchpad]]
*** [[Firefox/Projects/Startup_Time_Improvements/joelr_notes|Joel's notes]]
 
* Find dead code with JSHydra (David Dahl)
= Static Analysis =
** Status: incomplete, needs tuning and file bugs on dead code found
 
== Find dead code with JSHydra (David Dahl) ==
* '''Status''': in progress
* '''Todo'''
* '''Results'''
* '''Bugs'''
** {{bug|506128}} - run jshydra to find js functions that have no callers
** {{bug|506128}} - run jshydra to find js functions that have no callers
 
* JSHydra continuous testing
= Testing =
** possible test scenarios
 
== Dirty profile testing (Alice, David Dahl, Dietrich) ==
* '''Status''': in progress
* '''Todo'''
** Create various scenarios to measure
*** sessions, downloads, cookies, urlclassifier data
** Fix date updater for med/large profiles
** Roll-up reporting of results
* '''Results'''
** Builds marked "dirty" on the [http://tinderbox.mozilla.org/showbuilds.cgi?tree=MozillaTest test tree]
 
== JSHydra continuous testing ==
* '''Status''': not started
* '''Todo'''
** Feasibility analysis: need to find out if even possible
** Determine test scenarios
*** ending semicolon bug (XXX)
*** ending semicolon bug (XXX)
*** dead code finder
*** dead code finder


= Miscellaneous Improvements =
=Completed Projects=


Notes, other ideas to develop further, bugs to file, etc.
[http://tinyurl.com/yjp8d6w Fixed startup bugs]


TODO:
= References =
* enumerate findings, convert to best practices recommendation
* user-runnable Ts script
** paste into js console
** restarts browser, passing last known time
** loads data URI that reads startup time and prints it out
** record startup timestamp as a pref?


Bugs:
;Meta bugs
* FILEME - minification packaging step
* {{bug|459117}} Fennec performance meta bug
* {{bug|507101}} - component combining packaging step
* {{bug|447581}} Startup meta bug
* {{bug|509755}} - modules into jar file packaging step
* {{bug|479078}} Startup research meta bug
* FILEME - micro-benchmark tests
* {{bug|7251}} very old startup meta bug
** see also the mochitests i wrote for this (find the places bug for this)
* FILEME - dirty test (or micro?): need test for opening the 80th tab for example
* FILEME - tracing/trace-ability reporting
** traceviz ({{bug|497999}})
* FILEME - other dirty profiles
** sessions, downloads, urlclassifier data, post-crash session
* sql query count measurement (find my bug for this)
 
Notes:
* Hot vs. cold testing: running with fastload crippled/disabled
* Needs investigation: [https://bugzilla.mozilla.org/show_bug.cgi?id=279839#c29 string pool for jsxpcom]
 
= References =


* Vlad's blog posts
* Vlad's blog posts
** [http://blog.vlad1.com/2009/06/17/firefox-startup-wrangling/ Vlad's June posting on startup work]
** [http://blog.vlad1.com/2009/06/17/firefox-startup-wrangling/ Vlad's June posting on startup work]
** Vlad's July posts: [http://blog.vlad1.com/2009/07/27/startup-part-1/ 1] [http://blog.vlad1.com/2009/07/27/startup-again/ 2] [http://blog.vlad1.com/2009/07/28/startup-again-2/ 3] [http://blog.vlad1.com/2009/07/28/measuring-startup/ 4] [http://blog.vlad1.com/2009/07/29/startup-again-3/ 5]
** Vlad's July posts:
*** [http://blog.vlad1.com/2009/07/27/startup-part-1/ 1]
*** [http://blog.vlad1.com/2009/07/27/startup-again/ 2 - fs cache]
*** [http://blog.vlad1.com/2009/07/28/startup-again-2/ 3 - event processing]
*** [http://blog.vlad1.com/2009/07/28/measuring-startup/ 4 - measuring startup]  
*** [http://blog.vlad1.com/2009/07/29/startup-again-3/ 5 iosnoop]


* zpao's JS treemap visualizations
* zpao's JS treemap visualizations
Line 133: Line 191:


==Tips, Tools==
==Tips, Tools==
* [http://aegisknight.org/2009/04/flushing-disk-cache/ Flushing Windows' disk cache]
 
* [http://tuvix.apple.com/DOCUMENTATION/Darwin/Reference/ManPages/man8/purge.8.html Flushing Mac OS X's disk cache]
* Cold startup
* [[Firefox/Projects/Startup_Time_Improvements_Notes]]: Vlad's emails about cold startup, including Linux (maybe move this info to this page)
** [http://aegisknight.org/2009/04/flushing-disk-cache/ Flushing Windows' disk cache]
** [http://tuvix.apple.com/DOCUMENTATION/Darwin/Reference/ManPages/man8/purge.8.html Flushing Mac OS X's disk cache]
** [[Firefox/Projects/Startup_Time_Improvements_Notes]]: Vlad's emails about cold startup, including Linux (maybe move this info to this page)
 
* Windows Prefetch/Superfetch
** [http://en.wikipedia.org/wiki/Prefetcher XP Prefetch wiki]
** [http://en.wikipedia.org/wiki/Windows_Vista_I/O_technologies#SuperFetch Vista/Win7 SuperFetch wiki]
** [http://members.rushmore.com/~jsky/id37.html useful Pre/SuperFetch overview]
** [http://jessekornblum.com/presentations/dodcc08-2.html Presentation slides on the guts of Pref/SuperFetch by military forensic analyst]
*** Prefetch
**** Profile for each application: List of DLLs used, Run count, Time stamps
**** Prefetch files stored in %SystemRoot%\Prefetch: .pf extension, Up to 128 are kept
**** Can tell if same app run from multiple locations
*** SuperFetch
**** turn off: net stop sysmain
**** AG*.db files, contain "scenarios" for preloading
** [http://technet.microsoft.com/en-us/magazine/2007.03.vistakernel.aspx Technet article on Vista mem mgmnt]
** [http://www.howtogeek.com/howto/windows-vista/change-superfetch-to-only-cache-system-boot-files-in-vista/ registry keys for toggling SuperFetch]
 
* DTrace
* DTrace
** [https://wiki.mozilla.org/Performance/Optimizing_JavaScript_with_DTrace nuts and bolts how-to for getting dtrace running with mozilla]
** [https://wiki.mozilla.org/Performance/Optimizing_JavaScript_with_DTrace nuts and bolts how-to for getting dtrace running with mozilla]
Line 144: Line 220:
** [http://blogs.sun.com/jmr/entry/dtrace_mozilla_rfe_javascript_tracing brief descriptions of the javascript* probes]
** [http://blogs.sun.com/jmr/entry/dtrace_mozilla_rfe_javascript_tracing brief descriptions of the javascript* probes]
** [http://blog.mozilla.com/dmandelin/2008/02/14/dtrace-c-mysteries-solved/ David Mandelin's notes on tracing C++ code]
** [http://blog.mozilla.com/dmandelin/2008/02/14/dtrace-c-mysteries-solved/ David Mandelin's notes on tracing C++ code]
* comparing dynamic linking time between firefox and safari on mac
** DYLD_PRINT_STATISTICS=YES /Applications/Firefox.app/Contents/MacOS/firefox-bin
** DYLD_PRINT_STATISTICS=YES open -a Safari


==Fastload==
==Fastload==
Line 151: Line 231:


==Measuring Ts==
==Measuring Ts==
* startup-unix.pl in mozilla/tools/performance/startup
 
** edit it to use this HTML in place of startup-test.html:
We've been using a method Vlad blogged about [http://blog.vlad1.com/2009/07/28/measuring-startup/ here]. The steps are below.
<pre style="white-space: pre-wrap">
 
<html>
# save [http://people.mozilla.com/~vladimir/misc/startup.html this html file] somewhere locally
<body onload="
# create a new profile, run Firefox with it at least once, so all files are created, etc
  var now = (new Date()).getTime(); 
# execute this command, with your profile name substituted, and invoking firefox in a way appropriate for your platform:
  var begin = document.location.search.split('=')[1]; // ?begin=nnnnn
 
  dump((now - begin) + '\n');
<code>
  window.close();
./firefox -P YourProfileName -no-remote file:///..../startup.html#`python -c 'import time; print int(time.time() * 1000);'`
">
</code>
</body>
 
</html>
The following is specific to Mac OSX and is required to evict Firefox code pages from memory and clear the Unified Buffer Cache (UBC). <code>purge</code> does NOT do this.
</pre>
 
** set <code>dom.allow_scripts_to_close_windows</code> and <code>browser.dom.window.dump.enabled</code> to true in your testing profile
<pre>
** run it in a loop to collect more stable results:
#!/bin/sh
<pre style="white-space: pre-wrap">
 
#!/bin/bash
FF=/Volumes/Fujitsu80Gb
cd ~/moz/trunk/mozilla/tools/performance/startup
 
for ((i=0; i < 5; i++)) do perl startup-unix.pl ~/moz/trunk/build-dbg/dist/MinefieldDebug.app/Contents/MacOS/firefox-bin -P startup >> results.txt; done;
diskutil unmount force $FF
diskutil mount /dev/disk1s2
 
$FF/Minefield$*.app/Contents/MacOS/firefox-bin -no-remote -foreground -P clean file://$FF/startup.html#`python -c 'import time; print int(time.time() * 1000);'`
</pre>
</pre>
This assumes that your removable media is at /dev/disk1s2.
==Test Coverage==
This is an index of Firefox startup scenarios which need automated test coverage.
TODO:
* groups: chrome, content, extensions, labs, other?
* mark which need no-chrome testing
{| border=solid black 1px
| test || warm start || cold start || notes
|-
| empty profile ||style="background-color: lawngreen"|yes ||style="background-color: lawngreen"|yes ||
|-
| everything dirty || || || {{bug|515540}}
|-
| min places ||style="background-color: lawngreen"|yes ||style="background-color: lawngreen"|yes || informed by places-stats, {{bug|515540}}
|-
| med places ||style="background-color: lawngreen"|yes ||style="background-color: lawngreen"|yes || ditto
|-
| max places ||style="background-color: lawngreen"|yes ||style="background-color: lawngreen"|yes || ditto
|-
| med session || || || informed by test pilot data
|-
| max session || || || ditto
|-
| downloads || || ||
|-
| url-classifier data || || || data is fully downloaded, should test page-load for a match and no match
|-
| form history|| || ||
|-
| passwords || || ||
|-
| plugins || || ||
|-
| content preferences || || ||
|-
| extensions || || || top 5?
|-
| extension update || || ||
|-
| application update || || ||
|-
| persona applied || || ||
|-
| weave || || ||
|-
| jetpack || || ||
|-
| ubiquity || || ||
|-
| page links are visited || || ||
|-
| page has microformats || || ||
|-
| page is ssl || || ||
|-
| page has plugin || || ||
|}

Latest revision as of 17:51, 20 July 2011

Overview

Description: Improve startup time of Firefox and Fennec on all operating systems and platforms, including mobile devices.

Project lead:
Project members: Taras Glek, Ben Hsieh, Steve Fink, Michael Wu, Shawn Wilsher

Bugs: Open | Fixed | Fixed in 3.6

Results: Performance Snapshot (snapshot numbers for last 7 days, and version comparisons)

Graphs: Windows XP | Windows Vista | Mac Leopard | Linux

Status: Weekly status updates

Active Projects

Estimated win Bug # Summary Owner Status Notes
~10% "Dirty Profile" Startup Reduction Constant startup relative to profile size Shawn Wilsher
significant bug 558200 Extension profiler platform api Steve Fink There is an easy way to provide feedback to extension developers to help them figure out why their extension is misbehaving. We need to implement that ASAP, so typical firefox installs(with lots of extensions) can be fast


Help Wanted/Onhold

Estimated win Bug # Summary Owner Status Notes
~8% bug 561842 Fold libraries into libxul Ted Mielczarek proof of concept done
up to 40% bug 531406 Optimize code locality in binaries. Working on enabling pgo atm. Taras Glek Linux almost done, need to figure out integration. Windows proof of concept needs work.

See blog post for more details. Taras and Ehsan working on Windows locality improvements (bug 553721).

~10% bug 512584 Fast paths for Cc/Ci Confirmed win. Unfortunately this approach touches a lot of sensitive code, might be easier to port js to not use Cc/Ci
TBD bug 513149 bug 553456 Speed up CSS parsing Zack Weinberg
significant bug 559663 Measuring IOPs Our current infrastructure does not measure cold startup effectively, it should.
TBD bug 569629 Get rid of static initializers These slowdown library loading, cause a lot of pagefaults on gcc platforms.


Other efforts:

Measurement & Testing Projects

  • cold startup testing

Future Projects

Inactive Projects

  • bug 507101 - combining js components
  • minification
  • Mine the Ts DTrace viz/logs (Drew)
    • Status: complete, moved on to filesystem operations below
    • Results
      • cold startup is heavily I/O-bound. 90% of cold startup time is spent in page faults and other I/O syscalls, especially read, getattrlist, and stat.
      • majority of time spent after Firefox actually gets up and running is in XBL and CSS.
  • Log and mine filesystem operations during startup (Ryan, Drew)
  • Find dead code with JSHydra (David Dahl)
    • Status: incomplete, needs tuning and file bugs on dead code found
    • bug 506128 - run jshydra to find js functions that have no callers
  • JSHydra continuous testing
    • possible test scenarios
      • ending semicolon bug (XXX)
      • dead code finder

Completed Projects

Fixed startup bugs

References

Meta bugs

Tips, Tools

  • comparing dynamic linking time between firefox and safari on mac
    • DYLD_PRINT_STATISTICS=YES /Applications/Firefox.app/Contents/MacOS/firefox-bin
    • DYLD_PRINT_STATISTICS=YES open -a Safari

Fastload

Measuring Ts

We've been using a method Vlad blogged about here. The steps are below.

  1. save this html file somewhere locally
  2. create a new profile, run Firefox with it at least once, so all files are created, etc
  3. execute this command, with your profile name substituted, and invoking firefox in a way appropriate for your platform:

./firefox -P YourProfileName -no-remote file:///..../startup.html#`python -c 'import time; print int(time.time() * 1000);'`

The following is specific to Mac OSX and is required to evict Firefox code pages from memory and clear the Unified Buffer Cache (UBC). purge does NOT do this.

#!/bin/sh

FF=/Volumes/Fujitsu80Gb

diskutil unmount force $FF
diskutil mount /dev/disk1s2

$FF/Minefield$*.app/Contents/MacOS/firefox-bin -no-remote -foreground -P clean file://$FF/startup.html#`python -c 'import time; print int(time.time() * 1000);'`

This assumes that your removable media is at /dev/disk1s2.

Test Coverage

This is an index of Firefox startup scenarios which need automated test coverage.

TODO:

  • groups: chrome, content, extensions, labs, other?
  • mark which need no-chrome testing
test warm start cold start notes
empty profile yes yes
everything dirty bug 515540
min places yes yes informed by places-stats, bug 515540
med places yes yes ditto
max places yes yes ditto
med session informed by test pilot data
max session ditto
downloads
url-classifier data data is fully downloaded, should test page-load for a match and no match
form history
passwords
plugins
content preferences
extensions top 5?
extension update
application update
persona applied
weave
jetpack
ubiquity
page links are visited
page has microformats
page is ssl
page has plugin