Import Cobalt 9.70858
diff --git a/src/cobalt/base/c_val.h b/src/cobalt/base/c_val.h index 48227bf..92f8f6c 100644 --- a/src/cobalt/base/c_val.h +++ b/src/cobalt/base/c_val.h
@@ -567,7 +567,7 @@ std::string description_; CValType type_; - friend CValManager; + friend class base::CValManager; }; // This is a wrapper class that marks that we wish to track a value through
diff --git a/src/cobalt/browser/application.cc b/src/cobalt/browser/application.cc index cacaa86..934cdfb 100644 --- a/src/cobalt/browser/application.cc +++ b/src/cobalt/browser/application.cc
@@ -51,22 +51,15 @@ #endif // defined(__LB_SHELL__FOR_RELEASE__) #include "lbshell/src/lb_memory_pages.h" #endif // defined(__LB_SHELL__) -#if defined(OS_STARBOARD) #include "nb/lexical_cast.h" #include "starboard/configuration.h" #include "starboard/log.h" -#endif // defined(OS_STARBOARD) namespace cobalt { namespace browser { namespace { const int kStatUpdatePeriodMs = 1000; -#if defined(COBALT_BUILD_TYPE_GOLD) -const int kLiteStatUpdatePeriodMs = 1000; -#else -const int kLiteStatUpdatePeriodMs = 16; -#endif const char kDefaultURL[] = "https://www.youtube.com/tv"; @@ -380,8 +373,8 @@ : message_loop_(MessageLoop::current()), quit_closure_(quit_closure), start_time_(base::TimeTicks::Now()), - stats_update_timer_(true, true), - lite_stats_update_timer_(true, true) { + c_val_stats_(start_time_), + stats_update_timer_(true, true) { // Check to see if a timed_trace has been set, indicating that we should // begin a timed trace upon startup. base::TimeDelta trace_duration = GetTimedTraceDuration(); @@ -406,10 +399,6 @@ stats_update_timer_.Start( FROM_HERE, base::TimeDelta::FromMilliseconds(kStatUpdatePeriodMs), base::Bind(&Application::UpdatePeriodicStats, base::Unretained(this))); - lite_stats_update_timer_.Start( - FROM_HERE, base::TimeDelta::FromMilliseconds(kLiteStatUpdatePeriodMs), - base::Bind(&Application::UpdatePeriodicLiteStats, - base::Unretained(this))); // Get the initial URL. GURL initial_url = GetInitialURL(); @@ -695,7 +684,7 @@ #endif } -Application::CValStats::CValStats() +Application::CValStats::CValStats(base::TimeTicks start_time) : free_cpu_memory("Memory.CPU.Free", 0, "Total free application CPU memory remaining."), used_cpu_memory("Memory.CPU.Used", 0, @@ -704,16 +693,16 @@ exe_memory("Memory.CPU.Exe", 0, "Total memory occupied by the size of the executable."), #endif + app_start_time("Time.Cobalt.Start", start_time.ToInternalValue(), + "Start time of the application in microseconds."), app_lifetime("Cobalt.Lifetime", base::TimeDelta(), - "Application lifetime.") { -#if defined(OS_STARBOARD) + "Application lifetime in microseconds.") { if (SbSystemHasCapability(kSbSystemCapabilityCanQueryGPUMemoryStats)) { free_gpu_memory.emplace("Memory.GPU.Free", 0, "Total free application GPU memory remaining."); used_gpu_memory.emplace("Memory.GPU.Used", 0, "Total GPU memory allocated by the application."); } -#endif // defined(OS_STARBOARD) } void Application::RegisterUserLogs() { @@ -764,10 +753,6 @@ } } -void Application::UpdatePeriodicLiteStats() { - c_val_stats_.app_lifetime = base::TimeTicks::Now() - start_time_; -} - math::Size Application::InitSystemWindow(CommandLine* command_line) { base::optional<math::Size> viewport_size; if (command_line->HasSwitch(browser::switches::kViewport)) { @@ -821,6 +806,8 @@ void Application::UpdatePeriodicStats() { TRACE_EVENT0("cobalt::browser", "Application::UpdatePeriodicStats()"); + c_val_stats_.app_lifetime = base::TimeTicks::Now() - start_time_; + #if defined(__LB_SHELL__) bool memory_stats_updated = false; #if !defined(__LB_SHELL__FOR_RELEASE__)
diff --git a/src/cobalt/browser/application.h b/src/cobalt/browser/application.h index 2c10118..e700d83 100644 --- a/src/cobalt/browser/application.h +++ b/src/cobalt/browser/application.h
@@ -126,7 +126,7 @@ // Stats related struct CValStats { - CValStats(); + explicit CValStats(base::TimeTicks start_time); base::CVal<base::cval::SizeInBytes, base::CValPublic> free_cpu_memory; base::CVal<base::cval::SizeInBytes, base::CValPublic> used_cpu_memory; @@ -143,6 +143,7 @@ base::CVal<base::cval::SizeInBytes, base::CValPublic> exe_memory; #endif + base::CVal<int64> app_start_time; base::CVal<base::TimeDelta, base::CValPublic> app_lifetime; }; @@ -150,7 +151,6 @@ void UpdateAndMaybeRegisterUserAgent(); void UpdatePeriodicStats(); - void UpdatePeriodicLiteStats(); math::Size InitSystemWindow(CommandLine* command_line); @@ -170,7 +170,6 @@ CValStats c_val_stats_; base::Timer stats_update_timer_; - base::Timer lite_stats_update_timer_; scoped_ptr<memory_tracker::MemoryTrackerTool> memory_tracker_tool_; };
diff --git a/src/cobalt/browser/browser_module.cc b/src/cobalt/browser/browser_module.cc index 6ed091f..e0334fb 100644 --- a/src/cobalt/browser/browser_module.cc +++ b/src/cobalt/browser/browser_module.cc
@@ -231,6 +231,10 @@ web_module_loaded_(true /* manually_reset */, false /* initially_signalled */), web_module_recreated_callback_(options.web_module_recreated_callback), + navigate_time_("Time.Browser.Navigate", 0, + "The last time a navigation occurred."), + on_load_event_time_("Time.Browser.OnLoadEvent", 0, + "The last time the window.OnLoad event fired."), #if defined(ENABLE_DEBUG_CONSOLE) ALLOW_THIS_IN_INITIALIZER_LIST(fuzzer_toggle_command_handler_( kFuzzerToggleCommand, @@ -397,6 +401,10 @@ // run. web_module_.reset(NULL); + // Wait until after the old WebModule is destroyed before setting the navigate + // time so that it won't be included in the time taken to load the URL. + navigate_time_ = base::TimeTicks::Now().ToInternalValue(); + // Show a splash screen while we're waiting for the web page to load. const math::Size& viewport_size = renderer_module_.render_target()->GetSize(); DestroySplashScreen(); @@ -463,6 +471,7 @@ // changed unless the corresponding benchmark logic is changed as well. LOG(INFO) << "Loaded WebModule"; + on_load_event_time_ = base::TimeTicks::Now().ToInternalValue(); web_module_loaded_.Signal(); }
diff --git a/src/cobalt/browser/browser_module.h b/src/cobalt/browser/browser_module.h index fcb24ad..5712937 100644 --- a/src/cobalt/browser/browser_module.h +++ b/src/cobalt/browser/browser_module.h
@@ -310,6 +310,13 @@ // which could occur on navigation. base::Closure web_module_recreated_callback_; + // The time when a URL navigation starts. This is recorded after the previous + // WebModule is destroyed. + base::CVal<int64> navigate_time_; + + // The time when the WebModule's Window.onload event is fired. + base::CVal<int64> on_load_event_time_; + #if defined(ENABLE_DEBUG_CONSOLE) // Possibly null, but if not, will contain a reference to an instance of // a debug fuzzer input device manager.
diff --git a/src/cobalt/browser/web_module.cc b/src/cobalt/browser/web_module.cc index a3d807a..79d56ea 100644 --- a/src/cobalt/browser/web_module.cc +++ b/src/cobalt/browser/web_module.cc
@@ -35,6 +35,7 @@ #include "cobalt/dom/blob.h" #include "cobalt/dom/csp_delegate_factory.h" #include "cobalt/dom/element.h" +#include "cobalt/dom/global_stats.h" #include "cobalt/dom/local_storage_database.h" #include "cobalt/dom/mutation_observer_task_manager.h" #include "cobalt/dom/storage.h" @@ -631,7 +632,15 @@ DCHECK(thread_checker_.CalledOnValidThread()); DCHECK(is_running_); DCHECK(script_runner_); + + // JavaScript is being run. Track it in the global stats. + dom::GlobalStats::GetInstance()->StartJavaScriptEvent(); + *result = script_runner_->Execute(script_utf8, script_location); + + // JavaScript is done running. Stop tracking it in the global stats. + dom::GlobalStats::GetInstance()->StopJavaScriptEvent(); + got_result->Signal(); }
diff --git a/src/cobalt/browser/web_module_stat_tracker.cc b/src/cobalt/browser/web_module_stat_tracker.cc index bb5f370..4151969 100644 --- a/src/cobalt/browser/web_module_stat_tracker.cc +++ b/src/cobalt/browser/web_module_stat_tracker.cc
@@ -80,6 +80,7 @@ // If this is a valid event type, then start tracking it. if (current_event_type_ != kEventTypeInvalid) { event_is_processing_ = true; + event_start_time_ = base::TimeTicks::Now(); dom_stat_tracker_->OnStartEvent(); layout_stat_tracker_->OnStartEvent(); @@ -128,6 +129,12 @@ StringPrintf("Event.Count.%s.DOM.HtmlElement.Destroyed", name.c_str()), 0, "Number of HTML elements destroyed."), + count_dom_html_elements_added( + StringPrintf("Event.Count.%s.DOM.HtmlElement.Added", name.c_str()), 0, + "Number of HTML elements added to document."), + count_dom_html_elements_removed( + StringPrintf("Event.Count.%s.DOM.HtmlElement.Removed", name.c_str()), + 0, "Number of HTML elements removed from document."), count_dom_update_matching_rules( StringPrintf("Event.Count.%s.DOM.HtmlElement.UpdateMatchingRules", name.c_str()), @@ -225,6 +232,8 @@ void WebModuleStatTracker::EndCurrentEvent(bool was_render_tree_produced) { if (current_event_type_ == kEventTypeInvalid) { + dom_stat_tracker_->OnEndEvent(); + layout_stat_tracker_->OnEndEvent(); return; } @@ -240,6 +249,10 @@ dom_stat_tracker_->html_elements_created_count(); event_stats->count_dom_html_elements_destroyed = dom_stat_tracker_->html_elements_destroyed_count(); + event_stats->count_dom_html_elements_added = + dom_stat_tracker_->html_elements_added_to_document_count(); + event_stats->count_dom_html_elements_removed = + dom_stat_tracker_->html_elements_removed_from_document_count(); event_stats->count_dom_update_matching_rules = dom_stat_tracker_->update_matching_rules_count(); event_stats->count_dom_update_computed_style = @@ -283,17 +296,31 @@ layout::LayoutStatTracker::kStopWatchTypeRenderAndAnimate); #if defined(ENABLE_WEBDRIVER) + // Include the event's numbers in the total counts. + int html_elements_count = dom_stat_tracker_->html_elements_count() + + dom_stat_tracker_->html_elements_created_count() - + dom_stat_tracker_->html_elements_destroyed_count(); + int document_html_elements_count = + dom_stat_tracker_->document_html_elements_count() + + dom_stat_tracker_->html_elements_added_to_document_count() - + dom_stat_tracker_->html_elements_removed_from_document_count(); + int layout_boxes_count = layout_stat_tracker_->total_boxes() + + layout_stat_tracker_->boxes_created_count() - + layout_stat_tracker_->boxes_destroyed_count(); + // When the Webdriver is enabled, all of the event's values are stored within // a single string representing a dictionary of key-value pairs. This allows // the Webdriver to query a single CVal to retrieve all of the event's values. std::ostringstream oss; oss << "{" + << "\"StartTime\":" << event_start_time_.ToInternalValue() << ", " << "\"ProducedRenderTree\":" << was_render_tree_produced << ", " << "\"CntDomEventListeners\":" << dom::GlobalStats::GetInstance()->GetNumEventListeners() << ", " << "\"CntDomNodes\":" << dom::GlobalStats::GetInstance()->GetNumNodes() << ", " - << "\"CntDomHtmlElements\":" << dom_stat_tracker_->total_html_elements() + << "\"CntDomHtmlElements\":" << html_elements_count << ", " + << "\"CntDomDocumentHtmlElements\":" << document_html_elements_count << ", " << "\"CntDomHtmlElementsCreated\":" << dom_stat_tracker_->html_elements_created_count() << ", " @@ -306,7 +333,7 @@ << "\"CntDomGeneratePseudoComputedStyle\":" << dom_stat_tracker_->generate_pseudo_element_computed_style_count() << ", " - << "\"CntLayoutBoxes\":" << layout_stat_tracker_->total_boxes() << ", " + << "\"CntLayoutBoxes\":" << layout_boxes_count << ", " << "\"CntLayoutBoxesCreated\":" << layout_stat_tracker_->boxes_created_count() << ", " << "\"CntLayoutUpdateSize\":" << layout_stat_tracker_->update_size_count()
diff --git a/src/cobalt/browser/web_module_stat_tracker.h b/src/cobalt/browser/web_module_stat_tracker.h index 3956a52..08ae658 100644 --- a/src/cobalt/browser/web_module_stat_tracker.h +++ b/src/cobalt/browser/web_module_stat_tracker.h
@@ -19,6 +19,7 @@ #include <vector> #include "base/memory/scoped_vector.h" +#include "base/time.h" #include "cobalt/base/c_val.h" #include "cobalt/base/stop_watch.h" #include "cobalt/dom/dom_stat_tracker.h" @@ -83,6 +84,8 @@ // Count-related base::CVal<int, base::CValPublic> count_dom_html_elements_created; base::CVal<int, base::CValPublic> count_dom_html_elements_destroyed; + base::CVal<int, base::CValPublic> count_dom_html_elements_added; + base::CVal<int, base::CValPublic> count_dom_html_elements_removed; base::CVal<int, base::CValPublic> count_dom_update_matching_rules; base::CVal<int, base::CValPublic> count_dom_update_computed_style; base::CVal<int, base::CValPublic> @@ -144,7 +147,8 @@ std::string name_; - base::CVal<bool, base::CValPublic> event_is_processing_; + base::CVal<bool> event_is_processing_; + base::TimeTicks event_start_time_; }; } // namespace browser
diff --git a/src/cobalt/build/build.id b/src/cobalt/build/build.id index 210cbad..b145a60 100644 --- a/src/cobalt/build/build.id +++ b/src/cobalt/build/build.id
@@ -1 +1 @@ -62469 \ No newline at end of file +70858 \ No newline at end of file
diff --git a/src/cobalt/dom/animation_frame_request_callback_list.cc b/src/cobalt/dom/animation_frame_request_callback_list.cc index 6108afc..e20138e 100644 --- a/src/cobalt/dom/animation_frame_request_callback_list.cc +++ b/src/cobalt/dom/animation_frame_request_callback_list.cc
@@ -15,6 +15,7 @@ #include "cobalt/dom/animation_frame_request_callback_list.h" #include "base/debug/trace_event.h" +#include "cobalt/dom/global_stats.h" namespace cobalt { namespace dom { @@ -44,12 +45,18 @@ TRACE_EVENT1("cobalt::dom", "Window::RunAnimationFrameCallbacks()", "number_of_callbacks", frame_request_callbacks_.size()); + // The callbacks are now being run. Track it in the global stats. + GlobalStats::GetInstance()->StartJavaScriptEvent(); + for (InternalList::const_iterator iter = frame_request_callbacks_.begin(); iter != frame_request_callbacks_.end(); ++iter) { if (!(*iter)->cancelled) { (*iter)->callback.value().Run(animation_time); } } + + // The callbacks are done running. Stop tracking it in the global stats. + GlobalStats::GetInstance()->StopJavaScriptEvent(); } bool AnimationFrameRequestCallbackList::HasPendingCallbacks() const {
diff --git a/src/cobalt/dom/dom_stat_tracker.cc b/src/cobalt/dom/dom_stat_tracker.cc index cadf09e..e2e1219 100644 --- a/src/cobalt/dom/dom_stat_tracker.cc +++ b/src/cobalt/dom/dom_stat_tracker.cc
@@ -20,17 +20,28 @@ namespace dom { DomStatTracker::DomStatTracker(const std::string& name) - : total_html_elements_( - StringPrintf("Count.%s.DOM.HtmlElement", name.c_str()), 0, + : html_elements_count_( + StringPrintf("Count.%s.DOM.HtmlElement.Total", name.c_str()), 0, "Total number of HTML elements."), + document_html_elements_count_( + StringPrintf("Count.%s.DOM.HtmlElement.Document", name.c_str()), 0, + "Number of HTML elements in the document."), is_event_active_(false), event_video_start_delay_stop_watch_(kStopWatchTypeEventVideoStartDelay, base::StopWatch::kAutoStartOff, this), event_video_start_delay_( StringPrintf("Event.Duration.%s.DOM.VideoStartDelay", name.c_str()), base::TimeDelta(), "Total delay between event and video starting."), + script_element_execute_count_( + StringPrintf("Count.%s.DOM.HtmlScriptElement.Execute", name.c_str()), + 0, "Count of HTML script element execute calls."), + script_element_execute_time_( + StringPrintf("Time.%s.DOM.HtmlScriptElement.Execute", name.c_str()), + 0, "Time of the last HTML script element execute."), html_elements_created_count_(0), html_elements_destroyed_count_(0), + html_elements_inserted_into_document_count_(0), + html_elements_removed_from_document_count_(0), update_matching_rules_count_(0), update_computed_style_count_(0), generate_html_element_computed_style_count_(0), @@ -41,8 +52,10 @@ DomStatTracker::~DomStatTracker() { FlushPeriodicTracking(); - // Verify that all of the elements were destroyed. - DCHECK_EQ(total_html_elements_, 0); + // Verify that all of the elements were removed from the document and + // destroyed. + DCHECK_EQ(html_elements_count_, 0); + DCHECK_EQ(document_html_elements_count_, 0); event_video_start_delay_stop_watch_.Stop(); } @@ -84,12 +97,25 @@ } } +void DomStatTracker::OnHtmlScriptElementExecuted() { + ++script_element_execute_count_; + script_element_execute_time_ = base::TimeTicks::Now().ToInternalValue(); +} + void DomStatTracker::OnHtmlElementCreated() { ++html_elements_created_count_; } void DomStatTracker::OnHtmlElementDestroyed() { ++html_elements_destroyed_count_; } +void DomStatTracker::OnHtmlElementInsertedIntoDocument() { + ++html_elements_inserted_into_document_count_; +} + +void DomStatTracker::OnHtmlElementRemovedFromDocument() { + ++html_elements_removed_from_document_count_; +} + void DomStatTracker::OnUpdateMatchingRules() { ++update_matching_rules_count_; } void DomStatTracker::OnUpdateComputedStyle() { ++update_computed_style_count_; } @@ -117,12 +143,16 @@ void DomStatTracker::FlushPeriodicTracking() { // Update the CVals before clearing the periodic values. - total_html_elements_ += + html_elements_count_ += html_elements_created_count_ - html_elements_destroyed_count_; + document_html_elements_count_ += html_elements_inserted_into_document_count_ - + html_elements_removed_from_document_count_; // Now clear the values. html_elements_created_count_ = 0; html_elements_destroyed_count_ = 0; + html_elements_inserted_into_document_count_ = 0; + html_elements_removed_from_document_count_ = 0; update_matching_rules_count_ = 0; update_computed_style_count_ = 0; generate_html_element_computed_style_count_ = 0;
diff --git a/src/cobalt/dom/dom_stat_tracker.h b/src/cobalt/dom/dom_stat_tracker.h index 6e34ab2..35cedb7 100644 --- a/src/cobalt/dom/dom_stat_tracker.h +++ b/src/cobalt/dom/dom_stat_tracker.h
@@ -42,16 +42,22 @@ void OnEndEvent(); void OnHtmlVideoElementPlaying(); + void OnHtmlScriptElementExecuted(); // Periodic count-related void OnHtmlElementCreated(); void OnHtmlElementDestroyed(); + void OnHtmlElementInsertedIntoDocument(); + void OnHtmlElementRemovedFromDocument(); void OnUpdateMatchingRules(); void OnUpdateComputedStyle(); void OnGenerateHtmlElementComputedStyle(); void OnGeneratePseudoElementComputedStyle(); - int total_html_elements() const { return total_html_elements_; } + int html_elements_count() const { return html_elements_count_; } + int document_html_elements_count() const { + return document_html_elements_count_; + } int html_elements_created_count() const { return html_elements_created_count_; @@ -59,6 +65,12 @@ int html_elements_destroyed_count() const { return html_elements_destroyed_count_; } + int html_elements_added_to_document_count() const { + return html_elements_inserted_into_document_count_; + } + int html_elements_removed_from_document_count() const { + return html_elements_removed_from_document_count_; + } int update_matching_rules_count() const { return update_matching_rules_count_; } @@ -84,7 +96,8 @@ void FlushPeriodicTracking(); // Count cvals that are updated when the periodic tracking is flushed. - base::CVal<int, base::CValPublic> total_html_elements_; + base::CVal<int, base::CValPublic> html_elements_count_; + base::CVal<int, base::CValPublic> document_html_elements_count_; // Event-related bool is_event_active_; @@ -93,10 +106,16 @@ base::StopWatch event_video_start_delay_stop_watch_; base::CVal<base::TimeDelta> event_video_start_delay_; + // Count of HtmlScriptElement::Execute() calls and time of last call. + base::CVal<int> script_element_execute_count_; + base::CVal<int64> script_element_execute_time_; + // Periodic counts. The counts are cleared after the CVals are updated in // |FlushPeriodicTracking|. int html_elements_created_count_; int html_elements_destroyed_count_; + int html_elements_inserted_into_document_count_; + int html_elements_removed_from_document_count_; int update_matching_rules_count_; int update_computed_style_count_; int generate_html_element_computed_style_count_;
diff --git a/src/cobalt/dom/event_target.cc b/src/cobalt/dom/event_target.cc index b923be1..ca6593c 100644 --- a/src/cobalt/dom/event_target.cc +++ b/src/cobalt/dom/event_target.cc
@@ -83,10 +83,18 @@ return false; } + // The event is now being dispatched. Track it in the global stats. + GlobalStats::GetInstance()->StartJavaScriptEvent(); + event->set_target(this); event->set_event_phase(Event::kAtTarget); FireEventOnListeners(event); event->set_event_phase(Event::kNone); + + // The event has completed being dispatched. Stop tracking it in the global + // stats. + GlobalStats::GetInstance()->StopJavaScriptEvent(); + return !event->default_prevented(); }
diff --git a/src/cobalt/dom/global_stats.cc b/src/cobalt/dom/global_stats.cc index 8dc8f94..b2de28e 100644 --- a/src/cobalt/dom/global_stats.cc +++ b/src/cobalt/dom/global_stats.cc
@@ -42,9 +42,9 @@ "Total number of currently active nodes."), num_node_lists_("Count.DOM.NodeLists", 0, "Total number of currently active node lists."), - num_active_dispatch_events_( - "Count.DOM.ActiveDispatchEvents", 0, - "Total number of currently active dispatch events."), + num_active_java_script_events_( + "Count.DOM.ActiveJavaScriptEvents", 0, + "Total number of currently active JavaScript events."), num_xhrs_("Count.XHR", 0, "Total number of currently active XHRs."), xhr_memory_("Memory.XHR", 0, "Memory allocated by XHRs in bytes.") {} @@ -55,7 +55,8 @@ num_dom_token_lists_ == 0 && num_event_listeners_ == 0 && num_html_collections_ == 0 && num_named_node_maps_ == 0 && num_nodes_ == 0 && num_node_lists_ == 0 && - num_active_dispatch_events_ == 0 && num_xhrs_ == 0 && xhr_memory_ == 0; + num_active_java_script_events_ == 0 && num_xhrs_ == 0 && + xhr_memory_ == 0; } void GlobalStats::Add(Attr* /*object*/) { ++num_attrs_; } @@ -92,9 +93,9 @@ void GlobalStats::RemoveEventListener() { --num_event_listeners_; } -void GlobalStats::StartDispatchEvent() { ++num_active_dispatch_events_; } +void GlobalStats::StartJavaScriptEvent() { ++num_active_java_script_events_; } -void GlobalStats::StopDispatchEvent() { --num_active_dispatch_events_; } +void GlobalStats::StopJavaScriptEvent() { --num_active_java_script_events_; } void GlobalStats::Add(xhr::XMLHttpRequest* /* object */) { ++num_xhrs_; }
diff --git a/src/cobalt/dom/global_stats.h b/src/cobalt/dom/global_stats.h index 75d4feb..413fc90 100644 --- a/src/cobalt/dom/global_stats.h +++ b/src/cobalt/dom/global_stats.h
@@ -62,8 +62,8 @@ int GetNumEventListeners() const { return num_event_listeners_; } int GetNumNodes() const { return num_nodes_; } - void StartDispatchEvent(); - void StopDispatchEvent(); + void StartJavaScriptEvent(); + void StopJavaScriptEvent(); void Add(xhr::XMLHttpRequest* object); void Remove(xhr::XMLHttpRequest* object); @@ -84,7 +84,7 @@ base::CVal<int, base::CValPublic> num_nodes_; base::CVal<int> num_node_lists_; - base::CVal<int> num_active_dispatch_events_; + base::CVal<int> num_active_java_script_events_; // XHR-related tracking base::CVal<int> num_xhrs_;
diff --git a/src/cobalt/dom/html_element.cc b/src/cobalt/dom/html_element.cc index d9830c1..5f7e200 100644 --- a/src/cobalt/dom/html_element.cc +++ b/src/cobalt/dom/html_element.cc
@@ -750,7 +750,11 @@ HTMLElement::~HTMLElement() { --(non_trivial_static_fields.Get().html_element_count_log.count); + if (IsInDocument()) { + dom_stat_tracker_->OnHtmlElementRemovedFromDocument(); + } dom_stat_tracker_->OnHtmlElementDestroyed(); + style_->set_mutation_observer(NULL); } @@ -758,10 +762,14 @@ directionality_ = other.directionality_; } -void HTMLElement::OnMutation() { InvalidateMatchingRulesRecursively(); } +void HTMLElement::OnInsertedIntoDocument() { + Node::OnInsertedIntoDocument(); + dom_stat_tracker_->OnHtmlElementInsertedIntoDocument(); +} void HTMLElement::OnRemovedFromDocument() { Node::OnRemovedFromDocument(); + dom_stat_tracker_->OnHtmlElementRemovedFromDocument(); // When an element that is focused stops being a focusable element, or stops // being focused without another element being explicitly focused in its @@ -779,6 +787,8 @@ } } +void HTMLElement::OnMutation() { InvalidateMatchingRulesRecursively(); } + void HTMLElement::OnSetAttribute(const std::string& name, const std::string& value) { if (name == "class" || name == "id") {
diff --git a/src/cobalt/dom/html_element.h b/src/cobalt/dom/html_element.h index bae437d..608b865 100644 --- a/src/cobalt/dom/html_element.h +++ b/src/cobalt/dom/html_element.h
@@ -269,6 +269,9 @@ HTMLElement(Document* document, base::Token tag_name); ~HTMLElement() OVERRIDE; + void OnInsertedIntoDocument() OVERRIDE; + void OnRemovedFromDocument() OVERRIDE; + void CopyDirectionality(const HTMLElement& other); // HTMLElement keeps a pointer to the dom stat tracker to ensure that it can @@ -279,7 +282,6 @@ private: // From Node. void OnMutation() OVERRIDE; - void OnRemovedFromDocument() OVERRIDE; // From Element. void OnSetAttribute(const std::string& name,
diff --git a/src/cobalt/dom/html_media_element.cc b/src/cobalt/dom/html_media_element.cc index 384816c..0dbebf1 100644 --- a/src/cobalt/dom/html_media_element.cc +++ b/src/cobalt/dom/html_media_element.cc
@@ -1166,7 +1166,6 @@ if (ready_state_ >= WebMediaPlayer::kReadyStateHaveMetadata && old_state < WebMediaPlayer::kReadyStateHaveMetadata) { - PlayerOutputModeUpdated(); duration_ = player_->GetDuration(); ScheduleOwnEvent(base::Tokens::durationchange()); ScheduleOwnEvent(base::Tokens::loadedmetadata()); @@ -1583,6 +1582,15 @@ EndProcessingMediaPlayerCallback(); } +void HTMLMediaElement::OutputModeChanged() { + TRACE_EVENT0("cobalt::dom", "HTMLMediaElement::OutputModeChanged"); + // If the player mode is updated, trigger a re-layout so that we can setup + // the video render tree differently depending on whether we are in punch-out + // or decode-to-texture. + node_document()->OnDOMMutation(); + InvalidateLayoutBoxesOfNodeAndAncestors(); +} + void HTMLMediaElement::PlaybackStateChanged() { if (!player_) { return; @@ -1784,13 +1792,5 @@ } #endif // !defined(COBALT_MEDIA_SOURCE_2016) -void HTMLMediaElement::PlayerOutputModeUpdated() { - // If the player mode is updated, trigger a re-layout so that we can setup - // the video render tree differently depending on whether we are in punch-out - // or decode-to-texture. - node_document()->OnDOMMutation(); - InvalidateLayoutBoxesOfNodeAndAncestors(); -} - } // namespace dom } // namespace cobalt
diff --git a/src/cobalt/dom/html_media_element.h b/src/cobalt/dom/html_media_element.h index a45eb4e..b3d1f0d 100644 --- a/src/cobalt/dom/html_media_element.h +++ b/src/cobalt/dom/html_media_element.h
@@ -233,6 +233,7 @@ void ReadyStateChanged() OVERRIDE; void TimeChanged() OVERRIDE; void DurationChanged() OVERRIDE; + void OutputModeChanged() OVERRIDE; void PlaybackStateChanged() OVERRIDE; void SawUnsupportedTracks() OVERRIDE; float Volume() const OVERRIDE; @@ -264,10 +265,6 @@ void SetSourceState(MediaSourceReadyState ready_state); #endif // !defined(COBALT_MEDIA_SOURCE_2016) - // Called whenever the player's output mode (e.g. punch-out, - // decode-to-texture) is updated. - void PlayerOutputModeUpdated(); - scoped_ptr<WebMediaPlayer> player_; std::string current_src_;
diff --git a/src/cobalt/dom/html_script_element.cc b/src/cobalt/dom/html_script_element.cc index 840458d..9af2bcc 100644 --- a/src/cobalt/dom/html_script_element.cc +++ b/src/cobalt/dom/html_script_element.cc
@@ -23,6 +23,7 @@ #include "cobalt/base/tokens.h" #include "cobalt/dom/csp_delegate.h" #include "cobalt/dom/document.h" +#include "cobalt/dom/global_stats.h" #include "cobalt/dom/html_element_context.h" #include "cobalt/loader/fetcher_factory.h" #include "cobalt/loader/sync_loader.h" @@ -506,6 +507,9 @@ return; } + // The script is now being run. Track it in the global stats. + GlobalStats::GetInstance()->StartJavaScriptEvent(); + TRACE_EVENT2("cobalt::dom", "HTMLScriptElement::Execute()", "file_path", script_location.file_path, "line_number", script_location.line_number); @@ -536,6 +540,12 @@ PreventGarbageCollectionAndPostToDispatchEvent( FROM_HERE, base::Tokens::readystatechange()); } + + // The script is done running. Stop tracking it in the global stats. + GlobalStats::GetInstance()->StopJavaScriptEvent(); + + // Notify the DomStatTracker of the execution. + dom_stat_tracker_->OnHtmlScriptElementExecuted(); } void HTMLScriptElement::PreventGarbageCollectionAndPostToDispatchEvent(
diff --git a/src/cobalt/dom/node.cc b/src/cobalt/dom/node.cc index b1f0569..6b15337 100644 --- a/src/cobalt/dom/node.cc +++ b/src/cobalt/dom/node.cc
@@ -100,7 +100,7 @@ } // The event is now being dispatched. Track it in the global stats. - GlobalStats::GetInstance()->StartDispatchEvent(); + GlobalStats::GetInstance()->StartJavaScriptEvent(); typedef std::vector<scoped_refptr<Node> > Ancestors; Ancestors ancestors; @@ -139,7 +139,7 @@ // The event has completed being dispatched. Stop tracking it in the global // stats. - GlobalStats::GetInstance()->StopDispatchEvent(); + GlobalStats::GetInstance()->StopJavaScriptEvent(); return !event->default_prevented(); }
diff --git a/src/cobalt/dom/node.h b/src/cobalt/dom/node.h index e1fbecb..c91e304 100644 --- a/src/cobalt/dom/node.h +++ b/src/cobalt/dom/node.h
@@ -248,6 +248,8 @@ // removed from to its owner document. virtual void OnRemovedFromDocument(); + virtual bool IsInDocument() const { return inserted_into_document_; } + virtual void PurgeCachedBackgroundImagesOfNodeAndDescendants(); virtual void InvalidateComputedStylesOfNodeAndDescendants(); virtual void InvalidateLayoutBoxesOfNodeAndAncestors();
diff --git a/src/cobalt/dom/window_timers.cc b/src/cobalt/dom/window_timers.cc index 792ae47..265d0db 100644 --- a/src/cobalt/dom/window_timers.cc +++ b/src/cobalt/dom/window_timers.cc
@@ -18,6 +18,8 @@ #include "base/bind.h" #include "base/bind_helpers.h" +#include "base/debug/trace_event.h" +#include "cobalt/dom/global_stats.h" #include "nb/memory_scope.h" namespace cobalt { @@ -85,8 +87,13 @@ } void WindowTimers::RunTimerCallback(int handle) { + TRACE_EVENT0("cobalt::dom", "WindowTimers::RunTimerCallback"); Timers::iterator timer = timers_.find(handle); DCHECK(timer != timers_.end()); + + // The callback is now being run. Track it in the global stats. + GlobalStats::GetInstance()->StartJavaScriptEvent(); + // Keep a |TimerInfo| reference, so it won't be released when running the // callback. scoped_refptr<TimerInfo> timer_info = timer->second; @@ -99,6 +106,9 @@ if (timer != timers_.end() && !timer->second->timer()->IsRunning()) { timers_.erase(timer); } + + // The callback has finished running. Stop tracking it in the global stats. + GlobalStats::GetInstance()->StopJavaScriptEvent(); } } // namespace dom
diff --git a/src/cobalt/loader/resource_cache.h b/src/cobalt/loader/resource_cache.h index 2134423..336d137 100644 --- a/src/cobalt/loader/resource_cache.h +++ b/src/cobalt/loader/resource_cache.h
@@ -512,6 +512,7 @@ base::CVal<base::cval::SizeInBytes, base::CValPublic> size_in_bytes_; base::CVal<base::cval::SizeInBytes, base::CValPublic> capacity_in_bytes_; + base::CVal<int> count_requested_resources_; base::CVal<int> count_loading_resources_; base::CVal<int> count_pending_callbacks_; @@ -539,6 +540,9 @@ "The capacity, in bytes, of the resource cache. " "Exceeding this results in *unused* resources being " "purged."), + count_requested_resources_( + base::StringPrintf("Count.%s.RequestedResources", name_.c_str()), 0, + "The total number of resources that have been requested."), count_loading_resources_( base::StringPrintf("Count.%s.LoadingResources", name_.c_str()), 0, "The number of loading resources that are still outstanding."), @@ -576,6 +580,7 @@ } // If we reach this point, then the resource doesn't exist yet. + ++count_requested_resources_; // Add the resource to a loading set. If no current resources have pending // callbacks, then this resource will block callbacks until it is decoded.
diff --git a/src/cobalt/media/base/pipeline.h b/src/cobalt/media/base/pipeline.h index 82863ce..8516cac 100644 --- a/src/cobalt/media/base/pipeline.h +++ b/src/cobalt/media/base/pipeline.h
@@ -108,7 +108,8 @@ const PipelineStatusCB& error_cb, const PipelineStatusCB& seek_cb, const BufferingStateCB& buffering_state_cb, - const base::Closure& duration_change_cb) = 0; + const base::Closure& duration_change_cb, + const base::Closure& output_mode_change_cb) = 0; // Asynchronously stops the pipeline, executing |stop_cb| when the pipeline // teardown has completed.
diff --git a/src/cobalt/media/base/sbplayer_pipeline.cc b/src/cobalt/media/base/sbplayer_pipeline.cc index 452b4cd..e783005 100644 --- a/src/cobalt/media/base/sbplayer_pipeline.cc +++ b/src/cobalt/media/base/sbplayer_pipeline.cc
@@ -61,6 +61,7 @@ PipelineStatusCB seek_cb; Pipeline::BufferingStateCB buffering_state_cb; base::Closure duration_change_cb; + base::Closure output_mode_change_cb; }; // SbPlayerPipeline is a PipelineBase implementation that uses the SbPlayer @@ -82,7 +83,8 @@ const PipelineStatusCB& ended_cb, const PipelineStatusCB& error_cb, const PipelineStatusCB& seek_cb, const BufferingStateCB& buffering_state_cb, - const base::Closure& duration_change_cb) OVERRIDE; + const base::Closure& duration_change_cb, + const base::Closure& output_mode_change_cb) OVERRIDE; void Stop(const base::Closure& stop_cb) OVERRIDE; void Seek(TimeDelta time, const PipelineStatusCB& seek_cb); @@ -187,6 +189,7 @@ PipelineStatusCB error_cb_; BufferingStateCB buffering_state_cb_; base::Closure duration_change_cb_; + base::Closure output_mode_change_cb_; base::optional<bool> decode_to_texture_output_mode_; // Demuxer reference used for setting the preload value. @@ -259,7 +262,8 @@ const PipelineStatusCB& error_cb, const PipelineStatusCB& seek_cb, const BufferingStateCB& buffering_state_cb, - const base::Closure& duration_change_cb) { + const base::Closure& duration_change_cb, + const base::Closure& output_mode_change_cb) { TRACE_EVENT0("cobalt::media", "SbPlayerPipeline::Start"); DCHECK(demuxer); @@ -268,6 +272,7 @@ DCHECK(!seek_cb.is_null()); DCHECK(!buffering_state_cb.is_null()); DCHECK(!duration_change_cb.is_null()); + DCHECK(!output_mode_change_cb.is_null()); StartTaskParameters parameters; parameters.demuxer = demuxer; @@ -277,6 +282,7 @@ parameters.seek_cb = seek_cb; parameters.buffering_state_cb = buffering_state_cb; parameters.duration_change_cb = duration_change_cb; + parameters.output_mode_change_cb = output_mode_change_cb; message_loop_->PostTask( FROM_HERE, base::Bind(&SbPlayerPipeline::StartTask, this, parameters)); @@ -485,6 +491,7 @@ } buffering_state_cb_ = parameters.buffering_state_cb; duration_change_cb_ = parameters.duration_change_cb; + output_mode_change_cb_ = parameters.output_mode_change_cb; const bool kEnableTextTracks = false; demuxer_->Initialize(this, @@ -584,6 +591,14 @@ } if (player_->IsValid()) { + base::Closure output_mode_change_cb; + { + base::AutoLock auto_lock(lock_); + DCHECK(!output_mode_change_cb_.is_null()); + output_mode_change_cb = base::ResetAndReturn(&output_mode_change_cb_); + } + output_mode_change_cb.Run(); + return; }
diff --git a/src/cobalt/media/blink/webcontentdecryptionmodule_impl.h b/src/cobalt/media/blink/webcontentdecryptionmodule_impl.h index 4d09ac3..30a4fec 100644 --- a/src/cobalt/media/blink/webcontentdecryptionmodule_impl.h +++ b/src/cobalt/media/blink/webcontentdecryptionmodule_impl.h
@@ -53,7 +53,7 @@ scoped_refptr<MediaKeys> GetCdm(); private: - friend CdmSessionAdapter; + friend class CdmSessionAdapter; // Takes reference to |adapter|. explicit WebContentDecryptionModuleImpl(
diff --git a/src/cobalt/media/player/web_media_player.h b/src/cobalt/media/player/web_media_player.h index 94e372d..b3b5cb6 100644 --- a/src/cobalt/media/player/web_media_player.h +++ b/src/cobalt/media/player/web_media_player.h
@@ -196,6 +196,7 @@ virtual void ReadyStateChanged() = 0; virtual void TimeChanged() = 0; virtual void DurationChanged() = 0; + virtual void OutputModeChanged() = 0; virtual void PlaybackStateChanged() = 0; // TODO: Revisit the necessity of the following function. virtual void SetOpaque(bool /* opaque */) {}
diff --git a/src/cobalt/media/player/web_media_player_impl.cc b/src/cobalt/media/player/web_media_player_impl.cc index 623c892..1d9ada5 100644 --- a/src/cobalt/media/player/web_media_player_impl.cc +++ b/src/cobalt/media/player/web_media_player_impl.cc
@@ -695,7 +695,8 @@ BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnPipelineError), BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnPipelineSeek), BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnPipelineBufferingState), - BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnDurationChanged)); + BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnDurationChanged), + BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnOutputModeChanged)); } void WebMediaPlayerImpl::SetNetworkState(WebMediaPlayer::NetworkState state) { @@ -791,5 +792,9 @@ GetClient()->DurationChanged(); } +void WebMediaPlayerImpl::OnOutputModeChanged() { + GetClient()->OutputModeChanged(); +} + } // namespace media } // namespace cobalt
diff --git a/src/cobalt/media/player/web_media_player_impl.h b/src/cobalt/media/player/web_media_player_impl.h index 5f3477b..95fcbbd 100644 --- a/src/cobalt/media/player/web_media_player_impl.h +++ b/src/cobalt/media/player/web_media_player_impl.h
@@ -218,6 +218,7 @@ private: // Callbacks that forward duration change from |pipeline_| to |client_|. void OnDurationChanged(); + void OnOutputModeChanged(); base::Thread pipeline_thread_;
diff --git a/src/cobalt/media/sandbox/web_media_player_helper.cc b/src/cobalt/media/sandbox/web_media_player_helper.cc index adb3afe..58618a2 100644 --- a/src/cobalt/media/sandbox/web_media_player_helper.cc +++ b/src/cobalt/media/sandbox/web_media_player_helper.cc
@@ -37,6 +37,7 @@ void ReadyStateChanged() OVERRIDE {} void TimeChanged() OVERRIDE {} void DurationChanged() OVERRIDE {} + void OutputModeChanged() OVERRIDE {} void PlaybackStateChanged() OVERRIDE {} void SawUnsupportedTracks() OVERRIDE {} float Volume() const OVERRIDE { return 1.f; }
diff --git a/src/cobalt/renderer/pipeline.cc b/src/cobalt/renderer/pipeline.cc index 40a6db2..534f38c 100644 --- a/src/cobalt/renderer/pipeline.cc +++ b/src/cobalt/renderer/pipeline.cc
@@ -88,9 +88,20 @@ rasterize_animations_timer_("Renderer.Rasterize.Animations", kRasterizeAnimationsTimerMaxEntries, true /*enable_entry_list_c_val*/), + new_render_tree_rasterize_count_( + "Count.Renderer.Rasterize.NewRenderTree", 0, + "Total number of new render trees rasterized."), + new_render_tree_rasterize_time_( + "Time.Renderer.Rasterize.NewRenderTree", 0, + "The last time a new render tree was rasterized."), has_active_animations_c_val_( "Renderer.HasActiveAnimations", false, - "Is non-zero if the current render tree has active animations.") + "Is non-zero if the current render tree has active animations."), + animations_start_time_( + "Time.Renderer.Rasterize.Animations.Start", 0, + "The most recent time animations started playing."), + animations_end_time_("Time.Renderer.Rasterize.Animations.End", 0, + "The most recent time animations ended playing.") #if defined(ENABLE_DEBUG_CONSOLE) , ALLOW_THIS_IN_INITIALIZER_LIST(dump_current_render_tree_command_handler_( @@ -244,8 +255,9 @@ base::TimeTicks now = base::TimeTicks::Now(); Submission submission = submission_queue_->GetCurrentSubmission(now); - bool has_render_tree_changed = last_render_animations_active_ || - submission.render_tree != last_render_tree_; + bool is_new_render_tree = submission.render_tree != last_render_tree_; + bool has_render_tree_changed = + last_render_animations_active_ || is_new_render_tree; // If our render tree hasn't changed from the one that was previously // rendered and it's okay on this system to not flip the display buffer @@ -298,10 +310,16 @@ rasterize_animations_timer_.Stop(); } - // If animations are going from being active to expired, then set the c_val - // after rasterizing the final state of the tree. Now that we've finished - // tracking the animations, it's time to flush the timer. - if (last_render_animations_active_ && !are_animations_active) { + if (is_new_render_tree) { + ++new_render_tree_rasterize_count_; + new_render_tree_rasterize_time_ = base::TimeTicks::Now().ToInternalValue(); + } + + // Check for if the animations are starting or ending. + if (!last_render_animations_active_ && are_animations_active) { + animations_start_time_ = base::TimeTicks::Now().ToInternalValue(); + } else if (last_render_animations_active_ && !are_animations_active) { + animations_end_time_ = base::TimeTicks::Now().ToInternalValue(); has_active_animations_c_val_ = false; rasterize_animations_timer_.Flush(); }
diff --git a/src/cobalt/renderer/pipeline.h b/src/cobalt/renderer/pipeline.h index 8fab055..9df0d8a 100644 --- a/src/cobalt/renderer/pipeline.h +++ b/src/cobalt/renderer/pipeline.h
@@ -199,8 +199,17 @@ // tracking is flushed when the animations expire. base::CValCollectionTimerStats<base::CValDebug> rasterize_animations_timer_; - // Tracks whether or not animations are currently playing. + // The total number of new render trees that have been rasterized. + base::CVal<int> new_render_tree_rasterize_count_; + // The last time that a newly encountered render tree was first rasterized. + base::CVal<int64> new_render_tree_rasterize_time_; + + // Whether or not animations are currently playing. base::CVal<bool> has_active_animations_c_val_; + // The most recent time animations started playing. + base::CVal<int64> animations_start_time_; + // The most recent time animations ended playing. + base::CVal<int64> animations_end_time_; #if defined(ENABLE_DEBUG_CONSOLE) // Dumps the current render tree to the console.
diff --git a/src/cobalt/renderer/rasterizer/skia/skia/src/ports/SkStream_cobalt.h b/src/cobalt/renderer/rasterizer/skia/skia/src/ports/SkStream_cobalt.h index 77266cc..82f2057 100644 --- a/src/cobalt/renderer/rasterizer/skia/skia/src/ports/SkStream_cobalt.h +++ b/src/cobalt/renderer/rasterizer/skia/skia/src/ports/SkStream_cobalt.h
@@ -78,7 +78,7 @@ void PurgeUnusedMemoryChunks(); private: - friend SkFileMemoryChunkStreamProvider; + friend class SkFileMemoryChunkStreamProvider; // Attempts to reserve an available memory chunk and returns true if // successful. On success, |available_chunk_count_| is decremented by one. @@ -124,8 +124,8 @@ void PurgeUnusedMemoryChunks(); private: - friend SkFileMemoryChunkStream; - friend SkFileMemoryChunkStreamManager; + friend class SkFileMemoryChunkStream; + friend class SkFileMemoryChunkStreamManager; SkFileMemoryChunkStreamProvider(const std::string& file_path, SkFileMemoryChunkStreamManager* manager); @@ -183,7 +183,7 @@ virtual size_t getLength() const SK_OVERRIDE; private: - friend SkFileMemoryChunkStreamProvider; + friend class SkFileMemoryChunkStreamProvider; explicit SkFileMemoryChunkStream( SkFileMemoryChunkStreamProvider* stream_provider);
diff --git a/src/cobalt/script/mozjs-45/wrapper_private.h b/src/cobalt/script/mozjs-45/wrapper_private.h index 7e4b917..3ef8306 100644 --- a/src/cobalt/script/mozjs-45/wrapper_private.h +++ b/src/cobalt/script/mozjs-45/wrapper_private.h
@@ -131,7 +131,7 @@ GetOpaqueRootFunction get_opaque_root_function_; GetReachableWrappablesFunction get_reachable_wrappables_function_; - friend Tracer; + friend class Tracer; }; } // namespace mozjs
diff --git a/src/cobalt/script/mozjs/wrapper_private.h b/src/cobalt/script/mozjs/wrapper_private.h index 1ac464f..c384eda 100644 --- a/src/cobalt/script/mozjs/wrapper_private.h +++ b/src/cobalt/script/mozjs/wrapper_private.h
@@ -131,7 +131,7 @@ GetOpaqueRootFunction get_opaque_root_function_; GetReachableWrappablesFunction get_reachable_wrappables_function_; - friend Tracer; + friend class Tracer; }; } // namespace mozjs
diff --git a/src/cobalt/webdriver_benchmarks/c_val_names.py b/src/cobalt/webdriver_benchmarks/c_val_names.py index 3256e48..6ce4f4d 100644 --- a/src/cobalt/webdriver_benchmarks/c_val_names.py +++ b/src/cobalt/webdriver_benchmarks/c_val_names.py
@@ -5,18 +5,46 @@ from __future__ import print_function -def count_dom_active_dispatch_events(): - return "Count.DOM.ActiveDispatchEvents" +def count_dom_active_java_script_events(): + return "Count.DOM.ActiveJavaScriptEvents" + + +def count_dom_html_elements_document(): + return "Count.MainWebModule.DOM.HtmlElement.Document" + + +def count_dom_html_elements_total(): + return "Count.MainWebModule.DOM.HtmlElement.Total" + + +def count_dom_html_script_element_execute(): + return "Count.MainWebModule.DOM.HtmlScriptElement.Execute" + + +def count_layout_boxes(): + return "Count.MainWebModule.Layout.Box" def count_image_cache_loading_resources(): return "Count.MainWebModule.ImageCache.LoadingResources" +def count_image_cache_requested_resources(): + return "Count.MainWebModule.ImageCache.RequestedResources" + + +def count_rasterize_new_render_tree(): + return "Count.Renderer.Rasterize.NewRenderTree" + + def event_duration_dom_video_start_delay(): return "Event.Duration.MainWebModule.DOM.VideoStartDelay" +def event_is_processing(): + return "Event.MainWebModule.IsProcessing" + + def event_value_dictionary(event_type): return "Event.MainWebModule.{}.ValueDictionary".format(event_type) @@ -31,3 +59,31 @@ def renderer_has_active_animations(): return "Renderer.HasActiveAnimations" + + +def time_browser_navigate(): + return "Time.Browser.Navigate" + + +def time_browser_on_load_event(): + return "Time.Browser.OnLoadEvent" + + +def time_cobalt_start(): + return "Time.Cobalt.Start" + + +def time_dom_html_script_element_execute(): + return "Time.MainWebModule.DOM.HtmlScriptElement.Execute" + + +def time_rasterize_animations_start(): + return "Time.Renderer.Rasterize.Animations.Start" + + +def time_rasterize_animations_end(): + return "Time.Renderer.Rasterize.Animations.End" + + +def time_rasterize_new_render_tree(): + return "Time.Renderer.Rasterize.NewRenderTree"
diff --git a/src/cobalt/webdriver_benchmarks/container_util.py b/src/cobalt/webdriver_benchmarks/container_util.py index cab9451..56e948a 100644 --- a/src/cobalt/webdriver_benchmarks/container_util.py +++ b/src/cobalt/webdriver_benchmarks/container_util.py
@@ -50,38 +50,5 @@ if len(sorted_values) == index + 1: return sorted_values[index] - return sorted_values[index] * (1 - fractional - ) + sorted_values[index + 1] * fractional - - -def merge_dict(merge_into, merge_from): - """Merges the second dict into the first dict. - - Merge into differs from update in that it will not override values. If the - values already exist, the resulting value will be a list with a union of - existing and new items. - - Args: - merge_into: An output dict to merge values into. - merge_from: An input dict to iterate over and insert values from. - - Returns: - None - """ - if not merge_from: - return - for k, v in merge_from.items(): - try: - existing_value = merge_into[k] - except KeyError: - merge_into[k] = v - continue - - if not isinstance(v, list): - v = [v] - if isinstance(existing_value, list): - existing_value.extend(v) - else: - new_value = [existing_value] - new_value.extend(v) - merge_into[k] = new_value + return sorted_values[index] * ( + 1 - fractional) + sorted_values[index + 1] * fractional
diff --git a/src/cobalt/webdriver_benchmarks/container_util_test.py b/src/cobalt/webdriver_benchmarks/container_util_test.py index 371a61f..8c29bb4 100755 --- a/src/cobalt/webdriver_benchmarks/container_util_test.py +++ b/src/cobalt/webdriver_benchmarks/container_util_test.py
@@ -85,50 +85,5 @@ self.assertEqual(container_util.percentile([2, 1, 3, 4, 5], 100), 5) -class MergeDictTest(unittest.TestCase): - - def test_empty_merge(self): - a = {'x': 4} - b = {} - container_util.merge_dict(a, b) - self.assertEqual(a, {'x': 4}) - - def test_merge_into_empty(self): - a = {} - b = {'x': 4} - container_util.merge_dict(a, b) - self.assertEqual(a, {'x': 4}) - - def test_merge_non_overlapping_item(self): - a = {'x': 4} - b = {'y': 5} - container_util.merge_dict(a, b) - self.assertEqual(a, {'x': 4, 'y': 5}) - - def test_overlapping_item_with_item(self): - a = {'x': 4} - b = {'x': 5} - container_util.merge_dict(a, b) - self.assertEqual(a, {'x': [4, 5]}) - - def test_overlapping_list_with_item(self): - a = {'x': [4]} - b = {'x': 5} - container_util.merge_dict(a, b) - self.assertEqual(a, {'x': [4, 5]}) - - def test_overlapping_list_with_list(self): - a = {'x': [4]} - b = {'x': [5]} - container_util.merge_dict(a, b) - self.assertEqual(a, {'x': [4, 5]}) - - def test_overlapping_item_with_list(self): - a = {'x': 4} - b = {'x': [5]} - container_util.merge_dict(a, b) - self.assertEqual(a, {'x': [4, 5]}) - - if __name__ == '__main__': sys.exit(unittest.main())
diff --git a/src/cobalt/webdriver_benchmarks/default_query_param_constants.py b/src/cobalt/webdriver_benchmarks/default_query_param_constants.py new file mode 100644 index 0000000..c2347f2 --- /dev/null +++ b/src/cobalt/webdriver_benchmarks/default_query_param_constants.py
@@ -0,0 +1,10 @@ +"""Default query params to use when loading URLs.""" + +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +BASE_QUERY_PARAMS = {} + +INIT_QUERY_PARAMS = {} +INIT_QUERY_PARAMS_TRIGGER_RELOAD = False
diff --git a/src/cobalt/webdriver_benchmarks/tests/README.md b/src/cobalt/webdriver_benchmarks/tests/README.md index 032c41c..81fde36 100644 --- a/src/cobalt/webdriver_benchmarks/tests/README.md +++ b/src/cobalt/webdriver_benchmarks/tests/README.md
@@ -1,26 +1,40 @@ -Cobalt Webdriver-driven Benchmarks ---------------------- +# Cobalt Webdriver-driven Benchmarks This directory contains a set of webdriver-driven benchmarks for Cobalt. Each file should contain a set of tests in Python "unittest" format. -All tests in all of the files included within "all.py" will be run on the +All tests included within [performance.py](performance.py) will be run on the build system. Results can be recorded in the build results database. -To run an individual test, simply execute a script directly (or run -all of them via "all.py"). Platform configuration will be inferred from -the environment if set. Otherwise, it must be specified via commandline -parameters. +## Running the tests -To make a new test: +In most cases, you will want to run all performance tests, and you can do so by +executing the script [performance.py](performance.py). You can call +`python performance.py --help` to see a list of commandline parameters to call +it with. For example, to run tests on the raspi-2 QA build, you should run the +following command: + +``` +python performance.py -p raspi-2 -c qa -d $RASPI_ADDR +``` + +Where `RASPI_ADDR` is set to the IP of the target Raspberry Pi device. + +To run individual tests, simply execute the script directly. For all tests, +platform configuration will be inferred from the environment if set. Otherwise, +it must be specified via commandline parameters. + +## Creating a new test 1. If appropriate, create a new file borrowing the boilerplate from - an existing simple file, such as "browse_horizontal.py". + an existing simple file, such as + [browse_horizontal.py](performance/non_video/browse_horizontal.py). - 2. Add the file name to the tests added within "all.py", causing it run - when "all.py" is run. + 2. Add the file name to the tests added within + [performance.py](performance.py), causing it run when + [performance](performance.py) is run. 3. If this file contains internal names or details, consider adding it to the "EXCLUDE.FILES" list. @@ -29,4 +43,250 @@ appropriate. 5. Results must be added to the build results database schema. See - the internal "README-Updating-Result-Schema.md" file + the internal + [README-Updating-Result-Schema.md](README-Updating-Result-Schema.md) file. + +## Testing against specific loaders/labels + +To run the benchmarks against any desired loader, a --url command line parameter +can be provided. This will be the url that the tests will run against. + +It should have the following format: + +``` +python performance.py -p raspi-2 -c qa -d $RASPI_ADDR --url https://www.youtube.com/tv?loader=nllive +``` + +## Benchmark Results + +The results will be printed to stdout. You should redirect output to a file +if you would like to store the results. Each line of the benchmark output +prefixed with `webdriver_benchmark TEST_RESULT:` provides the result of one +measurment. Those lines have the following format: + +``` +webdriver_benchmark TEST_RESULT: result_name result_value +``` + +where `result_name` is the name of the result and `result_value` is a number +providing the measured result for that metric. For example, + +``` +webdriver_benchmark TEST RESULT: wbBrowseHorizontalDurLayoutBoxTreeUpdateUsedSizesUsPct50 3061.5 +``` + +gives the 50th percentile of the duration Cobalt took to update the box tree's +used sizes, on a horizontal scroll event, in microseconds. + +Note that most time-based measurements are in microseconds. + +### Interesting Timing-Related Benchmarks +Some particularly interesting timing-related benchmark results are: + +#### Startup + - `wbStartupDurLaunchToBrowseUs`: Measures the time it takes to launch Cobalt + and load the desired URL. The measurement ends when all images finish loading + and the final render tree is produced. This is only run once so it will be + noiser than other values but provides the most accurate measurement of the + requirement startup time. + - `wbStartupDurLaunchToUsableUs`: Measures the time it takes to launch Cobalt, + and fully load the desired URL, including loading all scripts. The + measurement ends when the Player JavaScript code finishes loading on the + Browse page, which is the point when Cobalt is fully usable. This is only run + once so it will be noiser than other values but provides the most accurate + measurement of the time when Cobalt is usable. + - `wbStartupDurNavigateToBrowseUs*`: Measures the time it takes to navigate to + the desired URL when Cobalt is already loaded. The measurement ends when all + images finish loading and the final render tree is produced. This is run + multiple times, so it will be less noisy than `wbStartupDurLaunchToBrowseUs`, + but it does not include Cobalt initialization so it is not as accurate of a + measurement. + - `wbStartupDurNavigateToUsableUs`: Measures the time it takes to navigate to + the desired URL when Cobalt is already loaded, including loading all scripts. + The measurement ends when the Player JavaScript code finishes loading on the + Browse page, which is the point when Cobalt is fully usable. This is run + multiple times, so it will be less noisy than `wbStartupDurLaunchToUsableUs`, + but it does not include Cobalt initialization so it is not as accurate of a + measurement. + +#### Browse Horizontal Scroll Events + - `wbBrowseHorizontalDurTotalUs*`: Measures the latency (i.e. JavaScript + execution time + layout time) during horizontal scroll events from keypress + until the render tree is submitted to the rasterize thread. It does not + include the time taken to rasterize the render tree so it will be smaller + than the observed latency. + - `wbBrowseHorizontalDurAnimationsStartDelayUs*`: Measures the input latency + during horizontal scroll events from the keypress until the animation starts. + This is the most accurate measure of input latency. + - `wbBrowseHorizontalDurAnimationsEndDelayUs*`: Measures the latency during + horizontal scroll events from the keypress until the animation ends. + - `wbBrowseHorizontalDurFinalRenderTreeDelayUs*`: Measures the latency during + horizontal scroll events from the keypress until the final render tree is + rendered and processing stops. + - `wbBrowseHorizontalDurRasterizeAnimationsUs*`: Measures the time it takes to + render each frame of the animation triggered by a horizontal scroll event. + The inverse of this number is the framerate. + +#### Browse Vertical Scroll Events + - `wbBrowseVerticalDurTotalUs*`: Measures the latency (i.e. JavaScript + execution time + layout time) during vertical scroll events from keypress + until the render tree is submitted to the rasterize thread. It does not + include the time taken to rasterize the render tree so it will be smaller + than the observed latency. + - `wbBrowseVerticalDurAnimationsStartDelayUs*`: Measures the input latency + during vertical scroll events from the keypress until the animation starts. + This is the most accurate measure of input latency. + - `wbBrowseVerticalDurAnimationsEndDelayUs*`: Measures the latency during + vertical scroll events from the keypress until the animation ends. + - `wbBrowseVerticalDurFinalRenderTreeDelayUs*`: Measures the latency during + vertical scroll events from the keypress until the final render tree is + rendered and processing stops. + - `wbBrowseVerticalDurRasterizeAnimationsUs*`: Measures the time it takes to + render each frame of the animation triggered by a vertical scroll event. + The inverse of this number is the framerate. + +#### Browse-to-Watch + - `wbBrowseToWatchDurVideoStartDelay*`: Measures the browse-to-watch time. + +In each case above, the `*` symbol can be one of either `Mean`, `Pct25`, +`Pct50`, `Pct75` or `Pct95`. For example, `wbStartupDurBlankToBrowseUsMean` or +`wbStartupDurBlankToBrowseUsPct95` are both valid measurements. The webdriver +benchmarks runs its tests many times in order to obtain multiple samples, so you +can drill into the data by exploring either the mean, or the various +percentiles. + +### Interesting Count-Related Benchmarks +Some particularly interesting count-related benchmark results are: + +#### Startup + - `wbStartupCntDomHtmlElements*`: Lists the number of HTML elements in + existence after startup completes. This includes HTML elements that are no + longer in the DOM but have not been garbage collected yet. + - `wbStartupCntDocumentDomHtmlElements*`: Lists the number of HTML + elements within the DOM tree after startup completes. + - `wbStartupCntLayoutBoxes*`: Lists the number of layout boxes within + the layout tree after startup completes. + - `wbStartupCntRenderTrees*`: Lists the number of render trees that were + generated during startup. + - `wbStartupCntRequestedImages*`: Lists the number of images that were + requested during startup. + +#### Browse Horizontal Scroll Events + - `wbBrowseHorizontalCntDomHtmlElements*`: Lists the number of HTML elements in + existence after the event. This includes HTML elements that are no longer in + the DOM but have not been garbage collected yet. + - `wbBrowseHorizontalCntDocumentDomHtmlElements*`: Lists the number of HTML + elements within the DOM tree after the event. + - `wbBrowseHorizontalCntLayoutBoxes*`: Lists the number of layout boxes within + the layout tree after the event. + - `wbBrowseHorizontalCntLayoutBoxesCreated*`: Lists the number of new layout + boxes that were created during the event. + - `wbBrowseHorizontalCntRenderTrees*`: Lists the number of render trees that + were generated by the event. + - `wbBrowseHorizontalCntRequestedImages*`: Lists the number of images that were + requested as a result of the event. + +#### Browse Vertical Scroll Events + - `wbBrowseVerticalCntDomHtmlElements*`: Lists the number of HTML elements in + existence after the event. This includes HTML elements that are no longer in + the DOM but have not been garbage collected yet. + - `wbBrowseVerticalCntDocumentDomHtmlElements*`: Lists the number of HTML + elements within the DOM tree after the event. + - `wbBrowseVerticalCntLayoutBoxes*`: Lists the number of layout boxes within + the layout tree after the event. + - `wbBrowseVerticalCntLayoutBoxesCreated*`: Lists the number of new layout + boxes that were created during the event. + - `wbBrowseVerticalCntRenderTrees*`: Lists the number of render trees that + were generated by the event. + - `wbBrowseVerticalCntRequestedImages*`: Lists the number of images that were + requested as a result of the event. + +In each case above, the `*` symbol can be one of either `Max`, `Median`, or +`Mean`. For example, `wbBrowseVerticalCntDomHtmlElementsMax` or +`wbBrowseVerticalCntDomHtmlElementsMedian` are both valid measurements. The +webdriver benchmarks runs its tests many times in order to obtain multiple +samples, so you can drill into the data by exploring either the max, median, or +mean. + +### Filtering results + +The webdriver benchmarks output many metrics, but you may only be interested +in a few. You will have to manually filter only the metrics that you are +interested in. You can do so with `grep`, for example: + +``` +python performance.py -p raspi-2 -c qa -d $RASPI_ADDR > results.txt +echo "" > filtered_results.txt +printf "=================================TIMING-RELATED=================================\n" >> filtered_results.txt +printf "\nSTARTUP\n" >> filtered_results.txt +grep -o "wbStartupDurLaunchToBrowseUs.*$" results.txt >> filtered_results.txt +grep -o "wbStartupDurLaunchToUsableUs.*$" results.txt >> filtered_results.txt +printf "\n" >> filtered_results.txt +grep -o "wbStartupDurNavigateToBrowseUs.*$" results.txt >> filtered_results.txt +printf "\n" >> filtered_results.txt +grep -o "wbStartupDurNavigateToUsableUs.*$" results.txt >> filtered_results.txt +printf "\n" >> filtered_results.txt +printf "\nBROWSE HORIZONTAL SCROLL EVENTS\n" >> filtered_results.txt +grep -o "wbBrowseHorizontalDurTotalUs.*$" results.txt >> filtered_results.txt +printf "\n" >> filtered_results.txt +grep -o "wbBrowseHorizontalDurAnimationsStartDelayUs.*$" results.txt >> filtered_results.txt +printf "\n" >> filtered_results.txt +grep -o "wbBrowseHorizontalDurAnimationsEndDelayUs.*$" results.txt >> filtered_results.txt +printf "\n" >> filtered_results.txt +grep -o "wbBrowseHorizontalDurFinalRenderTreeDelayUs.*$" results.txt >> filtered_results.txt +printf "\n" >> filtered_results.txt +grep -o "wbBrowseHorizontalDurRasterizeAnimationsUs.*$" results.txt >> filtered_results.txt +printf "\n" >> filtered_results.txt +printf "\nBROWSE VERTICAL SCROLL EVENTS\n" >> filtered_results.txt +grep -o "wbBrowseVerticalDurTotalUs.*$" results.txt >> filtered_results.txt +printf "\n" >> filtered_results.txt +grep -o "wbBrowseVerticalDurAnimationsStartDelayUs.*$" results.txt >> filtered_results.txt +printf "\n" >> filtered_results.txt +grep -o "wbBrowseVerticalDurAnimationsEndDelayUs.*$" results.txt >> filtered_results.txt +printf "\n" >> filtered_results.txt +grep -o "wbBrowseVerticalDurFinalRenderTreeDelayUs.*$" results.txt >> filtered_results.txt +printf "\n" >> filtered_results.txt +grep -o "wbBrowseVerticalDurRasterizeAnimationsUs.*$" results.txt >> filtered_results.txt +printf "\n" >> filtered_results.txt +printf "\nBROWSE TO WATCH\n" >> filtered_results.txt +grep -o "wbBrowseToWatchDurVideoStartDelay.*$" results.txt >> filtered_results.txt +printf "\n\n=================================COUNT-RELATED==================================\n" >> filtered_results.txt +printf "\nSTARTUP\n" >> filtered_results.txt +grep -o "wbStartupCntDomHtmlElements.*$" results.txt >> filtered_results.txt +printf "\n" >> filtered_results.txt +grep -o "wbStartupCntDomDocumentHtmlElements.*$" results.txt >> filtered_results.txt +printf "\n" >> filtered_results.txt +grep -o "wbStartupCntLayoutBoxes.*$" results.txt >> filtered_results.txt +printf "\n" >> filtered_results.txt +grep -o "wbStartupCntRenderTrees.*$" results.txt >> filtered_results.txt +printf "\n" >> filtered_results.txt +grep -o "wbStartupCntRequestedImages.*$" results.txt >> filtered_results.txt +printf "\n" >> filtered_results.txt +printf "\nBROWSE HORIZONTAL SCROLL EVENTS\n" >> filtered_results.txt +grep -o "wbBrowseHorizontalCntDomHtmlElementsM.*$" results.txt >> filtered_results.txt +printf "\n" >> filtered_results.txt +grep -o "wbBrowseHorizontalCntDomDocumentHtmlElements.*$" results.txt >> filtered_results.txt +printf "\n" >> filtered_results.txt +grep -o "wbBrowseHorizontalCntLayoutBoxesM.*$" results.txt >> filtered_results.txt +printf "\n" >> filtered_results.txt +grep -o "wbBrowseHorizontalCntLayoutBoxesCreated.*$" results.txt >> filtered_results.txt +printf "\n" >> filtered_results.txt +grep -o "wbBrowseHorizontalCntRenderTrees.*$" results.txt >> filtered_results.txt +printf "\n" >> filtered_results.txt +grep -o "wbBrowseHorizontalCntRequestedImages.*$" results.txt >> filtered_results.txt +printf "\n" >> filtered_results.txt +printf "\nBROWSE VERTICAL SCROLL EVENTS\n" >> filtered_results.txt +grep -o "wbBrowseVerticalCntDomHtmlElementsM.*$" results.txt >> filtered_results.txt +printf "\n" >> filtered_results.txt +grep -o "wbBrowseVerticalCntDomDocumentHtmlElements.*$" results.txt >> filtered_results.txt +printf "\n" >> filtered_results.txt +grep -o "wbBrowseVerticalCntLayoutBoxesM.*$" results.txt >> filtered_results.txt +printf "\n" >> filtered_results.txt +grep -o "wbBrowseVerticalCntLayoutBoxesCreated.*$" results.txt >> filtered_results.txt +printf "\n" >> filtered_results.txt +grep -o "wbBrowseVerticalCntRenderTrees.*$" results.txt >> filtered_results.txt +printf "\n" >> filtered_results.txt +grep -o "wbBrowseVerticalCntRequestedImages.*$" results.txt >> filtered_results.txt +printf "\n" >> filtered_results.txt +cat filtered_results.txt +```
diff --git a/src/cobalt/webdriver_benchmarks/tests/browse_to_watch.py b/src/cobalt/webdriver_benchmarks/tests/browse_to_watch.py deleted file mode 100755 index ed2f73e..0000000 --- a/src/cobalt/webdriver_benchmarks/tests/browse_to_watch.py +++ /dev/null
@@ -1,74 +0,0 @@ -#!/usr/bin/python2 -"""Simple benchmark for starting a video from browse.""" - -from __future__ import absolute_import -from __future__ import division -from __future__ import print_function - -import os -import sys - -# The parent directory is a module -sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.realpath(__file__)))) - -# pylint: disable=C6204,C6203 -import tv_testcase -import tv_testcase_event_recorder -import tv_testcase_util - -# selenium imports -keys = tv_testcase_util.import_selenium_module("webdriver.common.keys") - -NUM_LOAD_TV_CALLS = 1 -NUM_ITERATIONS_PER_LOAD_TV_CALL = 10 - -BROWSE_TO_WATCH_EVENT_NAME = "wbBrowseToWatch" -BROWSE_TO_WATCH_EVENT_TYPE = tv_testcase_util.EVENT_TYPE_KEY_UP - -WATCH_TO_BROWSE_EVENT_NAME = "wbWatchToBrowse" -WATCH_TO_BROWSE_EVENT_TYPE = tv_testcase_util.EVENT_TYPE_KEY_UP - - -class BrowseToWatchTest(tv_testcase.TvTestCase): - - def test_simple(self): - recorder_options = tv_testcase_event_recorder.EventRecorderOptions( - self, BROWSE_TO_WATCH_EVENT_NAME, BROWSE_TO_WATCH_EVENT_TYPE) - recorder_options.record_rasterize_animations = False - recorder_options.record_video_start_delay = True - browse_to_watch_recorder = tv_testcase_event_recorder.EventRecorder( - recorder_options) - - recorder_options = tv_testcase_event_recorder.EventRecorderOptions( - self, WATCH_TO_BROWSE_EVENT_NAME, WATCH_TO_BROWSE_EVENT_TYPE) - recorder_options.record_rasterize_animations = False - watch_to_browse_recorder = tv_testcase_event_recorder.EventRecorder( - recorder_options) - - for _ in xrange(NUM_LOAD_TV_CALLS): - self.load_tv() - - for _ in xrange(NUM_ITERATIONS_PER_LOAD_TV_CALL): - self.send_keys(keys.Keys.ARROW_DOWN) - self.wait_for_processing_complete_after_focused_shelf() - - browse_to_watch_recorder.on_start_event() - self.send_keys(keys.Keys.ENTER) - self.wait_for_media_element_playing() - browse_to_watch_recorder.on_end_event() - - # Wait for the title card hidden before sending the escape. Otherwise, - # two escapes are required to exit the video. - self.wait_for_title_card_hidden() - - watch_to_browse_recorder.on_start_event() - self.send_keys(keys.Keys.ESCAPE) - self.wait_for_processing_complete_after_focused_shelf() - watch_to_browse_recorder.on_end_event() - - browse_to_watch_recorder.on_end_test() - watch_to_browse_recorder.on_end_test() - - -if __name__ == "__main__": - tv_testcase.main()
diff --git a/src/cobalt/webdriver_benchmarks/tests/all.py b/src/cobalt/webdriver_benchmarks/tests/performance.py old mode 100755 new mode 100644 similarity index 64% copy from src/cobalt/webdriver_benchmarks/tests/all.py copy to src/cobalt/webdriver_benchmarks/tests/performance.py index c08d93c..8495f71 --- a/src/cobalt/webdriver_benchmarks/tests/all.py +++ b/src/cobalt/webdriver_benchmarks/tests/performance.py
@@ -1,5 +1,5 @@ #!/usr/bin/python2 -"""Target for running all tests cases.""" +"""Target for running all performance test cases.""" from __future__ import absolute_import from __future__ import division @@ -30,15 +30,8 @@ test_suite = unittest.TestSuite() dir_path = os.path.dirname(__file__) - # "time_to_shelf" must be the first test added. The timings that it - # records require it to run first. - _add_test(test_suite, dir_path, "startup") - _add_test(test_suite, dir_path, "browse_horizontal") - _add_test(test_suite, dir_path, "browse_vertical") - _add_test(test_suite, dir_path, "browse_to_guide") - _add_test(test_suite, dir_path, "browse_to_search") - _add_test(test_suite, dir_path, "browse_to_watch") - _add_test(test_suite, dir_path, "csi") + _add_test(test_suite, dir_path, "performance_non_video") + _add_test(test_suite, dir_path, "performance_video") return test_suite
diff --git a/src/cobalt/webdriver_benchmarks/tests/performance/__init__.py b/src/cobalt/webdriver_benchmarks/tests/performance/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/src/cobalt/webdriver_benchmarks/tests/performance/__init__.py
diff --git a/src/cobalt/webdriver_benchmarks/tests/performance/non_video/__init__.py b/src/cobalt/webdriver_benchmarks/tests/performance/non_video/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/src/cobalt/webdriver_benchmarks/tests/performance/non_video/__init__.py
diff --git a/src/cobalt/webdriver_benchmarks/tests/browse_horizontal.py b/src/cobalt/webdriver_benchmarks/tests/performance/non_video/browse_horizontal.py similarity index 86% rename from src/cobalt/webdriver_benchmarks/tests/browse_horizontal.py rename to src/cobalt/webdriver_benchmarks/tests/performance/non_video/browse_horizontal.py index dd21b3e..2da83c6 100755 --- a/src/cobalt/webdriver_benchmarks/tests/browse_horizontal.py +++ b/src/cobalt/webdriver_benchmarks/tests/performance/non_video/browse_horizontal.py
@@ -8,8 +8,11 @@ import os import sys -# The parent directory is a module -sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.realpath(__file__)))) +# Add the base webdriver_benchmarks path +sys.path.insert(0, + os.path.dirname( + os.path.dirname((os.path.dirname( + os.path.dirname(os.path.realpath(__file__))))))) # pylint: disable=C6204,C6203 import tv_testcase
diff --git a/src/cobalt/webdriver_benchmarks/tests/browse_to_guide.py b/src/cobalt/webdriver_benchmarks/tests/performance/non_video/browse_to_guide.py similarity index 89% rename from src/cobalt/webdriver_benchmarks/tests/browse_to_guide.py rename to src/cobalt/webdriver_benchmarks/tests/performance/non_video/browse_to_guide.py index 4a74c4a..7e5230f 100755 --- a/src/cobalt/webdriver_benchmarks/tests/browse_to_guide.py +++ b/src/cobalt/webdriver_benchmarks/tests/performance/non_video/browse_to_guide.py
@@ -8,8 +8,11 @@ import os import sys -# The parent directory is a module -sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.realpath(__file__)))) +# Add the base webdriver_benchmarks path +sys.path.insert(0, + os.path.dirname( + os.path.dirname((os.path.dirname( + os.path.dirname(os.path.realpath(__file__))))))) # pylint: disable=C6204,C6203 import tv
diff --git a/src/cobalt/webdriver_benchmarks/tests/browse_to_search.py b/src/cobalt/webdriver_benchmarks/tests/performance/non_video/browse_to_search.py similarity index 86% rename from src/cobalt/webdriver_benchmarks/tests/browse_to_search.py rename to src/cobalt/webdriver_benchmarks/tests/performance/non_video/browse_to_search.py index 688e939..a2d82de 100755 --- a/src/cobalt/webdriver_benchmarks/tests/browse_to_search.py +++ b/src/cobalt/webdriver_benchmarks/tests/performance/non_video/browse_to_search.py
@@ -8,8 +8,11 @@ import os import sys -# The parent directory is a module -sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.realpath(__file__)))) +# Add the base webdriver_benchmarks path +sys.path.insert(0, + os.path.dirname( + os.path.dirname((os.path.dirname( + os.path.dirname(os.path.realpath(__file__))))))) # pylint: disable=C6204,C6203 import tv @@ -35,13 +38,13 @@ def test_simple(self): recorder_options = tv_testcase_event_recorder.EventRecorderOptions( self, BROWSE_TO_SEARCH_EVENT_NAME, BROWSE_TO_SEARCH_EVENT_TYPE) - recorder_options.record_rasterize_animations = False + recorder_options.record_animations = False browse_to_search_recorder = tv_testcase_event_recorder.EventRecorder( recorder_options) recorder_options = tv_testcase_event_recorder.EventRecorderOptions( self, SEARCH_TO_BROWSE_EVENT_NAME, SEARCH_TO_BROWSE_EVENT_TYPE) - recorder_options.record_rasterize_animations = False + recorder_options.record_animations = False search_to_browse_recorder = tv_testcase_event_recorder.EventRecorder( recorder_options)
diff --git a/src/cobalt/webdriver_benchmarks/tests/browse_vertical.py b/src/cobalt/webdriver_benchmarks/tests/performance/non_video/browse_vertical.py similarity index 85% rename from src/cobalt/webdriver_benchmarks/tests/browse_vertical.py rename to src/cobalt/webdriver_benchmarks/tests/performance/non_video/browse_vertical.py index fb31b69..08a687e 100755 --- a/src/cobalt/webdriver_benchmarks/tests/browse_vertical.py +++ b/src/cobalt/webdriver_benchmarks/tests/performance/non_video/browse_vertical.py
@@ -8,8 +8,11 @@ import os import sys -# The parent directory is a module -sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.realpath(__file__)))) +# Add the base webdriver_benchmarks path +sys.path.insert(0, + os.path.dirname( + os.path.dirname((os.path.dirname( + os.path.dirname(os.path.realpath(__file__))))))) # pylint: disable=C6204,C6203 import tv_testcase
diff --git a/src/cobalt/webdriver_benchmarks/tests/performance/non_video/startup.py b/src/cobalt/webdriver_benchmarks/tests/performance/non_video/startup.py new file mode 100755 index 0000000..c37008e --- /dev/null +++ b/src/cobalt/webdriver_benchmarks/tests/performance/non_video/startup.py
@@ -0,0 +1,164 @@ +#!/usr/bin/python2 +"""Simple benchmark for measuring startup time.""" + +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +import os +import sys + +# Add the base webdriver_benchmarks path +sys.path.insert(0, + os.path.dirname( + os.path.dirname((os.path.dirname( + os.path.dirname(os.path.realpath(__file__))))))) + +# pylint: disable=C6204,C6203 +import c_val_names +import tv_testcase +import tv_testcase_util + +NUM_LOAD_TV_ITERATIONS = 20 + +STARTUP_RECORD_NAME = "wbStartup" + + +class StartupTest(tv_testcase.TvTestCase): + + def setUp(self): + # Override TvTestCase's setUp() so that blank startup can first be measured. + pass + + def test_simple(self): + """This test tries to measure the startup time for the YouTube TV page.""" + self.wait_for_processing_complete() + self.wait_for_html_script_element_execute_count(2) + + # Measure durations for the intial launch. + launch_time = self.get_cval(c_val_names.time_cobalt_start()) + navigate_time = self.get_cval(c_val_names.time_browser_navigate()) + on_load_event_time = self.get_cval(c_val_names.time_browser_on_load_event()) + browse_time = self.get_cval(c_val_names.time_rasterize_new_render_tree()) + usable_time = self.get_cval( + c_val_names.time_dom_html_script_element_execute()) + + dur_launch_to_navigate_us = navigate_time - launch_time + dur_launch_to_on_load_event_us = on_load_event_time - launch_time + dur_launch_to_browse_us = browse_time - launch_time + dur_launch_to_usable_us = usable_time - launch_time + + # Call TvTestCase's setUp() now that the launch times have been measured. + super(StartupTest, self).setUp() + + # Count record strategies + count_record_strategies = [] + count_record_strategies.append(tv_testcase_util.RecordStrategyMean()) + count_record_strategies.append(tv_testcase_util.RecordStrategyMin()) + count_record_strategies.append(tv_testcase_util.RecordStrategyMedian()) + count_record_strategies.append(tv_testcase_util.RecordStrategyMax()) + + # Duration record strategies + duration_record_strategies = [] + duration_record_strategies.append(tv_testcase_util.RecordStrategyMean()) + duration_record_strategies.append(tv_testcase_util.RecordStrategyMin()) + duration_record_strategies.append( + tv_testcase_util.RecordStrategyPercentile(25)) + duration_record_strategies.append( + tv_testcase_util.RecordStrategyPercentile(50)) + duration_record_strategies.append( + tv_testcase_util.RecordStrategyPercentile(75)) + duration_record_strategies.append( + tv_testcase_util.RecordStrategyPercentile(95)) + duration_record_strategies.append(tv_testcase_util.RecordStrategyMax()) + + # Count recorders + count_total_html_element_recorder = tv_testcase_util.ResultsRecorder( + STARTUP_RECORD_NAME + "CntDomHtmlElements", count_record_strategies) + count_document_html_element_recorder = tv_testcase_util.ResultsRecorder( + STARTUP_RECORD_NAME + "CntDomDocumentHtmlElements", + count_record_strategies) + count_layout_box_recorder = tv_testcase_util.ResultsRecorder( + STARTUP_RECORD_NAME + "CntLayoutBoxes", count_record_strategies) + count_render_trees_recorder = tv_testcase_util.ResultsRecorder( + STARTUP_RECORD_NAME + "CntRenderTrees", count_record_strategies) + count_requested_images_recorder = tv_testcase_util.ResultsRecorder( + STARTUP_RECORD_NAME + "CntRequestedImages", count_record_strategies) + + # Duration recorders + duration_navigate_to_on_load_recorder = tv_testcase_util.ResultsRecorder( + STARTUP_RECORD_NAME + "DurNavigateToOnLoadUs", + duration_record_strategies) + duration_navigate_to_browse_recorder = tv_testcase_util.ResultsRecorder( + STARTUP_RECORD_NAME + "DurNavigateToBrowseUs", + duration_record_strategies) + duration_navigate_to_usable_recorder = tv_testcase_util.ResultsRecorder( + STARTUP_RECORD_NAME + "DurNavigateToUsableUs", + duration_record_strategies) + + # Now measure counts and durations from reloading the URL. + for _ in range(NUM_LOAD_TV_ITERATIONS): + count_render_trees_start = self.get_cval( + c_val_names.count_rasterize_new_render_tree()) + + self.load_tv() + + count_render_trees_end = self.get_cval( + c_val_names.count_rasterize_new_render_tree()) + + count_total_html_elements = self.get_cval( + c_val_names.count_dom_html_elements_total()) + count_document_html_elements = self.get_cval( + c_val_names.count_dom_html_elements_document()) + count_layout_boxes = self.get_cval(c_val_names.count_layout_boxes()) + count_requested_images = self.get_cval( + c_val_names.count_image_cache_requested_resources()) + + navigate_time = self.get_cval(c_val_names.time_browser_navigate()) + on_load_event_time = self.get_cval( + c_val_names.time_browser_on_load_event()) + browse_time = self.get_cval(c_val_names.time_rasterize_new_render_tree()) + usable_time = self.get_cval( + c_val_names.time_dom_html_script_element_execute()) + + count_total_html_element_recorder.collect_value(count_total_html_elements) + count_document_html_element_recorder.collect_value( + count_document_html_elements) + count_layout_box_recorder.collect_value(count_layout_boxes) + count_render_trees_recorder.collect_value(count_render_trees_end - + count_render_trees_start) + count_requested_images_recorder.collect_value(count_requested_images) + + duration_navigate_to_on_load_recorder.collect_value( + on_load_event_time - navigate_time) + duration_navigate_to_browse_recorder.collect_value( + browse_time - navigate_time) + duration_navigate_to_usable_recorder.collect_value( + usable_time - navigate_time) + + # Record the counts + count_total_html_element_recorder.on_end_test() + count_document_html_element_recorder.on_end_test() + count_layout_box_recorder.on_end_test() + count_render_trees_recorder.on_end_test() + count_requested_images_recorder.on_end_test() + + # Record the durations + tv_testcase_util.record_test_result( + STARTUP_RECORD_NAME + "DurLaunchToNavigateUs", + dur_launch_to_navigate_us) + tv_testcase_util.record_test_result( + STARTUP_RECORD_NAME + "DurLaunchToOnLoadUs", + dur_launch_to_on_load_event_us) + tv_testcase_util.record_test_result( + STARTUP_RECORD_NAME + "DurLaunchToBrowseUs", dur_launch_to_browse_us) + tv_testcase_util.record_test_result( + STARTUP_RECORD_NAME + "DurLaunchToUsableUs", dur_launch_to_usable_us) + + duration_navigate_to_on_load_recorder.on_end_test() + duration_navigate_to_browse_recorder.on_end_test() + duration_navigate_to_usable_recorder.on_end_test() + + +if __name__ == "__main__": + tv_testcase.main()
diff --git a/src/cobalt/webdriver_benchmarks/tests/performance/video/__init__.py b/src/cobalt/webdriver_benchmarks/tests/performance/video/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/src/cobalt/webdriver_benchmarks/tests/performance/video/__init__.py
diff --git a/src/cobalt/webdriver_benchmarks/tests/performance/video/browse_to_watch.py b/src/cobalt/webdriver_benchmarks/tests/performance/video/browse_to_watch.py new file mode 100755 index 0000000..248e73c --- /dev/null +++ b/src/cobalt/webdriver_benchmarks/tests/performance/video/browse_to_watch.py
@@ -0,0 +1,111 @@ +#!/usr/bin/python2 +"""Simple benchmark for starting a video from browse.""" + +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +import os +import sys + +# Add the base webdriver_benchmarks path +sys.path.insert(0, + os.path.dirname( + os.path.dirname((os.path.dirname( + os.path.dirname(os.path.realpath(__file__))))))) + +# pylint: disable=C6204,C6203 +import tv_testcase +import tv_testcase_event_recorder +import tv_testcase_util + +# selenium imports +keys = tv_testcase_util.import_selenium_module("webdriver.common.keys") + +MAX_VIDEO_FAILURE_COUNT = 10 +MAX_SKIPPABLE_AD_COUNT = 8 + +NUM_LOAD_TV_CALLS = 4 +NUM_ITERATIONS_PER_LOAD_TV_CALL = 25 + +BROWSE_TO_WATCH_EVENT_NAME = "wbBrowseToWatch" +BROWSE_TO_WATCH_EVENT_TYPE = tv_testcase_util.EVENT_TYPE_KEY_UP + +WATCH_TO_BROWSE_EVENT_NAME = "wbWatchToBrowse" +WATCH_TO_BROWSE_EVENT_TYPE = tv_testcase_util.EVENT_TYPE_KEY_UP + + +class BrowseToWatchTest(tv_testcase.TvTestCase): + + class VideoFailureException(BaseException): + """Exception thrown when MAX_VIDEO_FAILURE_COUNT is exceeded.""" + + class AdvertisementFailureException(BaseException): + """Exception thrown when MAX_SKIPPABLE_AD_COUNT is exceeded.""" + + def test_simple(self): + recorder_options = tv_testcase_event_recorder.EventRecorderOptions( + self, BROWSE_TO_WATCH_EVENT_NAME, BROWSE_TO_WATCH_EVENT_TYPE) + recorder_options.record_animations = False + recorder_options.record_video = True + browse_to_watch_recorder = tv_testcase_event_recorder.EventRecorder( + recorder_options) + + recorder_options = tv_testcase_event_recorder.EventRecorderOptions( + self, WATCH_TO_BROWSE_EVENT_NAME, WATCH_TO_BROWSE_EVENT_TYPE) + recorder_options.record_animations = False + watch_to_browse_recorder = tv_testcase_event_recorder.EventRecorder( + recorder_options) + + failure_count = 0 + skippable_ad_count = 0 + + for _ in xrange(NUM_LOAD_TV_CALLS): + self.load_tv() + + for _ in xrange(NUM_ITERATIONS_PER_LOAD_TV_CALL): + self.send_keys(keys.Keys.ARROW_DOWN) + self.wait_for_processing_complete_after_focused_shelf() + + browse_to_watch_recorder.on_start_event() + self.send_keys(keys.Keys.ENTER) + + if not self.wait_for_media_element_playing(): + failure_count += 1 + print("Video failed to play! {} events failed.".format(failure_count)) + if failure_count > MAX_VIDEO_FAILURE_COUNT: + raise BrowseToWatchTest.VideoFailureException() + + self.send_keys(keys.Keys.ESCAPE) + self.wait_for_processing_complete_after_focused_shelf() + continue + + if self.skip_advertisement_if_playing(): + skippable_ad_count += 1 + print( + "Encountered skippable ad! {} total.".format(skippable_ad_count)) + if skippable_ad_count > MAX_SKIPPABLE_AD_COUNT: + raise BrowseToWatchTest.AdvertisementFailureException() + + self.wait_for_title_card_hidden() + self.send_keys(keys.Keys.ESCAPE) + self.wait_for_processing_complete_after_focused_shelf() + continue + + browse_to_watch_recorder.on_end_event() + + # Wait for the title card hidden before sending the escape. Otherwise, + # two escapes are required to exit the video. + self.wait_for_title_card_hidden() + + watch_to_browse_recorder.on_start_event() + self.send_keys(keys.Keys.ESCAPE) + self.wait_for_processing_complete_after_focused_shelf() + watch_to_browse_recorder.on_end_event() + + browse_to_watch_recorder.on_end_test() + watch_to_browse_recorder.on_end_test() + + +if __name__ == "__main__": + tv_testcase.main()
diff --git a/src/cobalt/webdriver_benchmarks/tests/all.py b/src/cobalt/webdriver_benchmarks/tests/performance_non_video.py old mode 100755 new mode 100644 similarity index 76% rename from src/cobalt/webdriver_benchmarks/tests/all.py rename to src/cobalt/webdriver_benchmarks/tests/performance_non_video.py index c08d93c..f71a433 --- a/src/cobalt/webdriver_benchmarks/tests/all.py +++ b/src/cobalt/webdriver_benchmarks/tests/performance_non_video.py
@@ -1,5 +1,5 @@ #!/usr/bin/python2 -"""Target for running all tests cases.""" +"""Target for running non-video performance test cases.""" from __future__ import absolute_import from __future__ import division @@ -18,10 +18,11 @@ def _add_test(test_suite, dir_path, test_name): - if os.path.isfile(os.path.join(dir_path, test_name + ".py")): + if os.path.isfile( + os.path.join(dir_path, "performance", "non_video", test_name + ".py")): print("Adding test: {}".format(test_name)) test_suite.addTest(unittest.TestLoader().loadTestsFromModule( - importlib.import_module("tests." + test_name))) + importlib.import_module("tests.performance.non_video." + test_name))) # pylint: disable=unused-argument @@ -30,15 +31,13 @@ test_suite = unittest.TestSuite() dir_path = os.path.dirname(__file__) - # "time_to_shelf" must be the first test added. The timings that it + # "startup" must be the first test added. The timings that it # records require it to run first. _add_test(test_suite, dir_path, "startup") _add_test(test_suite, dir_path, "browse_horizontal") _add_test(test_suite, dir_path, "browse_vertical") _add_test(test_suite, dir_path, "browse_to_guide") _add_test(test_suite, dir_path, "browse_to_search") - _add_test(test_suite, dir_path, "browse_to_watch") - _add_test(test_suite, dir_path, "csi") return test_suite
diff --git a/src/cobalt/webdriver_benchmarks/tests/performance_video.py b/src/cobalt/webdriver_benchmarks/tests/performance_video.py new file mode 100755 index 0000000..3784cc2 --- /dev/null +++ b/src/cobalt/webdriver_benchmarks/tests/performance_video.py
@@ -0,0 +1,40 @@ +#!/usr/bin/python2 +"""Target for running video performance test cases.""" + +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +import importlib +import os +import sys +import unittest + +# The parent directory is a module +sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.realpath(__file__)))) + +# pylint: disable=C6204,C6203 +import tv_testcase + + +def _add_test(test_suite, dir_path, test_name): + if os.path.isfile( + os.path.join(dir_path, "performance", "video", test_name + ".py")): + print("Adding test: {}".format(test_name)) + test_suite.addTest(unittest.TestLoader().loadTestsFromModule( + importlib.import_module("tests.performance.video." + test_name))) + + +# pylint: disable=unused-argument +def load_tests(loader, tests, pattern): + """This is a Python unittest "load_tests protocol method.""" + test_suite = unittest.TestSuite() + dir_path = os.path.dirname(__file__) + + _add_test(test_suite, dir_path, "browse_to_watch") + + return test_suite + + +if __name__ == "__main__": + tv_testcase.main()
diff --git a/src/cobalt/webdriver_benchmarks/tests/startup.py b/src/cobalt/webdriver_benchmarks/tests/startup.py deleted file mode 100755 index 4ea17fd..0000000 --- a/src/cobalt/webdriver_benchmarks/tests/startup.py +++ /dev/null
@@ -1,74 +0,0 @@ -#!/usr/bin/python2 -"""Simple benchmark for measuring startup time.""" - -from __future__ import absolute_import -from __future__ import division -from __future__ import print_function - -import os -import sys - -# The parent directory is a module -sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.realpath(__file__)))) - -# pylint: disable=C6204,C6203 -import timer -import tv_testcase -import tv_testcase_util - -NUM_BLANK_TO_BROWSE_ITERATIONS = 10 - -LAUNCH_TO_BLANK = "wbStartupDurLaunchToBlankUs" -BLANK_TO_BROWSE = "wbStartupDurBlankToBrowseUs" - - -class StartupTest(tv_testcase.TvTestCase): - - def setUp(self): - # Override TvTestCase's setUp() so that blank startup can first be measured. - pass - - def test_simple(self): - """This test tries to measure the startup time for the YouTube TV page. - - Specifically, this test uses the Cobalt CVal Cobalt.Lifetime, which gets - updated ~60Hz on a best effort basis and is in microseconds, to determine - "wbStartupDurLaunchToBlankUs" and uses Timer to determine - "wbStartupDurBlankToBrowseUs". - """ - - dur_launch_to_blank_us = self.get_cval("Cobalt.Lifetime") - - # Call TvTestCase's setUp() now that the blank startup time has been - # measured. - super(StartupTest, self).setUp() - - # Blank to browser record strategies - blank_to_browse_record_strategies = [] - blank_to_browse_record_strategies.append( - tv_testcase_util.RecordStrategyMean()) - blank_to_browse_record_strategies.append( - tv_testcase_util.RecordStrategyPercentile(25)) - blank_to_browse_record_strategies.append( - tv_testcase_util.RecordStrategyPercentile(50)) - blank_to_browse_record_strategies.append( - tv_testcase_util.RecordStrategyPercentile(75)) - blank_to_browse_record_strategies.append( - tv_testcase_util.RecordStrategyPercentile(95)) - - # Blank to browser recorder - blank_to_browse_recorder = tv_testcase_util.ResultsRecorder( - BLANK_TO_BROWSE, blank_to_browse_record_strategies) - - for _ in range(NUM_BLANK_TO_BROWSE_ITERATIONS): - self.load_blank() - with timer.Timer(BLANK_TO_BROWSE) as t: - self.load_tv() - blank_to_browse_recorder.collect_value(int(t.seconds_elapsed * 1000000)) - - tv_testcase_util.record_test_result(LAUNCH_TO_BLANK, dur_launch_to_blank_us) - blank_to_browse_recorder.on_end_test() - - -if __name__ == "__main__": - tv_testcase.main()
diff --git a/src/cobalt/webdriver_benchmarks/timer.py b/src/cobalt/webdriver_benchmarks/timer.py deleted file mode 100644 index 0ee08dc..0000000 --- a/src/cobalt/webdriver_benchmarks/timer.py +++ /dev/null
@@ -1,94 +0,0 @@ -# Copyright 2016 Google Inc. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================== -"""Contains a contextmanager for a timer. - - Example usage: - - from timer import Timer - - with Timer('SomeTask') as t: - # Do some time consuming task - print('So far {} seconds have passed'.format(t.seconds_elapsed)) - - print(t) # This will print something like 'SomeTask took 1.2 seconds' -""" - -from __future__ import absolute_import -from __future__ import division -from __future__ import print_function - -import timeit - - -class Timer(object): - """ContextManager for measuring time since an event.""" - - def __init__(self, description): - """Initializes the timer. - - Args: - description: A string containing the description of the timer. - """ - self.description = description - self._timer = timeit.default_timer # Choose best timer for the platform. - self.start_time = None - self._seconds_elapsed = None - - def __enter__(self): - """Starts the timer. - - __enter__ allows this class to be used as a ContextManager. - - Returns: - The object itself so it works with the |with| statement. - """ - self.start_time = self._timer() - return self - - def __exit__(self, unused_ex_type, unused_ex, unused_ex_trace): - """Stops the timer and records the duration. - - __enter__ allows this class to be used as a ContextManager. - - Returns: - False. Any exception raised within the body of the contextmanager will - propogate up the stack. - """ - self._seconds_elapsed = self._timer() - self.start_time - return False - - @property - def seconds_elapsed(self): - """Number of seconds elapsed since start until now or time when timer ended. - - This property will return the number of seconds since the timer was started, - or the duration of the timer's context manager. - - Returns: - A float containing the number of seconds elapsed. - """ - if self._seconds_elapsed is None: - return self._timer() - self.start_time - - return self._seconds_elapsed - - def __str__(self): - """A magic method for generating a string representation of the object. - - Returns: - A string containing a description and a human readable version of timer's - value. - """ - return '{} took {} seconds.'.format(self.description, self.seconds_elapsed)
diff --git a/src/cobalt/webdriver_benchmarks/tv.py b/src/cobalt/webdriver_benchmarks/tv.py index b3e6d29..332b3c9 100644 --- a/src/cobalt/webdriver_benchmarks/tv.py +++ b/src/cobalt/webdriver_benchmarks/tv.py
@@ -8,4 +8,6 @@ FOCUSED_SEARCH = '.focused.search' FOCUSED_SHELF = '.focused.selected.shelf' FOCUSED_SHELF_TITLE = '.focused.selected.shelf .shelf-header-title .main' +SKIP_AD_BUTTON_CAN_SKIP = '.skip-ad-button.canskip' +SKIP_AD_BUTTON_HIDDEN = '.skip-ad-button.hidden' TITLE_CARD_HIDDEN = '.title-card.hidden'
diff --git a/src/cobalt/webdriver_benchmarks/tv_testcase.py b/src/cobalt/webdriver_benchmarks/tv_testcase.py index dfdb5d9..dc49278 100644 --- a/src/cobalt/webdriver_benchmarks/tv_testcase.py +++ b/src/cobalt/webdriver_benchmarks/tv_testcase.py
@@ -19,16 +19,24 @@ import tv_testcase_runner import tv_testcase_util +try: + import custom_query_param_constants as query_param_constants +except ImportError: + import default_query_param_constants as query_param_constants + # selenium imports # pylint: disable=C0103 ActionChains = tv_testcase_util.import_selenium_module( submodule="webdriver.common.action_chains").ActionChains +keys = tv_testcase_util.import_selenium_module("webdriver.common.keys") WINDOWDRIVER_CREATED_TIMEOUT_SECONDS = 30 WEBMODULE_LOADED_TIMEOUT_SECONDS = 30 PAGE_LOAD_WAIT_SECONDS = 30 -PROCESSING_TIMEOUT_SECONDS = 15 +PROCESSING_TIMEOUT_SECONDS = 60 +HTML_SCRIPT_ELEMENT_EXECUTE_TIMEOUT_SECONDS = 30 MEDIA_TIMEOUT_SECONDS = 30 +SKIP_AD_TIMEOUT_SECONDS = 30 TITLE_CARD_HIDDEN_TIMEOUT_SECONDS = 30 _is_initialized = False @@ -50,8 +58,8 @@ class ProcessingTimeoutException(BaseException): """Exception thrown when processing did not complete in time.""" - class MediaTimeoutException(BaseException): - """Exception thrown when media did not complete in time.""" + class HtmlScriptElementExecuteTimeoutException(BaseException): + """Exception thrown when processing did not complete in time.""" class TitleCardHiddenTimeoutException(BaseException): """Exception thrown when title card did not disappear in time.""" @@ -67,17 +75,18 @@ def setUp(self): global _is_initialized if not _is_initialized: - # Initialize the tests. This involves loading a URL which applies the - # forcedOffAllExperiments cookies, ensuring that no subsequent loads - # include experiments. Additionally, loading this URL triggers a reload. - query_params = {"env_forcedOffAllExperiments": True} - triggers_reload = True - self.load_tv(None, query_params, triggers_reload) + # Initialize the tests. + query_params = query_param_constants.INIT_QUERY_PARAMS + triggers_reload = query_param_constants.INIT_QUERY_PARAMS_TRIGGER_RELOAD + self.load_tv(query_params, triggers_reload) _is_initialized = True def get_webdriver(self): return tv_testcase_runner.GetWebDriver() + def get_default_url(self): + return tv_testcase_runner.GetDefaultUrl() + def get_cval(self, cval_name): """Returns the Python object represented by a JSON cval string. @@ -103,26 +112,19 @@ self.get_webdriver().get("about:blank") self.wait_for_url_loaded_events() - def load_tv(self, - label=None, - additional_query_params=None, - triggers_reload=False): + def load_tv(self, query_params=None, triggers_reload=False): """Loads the main TV page and waits for it to display. Args: - label: A value for the label query parameter. - additional_query_params: A dict containing additional query parameters. + query_params: A dict containing additional query parameters. triggers_reload: Whether or not the navigation will trigger a reload. Raises: Underlying WebDriver exceptions """ - query_params = {} - if label is not None: - query_params = {"label": label} - if additional_query_params is not None: - query_params.update(additional_query_params) + self.get_webdriver().execute_script("h5vcc.storage.clearCookies()") self.clear_url_loaded_events() - self.get_webdriver().get(tv_testcase_util.get_tv_url(query_params)) + self.get_webdriver().get( + tv_testcase_util.generate_url(self.get_default_url(), query_params)) self.wait_for_url_loaded_events() if triggers_reload: self.clear_url_loaded_events() @@ -191,16 +193,16 @@ self.assertEqual(len(elements), expected_num) return elements - def send_keys(self, keys): + def send_keys(self, key_events): """Sends keys to whichever element currently has focus. Args: - keys: key events + key_events: key events Raises: Underlying WebDriver exceptions """ - ActionChains(self.get_webdriver()).send_keys(keys).perform() + ActionChains(self.get_webdriver()).send_keys(key_events).perform() def clear_url_loaded_events(self): """Clear the events that indicate that Cobalt finished loading a URL.""" @@ -240,6 +242,18 @@ required time. """ start_time = time.time() + + # First simply check for whether or not the event is still processing. + # There's no need to check anything else while the event is still going on. + # Once it is done processing, it won't get re-set, so there's no need to + # re-check it. + while self.get_cval(c_val_names.event_is_processing()): + if time.time() - start_time > PROCESSING_TIMEOUT_SECONDS: + raise TvTestCase.ProcessingTimeoutException() + + time.sleep(0.1) + + # Now wait for all processing to complete in Cobalt. count = 0 while count < 2: if self.is_processing(check_animations): @@ -254,26 +268,62 @@ def is_processing(self, check_animations): """Checks to see if Cobalt is currently processing.""" - return (self.get_cval(c_val_names.count_dom_active_dispatch_events()) or + return (self.get_cval(c_val_names.count_dom_active_java_script_events()) or self.get_cval(c_val_names.layout_is_dirty()) or (check_animations and self.get_cval(c_val_names.renderer_has_active_animations())) or self.get_cval(c_val_names.count_image_cache_loading_resources())) + def wait_for_html_script_element_execute_count(self, required_count): + """Waits for specified number of html script element Execute() calls. + + Args: + required_count: the number of executions that must occur + + Raises: + HtmlScriptElementExecuteTimeoutException: The required html script element + executions did not occur within the required time. + """ + start_time = time.time() + while self.get_cval( + c_val_names.count_dom_html_script_element_execute()) < required_count: + if time.time() - start_time > HTML_SCRIPT_ELEMENT_EXECUTE_TIMEOUT_SECONDS: + raise TvTestCase.HtmlScriptElementExecuteTimeoutException() + time.sleep(0.1) + def wait_for_media_element_playing(self): """Waits for a video to begin playing. - Raises: - MediaTimeoutException: The video does not start playing within the - required time. + Returns: + Whether or not the video started. """ start_time = time.time() while self.get_cval( c_val_names.event_duration_dom_video_start_delay()) == 0: if time.time() - start_time > MEDIA_TIMEOUT_SECONDS: - raise TvTestCase.MediaTimeoutException() + return False time.sleep(0.1) + return True + + def skip_advertisement_if_playing(self): + """Waits to skip an ad if it is encountered. + + Returns: + True if a skippable advertisement was encountered + """ + start_time = time.time() + if not self.find_elements(tv.SKIP_AD_BUTTON_HIDDEN): + while not self.find_elements(tv.SKIP_AD_BUTTON_CAN_SKIP): + if time.time() - start_time > SKIP_AD_TIMEOUT_SECONDS: + return True + time.sleep(0.1) + self.send_keys(keys.Keys.ENTER) + self.wait_for_processing_complete(False) + return True + + return False + def wait_for_title_card_hidden(self): """Waits for the title to disappear while a video is playing.
diff --git a/src/cobalt/webdriver_benchmarks/tv_testcase_event_recorder.py b/src/cobalt/webdriver_benchmarks/tv_testcase_event_recorder.py index cb49624..5905e84 100644 --- a/src/cobalt/webdriver_benchmarks/tv_testcase_event_recorder.py +++ b/src/cobalt/webdriver_benchmarks/tv_testcase_event_recorder.py
@@ -24,8 +24,8 @@ self.event_name = event_name self.event_type = event_type - self.record_rasterize_animations = True - self.record_video_start_delay = False + self.record_animations = True + self.record_video = False class EventRecorder(object): @@ -37,8 +37,8 @@ tv_testcase_util.py. Both rasterize animations and video start delay data can potentially be - recorded, depending on the |record_rasterize_animations| and - |record_video_start_delay| option flags. + recorded, depending on the |record_animations| and |record_video| option + flags. """ def __init__(self, options): @@ -59,21 +59,54 @@ # Each entry in the list contains a tuple with a key and value recorder. self.value_dictionary_recorders = [] + # Optional animations recorders self.animations_recorder = None + self.animations_start_delay_recorder = None + self.animations_end_delay_recorder = None + + # Optional video recorders self.video_delay_recorder = None # Count record strategies count_record_strategies = [] - count_record_strategies.append(tv_testcase_util.RecordStrategyMax()) - count_record_strategies.append(tv_testcase_util.RecordStrategyMedian()) count_record_strategies.append(tv_testcase_util.RecordStrategyMean()) + count_record_strategies.append(tv_testcase_util.RecordStrategyMedian()) + count_record_strategies.append(tv_testcase_util.RecordStrategyMax()) - # Count recorders + # Duration record strategies + duration_record_strategies = [] + duration_record_strategies.append(tv_testcase_util.RecordStrategyMean()) + duration_record_strategies.append( + tv_testcase_util.RecordStrategyPercentile(25)) + duration_record_strategies.append( + tv_testcase_util.RecordStrategyPercentile(50)) + duration_record_strategies.append( + tv_testcase_util.RecordStrategyPercentile(75)) + duration_record_strategies.append( + tv_testcase_util.RecordStrategyPercentile(95)) + + # Video delay record strategies + video_delay_record_strategies = [] + video_delay_record_strategies.append(tv_testcase_util.RecordStrategyMean()) + video_delay_record_strategies.append(tv_testcase_util.RecordStrategyMin()) + video_delay_record_strategies.append( + tv_testcase_util.RecordStrategyPercentile(25)) + video_delay_record_strategies.append( + tv_testcase_util.RecordStrategyPercentile(50)) + video_delay_record_strategies.append( + tv_testcase_util.RecordStrategyPercentile(75)) + video_delay_record_strategies.append( + tv_testcase_util.RecordStrategyPercentile(95)) + video_delay_record_strategies.append(tv_testcase_util.RecordStrategyMax()) + + # Dictionary count recorders self._add_value_dictionary_recorder("CntDomEventListeners", count_record_strategies) self._add_value_dictionary_recorder("CntDomNodes", count_record_strategies) self._add_value_dictionary_recorder("CntDomHtmlElements", count_record_strategies) + self._add_value_dictionary_recorder("CntDomDocumentHtmlElements", + count_record_strategies) self._add_value_dictionary_recorder("CntDomHtmlElementsCreated", count_record_strategies) self._add_value_dictionary_recorder("CntDomUpdateMatchingRules", @@ -95,19 +128,7 @@ self._add_value_dictionary_recorder("CntLayoutUpdateCrossReferences", count_record_strategies) - # Duration record strategies - duration_record_strategies = [] - duration_record_strategies.append(tv_testcase_util.RecordStrategyMean()) - duration_record_strategies.append( - tv_testcase_util.RecordStrategyPercentile(25)) - duration_record_strategies.append( - tv_testcase_util.RecordStrategyPercentile(50)) - duration_record_strategies.append( - tv_testcase_util.RecordStrategyPercentile(75)) - duration_record_strategies.append( - tv_testcase_util.RecordStrategyPercentile(95)) - - # Duration recorders + # Dictionary duration recorders self._add_value_dictionary_recorder("DurTotalUs", duration_record_strategies) self._add_value_dictionary_recorder("DurDomInjectEventUs", @@ -125,16 +146,32 @@ self._add_value_dictionary_recorder("DurLayoutRenderAndAnimateUs", duration_record_strategies) - # Optional rasterize animations recorders - if options.record_rasterize_animations: + self.count_render_trees_recorder = tv_testcase_util.ResultsRecorder( + self.event_name + "CntRenderTrees", count_record_strategies) + self.count_requested_images_recorder = tv_testcase_util.ResultsRecorder( + self.event_name + "CntRequestedImages", count_record_strategies) + + # Optional animations recorder + if options.record_animations: self.animations_recorder = tv_testcase_util.ResultsRecorder( self.event_name + "DurRasterizeAnimationsUs", duration_record_strategies) + self.animations_start_delay_recorder = tv_testcase_util.ResultsRecorder( + self.event_name + "DurAnimationsStartDelayUs", + duration_record_strategies) + self.animations_end_delay_recorder = tv_testcase_util.ResultsRecorder( + self.event_name + "DurAnimationsEndDelayUs", + duration_record_strategies) - # Optional video start delay recorder - if options.record_video_start_delay: + self.final_render_tree_delay_recorder = tv_testcase_util.ResultsRecorder( + self.event_name + "DurFinalRenderTreeDelayUs", + duration_record_strategies) + + # Optional video recorder + if options.record_video: self.video_delay_recorder = tv_testcase_util.ResultsRecorder( - self.event_name + "DurVideoStartDelayUs", duration_record_strategies) + self.event_name + "DurVideoStartDelayUs", + video_delay_record_strategies) def _add_value_dictionary_recorder(self, key, record_strategies): recorder = tv_testcase_util.ResultsRecorder(self.event_name + key, @@ -143,7 +180,10 @@ def on_start_event(self): """Handles logic related to the start of the event instance.""" - pass + self.count_render_trees_start = self.test.get_cval( + c_val_names.count_rasterize_new_render_tree()) + self.count_requested_images_start = self.test.get_cval( + c_val_names.count_image_cache_requested_resources()) def on_end_event(self): """Handles logic related to the end of the event instance.""" @@ -159,18 +199,44 @@ self.event_name, self.render_tree_failure_count)) return + event_start_time = value_dictionary.get("StartTime") + # Record all of the values from the event. for value_dictionary_recorder in self.value_dictionary_recorders: value = value_dictionary.get(value_dictionary_recorder[0]) if value is not None: value_dictionary_recorder[1].collect_value(value) + self.count_render_trees_end = self.test.get_cval( + c_val_names.count_rasterize_new_render_tree()) + self.count_render_trees_recorder.collect_value( + self.count_render_trees_end - self.count_render_trees_start) + + self.count_requested_images_end = self.test.get_cval( + c_val_names.count_image_cache_requested_resources()) + self.count_requested_images_recorder.collect_value( + self.count_requested_images_end - self.count_requested_images_start) + if self.animations_recorder: animation_entries = self.test.get_cval( c_val_names.rasterize_animations_entry_list()) for value in animation_entries: self.animations_recorder.collect_value(value) + animations_start_time = self.test.get_cval( + c_val_names.time_rasterize_animations_start()) + self.animations_start_delay_recorder.collect_value( + animations_start_time - event_start_time) + animations_end_time = self.test.get_cval( + c_val_names.time_rasterize_animations_end()) + self.animations_end_delay_recorder.collect_value(animations_end_time - + event_start_time) + + final_render_tree_time = self.test.get_cval( + c_val_names.time_rasterize_new_render_tree()) + self.final_render_tree_delay_recorder.collect_value(final_render_tree_time - + event_start_time) + if self.video_delay_recorder: self.video_delay_recorder.collect_value( self.test.get_cval( @@ -182,8 +248,15 @@ for value_dictionary_recorder in self.value_dictionary_recorders: value_dictionary_recorder[1].on_end_test() + self.count_render_trees_recorder.on_end_test() + self.count_requested_images_recorder.on_end_test() + if self.animations_recorder: self.animations_recorder.on_end_test() + self.animations_start_delay_recorder.on_end_test() + self.animations_end_delay_recorder.on_end_test() + + self.final_render_tree_delay_recorder.on_end_test() if self.video_delay_recorder: self.video_delay_recorder.on_end_test()
diff --git a/src/cobalt/webdriver_benchmarks/tv_testcase_runner.py b/src/cobalt/webdriver_benchmarks/tv_testcase_runner.py index 829c337..6f9981c 100755 --- a/src/cobalt/webdriver_benchmarks/tv_testcase_runner.py +++ b/src/cobalt/webdriver_benchmarks/tv_testcase_runner.py
@@ -27,7 +27,7 @@ arg_parser.add_argument( "-e", "--executable", - help="Path to cobalt executable. " + help="Path to Cobalt executable. " "Auto-derived if absent.") arg_parser.add_argument( "-c", @@ -42,6 +42,12 @@ help="Devkit or IP address for app_launcher." "Current hostname used if absent.") arg_parser.add_argument( + "--command_line", + nargs="*", + help="Command line arguments to pass to the Cobalt executable.") +arg_parser.add_argument( + "--url", help="Specifies the URL to run the tests against.") +arg_parser.add_argument( "-o", "--log_file", help="Logfile pathname. stdout if absent.") # Pattern to match Cobalt log line for when the WebDriver port has been @@ -67,6 +73,7 @@ _webdriver = None _windowdriver_created = threading.Event() _webmodule_loaded = threading.Event() +_default_url = "https://www.youtube.com/tv" def GetWebDriver(): @@ -84,6 +91,11 @@ return _webmodule_loaded +def GetDefaultUrl(): + """Returns the default url to use with tests.""" + return _default_url + + class TimeoutException(Exception): pass @@ -99,7 +111,12 @@ failed = False should_exit = threading.Event() - def __init__(self, platform, executable, devkit_name, log_file_path): + def __init__(self, platform, executable, devkit_name, command_line_args, + default_url, log_file_path): + global _default_url + if default_url is not None: + _default_url = default_url + self.selenium_webdriver_module = tv_testcase_util.import_selenium_module( "webdriver") @@ -113,10 +130,13 @@ platform, executable, devkit_name=devkit_name, close_output_file=False) args = [] + if command_line_args is not None: + for command_line_arg in command_line_args: + args.append("--" + command_line_arg) args.append("--enable_webdriver") args.append("--null_savegame") args.append("--debug_console=off") - args.append("--url=about:blank") + args.append("--url=" + _default_url) self.launcher.SetArgs(args) self.launcher.SetOutputCallback(self._HandleLine) @@ -138,8 +158,8 @@ def __exit__(self, exc_type, exc_value, traceback): # The unittest module terminates with a SystemExit # If this is a successful exit, then this is a successful run - success = exc_type is None or (exc_type is SystemExit and not exc_value.code - ) + success = exc_type is None or (exc_type is SystemExit and + not exc_value.code) self.SetShouldExit(failed=not success) self.thread.join(COBALT_EXIT_TIMEOUT_SECONDS) @@ -263,8 +283,8 @@ executable = GetCobaltExecutablePath(platform, args.config) try: - with CobaltRunner(platform, executable, args.devkit_name, - args.log_file) as runner: + with CobaltRunner(platform, executable, args.devkit_name, args.command_line, + args.url, args.log_file) as runner: unittest.main(testRunner=unittest.TextTestRunner( verbosity=0, stream=runner.log_file)) except TimeoutException:
diff --git a/src/cobalt/webdriver_benchmarks/tv_testcase_util.py b/src/cobalt/webdriver_benchmarks/tv_testcase_util.py index 34d574a..6cb9a52 100644 --- a/src/cobalt/webdriver_benchmarks/tv_testcase_util.py +++ b/src/cobalt/webdriver_benchmarks/tv_testcase_util.py
@@ -14,6 +14,11 @@ import container_util +try: + import custom_query_param_constants as query_param_constants +except ImportError: + import default_query_param_constants as query_param_constants + # These are watched for in webdriver_benchmark_test.py TEST_RESULT = "webdriver_benchmark TEST RESULT" TEST_COMPLETE = "webdriver_benchmark TEST COMPLETE" @@ -22,11 +27,6 @@ EVENT_TYPE_KEY_DOWN = "KeyDown" EVENT_TYPE_KEY_UP = "KeyUp" -# URL-related constants -BASE_URL = "https://www.youtube.com/" -TV_APP_PATH = "/tv" -BASE_PARAMS = {} - def import_selenium_module(submodule=None): """Dynamically imports a selenium.webdriver submodule. @@ -61,23 +61,28 @@ return module -def get_url(path, query_params=None): - """Returns the URL indicated by the path and query parameters.""" - parsed_url = list(urlparse.urlparse(BASE_URL)) - parsed_url[2] = path - query_dict = BASE_PARAMS.copy() - if query_params: - query_dict.update(urlparse.parse_qsl(parsed_url[4])) - container_util.merge_dict(query_dict, query_params) - parsed_url[4] = urlencode(query_dict, doseq=True) +def generate_url(default_url, query_params_override=None): + """Returns the URL indicated by the path and query parameters. + + Args: + default_url: the default url to use; its query params may be overridden + query_params_override: optional query params that override the ones + contained within the default URL + Returns: + the url generated from the parameters + """ + parsed_url = list(urlparse.urlparse(default_url)) + + query_params = query_param_constants.BASE_QUERY_PARAMS + if query_params_override: + query_params.update(query_params_override) + else: + query_params.update(urlparse.parse_qsl(parsed_url[4])) + + parsed_url[4] = urlencode(query_params, doseq=True) return urlparse.urlunparse(parsed_url) -def get_tv_url(query_params=None): - """Returns the tv URL indicated by the query parameters.""" - return get_url(TV_APP_PATH, query_params) - - def record_test_result(name, result): """Records an individual scalar result of a benchmark test.
diff --git a/src/media/base/video_resolution.h b/src/media/base/video_resolution.h index 714cca1..29ae65f 100644 --- a/src/media/base/video_resolution.h +++ b/src/media/base/video_resolution.h
@@ -17,6 +17,7 @@ #ifndef MEDIA_BASE_VIDEO_RESOLUTION_H_ #define MEDIA_BASE_VIDEO_RESOLUTION_H_ +#include "base/logging.h" #include "media/base/media_export.h" #include "ui/gfx/size.h" @@ -24,11 +25,15 @@ // Enumerates the various representations of the resolution of videos. Note // that except |kVideoResolutionInvalid|, all other values are guaranteed to be -// in the same order as its (width, height) pair. +// in the same order as its (width, height) pair. Note, unlike the other valid +// resolution levels, |kVideoResolutionHighRes| is not a 16:9 resolution. enum VideoResolution { - kVideoResolution1080p, // 1920 x 1080 - kVideoResolution2k, // 2560 x 1440 - kVideoResolution4k, // 3840 x 2160 + kVideoResolution1080p, // 1920 x 1080 + kVideoResolution2k, // 2560 x 1440 + kVideoResolution4k, // 3840 x 2160 + kVideoResolution5k, // 5120 × 2880 + kVideoResolution8k, // 7680 x 4320 + kVideoResolutionHighRes, // 8192 x 8192 kVideoResolutionInvalid }; @@ -42,6 +47,17 @@ if (width <= 3840 && height <= 2160) { return kVideoResolution4k; } + if (width <= 5120 && height <= 2880) { + return kVideoResolution5k; + } + if (width <= 7680 && height <= 4320) { + return kVideoResolution8k; + } + if (width <= 8192 && height <= 8192) { + return kVideoResolutionHighRes; + } + DLOG(FATAL) << "Invalid VideoResolution: width: " << width + << " height: " << height; return kVideoResolutionInvalid; }
diff --git a/src/starboard/shared/starboard/application.h b/src/starboard/shared/starboard/application.h index baf00f0..2469a6e 100644 --- a/src/starboard/shared/starboard/application.h +++ b/src/starboard/shared/starboard/application.h
@@ -217,9 +217,7 @@ int y, int width, int height); -#endif // SB_HAS(PLAYER) && \ - (SB_API_VERSION >= 4 || \ - SB_IS(PLAYER_PUNCHED_OUT)) +#endif // SB_HAS(PLAYER) && (SB_API_VERSION >= 4 || SB_IS(PLAYER_PUNCHED_OUT)) // Registers a |callback| function that will be called when |Teardown| is // called. @@ -256,9 +254,7 @@ int y, int width, int height) {} -#endif // SB_HAS(PLAYER) && \ - (SB_API_VERSION >= 4 || \ - SB_IS(PLAYER_PUNCHED_OUT)) +#endif // SB_HAS(PLAYER) && (SB_API_VERSION >= 4 || SB_IS(PLAYER_PUNCHED_OUT)) // Blocks until the next event is available. Subclasses must implement this // method to provide events for the platform. Gives ownership to the caller.