Skip to content

Commit 27ef132

Browse files
committed
Doc: add some notes about performance of the List functions.
Per suggestion from Andres Freund. Discussion: https://postgr.es/m/20211104221248.pgo4h6wvnjl6uvkb@alap3.anarazel.de
1 parent 87bb606 commit 27ef132

File tree

1 file changed

+55
-5
lines changed

1 file changed

+55
-5
lines changed

src/backend/nodes/list.c

Lines changed: 55 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -410,6 +410,9 @@ insert_new_cell(List *list, int pos)
410410
/*
411411
* Insert the given datum at position 'pos' (measured from 0) in the list.
412412
* 'pos' must be valid, ie, 0 <= pos <= list's length.
413+
*
414+
* Note that this takes time proportional to the distance to the end of the
415+
* list, since the following entries must be moved.
413416
*/
414417
List *
415418
list_insert_nth(List *list, int pos, void *datum)
@@ -460,6 +463,9 @@ list_insert_nth_oid(List *list, int pos, Oid datum)
460463
* value, rather than continuing to use the pointer passed as the
461464
* second argument.
462465
*
466+
* Note that this takes time proportional to the length of the list,
467+
* since the existing entries must be moved.
468+
*
463469
* Caution: before Postgres 8.0, the original List was unmodified and
464470
* could be considered to retain its separate identity. This is no longer
465471
* the case.
@@ -525,6 +531,10 @@ lcons_oid(Oid datum, List *list)
525531
* Callers should be sure to use the return value as the new pointer to the
526532
* concatenated list: the 'list1' input pointer may or may not be the same
527533
* as the returned pointer.
534+
*
535+
* Note that this takes at least time proportional to the length of list2.
536+
* It'd typically be the case that we have to enlarge list1's storage,
537+
* probably adding time proportional to the length of list1.
528538
*/
529539
List *
530540
list_concat(List *list1, const List *list2)
@@ -623,6 +633,8 @@ list_truncate(List *list, int new_size)
623633
* Return true iff 'datum' is a member of the list. Equality is
624634
* determined via equal(), so callers should ensure that they pass a
625635
* Node as 'datum'.
636+
*
637+
* This does a simple linear search --- avoid using it on long lists.
626638
*/
627639
bool
628640
list_member(const List *list, const void *datum)
@@ -706,6 +718,9 @@ list_member_oid(const List *list, Oid datum)
706718
* Delete the n'th cell (counting from 0) in list.
707719
*
708720
* The List is pfree'd if this was the last member.
721+
*
722+
* Note that this takes time proportional to the distance to the end of the
723+
* list, since the following entries must be moved.
709724
*/
710725
List *
711726
list_delete_nth_cell(List *list, int n)
@@ -777,6 +792,9 @@ list_delete_nth_cell(List *list, int n)
777792
*
778793
* The List is pfree'd if this was the last member. However, we do not
779794
* touch any data the cell might've been pointing to.
795+
*
796+
* Note that this takes time proportional to the distance to the end of the
797+
* list, since the following entries must be moved.
780798
*/
781799
List *
782800
list_delete_cell(List *list, ListCell *cell)
@@ -787,6 +805,8 @@ list_delete_cell(List *list, ListCell *cell)
787805
/*
788806
* Delete the first cell in list that matches datum, if any.
789807
* Equality is determined via equal().
808+
*
809+
* This does a simple linear search --- avoid using it on long lists.
790810
*/
791811
List *
792812
list_delete(List *list, void *datum)
@@ -870,6 +890,13 @@ list_delete_oid(List *list, Oid datum)
870890
* where the intent is to alter the list rather than just traverse it.
871891
* Beware that the list is modified, whereas the Lisp-y coding leaves
872892
* the original list head intact in case there's another pointer to it.
893+
*
894+
* Note that this takes time proportional to the length of the list,
895+
* since the remaining entries must be moved. Consider reversing the
896+
* list order so that you can use list_delete_last() instead. However,
897+
* if that causes you to replace lappend() with lcons(), you haven't
898+
* improved matters. (In short, you can make an efficient stack from
899+
* a List, but not an efficient FIFO queue.)
873900
*/
874901
List *
875902
list_delete_first(List *list)
@@ -884,9 +911,6 @@ list_delete_first(List *list)
884911

885912
/*
886913
* Delete the last element of the list.
887-
*
888-
* This is the opposite of list_delete_first(), but is noticeably cheaper
889-
* with a long list, since no data need be moved.
890914
*/
891915
List *
892916
list_delete_last(List *list)
@@ -910,6 +934,9 @@ list_delete_last(List *list)
910934
* Delete the first N cells of the list.
911935
*
912936
* The List is pfree'd if the request causes all cells to be deleted.
937+
*
938+
* Note that this takes time proportional to the distance to the end of the
939+
* list, since the following entries must be moved.
913940
*/
914941
List *
915942
list_delete_first_n(List *list, int n)
@@ -989,8 +1016,10 @@ list_delete_first_n(List *list, int n)
9891016
* you probably want to use list_concat_unique() instead to avoid wasting
9901017
* the storage of the old x list.
9911018
*
992-
* This function could probably be implemented a lot faster if it is a
993-
* performance bottleneck.
1019+
* Note that this takes time proportional to the product of the list
1020+
* lengths, so beware of using it on long lists. (We could probably
1021+
* improve that, but really you should be using some other data structure
1022+
* if this'd be a performance bottleneck.)
9941023
*/
9951024
List *
9961025
list_union(const List *list1, const List *list2)
@@ -1094,6 +1123,11 @@ list_union_oid(const List *list1, const List *list2)
10941123
* This variant works on lists of pointers, and determines list
10951124
* membership via equal(). Note that the list1 member will be pointed
10961125
* to in the result.
1126+
*
1127+
* Note that this takes time proportional to the product of the list
1128+
* lengths, so beware of using it on long lists. (We could probably
1129+
* improve that, but really you should be using some other data structure
1130+
* if this'd be a performance bottleneck.)
10971131
*/
10981132
List *
10991133
list_intersection(const List *list1, const List *list2)
@@ -1152,6 +1186,11 @@ list_intersection_int(const List *list1, const List *list2)
11521186
*
11531187
* This variant works on lists of pointers, and determines list
11541188
* membership via equal()
1189+
*
1190+
* Note that this takes time proportional to the product of the list
1191+
* lengths, so beware of using it on long lists. (We could probably
1192+
* improve that, but really you should be using some other data structure
1193+
* if this'd be a performance bottleneck.)
11551194
*/
11561195
List *
11571196
list_difference(const List *list1, const List *list2)
@@ -1256,6 +1295,8 @@ list_difference_oid(const List *list1, const List *list2)
12561295
*
12571296
* Whether an element is already a member of the list is determined
12581297
* via equal().
1298+
*
1299+
* This does a simple linear search --- avoid using it on long lists.
12591300
*/
12601301
List *
12611302
list_append_unique(List *list, void *datum)
@@ -1313,6 +1354,11 @@ list_append_unique_oid(List *list, Oid datum)
13131354
* modified in-place rather than being copied. However, callers of this
13141355
* function may have strict ordering expectations -- i.e. that the relative
13151356
* order of those list2 elements that are not duplicates is preserved.
1357+
*
1358+
* Note that this takes time proportional to the product of the list
1359+
* lengths, so beware of using it on long lists. (We could probably
1360+
* improve that, but really you should be using some other data structure
1361+
* if this'd be a performance bottleneck.)
13161362
*/
13171363
List *
13181364
list_concat_unique(List *list1, const List *list2)
@@ -1401,6 +1447,8 @@ list_concat_unique_oid(List *list1, const List *list2)
14011447
*
14021448
* It is caller's responsibility to have sorted the list to bring duplicates
14031449
* together, perhaps via list_sort(list, list_oid_cmp).
1450+
*
1451+
* Note that this takes time proportional to the length of the list.
14041452
*/
14051453
void
14061454
list_deduplicate_oid(List *list)
@@ -1557,6 +1605,8 @@ list_copy_deep(const List *oldlist)
15571605
*
15581606
* Like qsort(), this provides no guarantees about sort stability
15591607
* for equal keys.
1608+
*
1609+
* This is based on qsort(), so it likewise has O(N log N) runtime.
15601610
*/
15611611
void
15621612
list_sort(List *list, list_sort_comparator cmp)

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy