Jump to content

snowdev

Members
  • Content Count

    8
  • Joined

  • Last visited

Community Reputation

0 Neutral

Recent Profile Visitors

The recent visitors block is disabled and is not being shown to other users.

  1. Just an update here. I refactoring the entire application into the MVC pattern for better maintability and improve the codebase, and I just forgot the use of interfaces as transport objects. Just for refreshing, nowdays I use TObject descendents which need the object releasing to manage the memory, as the queue manages the object lifetime I must clone objects when transporting information between threads. I never used interfaces for those kind of task (transport information between threads)... may I get into troubbles switching from TObject to interface based queue? In my benchmarks the difference isn't a big deal... but the tests run transporting data over only two threads, in my application the data can be transported between two or three threads, which means more object clonning overhead. I also tested the suggested ring buffer like as queue, but the differences aren't huge either, even compared with a TQueue<T> with a lock object... and this comes to my second question. I always use lock objects (generally TCriticalSection) when working with threads and I not sure if the data is thread-safe. In my threaded queue I have other threads pushing items in the TQueue, and the thread itself consuming them, in my mind make sense using lock objects to push and pop items as other threads also access the TQueue, why a ring buffer bases queue wouldn't needed? @Anders Melander, the Intel VTune works fine with your solution. Thanks. Thanks in advance.
  2. Good, I’ll try out with Intel VTune since my processor is Intel. I’ll try the instructions in your post and repo, if I got doubts I ask you in PM. Really thanks!
  3. What I posted here I also tried with ChatGPT and here we are. I use the free plan and in general didnt get good answers for real world problems or context needed problems. Of course my prompt may be not good at all. I mainly use to understand something or get some examples, but (at least for Delphi) the code generated generally doesnt work. Now imagine for a optimized code… Well, its my experience till now. But its not the topic subject…
  4. @Anders Melander you mentioned profiling, I searched about and found the https://www.delphitools.info/samplingprofiler/ , but realized that only works for Maintthread functions, what doesnt help me alot since I handle almost everything in threads. Also I found your solution at https://github.com/andersmelander/map2pdb and saw that (at least) initial releases hasnt support for 64bits .exe... tried to find something on the post discussion about but not sure if supports 64bit applications, also tried to search in repo but didnt find mentions. Your solution works for 64bits applications?
  5. Just an update. I tested a ringbuffer solution (i’ve used this one for benchmarking: https://github.com/MHumm/CircularBuffer) I didnt get into implementations details to check if its well optmized or not, just tested out. My results was same as TQueue (with critical section) for pushing items on queue, and a slighty difference for consuming (like 5ms +/-). Testes both with TObject descendent and TRecord (not pointers), and the last I got better results. I’ll do more tests, but for now is safier I just change to a faster read/write-lock to the current solution… at least till I being able to write my own ringbuffer-based and understand 100% whats going on for maintability.
  6. Its a bit weird. I also running in debug and didnt got leaks. Ya, I forgot the correct term. Anyway I already planning some changes: -Change TCriticalSection locking for TLightweigtMREW gabr42 version (discussion here: https://www.thedelphigeek.com/2021/02/readers-writ-47358-48721-45511-46172.html?m=1) Another change would be: -Switch from single worker thread processing to N worker thread processing: I have a worker that loops an array and do what is necessary based on the item settings, so the thread retrieve the data every notification from this array… Instead I’ll create a threadpool like (or a simple TThread list) and pre-creates the worker threads with the pre-defined parameters, then I’ll just signaling they when necessary, the necessary information already be there. Final probably change: -Switch from TQueue to ring buffer like. Thanks for educate me. The external API which I consume returns PWideChar and is a pain to work in certain circumstances… I’ll evaluate change to array of char. Thanks again Anders.
  7. I’ve search over the internet when I started the project and found some posts around TMonitor performance. I also found a gabr42’s (OmniThreadLibrary creator) blog post about this and just decided to use TCriticalSection. Thats make sense, I’ve tested this way and got similar results, and the simple fifo queue wons (working with objects or pointers). Not exactly, using ReportMemoryLeaksOnShutdown didnt take any leak running the tests… every queue format release their resources. I’ll take a look into that, usually dont. This reason I dont included in the given example… every thread became up on the app initialization. Thanks for the tip. I dont know a profiling lib for Delphi, but I’ll measure them with stopwatches. I just use locking because I dont know if there could have a deadlock when other thread is pushing and the worker is popping, so I do it just in case. You say that this scenario isnt that possible? About Windows message queue, it seems slow as a simple fifo aswell, thought continue using this approach. In the next few days I’ll build a ring buffer like approach and test the performance compared to TQueue, it internal uses an array of T btw. About strings I could switch to PWideChar aswell, I use string for ease. Almost same performance as TQueue. Thanks for the reply.
  8. I have an application which continuously receives websocket data and proccess them in the background on worker threads. Some data is critical and must be proccessed as quickly as possible. Once I receive the websocket data I fill a TObject descendent with the information and push it to the corresponding worker thread, which proccess and frees the object. I use Delphi 12. I would like to reduce as much overhead as possible in the flow, and beside the business rules, I believe there is an overhead in my worker thread consumer implementation, especially because I work with TObject descendants to transport the data. Also there has TObject cloning when the communication occurs from worker thread to worker thread, because each worker thread owns the queue objects lifetime, so I need to send a copy for each worker thread. I decided to make a benchmark to check by myself the differente in the differet approachs that I know about threading queues and know what has the best performance, attached has the benchmark I build. Nowdays I use CustomQueueObject.pas queue model in prod. In the example, has 4 examples of threading consumer queues: -A thread with TQueue<TObject>, TSempahore and TCritical Section; -A thread with TQueue<Pointer>, TSempahore and TCritical Section; -A thread with internal TThread queue processing TObject descendents, without events and sync objects; -A thread with internal TThread queue processing Pointers, without events and sync objects; After making tons of tests, for my surprise the fastest consumer queue is the example in CustomQueueObject.pas (which I already use), even with more creation/deletion and access control (sync object)... what brought me here to ask more experienced developers if I doing something wrong (according my examples as is my base). Mainly on Pointer examples as I rarely use pointers but I willing to change if its better. In my mind the internal thread queue would much more efficient for the reasons said above... I also thought that work with Pointers could highly improve the overal performance as in the workflow since I would have a single reference and only freed in the final. Could I be measuring the performance incorrectly? Thanks in advance! MultithreadingQueueBenchmark.zip
×