6 #ifndef TURI_TABLE_PRINTER_H_ 7 #define TURI_TABLE_PRINTER_H_ 10 #include <core/logging/assertions.hpp> 11 #include <timer/timer.hpp> 12 #include <core/parallel/pthread_tools.hpp> 13 #include <core/storage/sframe_data/sframe.hpp> 14 #include <core/parallel/atomic.hpp> 18 #include <core/util/code_optimization.hpp> 19 #include <core/logging/table_printer/table_element_printers.hpp> 23 extern double MIN_SECONDS_BETWEEN_TICK_PRINTS;
30 explicit progress_time(
double seconds) : elapsed_seconds(seconds) {}
35 double elapsed_seconds;
217 table_printer(
const std::vector<std::pair<std::string, size_t> >& _format,
218 size_t track_interval = 1);
230 alt_output_stream = &out_stream;
242 void print_header()
const;
250 void print_line_break()
const;
258 void print_footer()
const;
270 template <
typename... Args>
272 ASSERT_EQ(
size_t(
sizeof...(Args)), format.size());
274 std::ostringstream ss;
275 size_t column_index = 0;
279 _add_values_in_row(ss, column_index, columns...);
286 template <
typename T>
287 void print_row(
const std::vector<T>& row_string)
const {
288 ASSERT_EQ(row_string.size(), format.size());
290 std::ostringstream ss;
294 for (
size_t i = 0; i < row_string.size(); ++i) {
295 os_log_value(i, row_string[i]);
296 _get_table_printer(row_string[i]).print(ss, format[i].second);
305 bool time_for_next_row()
const {
306 double time_ms = lowres_tt.ms();
307 return (time_ms >= next_timed_print);
313 template <
typename... Args>
316 double time_ms = lowres_tt.ms();
318 if(time_ms >= next_timed_print) {
319 std::lock_guard<mutex> pl_guard(print_lock);
321 if(time_ms < next_timed_print)
324 if(next_timed_print == -1) {
325 next_timed_print = time_ms + 1000.0 * MIN_SECONDS_BETWEEN_TICK_PRINTS;
328 next_timed_print += 1000.0 * MIN_SECONDS_BETWEEN_TICK_PRINTS;
331 if(next_timed_print < time_ms)
332 next_timed_print = time_ms + 1000.0 * MIN_SECONDS_BETWEEN_TICK_PRINTS;
335 _print_progress_row(columns...);
339 if(track_interval != 0)
340 _track_progress(
true, columns...);
359 template <
typename... Args>
362 size_t ticks_so_far = ++num_ticks_so_far;
363 bool was_printed =
false;
365 if(register_tick(tick, ticks_so_far)) {
366 std::unique_lock<mutex> pl_guard(print_lock, std::defer_lock);
367 if(pl_guard.try_lock()) {
368 _print_progress_row(columns...);
373 if((track_interval != 0) && ((ticks_so_far - 1) % track_interval) == 0) {
374 _track_progress(was_printed, columns...);
387 ASSERT_EQ(cols.size(), format.size());
389 size_t ticks_so_far = ++num_ticks_so_far;
390 bool was_printed =
false;
392 if(register_tick(tick, ticks_so_far)) {
393 std::lock_guard<mutex> pl_guard(print_lock);
398 if (track_interval != 0 && ((ticks_so_far - 1) % track_interval) == 0) {
399 std::lock_guard<mutex> guard(track_register_lock);
401 if (!tracker_is_initialized) {
402 track_row_values_.resize(cols.size());
403 track_row_styles_.resize(cols.size());
406 for (
size_t i = 0; i < cols.size(); ++i) {
407 track_row_values_[i] = cols[i];
408 track_row_styles_[i] = style_type::kDefault;
411 track_progress_row(track_row_values_);
412 track_row_was_printed_ = was_printed;
421 double elapsed_time()
const;
429 sframe get_tracked_table();
436 static void os_log_value(
size_t column_index,
unsigned long long value);
437 static void os_log_value(
size_t column_index,
unsigned long value);
438 static void os_log_value(
size_t column_index,
unsigned int value);
439 static void os_log_value(
size_t column_index,
long long value);
440 static void os_log_value(
size_t column_index,
long value);
441 static void os_log_value(
size_t column_index,
int value);
442 static void os_log_value(
size_t column_index,
double value);
443 static void os_log_value(
size_t column_index,
float value);
444 void os_log_value(
size_t column_index,
const progress_time& value)
const;
445 static void os_log_value(
size_t column_index,
const char* value);
446 static void os_log_value(
size_t column_index,
bool value);
447 static void os_log_value(
size_t column_index,
const flexible_type& value);
452 template <
typename T>
453 table_internal::table_printer_element_base::style_type
454 _get_table_printer_style(
const T& v) {
455 static_assert(table_internal::table_printer_element<T>::valid_type,
456 "Table printer not available for this type; please cast to approprate type.");
458 return table_internal::table_printer_element<T>::style;
463 template <
typename T>
464 table_internal::table_printer_element<T> _get_table_printer(
const T& v)
const {
465 static_assert(table_internal::table_printer_element<T>::valid_type,
466 "Table printer not available for this type; please cast to approprate type.");
468 return table_internal::table_printer_element<T>(v);
474 table_internal::table_printer_element<progress_time> _get_table_printer(
const progress_time& pt)
const {
476 double t = (pt.elapsed_seconds < 0) ? tt.current_time() : pt.elapsed_seconds;
477 return table_internal::table_printer_element<progress_time>(t);
482 template <
typename T,
typename... Args>
484 const T& t,
const Args&... columns)
const {
486 os_log_value(column_index, t);
487 _get_table_printer(t).print(ss, format[column_index].second);
488 _add_values_in_row(ss, column_index + 1, columns...);
493 template <
typename T,
typename... Args>
494 GL_HOT_INLINE_FLATTEN void _add_values_in_row(std::ostringstream& ss,
size_t column_index,
const T& t)
const {
495 os_log_value(column_index, t);
496 _get_table_printer(t).print(ss, format[column_index].second);
502 template <
typename... Args>
503 GL_HOT_NOINLINE
void _print_progress_row(
const Args&... columns) {
505 print_row(columns...);
513 void _p(std::ostringstream& ss)
const {
515 if(alt_output_stream ==
nullptr) {
518 (*alt_output_stream) << ss.str() << std::endl;
523 std::vector<std::pair<std::string, size_t> > format;
531 std::ostream* alt_output_stream =
nullptr;
536 atomic<double> time_of_first_tick;
537 atomic<size_t> value_of_first_tick;
539 atomic<size_t> num_ticks_so_far;
540 atomic<size_t> next_tick_to_print;
541 size_t tick_interval = 0;
544 mutex tick_interval_lock;
547 double next_timed_print = -1;
553 inline bool register_tick(
size_t tick,
size_t ticks_so_far) {
564 if(ticks_so_far == 1) {
565 value_of_first_tick = tick;
570 }
else if(ticks_so_far < 5) {
573 }
else if (ticks_so_far == 5) {
576 while(time_of_first_tick == -1.0);
578 tick_interval = set_up_time_printing_interval(tick);
581 size_t nttp = ( (tick + 1) + tick_interval);
582 size_t rounded_nttp = nttp - nttp % tick_interval;
583 if(rounded_nttp <= tick)
584 rounded_nttp += tick_interval;
587 next_tick_to_print = rounded_nttp;
593 }
else if(ticks_so_far > 5) {
596 if(UNLIKELY(next_tick_to_print == 0)) {
597 while(next_tick_to_print == 0);
600 size_t next_tick = next_tick_to_print;
602 if(tick < next_tick) {
603 return always_print(tick);
607 DASSERT_GT(tick_interval, 0);
609 std::unique_lock<mutex> til_guard(tick_interval_lock, std::defer_lock);
611 if (til_guard.try_lock()) {
612 if(tick < next_tick_to_print) {
613 return always_print(tick);
616 while(next_tick_to_print <= tick)
617 next_tick_to_print += tick_interval;
633 size_t set_up_time_printing_interval(
size_t tick);
648 while( (tick_index % 10) == 0)
651 return (tick_index == 1 || tick_index == 5);
657 using style_type = table_internal::table_printer_element_base::style_type;
659 mutable mutex track_register_lock;
661 bool tracker_is_initialized =
false;
662 bool track_row_was_printed_ =
false;
664 std::vector<flexible_type> track_row_values_;
665 std::vector<style_type> track_row_styles_;
666 size_t track_interval = 1;
671 template <
typename... Args>
672 inline GL_HOT_NOINLINE
void _track_progress(
673 bool was_printed,
const Args&... columns) {
675 std::lock_guard<decltype(track_register_lock)> register_lock_gourd(track_register_lock);
677 const size_t n =
sizeof...(columns);
679 DASSERT_EQ(n, format.size());
681 if(!tracker_is_initialized) {
682 track_row_values_.resize(n);
683 track_row_styles_.resize(n);
686 _register_values_in_row(0, columns...);
687 track_progress_row(track_row_values_);
688 track_row_was_printed_ = was_printed;
691 void print_track_row_if_necessary()
const;
693 inline GL_HOT_NOINLINE
void 694 track_progress_row(
const std::vector<flexible_type>& track_row_buffer) {
696 size_t n = track_row_buffer.size();
697 if(!tracker_is_initialized) {
701 std::vector<std::string> column_names(n);
702 std::vector<flex_type_enum> column_types(n);
704 for(
size_t i = 0; i < n; ++i) {
705 column_names[i] = format[i].first;
706 column_types[i] = track_row_buffer[i].get_type();
711 tracker_is_initialized =
true;
714 *tracking_out_iter = track_row_buffer;
720 template <
typename T,
typename... Args>
722 size_t column_index,
const T& t,
const Args&... columns) {
723 DASSERT_LT(column_index, track_row_values_.size());
724 DASSERT_LT(column_index, track_row_styles_.size());
726 track_row_values_[column_index] = _get_table_printer(t).get_value();
727 track_row_styles_[column_index] = _get_table_printer_style(t);
728 _register_values_in_row(column_index + 1, columns...);
733 template <
typename T,
typename... Args>
735 size_t column_index,
const T& t) {
736 DASSERT_LT(column_index, track_row_values_.size());
737 DASSERT_LT(column_index, track_row_styles_.size());
739 track_row_values_[column_index] = _get_table_printer(t).get_value();
740 track_row_styles_[column_index] = _get_table_printer_style(t);
iterator get_output_iterator(size_t segmentid)
GL_HOT_INLINE void print_timed_progress_row(const Args &... columns)
double current_time() const
Returns the elapsed time in seconds since turi::timer::start was last called.
#define logprogress_stream
GL_HOT_INLINE void print_progress_row_strs(size_t tick, const std::vector< std::string > &cols)
#define GL_HOT_INLINE_FLATTEN
void open_for_write(const std::vector< std::string > &column_names, const std::vector< flex_type_enum > &column_types, const std::string &frame_sidx_file="", size_t nsegments=SFRAME_DEFAULT_NUM_SEGMENTS, bool fail_on_column_names=true)
GL_HOT_INLINE void print_progress_row(size_t tick, const Args &... columns)
void print_row(const std::vector< T > &row_string) const
void print_row(const Args &... columns) const
A simple class that can be used for benchmarking/timing up to microsecond resolution.
void set_output_stream(std::ostream &out_stream)