Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Special Interest Groups
  3. C++ Gurus
  4. Performance of signals/slots for plotting/oscilloscope (performance questions)

Performance of signals/slots for plotting/oscilloscope (performance questions)

Scheduled Pinned Locked Moved Solved C++ Gurus
14 Posts 3 Posters 3.8k Views 3 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.
  • fcarneyF Offline
    fcarneyF Offline
    fcarney
    wrote on last edited by
    #1

    I am currently developing my own QtQuick based GL type plotting solution. I have used the basic QtQuick plotting example provided with Qt 5.12.x. The one with a shadow and nice background. I have a callback that is running in a QThread of an audio synthesis library. I modified the library (called Gamma) to use QtThreads. In this callback I am emitting a signal with a std::vector<double> as the parameter. I know this copies the data so there may be a performance hit there. This is connected to the QtQuick Graph object I am developing. In this Graph I am trying to simulate level triggered searching to find the zero crossover in either the positive or negative direction. This seems to work fairly well.

    I get tearing in the data (like I am missing a sample) and I am not sure if this is coming from the Gamma library (it sounds okay) or I am somehow missing frames.

    If a slot is called multiple times is this queued up? My code "appears" to keep up with the signal, but I am not entirely sure. I think I need to calculate the samples per second of the Gamma library and compare to how often my slot is called.

    Is there a better way to isolate the QThread from the main thread different from signals to get better performance?

    Is there a better way to approach writing an oscilloscope type system?

    I don't really want to use a library. I want to create a scope myself for fun and learning some more real time coding approaches.

    C++ is a perfectly valid school of magic.

    J.HilkJ 1 Reply Last reply
    0
    • fcarneyF Offline
      fcarneyF Offline
      fcarney
      wrote on last edited by
      #2

      Also, in the the receiving slot I tried to create a smart pointer with make_unique. For some reason adding that caused my app to crash. It was very odd. The pointer was valid so I don't understand what happened. By the time it hits the slot it should be running in the GUI (main) thread.

      C++ is a perfectly valid school of magic.

      1 Reply Last reply
      0
      • fcarneyF fcarney

        I am currently developing my own QtQuick based GL type plotting solution. I have used the basic QtQuick plotting example provided with Qt 5.12.x. The one with a shadow and nice background. I have a callback that is running in a QThread of an audio synthesis library. I modified the library (called Gamma) to use QtThreads. In this callback I am emitting a signal with a std::vector<double> as the parameter. I know this copies the data so there may be a performance hit there. This is connected to the QtQuick Graph object I am developing. In this Graph I am trying to simulate level triggered searching to find the zero crossover in either the positive or negative direction. This seems to work fairly well.

        I get tearing in the data (like I am missing a sample) and I am not sure if this is coming from the Gamma library (it sounds okay) or I am somehow missing frames.

        If a slot is called multiple times is this queued up? My code "appears" to keep up with the signal, but I am not entirely sure. I think I need to calculate the samples per second of the Gamma library and compare to how often my slot is called.

        Is there a better way to isolate the QThread from the main thread different from signals to get better performance?

        Is there a better way to approach writing an oscilloscope type system?

        I don't really want to use a library. I want to create a scope myself for fun and learning some more real time coding approaches.

        J.HilkJ Offline
        J.HilkJ Offline
        J.Hilk
        Moderators
        wrote on last edited by
        #3

        @fcarney said in Performance of signals/slots for plotting/oscilloscope (performance questions):

        If a slot is called multiple times is this queued up

        the the emitting signal is from a different thread , than yes, they are queued up and called one after the other

        Is there a better way to isolate the QThread from the main thread different from signals to get better performance

        There's QMutex it's more low level but can be a good amount faster than Signal/Slot

        Is there a better way to approach writing an oscilloscope type system?

        No Ideas sorry 😔


        Be aware of the Qt Code of Conduct, when posting : https://forum.qt.io/topic/113070/qt-code-of-conduct


        Q: What's that?
        A: It's blue light.
        Q: What does it do?
        A: It turns blue.

        1 Reply Last reply
        1
        • fcarneyF Offline
          fcarneyF Offline
          fcarney
          wrote on last edited by
          #4

          I determined that I am not missing any frames. So I must be doing something funky with the data, or the data I am getting is funky. I did determine that my function is being called 170+ times per second. So not super fast.

          @J-Hilk Thanks for the info.

          C++ is a perfectly valid school of magic.

          1 Reply Last reply
          0
          • fcarneyF Offline
            fcarneyF Offline
            fcarney
            wrote on last edited by
            #5

            Here is my solution to reading data in and buffering:
            CircularBuffer

            I have some planned expansion of this buffer, but so far it performs really well. I read up more on signals. It does have some overhead, but so far it has been acceptable performance. I did find an article that explained the overhead for differing kinds of signal/slot operations. They are not great, but they are not bad either.

            C++ is a perfectly valid school of magic.

            kshegunovK 1 Reply Last reply
            0
            • fcarneyF fcarney

              Here is my solution to reading data in and buffering:
              CircularBuffer

              I have some planned expansion of this buffer, but so far it performs really well. I read up more on signals. It does have some overhead, but so far it has been acceptable performance. I did find an article that explained the overhead for differing kinds of signal/slot operations. They are not great, but they are not bad either.

              kshegunovK Offline
              kshegunovK Offline
              kshegunov
              Moderators
              wrote on last edited by
              #6

              Some food for thought:
              Your buffer doesn't have smash-protection (just noting) and more importantly it is not thread safe. Is this by design?
              When thinking about a circular buffer you have to be careful how you distinguish full one and an empty one (i.e. when the begin iterator gets equal to the end iterator).

              Read and abide by the Qt Code of Conduct

              1 Reply Last reply
              1
              • fcarneyF Offline
                fcarneyF Offline
                fcarney
                wrote on last edited by fcarney
                #7

                @kshegunov said in Performance of signals/slots for plotting/oscilloscope (performance questions):

                Your buffer doesn't have smash-protection (just noting) and more importantly it is not thread safe.

                Not sure what smash-protection is.
                I need to learn more about making code thread safe. I am currently using it in a single thread. That may change though. Is it because operations are not atomic?

                I expect the fake iterators to be used in a way that allows comparisons for equality to prevent going beyond the end of the buffer. I need to add an operator== to the sub class.

                Edit:
                I just went ahead and got a modern book on C++ multithreading. I need to get a better feel for thread safety.

                C++ is a perfectly valid school of magic.

                kshegunovK 1 Reply Last reply
                0
                • fcarneyF fcarney

                  @kshegunov said in Performance of signals/slots for plotting/oscilloscope (performance questions):

                  Your buffer doesn't have smash-protection (just noting) and more importantly it is not thread safe.

                  Not sure what smash-protection is.
                  I need to learn more about making code thread safe. I am currently using it in a single thread. That may change though. Is it because operations are not atomic?

                  I expect the fake iterators to be used in a way that allows comparisons for equality to prevent going beyond the end of the buffer. I need to add an operator== to the sub class.

                  Edit:
                  I just went ahead and got a modern book on C++ multithreading. I need to get a better feel for thread safety.

                  kshegunovK Offline
                  kshegunovK Offline
                  kshegunov
                  Moderators
                  wrote on last edited by kshegunov
                  #8

                  @fcarney said in Performance of signals/slots for plotting/oscilloscope (performance questions):

                  Not sure what smash-protection is.

                  You don't have a guard in place to prevent you (or at least signal you) if you overfill the buffer. Say you take 250 item buffer, if you insert 251 items, then your code is going to wrongly assume that it has 1 item.

                  Is it because operations are not atomic?

                  Yes, but even if they were atomic that doesn't solve all problems. Actually, lockless programming is rather more complicated than writing blocking code.

                  I expect the fake iterators to be used in a way that allows comparisons for equality to prevent going beyond the end of the buffer.

                  That's correct thinking. They should wrap around internally.

                  I need to add an operator== to the sub class.

                  And some other bells and whistles. For example there's no distinction between an empty and full buffer; just between an empty and a partially filled one.

                  You could've just used the std::vector iterator as a typedef, since you

                  @fcarney said in Performance of signals/slots for plotting/oscilloscope (performance questions):

                  I just went ahead and got a modern book on C++ multithreading. I need to get a better feel for thread safety.

                  It boils down to one principle - not to allow simultaneous mutation on a data field. In practice, however, realizing this requirement isn't so trivial. One note, C++ multithreading has nothing to do with C++ specifically; it's the same in pretty much every language there is.

                  Read and abide by the Qt Code of Conduct

                  1 Reply Last reply
                  2
                  • fcarneyF Offline
                    fcarneyF Offline
                    fcarney
                    wrote on last edited by fcarney
                    #9

                    @kshegunov said in Performance of signals/slots for plotting/oscilloscope (performance questions):

                    You don't have a guard in place

                    When you push a value into the buffer and m_end meets up m_begin, then m_begin gets pushed ahead. So at that point it is lossy. For my use case I use up the data faster than I put in the data. But yes, if the input rate exceeds the output rate it will move the m_begin forward as a result. This is so it favors more recent data in case it stops consuming for some reason.

                    You could've just used the std::vector iterator as a typedef, since you

                    ? not sure what you mean here.

                    C++ is a perfectly valid school of magic.

                    kshegunovK 1 Reply Last reply
                    0
                    • fcarneyF fcarney

                      @kshegunov said in Performance of signals/slots for plotting/oscilloscope (performance questions):

                      You don't have a guard in place

                      When you push a value into the buffer and m_end meets up m_begin, then m_begin gets pushed ahead. So at that point it is lossy. For my use case I use up the data faster than I put in the data. But yes, if the input rate exceeds the output rate it will move the m_begin forward as a result. This is so it favors more recent data in case it stops consuming for some reason.

                      You could've just used the std::vector iterator as a typedef, since you

                      ? not sure what you mean here.

                      kshegunovK Offline
                      kshegunovK Offline
                      kshegunov
                      Moderators
                      wrote on last edited by kshegunov
                      #10

                      @fcarney said in Performance of signals/slots for plotting/oscilloscope (performance questions):

                      So at that point it is lossy.

                      Yes, that's my point.

                      This is so it favors more recent data in case it stops consuming for some reason.

                      Yes, but you don't shift the old elements back so you're always dropping the oldest. You invalidate all of them and start anew.

                      ? not sure what you mean here.

                      Something I was thinking, and thinking about it badly. Just disregard it it's just a remnant from a thought process (unfinished and worng).

                      Read and abide by the Qt Code of Conduct

                      1 Reply Last reply
                      0
                      • fcarneyF Offline
                        fcarneyF Offline
                        fcarney
                        wrote on last edited by
                        #11

                        @kshegunov said in Performance of signals/slots for plotting/oscilloscope (performance questions):

                        Yes, but you don't shift the old elements back so you're always dropping the oldest. You invalidate all of them and start anew.

                        I guess I don't understand what you mean. I want it to lose the old data. It shifts the m_begin forward. So it stays the same size once it is full. Right at 512 elements. I have tested this. m_end does not pass up m_begin.

                        Oh, and the external begin and end pseudo iterators need more work anyway. The push and pop are primarily what I use for adding and removing data.

                        C++ is a perfectly valid school of magic.

                        1 Reply Last reply
                        0
                        • fcarneyF Offline
                          fcarneyF Offline
                          fcarney
                          wrote on last edited by
                          #12

                          I just updated the repo with my changes to the buffer.

                          C++ is a perfectly valid school of magic.

                          1 Reply Last reply
                          0
                          • fcarneyF Offline
                            fcarneyF Offline
                            fcarney
                            wrote on last edited by
                            #13

                            @kshegunov said in Performance of signals/slots for plotting/oscilloscope (performance questions):

                            invalidate all of them

                            I think I see what you mean here (brain finally comprehending...). I need some bounds on my iterator manipulation. Thanks for pointing this out.

                            C++ is a perfectly valid school of magic.

                            kshegunovK 1 Reply Last reply
                            0
                            • fcarneyF fcarney

                              @kshegunov said in Performance of signals/slots for plotting/oscilloscope (performance questions):

                              invalidate all of them

                              I think I see what you mean here (brain finally comprehending...). I need some bounds on my iterator manipulation. Thanks for pointing this out.

                              kshegunovK Offline
                              kshegunovK Offline
                              kshegunov
                              Moderators
                              wrote on last edited by
                              #14

                              Yeah, sorry for not writing, I was rather busy. This indeed was my point.

                              Read and abide by the Qt Code of Conduct

                              1 Reply Last reply
                              0

                              • Login

                              • Login or register to search.
                              • First post
                                Last post
                              0
                              • Categories
                              • Recent
                              • Tags
                              • Popular
                              • Users
                              • Groups
                              • Search
                              • Get Qt Extensions
                              • Unsolved