Reworked the XOR progress UI for better performance.

This commit is contained in:
Matthias Koefferlein 2017-09-20 22:52:52 +02:00
parent 083e1d75e9
commit 62b59fe71c
3 changed files with 108 additions and 52 deletions

View File

@ -32,6 +32,46 @@
namespace ext namespace ext
{ {
static inline void merge (size_t &a, size_t b)
{
if (a == missing_in_a || a == missing_in_a) {
// leave a
} else if (b == missing_in_a || b == missing_in_a) {
a = b;
} else {
a += b;
}
}
static void merge (std::vector<std::vector<size_t> > &a, const std::vector<std::vector<size_t> > &b)
{
if (a.size () < b.size ()) {
a.resize (b.size (), std::vector<size_t> ());
}
std::vector<std::vector<size_t> >::iterator ia = a.begin ();
for (std::vector<std::vector<size_t> >::const_iterator ib = b.begin (); ib != b.end (); ++ib, ++ia) {
if (ia->size () < ib->size ()) {
ia->resize (ib->size (), 0);
}
std::vector<size_t>::iterator ja = ia->begin ();
for (std::vector<size_t>::const_iterator jb = ib->begin (); jb != ib->end (); ++jb, ++ja) {
merge (*ja, *jb);
}
}
}
static size_t sum (const std::vector<std::vector<size_t> > &b)
{
size_t n = 0;
for (std::vector<std::vector<size_t> >::const_iterator i = b.begin (); i != b.end (); ++i) {
for (std::vector<size_t>::const_iterator j = i->begin (); j != i->end (); ++j) {
n += *j;
}
}
return n;
}
// -------------------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------------------
// The progress widget class // The progress widget class
@ -78,7 +118,7 @@ public:
return QSize (int (m_tolerance_labels.size ()) * (m_column_width + m_spacing) + m_first_column_width, (m_line_height + m_spacing) * m_max_lines + m_font_height * 2 + m_spacing); return QSize (int (m_tolerance_labels.size ()) * (m_column_width + m_spacing) + m_first_column_width, (m_line_height + m_spacing) * m_max_lines + m_font_height * 2 + m_spacing);
} }
void set_results (double dbu, int nx, int ny, const std::map<std::pair<size_t, size_t>, std::map<std::pair<db::LayerProperties, db::Coord>, size_t> > &results, const std::map<db::LayerProperties, size_t> &count_per_layer, const std::vector<db::Coord> &tolerances) void set_results (double dbu, int nx, int ny, const std::map<std::pair<db::LayerProperties, db::Coord>, std::vector<std::vector<size_t> > > &results, const std::map<db::LayerProperties, size_t> &count_per_layer, const std::vector<db::Coord> &tolerances)
{ {
m_labels.clear (); m_labels.clear ();
m_layer_labels.clear (); m_layer_labels.clear ();
@ -135,45 +175,51 @@ public:
size_t tot_count = 0; size_t tot_count = 0;
for (std::map<std::pair<size_t, size_t>, std::map<std::pair<db::LayerProperties, db::Coord>, size_t> >::const_iterator r = results.begin (); r != results.end (); ++r) { std::map<std::pair<db::LayerProperties, db::Coord>, std::vector<std::vector<size_t> > >::const_iterator rm = results.find (std::make_pair (c->first, *t));
if (rm != results.end ()) {
const std::map<std::pair<db::LayerProperties, db::Coord>, size_t> &rm = r->second; const std::vector<std::vector<size_t> > &counts = rm->second;
tot_count = sum (counts);
std::map<std::pair<db::LayerProperties, db::Coord>, size_t>::const_iterator rl = rm.find (std::make_pair (c->first, *t)); int ix = 0;
if (rl != rm.end ()) { for (std::vector<std::vector<size_t> >::const_iterator c = counts.begin (); c != counts.end (); ++c, ++ix) {
tot_count += rl->second; int iy = 0;
for (std::vector<size_t>::const_iterator cc = c->begin (); cc != c->end (); ++cc, ++iy) {
QImage *img = 0; QImage *img = 0;
if (rl->second == 0) { if (*cc == 0) {
img = &m_green_images.back ().back (); img = &m_green_images.back ().back ();
} else if (rl->second == missing_in_a) { } else if (*cc == missing_in_a) {
m_blue_images.back ().back ().fill (Qt::white); m_blue_images.back ().back ().fill (Qt::white);
} else if (rl->second == missing_in_b) { } else if (*cc == missing_in_b) {
m_yellow_images.back ().back ().fill (Qt::white); m_yellow_images.back ().back ().fill (Qt::white);
} else {
img = &m_red_images.back ().back ();
}
if (img) {
if (nx == 0 || ny == 0) {
img->fill (Qt::white);
} else { } else {
img = &m_red_images.back ().back ();
}
int ix = r->first.first; if (img) {
int iy = r->first.second;
int y2 = m_pixmap_size - 1 - (iy * m_pixmap_size + m_pixmap_size / 2) / ny; if (nx == 0 || ny == 0) {
int y1 = m_pixmap_size - 1 - ((iy + 1) * m_pixmap_size + m_pixmap_size / 2) / ny;
int x1 = (ix * m_pixmap_size + m_pixmap_size / 2) / nx; img->fill (Qt::white);
int x2 = ((ix + 1) * m_pixmap_size + m_pixmap_size / 2) / nx;
} else {
int y2 = m_pixmap_size - 1 - (iy * m_pixmap_size + m_pixmap_size / 2) / ny;
int y1 = m_pixmap_size - 1 - ((iy + 1) * m_pixmap_size + m_pixmap_size / 2) / ny;
int x1 = (ix * m_pixmap_size + m_pixmap_size / 2) / nx;
int x2 = ((ix + 1) * m_pixmap_size + m_pixmap_size / 2) / nx;
// "draw" the field
for (int y = y1; y <= y2 && y >= 0 && y < m_pixmap_size; ++y) {
*((uint32_t *) img->scanLine (y)) &= (((1 << x1) - 1) | ~((1 << (x2 + 1)) - 1));
}
// "draw" the field
for (int y = y1; y <= y2 && y >= 0 && y < m_pixmap_size; ++y) {
*((uint32_t *) img->scanLine (y)) &= (((1 << x1) - 1) | ~((1 << (x2 + 1)) - 1));
} }
} }
} }
} }
@ -333,17 +379,26 @@ void XORProgress::render_progress (QWidget *widget) const
} }
} }
void XORProgress::set_results (double dbu, int nx, int ny, const std::map<std::pair<size_t, size_t>, std::map<std::pair<db::LayerProperties, db::Coord>, size_t> > &results, const std::map<db::LayerProperties, size_t> &count_per_layer, const std::vector<db::Coord> &tol) void XORProgress::configure (double dbu, int nx, int ny, const std::vector<db::Coord> &tol)
{ {
if (m_count_per_layer != count_per_layer) { if (m_tolerances != tol || fabs (m_dbu - dbu) > 1e-6 || m_nx != nx || m_ny != ny) {
m_dbu = dbu; m_dbu = dbu;
m_nx = nx; m_nx = nx;
m_ny = ny; m_ny = ny;
m_results = results;
m_tolerances = tol; m_tolerances = tol;
m_count_per_layer = count_per_layer;
m_needs_update = true; m_needs_update = true;
} }
} }
void XORProgress::merge_results (std::map<std::pair<db::LayerProperties, db::Coord>, std::vector<std::vector<size_t> > > &results)
{
for (std::map<std::pair<db::LayerProperties, db::Coord>, std::vector<std::vector<size_t> > >::const_iterator r = results.begin (); r != results.end (); ++r) {
m_needs_update = true;
merge (m_results [r->first], r->second);
merge (m_count_per_layer [r->first.first], sum (r->second));
}
results.clear ();
}
} }

View File

@ -54,10 +54,12 @@ public:
virtual QWidget *progress_widget () const; virtual QWidget *progress_widget () const;
virtual void render_progress (QWidget *widget) const; virtual void render_progress (QWidget *widget) const;
void set_results (double dbu, int nx, int ny, const std::map<std::pair<size_t, size_t>, std::map<std::pair<db::LayerProperties, db::Coord>, size_t> > &results, const std::map<db::LayerProperties, size_t> &count_per_layer, const std::vector<db::Coord> &tol);
void configure (double dbu, int nx, int ny, const std::vector<db::Coord> &tol);
void merge_results (std::map<std::pair<db::LayerProperties, db::Coord>, std::vector<std::vector<size_t> > > &results);
private: private:
std::map<std::pair<size_t, size_t>, std::map<std::pair<db::LayerProperties, db::Coord>, size_t> > m_results; std::map<std::pair<db::LayerProperties, db::Coord>, std::vector<std::vector<size_t> > > m_results;
std::map<db::LayerProperties, size_t> m_count_per_layer; std::map<db::LayerProperties, size_t> m_count_per_layer;
std::vector<db::Coord> m_tolerances; std::vector<db::Coord> m_tolerances;
bool m_needs_update; bool m_needs_update;

View File

@ -390,10 +390,8 @@ public:
m_rdb (rdb), m_rdb (rdb),
m_rdb_cell (rdb_cell), m_rdb_cell (rdb_cell),
m_progress (0), m_progress (0),
m_update_results (false),
m_nx (0), m_ny (0) m_nx (0), m_ny (0)
{ {
// .. nothing yet ..
} }
output_mode_t output_mode () const output_mode_t output_mode () const
@ -457,16 +455,21 @@ public:
void add_results (const db::LayerProperties &lp, db::Coord tol, size_t n, size_t ix, size_t iy) void add_results (const db::LayerProperties &lp, db::Coord tol, size_t n, size_t ix, size_t iy)
{ {
QMutexLocker locker (&m_mutex); QMutexLocker locker (&m_mutex);
if (n == missing_in_a || n == missing_in_b) {
m_results [std::make_pair (ix, iy)][std::make_pair (lp, tol)] = n; std::vector<std::vector<size_t> > &cc = m_results [std::make_pair (lp, tol)];
m_count_per_layer [lp] = n; if (cc.size () <= ix) {
} else { cc.resize (ix + 1, std::vector<size_t> ());
// NOTE: we will not get a "normal" n after missing_in_a or missing_in_b }
m_results [std::make_pair (ix, iy)][std::make_pair (lp, tol)] += n; if (cc [ix].size () <= iy) {
m_count_per_layer [lp] += n; cc [ix].resize (iy + 1, 0);
} }
m_update_results = true; if (n == missing_in_a || n == missing_in_b) {
cc[ix][iy] = n;
} else {
// NOTE: we will not get a "normal" n after missing_in_a or missing_in_b
cc[ix][iy] += n;
}
} }
void update_progress (XORProgress &progress) void update_progress (XORProgress &progress)
@ -475,10 +478,8 @@ public:
{ {
QMutexLocker locker (&m_mutex); QMutexLocker locker (&m_mutex);
p = m_progress; p = m_progress;
if (m_update_results) { progress.configure (m_dbu, m_nx, m_ny, m_tolerances);
progress.set_results (m_dbu, m_nx, m_ny, m_results, m_count_per_layer, m_tolerances); progress.merge_results (m_results);
m_update_results = false;
}
} }
progress.set (p, true /*force yield*/); progress.set (p, true /*force yield*/);
@ -550,10 +551,8 @@ private:
unsigned int m_progress; unsigned int m_progress;
QMutex m_mutex; QMutex m_mutex;
std::string m_result_string; std::string m_result_string;
bool m_update_results;
size_t m_nx, m_ny; size_t m_nx, m_ny;
std::map<std::pair<size_t, size_t>, std::map<std::pair<db::LayerProperties, db::Coord>, size_t> > m_results; std::map<std::pair<db::LayerProperties, db::Coord>, std::vector<std::vector<size_t> > > m_results;
std::map<db::LayerProperties, size_t> m_count_per_layer;
}; };
class XORTask class XORTask