Blame gegl/gegl-instrument.c

Packit Service 2781ba
/* This file is part of GEGL
Packit Service 2781ba
 *
Packit Service 2781ba
 * GEGL is free software; you can redistribute it and/or
Packit Service 2781ba
 * modify it under the terms of the GNU Lesser General Public
Packit Service 2781ba
 * License as published by the Free Software Foundation; either
Packit Service 2781ba
 * version 3 of the License, or (at your option) any later version.
Packit Service 2781ba
 *
Packit Service 2781ba
 * GEGL is distributed in the hope that it will be useful,
Packit Service 2781ba
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 2781ba
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit Service 2781ba
 * Lesser General Public License for more details.
Packit Service 2781ba
 *
Packit Service 2781ba
 * You should have received a copy of the GNU Lesser General Public
Packit Service 2781ba
 * License along with GEGL; if not, see <http://www.gnu.org/licenses/>.
Packit Service 2781ba
 *
Packit Service 2781ba
 * Copyright 2006 Øyvind Kolås
Packit Service 2781ba
 */
Packit Service 2781ba
Packit Service 2781ba
#include "config.h"
Packit Service 2781ba
#include <glib.h>
Packit Service 2781ba
#include <string.h>
Packit Service 2781ba
#include "gegl-instrument.h"
Packit Service 2781ba
Packit Service 2781ba
long babl_ticks (void);
Packit Service 2781ba
long gegl_ticks (void)
Packit Service 2781ba
{
Packit Service 2781ba
  return babl_ticks ();
Packit Service 2781ba
}
Packit Service 2781ba
Packit Service 2781ba
typedef struct _Timing Timing;
Packit Service 2781ba
Packit Service 2781ba
struct _Timing
Packit Service 2781ba
{
Packit Service 2781ba
  gchar  *name;
Packit Service 2781ba
  long    usecs;
Packit Service 2781ba
  Timing *parent;
Packit Service 2781ba
  Timing *children;
Packit Service 2781ba
  Timing *next;
Packit Service 2781ba
};
Packit Service 2781ba
Packit Service 2781ba
static Timing *root = NULL;
Packit Service 2781ba
Packit Service 2781ba
static Timing *iter_next (Timing *iter)
Packit Service 2781ba
{
Packit Service 2781ba
  if (iter->children)
Packit Service 2781ba
    {
Packit Service 2781ba
      iter = iter->children;
Packit Service 2781ba
    }
Packit Service 2781ba
  else if (iter->next)
Packit Service 2781ba
    {
Packit Service 2781ba
      iter = iter->next;
Packit Service 2781ba
    }
Packit Service 2781ba
  else
Packit Service 2781ba
    {
Packit Service 2781ba
      while (iter && !iter->next)
Packit Service 2781ba
        iter = iter->parent;
Packit Service 2781ba
      if (iter && iter->next)
Packit Service 2781ba
        iter = iter->next;
Packit Service 2781ba
      else
Packit Service 2781ba
        return NULL;
Packit Service 2781ba
    }
Packit Service 2781ba
  return iter;
Packit Service 2781ba
}
Packit Service 2781ba
Packit Service 2781ba
static gint timing_depth (Timing *timing)
Packit Service 2781ba
{
Packit Service 2781ba
  Timing *iter = timing;
Packit Service 2781ba
  gint    ret  = 0;
Packit Service 2781ba
Packit Service 2781ba
  while (iter &&
Packit Service 2781ba
         iter->parent)
Packit Service 2781ba
    {
Packit Service 2781ba
      ret++;
Packit Service 2781ba
      iter = iter->parent;
Packit Service 2781ba
    }
Packit Service 2781ba
Packit Service 2781ba
  return ret;
Packit Service 2781ba
}
Packit Service 2781ba
Packit Service 2781ba
static Timing *timing_find (Timing      *root,
Packit Service 2781ba
                            const gchar *name)
Packit Service 2781ba
{
Packit Service 2781ba
  Timing *iter = root;
Packit Service 2781ba
Packit Service 2781ba
  if (!iter)
Packit Service 2781ba
    return NULL;
Packit Service 2781ba
Packit Service 2781ba
  while (iter)
Packit Service 2781ba
    {
Packit Service 2781ba
      if (!strcmp (iter->name, name))
Packit Service 2781ba
        return iter;
Packit Service 2781ba
      if (timing_depth (iter_next (iter)) <= timing_depth (root))
Packit Service 2781ba
        return NULL;
Packit Service 2781ba
      iter = iter_next (iter);
Packit Service 2781ba
    }
Packit Service 2781ba
  return NULL;
Packit Service 2781ba
}
Packit Service 2781ba
Packit Service 2781ba
void
Packit Service 2781ba
gegl_instrument (const gchar *parent_name,
Packit Service 2781ba
                 const gchar *name,
Packit Service 2781ba
                 long         usecs)
Packit Service 2781ba
{
Packit Service 2781ba
  Timing *iter;
Packit Service 2781ba
  Timing *parent;
Packit Service 2781ba
Packit Service 2781ba
  if (root == NULL)
Packit Service 2781ba
    {
Packit Service 2781ba
      root       = g_slice_new0 (Timing);
Packit Service 2781ba
      root->name = g_strdup (parent_name);
Packit Service 2781ba
    }
Packit Service 2781ba
  parent = timing_find (root, parent_name);
Packit Service 2781ba
  if (!parent)
Packit Service 2781ba
    {
Packit Service 2781ba
      gegl_instrument (root->name, parent_name, 0);
Packit Service 2781ba
      parent = timing_find (root, parent_name);
Packit Service 2781ba
    }
Packit Service 2781ba
  g_assert (parent);
Packit Service 2781ba
  iter = timing_find (parent, name);
Packit Service 2781ba
  if (!iter)
Packit Service 2781ba
    {
Packit Service 2781ba
      iter             = g_slice_new0 (Timing);
Packit Service 2781ba
      iter->name       = g_strdup (name);
Packit Service 2781ba
      iter->parent     = parent;
Packit Service 2781ba
      iter->next       = parent->children;
Packit Service 2781ba
      parent->children = iter;
Packit Service 2781ba
    }
Packit Service 2781ba
  iter->usecs += usecs;
Packit Service 2781ba
}
Packit Service 2781ba
Packit Service 2781ba
Packit Service 2781ba
static glong timing_child_sum (Timing *timing)
Packit Service 2781ba
{
Packit Service 2781ba
  Timing *iter = timing->children;
Packit Service 2781ba
  glong   sum  = 0;
Packit Service 2781ba
Packit Service 2781ba
  while (iter)
Packit Service 2781ba
    {
Packit Service 2781ba
      sum += iter->usecs;
Packit Service 2781ba
      iter = iter->next;
Packit Service 2781ba
    }
Packit Service 2781ba
Packit Service 2781ba
  return sum;
Packit Service 2781ba
}
Packit Service 2781ba
Packit Service 2781ba
static glong timing_other (Timing *timing)
Packit Service 2781ba
{
Packit Service 2781ba
  if (timing->children)
Packit Service 2781ba
    return timing->usecs - timing_child_sum (timing);
Packit Service 2781ba
  return 0;
Packit Service 2781ba
}
Packit Service 2781ba
Packit Service 2781ba
static float seconds (glong usecs)
Packit Service 2781ba
{
Packit Service 2781ba
  return usecs / 1000000.0;
Packit Service 2781ba
}
Packit Service 2781ba
Packit Service 2781ba
static float normalized (glong usecs)
Packit Service 2781ba
{
Packit Service 2781ba
  return 1.0 * usecs / root->usecs;
Packit Service 2781ba
}
Packit Service 2781ba
Packit Service 2781ba
#include <string.h>
Packit Service 2781ba
Packit Service 2781ba
static GString *
Packit Service 2781ba
tab_to (GString *string, gint position)
Packit Service 2781ba
{
Packit Service 2781ba
  gchar *p;
Packit Service 2781ba
  gint   curcount = 0;
Packit Service 2781ba
  gint   i;
Packit Service 2781ba
Packit Service 2781ba
  p = strrchr (string->str, '\n');
Packit Service 2781ba
  if (!p)
Packit Service 2781ba
    {
Packit Service 2781ba
      p = string->str;
Packit Service 2781ba
      curcount++;
Packit Service 2781ba
    }
Packit Service 2781ba
  while (p && *p != '\0')
Packit Service 2781ba
    {
Packit Service 2781ba
      curcount++;
Packit Service 2781ba
      p++;
Packit Service 2781ba
    }
Packit Service 2781ba
Packit Service 2781ba
  if (curcount > position && position != 0)
Packit Service 2781ba
    {
Packit Service 2781ba
      g_warning ("%s tab overflow %i>%i", G_STRLOC, curcount, position);
Packit Service 2781ba
    }
Packit Service 2781ba
  else
Packit Service 2781ba
    {
Packit Service 2781ba
      for (i = 0; i <= position - curcount; i++)
Packit Service 2781ba
        string = g_string_append (string, " ");
Packit Service 2781ba
    }
Packit Service 2781ba
  return string;
Packit Service 2781ba
}
Packit Service 2781ba
Packit Service 2781ba
static gchar *eight[] = {
Packit Service 2781ba
  " ",
Packit Service 2781ba
  "▏",
Packit Service 2781ba
  "▍",
Packit Service 2781ba
  "▌",
Packit Service 2781ba
  "▋",
Packit Service 2781ba
  "▊",
Packit Service 2781ba
  "▉",
Packit Service 2781ba
  "█"
Packit Service 2781ba
};
Packit Service 2781ba
Packit Service 2781ba
static GString *
Packit Service 2781ba
bar (GString *string, gint width, gfloat value)
Packit Service 2781ba
{
Packit Service 2781ba
  gboolean utf8 = TRUE;
Packit Service 2781ba
  gint     i;
Packit Service 2781ba
Packit Service 2781ba
  if (value < 0)
Packit Service 2781ba
    return string;
Packit Service 2781ba
  if (utf8)
Packit Service 2781ba
    {
Packit Service 2781ba
      gint blocks = width * 8 * value;
Packit Service 2781ba
Packit Service 2781ba
      for (i = 0; i < blocks / 8; i++)
Packit Service 2781ba
        {
Packit Service 2781ba
          string = g_string_append (string, "█");
Packit Service 2781ba
        }
Packit Service 2781ba
      string = g_string_append (string, eight[blocks % 8]);
Packit Service 2781ba
    }
Packit Service 2781ba
  else
Packit Service 2781ba
    {
Packit Service 2781ba
      for (i = 0; i < width; i++)
Packit Service 2781ba
        {
Packit Service 2781ba
          if (width * value > i)
Packit Service 2781ba
            string = g_string_append (string, "X");
Packit Service 2781ba
        }
Packit Service 2781ba
    }
Packit Service 2781ba
  return string;
Packit Service 2781ba
}
Packit Service 2781ba
Packit Service 2781ba
#define INDENT_SPACES    2
Packit Service 2781ba
#define SECONDS_COL      29
Packit Service 2781ba
#define BAR_COL          36
Packit Service 2781ba
#define BAR_WIDTH        (78 - BAR_COL)
Packit Service 2781ba
Packit Service 2781ba
static void
Packit Service 2781ba
sort_children (Timing *parent)
Packit Service 2781ba
{
Packit Service 2781ba
  Timing  *iter;
Packit Service 2781ba
  Timing  *prev;
Packit Service 2781ba
  gboolean changed = FALSE;
Packit Service 2781ba
Packit Service 2781ba
  do
Packit Service 2781ba
    {
Packit Service 2781ba
      iter    = parent->children;
Packit Service 2781ba
      changed = FALSE;
Packit Service 2781ba
      prev    = NULL;
Packit Service 2781ba
      while (iter && iter->next)
Packit Service 2781ba
        {
Packit Service 2781ba
          Timing *next = iter->next;
Packit Service 2781ba
Packit Service 2781ba
          if (next->usecs > iter->usecs)
Packit Service 2781ba
            {
Packit Service 2781ba
              changed = TRUE;
Packit Service 2781ba
              if (prev)
Packit Service 2781ba
                {
Packit Service 2781ba
                  prev->next = next;
Packit Service 2781ba
                  iter->next = next->next;
Packit Service 2781ba
                  next->next = iter;
Packit Service 2781ba
                }
Packit Service 2781ba
              else
Packit Service 2781ba
                {
Packit Service 2781ba
                  iter->next       = next->next;
Packit Service 2781ba
                  next->next       = iter;
Packit Service 2781ba
                  parent->children = next;
Packit Service 2781ba
                }
Packit Service 2781ba
            }
Packit Service 2781ba
          prev = iter;
Packit Service 2781ba
          iter = iter->next;
Packit Service 2781ba
        }
Packit Service 2781ba
    } while (changed);
Packit Service 2781ba
Packit Service 2781ba
Packit Service 2781ba
  iter = parent->children;
Packit Service 2781ba
  while (iter && iter->next)
Packit Service 2781ba
    {
Packit Service 2781ba
      sort_children (iter);
Packit Service 2781ba
      iter = iter->next;
Packit Service 2781ba
    }
Packit Service 2781ba
}
Packit Service 2781ba
Packit Service 2781ba
gchar *
Packit Service 2781ba
gegl_instrument_utf8 (void)
Packit Service 2781ba
{
Packit Service 2781ba
  GString *s = g_string_new ("");
Packit Service 2781ba
  gchar   *ret;
Packit Service 2781ba
  Timing  *iter = root;
Packit Service 2781ba
Packit Service 2781ba
  sort_children (root);
Packit Service 2781ba
Packit Service 2781ba
  while (iter)
Packit Service 2781ba
    {
Packit Service 2781ba
      gchar *buf;
Packit Service 2781ba
Packit Service 2781ba
      if (!strcmp (iter->name, root->name))
Packit Service 2781ba
        {
Packit Service 2781ba
          buf = g_strdup_printf ("Total time: %.3fs\n", seconds (iter->usecs));
Packit Service 2781ba
          s   = g_string_append (s, buf);
Packit Service 2781ba
          g_free (buf);
Packit Service 2781ba
        }
Packit Service 2781ba
Packit Service 2781ba
      s = tab_to (s, timing_depth (iter) * INDENT_SPACES);
Packit Service 2781ba
      s = g_string_append (s, iter->name);
Packit Service 2781ba
Packit Service 2781ba
      s   = tab_to (s, SECONDS_COL);
Packit Service 2781ba
      buf = g_strdup_printf ("%5.1f%%", iter->parent ? 100.0 * iter->usecs / iter->parent->usecs : 100.0);
Packit Service 2781ba
      s   = g_string_append (s, buf);
Packit Service 2781ba
      g_free (buf);
Packit Service 2781ba
      s = tab_to (s, BAR_COL);
Packit Service 2781ba
      s = bar (s, BAR_WIDTH, normalized (iter->usecs));
Packit Service 2781ba
      s = g_string_append (s, "\n");
Packit Service 2781ba
Packit Service 2781ba
      if (timing_depth (iter_next (iter)) < timing_depth (iter))
Packit Service 2781ba
        {
Packit Service 2781ba
          if (timing_other (iter->parent) > 0)
Packit Service 2781ba
            {
Packit Service 2781ba
              s   = tab_to (s, timing_depth (iter) * INDENT_SPACES);
Packit Service 2781ba
              s   = g_string_append (s, "other");
Packit Service 2781ba
              s   = tab_to (s, SECONDS_COL);
Packit Service 2781ba
              buf = g_strdup_printf ("%5.1f%%", 100 * normalized (timing_other (iter->parent)));
Packit Service 2781ba
              s   = g_string_append (s, buf);
Packit Service 2781ba
              g_free (buf);
Packit Service 2781ba
              s = tab_to (s, BAR_COL);
Packit Service 2781ba
              s = bar (s, BAR_WIDTH, normalized (timing_other (iter->parent)));
Packit Service 2781ba
              s = g_string_append (s, "\n");
Packit Service 2781ba
            }
Packit Service 2781ba
          s = g_string_append (s, "\n");
Packit Service 2781ba
        }
Packit Service 2781ba
Packit Service 2781ba
      iter = iter_next (iter);
Packit Service 2781ba
    }
Packit Service 2781ba
Packit Service 2781ba
  ret = g_strdup (s->str);
Packit Service 2781ba
  g_string_free (s, TRUE);
Packit Service 2781ba
  return ret;
Packit Service 2781ba
}