Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. The Lounge
  3. Ah the joys of late stage optimization

Ah the joys of late stage optimization

Scheduled Pinned Locked Moved The Lounge
performancegraphicsalgorithmsarchitecturecode-review
11 Posts 6 Posters 0 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • H Offline
    H Offline
    honey the codewitch
    wrote on last edited by
    #1

    Don't optimize until you have to generally. But that can sometimes backfire, like when an optimization requires an architecture change. To save memory and remain flexible, my SVG engine writes its SVGs out using callbacks with color runs and coordinates. The exception is when A) your canvas bounds are the same as the bound bitmap bounding box B) the bitmap is RGBA8888 (32-bit pixels) I just added an optimization to do direct writes in lieu of using callbacks. It greatly speeds up rendering - if you have the memory for it. Despite being a totally different way of rendering, I exposed it through a relatively common interface, and automatically direct bind to targets that fulfill A and B:

    template
    struct xdraw_canvas_binder {
    static gfx_result canvas(Destination& destination, const srect16& bounds, ::gfx::canvas* out_canvas) {
    ::gfx::canvas result((size16)bounds.dimensions());
    gfx_result gr = result.initialize();
    if(gr!=gfx_result::success) {
    return gr;
    }
    using st_t = xdraw_canvas_state;
    st_t* st = (st_t*)malloc(sizeof(st_t));
    if(st==nullptr) {
    result.deinitialize();
    return gfx_result::out_of_memory;
    }
    st->dest = &destination;
    st->dim = (size16)bounds.dimensions();
    st->offset = bounds.point1();
    *out_canvas=gfx_move(result);
    out_canvas->on_write_callback(xdraw_canvas_write_callback,st,::free);
    out_canvas->on_read_callback(xdraw_canvas_read_callback,st,::free);
    return gfx_result::success;
    }
    };
    template<>
    struct xdraw_canvas_binder>>
    {
    static gfx_result canvas(bitmap>& destination, const srect16& bounds, ::gfx::canvas* out_canvas) {
    ::gfx::canvas result((size16)bounds.dimensions());
    gfx_result gr = result.initialize();
    if(gr!=gfx_result::success) {
    return gr;
    }
    using st_t = xdraw_canvas_state>>;
    st_t* st = (st_t*)malloc(sizeof(st_t));
    if(st==nullptr) {
    result.deinitialize();
    return gfx_result::out_of_memory;
    }
    st->dest = &destination;
    st->dim = (size16)bounds.dimensions();
    st->offset = bounds.point1();
    *out_canvas=::gfx::helpers::gfx_move(result);
    if(bounds==(srect16)destination.bounds()) {
    gr=out_canvas->d

    O P C N 4 Replies Last reply
    0
    • H honey the codewitch

      Don't optimize until you have to generally. But that can sometimes backfire, like when an optimization requires an architecture change. To save memory and remain flexible, my SVG engine writes its SVGs out using callbacks with color runs and coordinates. The exception is when A) your canvas bounds are the same as the bound bitmap bounding box B) the bitmap is RGBA8888 (32-bit pixels) I just added an optimization to do direct writes in lieu of using callbacks. It greatly speeds up rendering - if you have the memory for it. Despite being a totally different way of rendering, I exposed it through a relatively common interface, and automatically direct bind to targets that fulfill A and B:

      template
      struct xdraw_canvas_binder {
      static gfx_result canvas(Destination& destination, const srect16& bounds, ::gfx::canvas* out_canvas) {
      ::gfx::canvas result((size16)bounds.dimensions());
      gfx_result gr = result.initialize();
      if(gr!=gfx_result::success) {
      return gr;
      }
      using st_t = xdraw_canvas_state;
      st_t* st = (st_t*)malloc(sizeof(st_t));
      if(st==nullptr) {
      result.deinitialize();
      return gfx_result::out_of_memory;
      }
      st->dest = &destination;
      st->dim = (size16)bounds.dimensions();
      st->offset = bounds.point1();
      *out_canvas=gfx_move(result);
      out_canvas->on_write_callback(xdraw_canvas_write_callback,st,::free);
      out_canvas->on_read_callback(xdraw_canvas_read_callback,st,::free);
      return gfx_result::success;
      }
      };
      template<>
      struct xdraw_canvas_binder>>
      {
      static gfx_result canvas(bitmap>& destination, const srect16& bounds, ::gfx::canvas* out_canvas) {
      ::gfx::canvas result((size16)bounds.dimensions());
      gfx_result gr = result.initialize();
      if(gr!=gfx_result::success) {
      return gr;
      }
      using st_t = xdraw_canvas_state>>;
      st_t* st = (st_t*)malloc(sizeof(st_t));
      if(st==nullptr) {
      result.deinitialize();
      return gfx_result::out_of_memory;
      }
      st->dest = &destination;
      st->dim = (size16)bounds.dimensions();
      st->offset = bounds.point1();
      *out_canvas=::gfx::helpers::gfx_move(result);
      if(bounds==(srect16)destination.bounds()) {
      gr=out_canvas->d

      O Offline
      O Offline
      obermd
      wrote on last edited by
      #2

      The best optimizations are usually design changes. Any optimization that requires an architectural change is a design change.

      H 1 Reply Last reply
      0
      • O obermd

        The best optimizations are usually design changes. Any optimization that requires an architectural change is a design change.

        H Offline
        H Offline
        honey the codewitch
        wrote on last edited by
        #3

        I didn't mean to imply otherwise. Edit: Adding, generally the ones that require design changes are usually "the best" (as in, have the most impact) because they are often what I call algorithmic changes. You can change the way something works as opposed to doing last mile bit twiddling which tends to (except in some cases, like in my SVG direct writes) yield less spectacular results. What I'm talking about in the OP is ways to identify potential areas where a design change might be in order for optimization purposes later, and then designing such that you can shoehorn it in without upending the whole thing.

        Check out my IoT graphics library here: https://honeythecodewitch.com/gfx And my IoT UI/User Experience library here: https://honeythecodewitch.com/uix

        1 Reply Last reply
        0
        • H honey the codewitch

          Don't optimize until you have to generally. But that can sometimes backfire, like when an optimization requires an architecture change. To save memory and remain flexible, my SVG engine writes its SVGs out using callbacks with color runs and coordinates. The exception is when A) your canvas bounds are the same as the bound bitmap bounding box B) the bitmap is RGBA8888 (32-bit pixels) I just added an optimization to do direct writes in lieu of using callbacks. It greatly speeds up rendering - if you have the memory for it. Despite being a totally different way of rendering, I exposed it through a relatively common interface, and automatically direct bind to targets that fulfill A and B:

          template
          struct xdraw_canvas_binder {
          static gfx_result canvas(Destination& destination, const srect16& bounds, ::gfx::canvas* out_canvas) {
          ::gfx::canvas result((size16)bounds.dimensions());
          gfx_result gr = result.initialize();
          if(gr!=gfx_result::success) {
          return gr;
          }
          using st_t = xdraw_canvas_state;
          st_t* st = (st_t*)malloc(sizeof(st_t));
          if(st==nullptr) {
          result.deinitialize();
          return gfx_result::out_of_memory;
          }
          st->dest = &destination;
          st->dim = (size16)bounds.dimensions();
          st->offset = bounds.point1();
          *out_canvas=gfx_move(result);
          out_canvas->on_write_callback(xdraw_canvas_write_callback,st,::free);
          out_canvas->on_read_callback(xdraw_canvas_read_callback,st,::free);
          return gfx_result::success;
          }
          };
          template<>
          struct xdraw_canvas_binder>>
          {
          static gfx_result canvas(bitmap>& destination, const srect16& bounds, ::gfx::canvas* out_canvas) {
          ::gfx::canvas result((size16)bounds.dimensions());
          gfx_result gr = result.initialize();
          if(gr!=gfx_result::success) {
          return gr;
          }
          using st_t = xdraw_canvas_state>>;
          st_t* st = (st_t*)malloc(sizeof(st_t));
          if(st==nullptr) {
          result.deinitialize();
          return gfx_result::out_of_memory;
          }
          st->dest = &destination;
          st->dim = (size16)bounds.dimensions();
          st->offset = bounds.point1();
          *out_canvas=::gfx::helpers::gfx_move(result);
          if(bounds==(srect16)destination.bounds()) {
          gr=out_canvas->d

          P Offline
          P Offline
          PIEBALDconsult
          wrote on last edited by
          #4

          Lowercase variables require less space.

          T 1 Reply Last reply
          0
          • P PIEBALDconsult

            Lowercase variables require less space.

            T Offline
            T Offline
            trønderen
            wrote on last edited by
            #5

            Oh'Really?

            Religious freedom is the freedom to say that two plus two make five.

            O 1 Reply Last reply
            0
            • T trønderen

              Oh'Really?

              Religious freedom is the freedom to say that two plus two make five.

              O Offline
              O Offline
              obermd
              wrote on last edited by
              #6

              Yep, lowercase tends to use less space on a line when using a variable width font. :laugh:

              1 Reply Last reply
              0
              • H honey the codewitch

                Don't optimize until you have to generally. But that can sometimes backfire, like when an optimization requires an architecture change. To save memory and remain flexible, my SVG engine writes its SVGs out using callbacks with color runs and coordinates. The exception is when A) your canvas bounds are the same as the bound bitmap bounding box B) the bitmap is RGBA8888 (32-bit pixels) I just added an optimization to do direct writes in lieu of using callbacks. It greatly speeds up rendering - if you have the memory for it. Despite being a totally different way of rendering, I exposed it through a relatively common interface, and automatically direct bind to targets that fulfill A and B:

                template
                struct xdraw_canvas_binder {
                static gfx_result canvas(Destination& destination, const srect16& bounds, ::gfx::canvas* out_canvas) {
                ::gfx::canvas result((size16)bounds.dimensions());
                gfx_result gr = result.initialize();
                if(gr!=gfx_result::success) {
                return gr;
                }
                using st_t = xdraw_canvas_state;
                st_t* st = (st_t*)malloc(sizeof(st_t));
                if(st==nullptr) {
                result.deinitialize();
                return gfx_result::out_of_memory;
                }
                st->dest = &destination;
                st->dim = (size16)bounds.dimensions();
                st->offset = bounds.point1();
                *out_canvas=gfx_move(result);
                out_canvas->on_write_callback(xdraw_canvas_write_callback,st,::free);
                out_canvas->on_read_callback(xdraw_canvas_read_callback,st,::free);
                return gfx_result::success;
                }
                };
                template<>
                struct xdraw_canvas_binder>>
                {
                static gfx_result canvas(bitmap>& destination, const srect16& bounds, ::gfx::canvas* out_canvas) {
                ::gfx::canvas result((size16)bounds.dimensions());
                gfx_result gr = result.initialize();
                if(gr!=gfx_result::success) {
                return gr;
                }
                using st_t = xdraw_canvas_state>>;
                st_t* st = (st_t*)malloc(sizeof(st_t));
                if(st==nullptr) {
                result.deinitialize();
                return gfx_result::out_of_memory;
                }
                st->dest = &destination;
                st->dim = (size16)bounds.dimensions();
                st->offset = bounds.point1();
                *out_canvas=::gfx::helpers::gfx_move(result);
                if(bounds==(srect16)destination.bounds()) {
                gr=out_canvas->d

                C Offline
                C Offline
                charlieg
                wrote on last edited by
                #7

                What vitamins do you take? Do you hear voices in your head? You scare me. :laugh: <-- in case you missed the humor. That's some impressive stuff. Templates have always scared me - I don't understand them (confession) but they seem like C++'s version of macros on steroids and PCP. I need to go learn them.

                Charlie Gilley “Microsoft is the virus..." "the problem with socialism is that eventually you run out of other people's money"

                H 1 Reply Last reply
                0
                • C charlieg

                  What vitamins do you take? Do you hear voices in your head? You scare me. :laugh: <-- in case you missed the humor. That's some impressive stuff. Templates have always scared me - I don't understand them (confession) but they seem like C++'s version of macros on steroids and PCP. I need to go learn them.

                  Charlie Gilley “Microsoft is the virus..." "the problem with socialism is that eventually you run out of other people's money"

                  H Offline
                  H Offline
                  honey the codewitch
                  wrote on last edited by
                  #8

                  They are basically that. I think of them as kind of a mail merge with "smart" (typed) arguments. A template is a source code generator. The C++ compiler process the arguments using the compiler's type info, and then emits more *textual* C++ code as a result. That result is then fed back into the compiler and parsed, much like a preprocessor macro. Where templates get primarily confusing is template specializations, but that's where their real power is, and what I'm using above. The two struct templates are part of the same overall template. The second one is a specialization for when the draw destination is a bitmap>. When the compiler sees that it generates the alternate.

                  Check out my IoT graphics library here: https://honeythecodewitch.com/gfx And my IoT UI/User Experience library here: https://honeythecodewitch.com/uix

                  C 1 Reply Last reply
                  0
                  • H honey the codewitch

                    They are basically that. I think of them as kind of a mail merge with "smart" (typed) arguments. A template is a source code generator. The C++ compiler process the arguments using the compiler's type info, and then emits more *textual* C++ code as a result. That result is then fed back into the compiler and parsed, much like a preprocessor macro. Where templates get primarily confusing is template specializations, but that's where their real power is, and what I'm using above. The two struct templates are part of the same overall template. The second one is a specialization for when the draw destination is a bitmap>. When the compiler sees that it generates the alternate.

                    Check out my IoT graphics library here: https://honeythecodewitch.com/gfx And my IoT UI/User Experience library here: https://honeythecodewitch.com/uix

                    C Offline
                    C Offline
                    charlieg
                    wrote on last edited by
                    #9

                    Yup - I understand the basic concept. I think a developer's attitude toward templates (and macros for that matter) depends on their initial exposure to them. I've seen templates used in a) books and b) one project that I support. The book examples tend not to really demonstrate the problem they are trying to solve - it's just dry, it gets complicated and most of the time I hit the location of "what's the point?" How is this really helping me? The second example - templates in use have to be done correctly if you want to be able to understand the problem they solve. I've seen templates used in code that just make everything more complicated and add unnecessary complexity. Or the template approach used just doesn't make any sense - more of a "hey let's try a template approach..." I need to go grab some older but much cheaper books on the subject to revisit.

                    Charlie Gilley “Microsoft is the virus..." "the problem with socialism is that eventually you run out of other people's money"

                    H 1 Reply Last reply
                    0
                    • C charlieg

                      Yup - I understand the basic concept. I think a developer's attitude toward templates (and macros for that matter) depends on their initial exposure to them. I've seen templates used in a) books and b) one project that I support. The book examples tend not to really demonstrate the problem they are trying to solve - it's just dry, it gets complicated and most of the time I hit the location of "what's the point?" How is this really helping me? The second example - templates in use have to be done correctly if you want to be able to understand the problem they solve. I've seen templates used in code that just make everything more complicated and add unnecessary complexity. Or the template approach used just doesn't make any sense - more of a "hey let's try a template approach..." I need to go grab some older but much cheaper books on the subject to revisit.

                      Charlie Gilley “Microsoft is the virus..." "the problem with socialism is that eventually you run out of other people's money"

                      H Offline
                      H Offline
                      honey the codewitch
                      wrote on last edited by
                      #10

                      I taught myself C++ without picking up a book since the 1990s (i had exactly one, and it was crap)**, so there are holes in my knowledge, but what I have learned is practical. Where templates really open the language up and make it do things no other major language can is metaprogramming. Metaprogramming is incredibly powerful. Metaprogramming is confusing, because C++ wasn't designed to do it. Rather, it was discovered and accomplished by stretching the intended purpose of the template keyword well beyond what it was initially designed to do. Try this on for size - my terminology might be a little off, but the concepts therein are sound: Metaprogramming in C++: A Gentle Introduction[^] ** Edit: I have to amend that. For some reason I forgot about Accelerated C++, which was actually quite good, if dated now.

                      Check out my IoT graphics library here: https://honeythecodewitch.com/gfx And my IoT UI/User Experience library here: https://honeythecodewitch.com/uix

                      1 Reply Last reply
                      0
                      • H honey the codewitch

                        Don't optimize until you have to generally. But that can sometimes backfire, like when an optimization requires an architecture change. To save memory and remain flexible, my SVG engine writes its SVGs out using callbacks with color runs and coordinates. The exception is when A) your canvas bounds are the same as the bound bitmap bounding box B) the bitmap is RGBA8888 (32-bit pixels) I just added an optimization to do direct writes in lieu of using callbacks. It greatly speeds up rendering - if you have the memory for it. Despite being a totally different way of rendering, I exposed it through a relatively common interface, and automatically direct bind to targets that fulfill A and B:

                        template
                        struct xdraw_canvas_binder {
                        static gfx_result canvas(Destination& destination, const srect16& bounds, ::gfx::canvas* out_canvas) {
                        ::gfx::canvas result((size16)bounds.dimensions());
                        gfx_result gr = result.initialize();
                        if(gr!=gfx_result::success) {
                        return gr;
                        }
                        using st_t = xdraw_canvas_state;
                        st_t* st = (st_t*)malloc(sizeof(st_t));
                        if(st==nullptr) {
                        result.deinitialize();
                        return gfx_result::out_of_memory;
                        }
                        st->dest = &destination;
                        st->dim = (size16)bounds.dimensions();
                        st->offset = bounds.point1();
                        *out_canvas=gfx_move(result);
                        out_canvas->on_write_callback(xdraw_canvas_write_callback,st,::free);
                        out_canvas->on_read_callback(xdraw_canvas_read_callback,st,::free);
                        return gfx_result::success;
                        }
                        };
                        template<>
                        struct xdraw_canvas_binder>>
                        {
                        static gfx_result canvas(bitmap>& destination, const srect16& bounds, ::gfx::canvas* out_canvas) {
                        ::gfx::canvas result((size16)bounds.dimensions());
                        gfx_result gr = result.initialize();
                        if(gr!=gfx_result::success) {
                        return gr;
                        }
                        using st_t = xdraw_canvas_state>>;
                        st_t* st = (st_t*)malloc(sizeof(st_t));
                        if(st==nullptr) {
                        result.deinitialize();
                        return gfx_result::out_of_memory;
                        }
                        st->dest = &destination;
                        st->dim = (size16)bounds.dimensions();
                        st->offset = bounds.point1();
                        *out_canvas=::gfx::helpers::gfx_move(result);
                        if(bounds==(srect16)destination.bounds()) {
                        gr=out_canvas->d

                        N Offline
                        N Offline
                        Nelek
                        wrote on last edited by
                        #11

                        First rule of optimization: Don't do it Second rule of optimization (only for experts): Don't do it... yet :rolleyes: :rolleyes: :laugh: :laugh: Just in case... it is a quote by someone I do not remember and I now am too lazy to look for.

                        M.D.V. ;) If something has a solution... Why do we have to worry about?. If it has no solution... For what reason do we have to worry about? Help me to understand what I'm saying, and I'll explain it better to you Rating helpful answers is nice, but saying thanks can be even nicer.

                        1 Reply Last reply
                        0
                        Reply
                        • Reply as topic
                        Log in to reply
                        • Oldest to Newest
                        • Newest to Oldest
                        • Most Votes


                        • Login

                        • Don't have an account? Register

                        • Login or register to search.
                        • First post
                          Last post
                        0
                        • Categories
                        • Recent
                        • Tags
                        • Popular
                        • World
                        • Users
                        • Groups