Announcement

Collapse

Looking for a User App or Add-On built by the NinjaTrader community?

Visit NinjaTrader EcoSystem and our free User App Share!

Have a question for the NinjaScript developer community? Open a new thread in our NinjaScript File Sharing Discussion Forum!
See more
See less

Partner 728x90

Collapse

OnRender() Performance Booster

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

    OnRender() Performance Booster

    Hi, I have a basic question: does it make sense to use a foreach loop in OnRender(), to outsource the content to multiple tasks? If a lot of data is loaded in the chart, the chart starts to jerk and the mouse movements are also no longer fluid. Could this perhaps improve with the division of the work to several tasks?
    sidlercom80
    NinjaTrader Ecosystem Vendor - Sidi Trading

    #2
    Hello sidlercom80,

    That depends on the task, in general you can use loops in OnRender to do something repetitive. I would not be able to say if in your specific use case if that will be helpful or not, I would need more details about what task you are trying to make have better performance.
    JesseNinjaTrader Customer Service

    Comment


      #3
      Hi Jesse, thank you for your answer.
      Code:
      foreach (var kvp in xyToDraw.ToList())
      {[INDENT]DrawXy(chartControl, chartScale, kvp.Value);[/INDENT]
       }
      Let's assume that a lot of lines are drawn in this method. Would it make sense here if each list entry were calculated in a separate task?
      sidlercom80
      NinjaTrader Ecosystem Vendor - Sidi Trading

      Comment


        #4
        Hello sidlercom80,

        Yes that would be a good use for a loop. Just to clarify the loop is going to do those one after another the same as if you had manually typed out a bunch of lines of code. The only efficiency gained here is less code because it is still the same work being done, the loop just automates the repetitive parts.

        JesseNinjaTrader Customer Service

        Comment


          #5
          Originally posted by sidlercom80 View Post
          Hi Jesse, thank you for your answer.
          Code:
          foreach (var kvp in xyToDraw[COLOR=#e74c3c].ToList()[/COLOR])
          {[INDENT]DrawXy(chartControl, chartScale, kvp.Value);[/INDENT]
          }
          Let's assume that a lot of lines are drawn in this method. Would it make sense here if each list entry were calculated in a separate task?
          Is there no other way to access the member data of xyToDraw?
          I mean, is that ToList() really necessary?

          Comment


            #6
            Originally posted by bltdavid View Post

            Is there no other way to access the member data of xyToDraw?
            I mean, is that ToList() really necessary?
            Hi bltdavid, no it's also possible without, it's only an example, why?
            That still does not answer the question ;-) do you know perhaps an example in OnRender() a foreach loop with a task or similar was worked?
            sidlercom80
            NinjaTrader Ecosystem Vendor - Sidi Trading

            Comment


              #7
              Hi, I have another understanding question: which is the better solution? To do the .Dispose after every RenderTarget, or is it enough once at the end of the method?
              Which type needs less resources (memory and CPU)?

              Code:
              TextFormat tf = new TextFormat(new Factory(), sf.Family.ToString(), SharpDX.DirectWrite.FontWeight.Bold, SharpDX.DirectWrite.FontStyle.Normal, (float)sf.Size + 2);
              TextLayout tl = null;
              ...
              tl = new TextLayout(Globals.DirectWriteFactory, "Test1", tf, 100, 20);
              RenderTarget.DrawTextLayout(vec1, tl, "TestColor");
              ...
              tl = new TextLayout(Globals.DirectWriteFactory, "Test2", tf, 100, 20);
              RenderTarget.DrawTextLayout(vec1, tl, "TestColor");
              ...
              tf.Dispose();
              tl.Dispose();
              Code:
              TextFormat tf = new TextFormat(new Factory(), sf.Family.ToString(), SharpDX.DirectWrite.FontWeight.Bold, SharpDX.DirectWrite.FontStyle.Normal, (float)sf.Size + 2);
              TextLayout tl = null;
              ...
              tl = new TextLayout(Globals.DirectWriteFactory, "Test1", tf, 100, 20);
              RenderTarget.DrawTextLayout(vec1, tl, "TestColor");
              tl.Dispose();
              ...
              tl = new TextLayout(Globals.DirectWriteFactory, "Test2", tf, 100, 20);
              RenderTarget.DrawTextLayout(vec1, tl, "TestColor");
              tl.Dispose();
              ...
              tf.Dispose();
              sidlercom80
              NinjaTrader Ecosystem Vendor - Sidi Trading

              Comment


                #8
                Hello sidlercom80,

                The most efficient way to create resources that are shared would be to use OnRenderTargetChanged. For items that need created dynamically or require specific rendering items like X/Y values you would just create and dispose of those objects in OnRender. Where you dispose of that in OnRender doesn't really matter as long as it is disposed. Your first example is missing a dispose because you assign the variable twice but dispose once so 1 resource is left in memory.
                JesseNinjaTrader Customer Service

                Comment


                  #9
                  Originally posted by sidlercom80 View Post
                  [CODE}foreach (var kvp in xyToDraw.ToList())
                  {
                  DrawXy(chartControl, chartScale, kvp.Value);


                  }
                  [/CODE]
                  Let's assume that a lot of lines are drawn in this method. Would it make sense here if each list entry were calculated in a separate task?
                  Let's be blunt.
                  (You asked for more help in a private message, see that reply also.)

                  Have you studied every OnRender in the Indicators folder?
                  Do you see some very similar techniques?
                  Do those techniques look anything like what you're doing?

                  You've given very little of your code to study, so I'm going to make
                  the easy assumption that your OnRender fails to closely model
                  the OnRender techniques employed by NinjaTrader.

                  Not to mention, there is the fundamental question that kinda
                  bugs me -- why are you drawing lines? I mean, the standard
                  Ninja line drawing methods are handled automatically by the
                  internal OnRender -- what's so special that you gotta handle
                  your own line drawing in a custom OnRender?

                  Ok, you're right, legitimate cases do exist.
                  Let's study one of those.

                  Have you looked at @Pivots.cs?
                  It draws horizontal lines using a custom OnRender.
                  But look closely at the code, it does not paint every single
                  element of the line for every single bar in the bar series.

                  It only paints line elements for bars that are visible inside
                  the chart, starting at bar index 'ChartBars.FromIndex' and
                  ending at 'ChartBars.ToIndex'.

                  That is, the viewable canvas area can only show 'X' bars at
                  any one time. As a new bar is added on the right, the oldest
                  visible bar on the left scrolls off of the visible canvas, and you
                  still have 'X' bars viewable.

                  When your code DrawXy draws its lines, are you drawing
                  for all bars 0 to CurrentBar? That is wrong.

                  Your code should be doing its own 'clipping' of the lines that
                  need to be painted, and it should only issue draw commands
                  for the visible portions of those lines.

                  You may be doing all that already.
                  I may be completely off base.

                  But who knows?
                  The code you provided is completely inadequate to know anything
                  about what you are doing ... much less if it's right or wrong.

                  -=o=-

                  As far as using separate tasks, why do you think that will
                  make a difference? I've never seen any code do that, and
                  until you have timing benchmarks from a profiler telling you
                  where in the code all the time is being spent, thinking along
                  those lines (pun?) is premature and way overkill -- separate
                  tasks don't strike me as the most appropriate weapon for
                  this fight.

                  Last edited by bltdavid; 03-09-2022, 04:05 PM.

                  Comment


                    #10
                    Originally posted by bltdavid View Post

                    Let's be blunt.
                    (You asked for more help in a private message, see that reply also.)

                    Have you studied every OnRender in the Indicators folder?
                    Do you see some very similar techniques?
                    Do those techniques look anything like what you're doing?

                    You've given very little of your code to study, so I'm going to make
                    the easy assumption that your OnRender fails to closely model
                    the OnRender techniques employed by NinjaTrader.

                    Not to mention, there is the fundamental question that kinda
                    bugs me -- why are you drawing lines? I mean, the standard
                    Ninja line drawing methods are handled automatically by the
                    internal OnRender -- what's so special that you gotta handle
                    your own line drawing in a custom OnRender?

                    Ok, you're right, legitimate cases do exist.
                    Let's study one of those.

                    Have you looked at @Pivots.cs?
                    It draws horizontal lines using a custom OnRender.
                    But look closely at the code, it does not paint every single
                    element of the line for every single bar in the bar series.

                    It only paints line elements for bars that are visible inside
                    the chart, starting at bar index 'ChartBars.FromIndex' and
                    ending at 'ChartBars.ToIndex'.

                    That is, the viewable canvas area can only show 'X' bars at
                    any one time. As a new bar is added on the right, the oldest
                    visible bar on the left scrolls off of the visible canvas, and you
                    still have 'X' bars viewable.

                    When your code DrawXy draws its lines, are you drawing
                    for all bars 0 to CurrentBar? That is wrong.

                    Your code should be doing its own 'clipping' of the lines that
                    need to be painted, and it should only issue draw commands
                    for the visible portions of those lines.

                    You may be doing all that already.
                    I may be completely off base.

                    But who knows?
                    The code you provided is completely inadequate to know anything
                    about what you are doing ... much less if it's right or wrong.

                    -=o=-

                    As far as using separate tasks, why do you think that will
                    make a difference? I've never seen any code do that, and
                    until you have timing benchmarks from a profiler telling you
                    where in the code all the time is being spent, thinking along
                    those lines (pun?) is premature and way overkill -- separate
                    tasks don't strike me as the most appropriate weapon for
                    this fight.

                    I don't draw all bars but only the visible ones, like in your example above. My request was a general question how to handle things in OnRender better and therefore faster. Whether it is at all possible to outsource things in task to increase the performance, or whether that is basically not possible.
                    sidlercom80
                    NinjaTrader Ecosystem Vendor - Sidi Trading

                    Comment

                    Latest Posts

                    Collapse

                    Topics Statistics Last Post
                    Started by DanielSanMartin, Yesterday, 02:37 PM
                    2 responses
                    12 views
                    0 likes
                    Last Post DanielSanMartin  
                    Started by DJ888, 04-16-2024, 06:09 PM
                    4 responses
                    12 views
                    0 likes
                    Last Post DJ888
                    by DJ888
                     
                    Started by terofs, Today, 04:18 PM
                    0 responses
                    11 views
                    0 likes
                    Last Post terofs
                    by terofs
                     
                    Started by nandhumca, Today, 03:41 PM
                    0 responses
                    7 views
                    0 likes
                    Last Post nandhumca  
                    Started by The_Sec, Today, 03:37 PM
                    0 responses
                    3 views
                    0 likes
                    Last Post The_Sec
                    by The_Sec
                     
                    Working...
                    X