Is there a faster TList implementation?

前端 未结 4 1542
遇见更好的自我
遇见更好的自我 2021-01-01 02:11

My application makes heavy use of TList, so I was wondering if there are any alternative implementations that are faster or optimized for particular use case.

I know

相关标签:
4条回答
  • 2021-01-01 02:45

    One of the biggest bottleneck I know about TList is the Delete/Extract on large list. Removing item[0] is a lot slower than removing Item[Count-1] because of the memory move that follows it.

    For exemple, on a list containing 65536 elements:

    while list.Count > 0 do List.Delete(0) //Takes 2 mins to complete
    
    for I := List.Count-1 downto 0 do List.Delete(I) //Takes less than 1 sec
    

    So if you have a TList with millions of elements, deleting a low index item can be expensive performance-wise. Also, consider that having a list that isn't sorted makes it very slow to find an element in it. IndexOf is very slow on large list. You might want to consider keeping the list sorted.

    Also, considering your item count can be pretty large, you might want to consider using a List of TList to store your elements, which will help reduce the Delete/Extract overhead I already mentioned.

    0 讨论(0)
  • 2021-01-01 03:03

    It looks like you're doing a lot of adds. I don't know how many lists that's spread over, but if your individual lists are growing very large, you might want to implement a list that grows faster.

    Take a look at TList.Grow, which is called when you try to add an item to a list where all its array elements are in use, and you'll see that it grows by 25%. This is to keep memory use down to a reasonable level. But if you need really large lists, make your own descendant class and override Grow so that in the second line, instead of Delta := FCapacity div 4 it says Delta := FCapacity. This makes your list grow twice as large each time, which means less reallocs and less copies.

    But the thing that's probably killing you is all those Remove calls. Remove has to find the item before it can remove it, which involves a call to IndexOf, which is a linear scan of the entire array. If you've got a large list and you're doing a lot of removes, that's gonna kill your performance.

    What are you using these lists for, especially the big ones? Depending on what you're doing with them, there may be better data structures for the job.

    0 讨论(0)
  • 2021-01-01 03:04

    Are you using the Notify procedure? If not, make your own TList implementation. Because of the Notify procedure, the TList.Clear (which is called at destruction) is a O(n) operation. The TList.Clear method calls SetCount which in turn calls Delete for all the items it contains so the Notify procedure will be called for every removed item. When you don't need to override the Notify method, you can adjust the SetCount procedure to not call Delete. This can save you the time of 15.766.012 - 10.630.000 = 5.136.012 Delete calls.

    NB: the performance gain you get will never be as big as the performance gain you get by sorting your list and optimizing your remove procedure, as suggested by Mason Wheeler. Unless the list you have contain a very small number of items and the compare function takes a lot of time.

    0 讨论(0)
  • 2021-01-01 03:04

    The fastest data structure is usually not a data structure at all, but instead a mock that pulls data only as it's needed, much like Virtual Treeview does. Perhaps you can write some sort of TVirtualList that calls the appropriate functions to gather the required data when the elements are requested.

    0 讨论(0)
提交回复
热议问题