/*++ Copyright (c) 2006 Microsoft Corporation Module Name: dl_costs.cpp Abstract: Author: Krystof Hoder (t-khoder) 2010-09-20. Revision History: --*/ #include "debug.h" #include "stopwatch.h" #include "dl_context.h" #include "dl_rule.h" #include "dl_costs.h" namespace datalog { // ----------------------------------- // // costs // // ----------------------------------- costs::costs() : milliseconds(0), instructions(0) {} bool costs::empty() const { return !milliseconds && !instructions; } void costs::reset() { milliseconds = 0; instructions = 0; } costs costs::operator-(const costs & o) const { costs res(*this); SASSERT(milliseconds>o.milliseconds); res.milliseconds-=o.milliseconds; SASSERT(instructions>o.instructions); res.instructions-=o.instructions; return res; } void costs::operator+=(const costs & o) { milliseconds+=o.milliseconds; instructions+=o.instructions; } bool costs::passes_thresholds(context & ctx) const { return milliseconds >= ctx.dl_profile_milliseconds_threshold(); } void costs::output(std::ostream & out) const { out << "instr: " << instructions << " time: " << milliseconds << "ms"; } // ----------------------------------- // // accounted_object // // ----------------------------------- accounted_object::~accounted_object() { if(m_parent_object) { SASSERT(m_context); m_context->get_rule_manager().dec_ref(m_parent_object); } } void accounted_object::set_accounting_parent_object(context & ctx, rule * parent) { if(m_parent_object) { SASSERT(m_context); SASSERT(m_context==&ctx); m_context->get_rule_manager().dec_ref(m_parent_object); } m_context = &ctx; m_parent_object = parent; m_context->get_rule_manager().inc_ref(m_parent_object); } void accounted_object::process_costs() { costs delta = get_current_costs(); if(delta.empty()) { return; } get_current_costs().reset(); accounted_object * obj = this; do { obj->m_processed_cost+=delta; obj=obj->m_parent_object; } while(obj); } void accounted_object::get_total_cost(costs & result) const { result.reset(); result+=m_current_cost; result+=m_processed_cost; } bool accounted_object::passes_output_thresholds(context & ctx) const { costs c; get_total_cost(c); return c.passes_thresholds(ctx); } void accounted_object::output_profile(context & ctx, std::ostream & out) const { costs c; get_total_cost(c); c.output(out); } // ----------------------------------- // // cost_recorder // // ----------------------------------- cost_recorder::cost_recorder() : m_obj(0) { m_stopwatch = alloc(stopwatch); m_stopwatch->start(); } cost_recorder::~cost_recorder() { if(m_obj) { finish(); } dealloc(m_stopwatch); } void cost_recorder::start(accounted_object * obj) { uint64 curr_time = static_cast(m_stopwatch->get_current_seconds()*1000); if(m_obj) { costs::time_type time_delta = static_cast(curr_time-m_last_time); costs & c = m_obj->get_current_costs(); c.instructions++; c.milliseconds+=time_delta; m_obj->m_being_recorded = false; } m_running = obj!=0; m_obj = obj; m_last_time = curr_time; if(obj) { m_obj->m_being_recorded = true; } } };