clayborg requested changes to this revision.
clayborg added a comment.
This revision now requires changes to proceed.

In https://reviews.llvm.org/D32757#743567, @scott.smith wrote:

> IMO, this is a simpler interface than TaskRunner.  Also, after this, there 
> are no users of TaskRunner left.  Should I just delete them?


I think you might not have understood TaskRunner's real benefits. It is smart 
in the way it runs things: it lets you run N things and get each item **as soon 
as it completes**. The TaskMap will serialize everything. So if you have 100 
items to do and item 0 takes 200 seconds to complete, and items 1 - 99 take 1ms 
to complete, you will need to wait for task 0 to complete before you can start 
parsing the data. This will slow down the DWARF parser if you switch over to 
this. TaskRunner should not be deleted as it has a very specific purpose. Your 
TaskMap works fine for one case, but not in the other.

> I did this change to help parallel symbol demangling (to come in a separate 
> patch).  Rather than have the symbol demangler use batching, etc, I thought 
> it should be a higher level function.

Make sure this is a win before switching demangling over to using threads. I 
tried to improve performance on demangling before and I got worse performance 
on MacOS when we tried it because all of the malloc contention and threading 
overhead.



================
Comment at: source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp:1988
     //----------------------------------------------------------------------
-    while (true) {
-      auto f = task_runner_extract.WaitForNextCompletedTask();
-      if (!f.valid())
-        break;
-      unsigned cu_idx;
-      bool clear;
-      std::tie(cu_idx, clear) = f.get();
-      clear_cu_dies[cu_idx] = clear;
-    }
+    TaskMap(num_compile_units, 1, extract_fn);
 
----------------
This replacement is ok, since no expensive work is being done in the while loop 
that did the task_runner_extract.WaitForNextCompletedTask();.


================
Comment at: source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp:1994
 
-    TaskRunner<uint32_t> task_runner;
-    for (uint32_t cu_idx = 0; cu_idx < num_compile_units; ++cu_idx)
-      task_runner.AddTask(parser_fn, cu_idx);
-
-    while (true) {
-      std::future<uint32_t> f = task_runner.WaitForNextCompletedTask();
-      if (!f.valid())
-        break;
-      uint32_t cu_idx = f.get();
+    TaskMap(num_compile_units, 1, parser_fn);
 
----------------
Note that we lost performance here. The old code would run:

```
while (true) {
    std::future<uint32_t> f = task_runner.WaitForNextCompletedTask();
    // Do expensive work as soon as possible with any random task that 
completes as soon as it completes.
```

Your current code says "wait to do all expensive work until I complete 
everything and then do all of the expensive work".






================
Comment at: source/Utility/TaskPool.cpp:77
+
+void TaskMap(size_t size, size_t batch, std::function<void(size_t)> const & 
func)
+{
----------------
Is this named correctly? Maybe SerializedTaskMap? Or BatchedTaskMap?


================
Comment at: source/Utility/TaskPool.cpp:100
+  for (size_t i = 0; i < est_batches; i++)
+    futures[i].wait();
+}
----------------
TaskRunner is smart in the way it runs things: it lets you run N things and get 
each item as it completes. This implementation, if read it correctly, will 
serialize everything. So if you have 100 items to do and item at index 0 takes 
200 seconds to complete, and items 1 - 99 take 1ms to complete, you will need 
to wait for task 0 to complete before you can start parsing the data. This will 
slow down the DWARF parser if you switch over to this.


Repository:
  rL LLVM

https://reviews.llvm.org/D32757



_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to