Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. How to update a large model efficiently

How to update a large model efficiently

Scheduled Pinned Locked Moved Solved General and Desktop
24 Posts 3 Posters 4.4k 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.
  • ozcanayO Offline
    ozcanayO Offline
    ozcanay
    wrote on last edited by
    #14

    "QHash<ID, int> is the index in the vector would have been much easier" -> would that even work? Then why is QPersistentModelIndex needed?

    Christian EhrlicherC 1 Reply Last reply
    0
    • ozcanayO ozcanay

      "QHash<ID, int> is the index in the vector would have been much easier" -> would that even work? Then why is QPersistentModelIndex needed?

      Christian EhrlicherC Offline
      Christian EhrlicherC Offline
      Christian Ehrlicher
      Lifetime Qt Champion
      wrote on last edited by Christian Ehrlicher
      #15

      @ozcanay said in How to update a large model efficiently:

      would that even work?

      Why not? You're the owner of the model so you know when you modify the order and can update the hash. Don't see why you need persistent indexes here at all. They're needed for QSFPM to make sure that they're properly mapped to the new index after a sorting/filtering

      Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
      Visit the Qt Academy at https://academy.qt.io/catalog

      1 Reply Last reply
      0
      • ozcanayO Offline
        ozcanayO Offline
        ozcanay
        wrote on last edited by
        #16

        My worry was that Qt itself under the hood could be messing up with the model indices, changing them from time to time maybe. Especially considering that I wrap my model via QSortFilterProxyModel to filter and sort, I thought that I would need QPersistentModelIndex.

        Christian EhrlicherC 1 Reply Last reply
        0
        • ozcanayO ozcanay

          My worry was that Qt itself under the hood could be messing up with the model indices, changing them from time to time maybe. Especially considering that I wrap my model via QSortFilterProxyModel to filter and sort, I thought that I would need QPersistentModelIndex.

          Christian EhrlicherC Offline
          Christian EhrlicherC Offline
          Christian Ehrlicher
          Lifetime Qt Champion
          wrote on last edited by Christian Ehrlicher
          #17

          @ozcanay said in How to update a large model efficiently:

          My worry was that Qt itself under the hood could be messing up with the model indices, changing them from time to time maybe.

          Again: you are the owner, you create the indexes, you modify the data - how should Qt be able to modify something in your structures without your knowing?

          And QSortFilterProxyModel is there to NOT have the need to modify the source model.

          Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
          Visit the Qt Academy at https://academy.qt.io/catalog

          1 Reply Last reply
          0
          • ozcanayO Offline
            ozcanayO Offline
            ozcanay
            wrote on last edited by ozcanay
            #18

            Yes, you are right.

            I made the following changes and it works:

            QVector<Order> orders_;
            std::unordered_map<QString, QPair<Order, std::size_t>> order_index_map_;
            
            void OrdersModel::process(const Order& order) {
                const auto& order_id = order.order_id_;
            
                if(auto it = order_index_map_.find(order_id); it == order_index_map_.end()) {
                    beginInsertRows({}, orders_.count(), orders_.count());
                    orders_.push_back(order);
                    endInsertRows();
            
                    order_index_map_[order_id] = {order, orders_.size() - 1};
            
                    emit orderEntryAdded(&order);
                } else {
                    const int row_index = (*it).second.second;
                    orders_[row_index] = order;
                    emit dataChanged(index(row_index, 0), index(row_index, column_count_));
                }
            }
            

            However, I aim to do this processing in a different thread other than UI thread to not to freeze UI, when there are lots of updates. I want to use QtConcurrent::run for this purpose.

            Christian EhrlicherC 1 Reply Last reply
            0
            • ozcanayO ozcanay

              Yes, you are right.

              I made the following changes and it works:

              QVector<Order> orders_;
              std::unordered_map<QString, QPair<Order, std::size_t>> order_index_map_;
              
              void OrdersModel::process(const Order& order) {
                  const auto& order_id = order.order_id_;
              
                  if(auto it = order_index_map_.find(order_id); it == order_index_map_.end()) {
                      beginInsertRows({}, orders_.count(), orders_.count());
                      orders_.push_back(order);
                      endInsertRows();
              
                      order_index_map_[order_id] = {order, orders_.size() - 1};
              
                      emit orderEntryAdded(&order);
                  } else {
                      const int row_index = (*it).second.second;
                      orders_[row_index] = order;
                      emit dataChanged(index(row_index, 0), index(row_index, column_count_));
                  }
              }
              

              However, I aim to do this processing in a different thread other than UI thread to not to freeze UI, when there are lots of updates. I want to use QtConcurrent::run for this purpose.

              Christian EhrlicherC Offline
              Christian EhrlicherC Offline
              Christian Ehrlicher
              Lifetime Qt Champion
              wrote on last edited by
              #19

              @ozcanay said in How to update a large model efficiently:

              However, I aim to do this processing in a different thread other than UI

              This will not work.

              Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
              Visit the Qt Academy at https://academy.qt.io/catalog

              1 Reply Last reply
              0
              • ozcanayO Offline
                ozcanayO Offline
                ozcanay
                wrote on last edited by
                #20

                Can you elaborate on why that won't work? If there is heavy processing to do on UI thread what should I do then?

                Christian EhrlicherC 1 Reply Last reply
                0
                • ozcanayO ozcanay

                  Can you elaborate on why that won't work? If there is heavy processing to do on UI thread what should I do then?

                  Christian EhrlicherC Offline
                  Christian EhrlicherC Offline
                  Christian Ehrlicher
                  Lifetime Qt Champion
                  wrote on last edited by
                  #21

                  @ozcanay said in How to update a large model efficiently:

                  Can you elaborate on why that won't work?

                  You must not modify any UI stuff outside the ui (main) thread. emiting dataChanged() is therefore not possible outside the main thread.
                  Do your calculations outside the main thread, modify the model in the main thread - when modifying a model (which is more or less just a simple copy in your case) will lock your main thread then you're doing something wrong. The only thing I can think of is a too high data rate for your incoming data - but then it's somehow useless to update the model that frequently because noone can see the changes on the ui at all.

                  Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
                  Visit the Qt Academy at https://academy.qt.io/catalog

                  ozcanayO 1 Reply Last reply
                  0
                  • Christian EhrlicherC Christian Ehrlicher

                    @ozcanay said in How to update a large model efficiently:

                    Can you elaborate on why that won't work?

                    You must not modify any UI stuff outside the ui (main) thread. emiting dataChanged() is therefore not possible outside the main thread.
                    Do your calculations outside the main thread, modify the model in the main thread - when modifying a model (which is more or less just a simple copy in your case) will lock your main thread then you're doing something wrong. The only thing I can think of is a too high data rate for your incoming data - but then it's somehow useless to update the model that frequently because noone can see the changes on the ui at all.

                    ozcanayO Offline
                    ozcanayO Offline
                    ozcanay
                    wrote on last edited by
                    #22

                    @Christian-Ehrlicher
                    I think you are absolutely right as users won't be even able to see updates processed at this rate. So, I think that I need a way to throttle view updating. I am planning to have a std::set of processed indices, and I will use those indices to emit dataChanged signal every X seconds (or milliseconds) and reset that set at every timer firing. In theory, this should work as sometimes a single order gets updated 100 times in matter of seconds that reforces a repaint on view via dataChanged signal.

                    1 Reply Last reply
                    0
                    • Christian EhrlicherC Offline
                      Christian EhrlicherC Offline
                      Christian Ehrlicher
                      Lifetime Qt Champion
                      wrote on last edited by
                      #23

                      I would do it in a similar way. Collect the updated data in a separate thread and batch-update the model every second or so. Can be even done in your model with a custom setter for the second thread to collect the data and put it in another container which gets read every second. Don't forget to use a mutex for this container access.

                      Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
                      Visit the Qt Academy at https://academy.qt.io/catalog

                      1 Reply Last reply
                      2
                      • ozcanayO Offline
                        ozcanayO Offline
                        ozcanay
                        wrote on last edited by ozcanay
                        #24

                        I have overriden timerEvent of the model, and used startTimer() to trigger the timer event every second. I created a public function named acknowledge(...) that just stores the order in a map of format <order_id, order>. If an price update to a order occurs multiple times, only the last update will be taken into consideration. Let's call this map batched_orders. In timer event callback, there is a private method called batchProcess, that basically iterates over batched_orders and processes them. This is not the most ideal solution to the problem (the best solution is what @Christian-Ehrlicher suggested), however, this seems to be doing the job for my application. CPU usage reduced dramatically. @JonB is it possible to change the solution for this post?

                        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