Thread

Commits

  1. Prevent query-lifespan memory leakage of SP-GiST traversal values.

  1. IndexJoin memory problem using spgist and boxes

    Anton Dignös <dignoes@inf.unibz.it> — 2018-02-01T08:43:14Z

    Hi,
    
    I came across a strange memory problem when doing an IndexJoin using
    spgist on boxes.
    I also found it mentioned here:
    https://www.postgresql.org/message-id/flat/CAPqRbE5vTGWCGrOc91Bmu-0o7CwsU0UCnAshOtpDR8cSpSjy0g%40mail.gmail.com#CAPqRbE5vTGWCGrOc91Bmu-0o7CwsU0UCnAshOtpDR8cSpSjy0g@mail.gmail.com
    
    With the following setting:
    
    CREATE TABLE r AS SELECT 1 i, box(point(generate_series,
    generate_series), point(generate_series+10, generate_series+10)) FROM
    generate_series(1, 1000000);
    CREATE TABLE s AS SELECT 1 i, box(point(generate_series,
    generate_series), point(generate_series+10, generate_series+10)) FROM
    generate_series(1, 1000000) ORDER BY random(); -- random sort just
    speeds up index creation
    CREATE INDEX s_idx ON s USING spgist(box);
    
    postgres consumes several GBs of main memory for the following query:
    
    SELECT * FROM r, s WHERE r.box && s.box;
    
    The problem also occurs for polygons which are based on boxes and are
    now part of the dev version.
    
    The attached patch should fix this problem by maintaining the
    traversal memory per index scan instead of for the entire join.
    
    Best regards,
    Anton
    
  2. Re: IndexJoin memory problem using spgist and boxes

    Alexander Kuzmenkov <a.kuzmenkov@postgrespro.ru> — 2018-03-02T18:47:27Z

    Hi Anton,
    
    I can reproduce the high memory consumption with your queries.
    
    Looking at the patch, I see that you changed the lifetime of the 
    temporary context from per-tuple to per-index-scan. It is not obvious 
    that this change is correct. Could you explain, what memory context are 
    involved in the scan, and what their lifetimes are, before and after 
    your changes? What are these memory allocations that are causing the 
    high consumption, and what code makes them? This will make it easier to 
    understand your changes.
    
    
    > https://www.postgresql.org/message-id/flat/CAPqRbE5vTGWCGrOc91Bmu-0o7CwsU0UCnAshOtpDR8cSpSjy0g%40mail.gmail.com#CAPqRbE5vTGWCGrOc91Bmu-0o7CwsU0UCnAshOtpDR8cSpSjy0g@mail.gmail.com
    
    Also, this link doesn't open for me.
    
    -- 
    Alexander Kuzmenkov
    Postgres Professional: http://www.postgrespro.com
    The Russian Postgres Company
    
    
    
    
  3. Re: IndexJoin memory problem using spgist and boxes

    Anton Dignös <dignoes@inf.unibz.it> — 2018-03-04T17:20:27Z

    Hi Alexander,
    
    thanks for the feedback.
    
    > I can reproduce the high memory consumption with your queries.
    >
    > Looking at the patch, I see that you changed the lifetime of the temporary
    > context from per-tuple to per-index-scan. It is not obvious that this change
    > is correct. Could you explain, what memory context are involved in the scan,
    > and what their lifetimes are, before and after your changes? What are these
    > memory allocations that are causing the high consumption, and what code
    > makes them? This will make it easier to understand your changes.
    >
    Yes, you are right, I changed the temporary context for calling the
    user-defined inner consistent method from per-tuple to per-index-scan.
    For boxes this function is spg_box_quad_inner_consistent in
    geo_spgist.c that allocates nodes, RangeBoxes, and RectBoxes.
    
    The problem before this patch was that the traversalMemoryContext in
    this function was set to per-query lifetime.
    The memory allocations in the per-query lifetime caused this high
    memory consumption.
    
    I changed the temporary context to per-index-scan so that it can also
    be used for traversalMemoryContext.
    Calling the function in per-index-scan lifetime did cause a high
    memory consumption.
    
    The better alternative may be to have two temporary memory contexts,
    one per-tuple for calling the inner consistent method and one
    per-index-scan for the traversal memory.
    
    What do you think?
    
    >
    >>
    >> https://www.postgresql.org/message-id/flat/CAPqRbE5vTGWCGrOc91Bmu-0o7CwsU0UCnAshOtpDR8cSpSjy0g%40mail.gmail.com#CAPqRbE5vTGWCGrOc91Bmu-0o7CwsU0UCnAshOtpDR8cSpSjy0g@mail.gmail.com
    >
    >
    > Also, this link doesn't open for me.
    >
    The link works perfectly fine for me.
    
    Best regards,
    Anton
    
    
    
  4. Re: IndexJoin memory problem using spgist and boxes

    Tom Lane <tgl@sss.pgh.pa.us> — 2018-03-04T19:46:22Z

    =?UTF-8?Q?Anton_Dign=C3=B6s?= <dignoes@inf.unibz.it> writes:
    >> Looking at the patch, I see that you changed the lifetime of the temporary
    >> context from per-tuple to per-index-scan. It is not obvious that this change
    >> is correct.
    
    > The problem before this patch was that the traversalMemoryContext in
    > this function was set to per-query lifetime.
    > The memory allocations in the per-query lifetime caused this high
    > memory consumption.
    
    Yeah ...
    
    > I changed the temporary context to per-index-scan so that it can also
    > be used for traversalMemoryContext.
    
    But we have also had many complaints about leakage across a single index
    scan, if it traverses many index entries.  I think you're just moving the
    pain out of one use-case and into another.
    
    			regards, tom lane
    
    
    
  5. Re: IndexJoin memory problem using spgist and boxes

    Alexander Kuzmenkov <a.kuzmenkov@postgrespro.ru> — 2018-03-05T18:46:04Z

    On 04.03.2018 20:20, Anton Dignös wrote:
    > The better alternative may be to have two temporary memory contexts,
    > one per-tuple for calling the inner consistent method and one
    > per-index-scan for the traversal memory.
    
    Yes, this seems to be a better way of fixing the problem without 
    introducing regressions mentioned by Tom. We'd keep a separate traversal 
    context in ScanOpaque and run most of the spgWalk in it, except calling 
    storeRes in query context and the inner consistent method in short-lived 
    context.
    
    Also, I think it would be worthwhile to test the resulting patch with 
    valgrind. The allocations are not very apparent in the code, so it's 
    easy to miss something.
    
    -- 
    Alexander Kuzmenkov
    Postgres Professional: http://www.postgrespro.com
    The Russian Postgres Company
    
    
    
    
  6. Re: IndexJoin memory problem using spgist and boxes

    Anton Dignös <dignoes@inf.unibz.it> — 2018-03-06T10:41:58Z

    >> The better alternative may be to have two temporary memory contexts,
    >> one per-tuple for calling the inner consistent method and one
    >> per-index-scan for the traversal memory.
    >
    >
    > Yes, this seems to be a better way of fixing the problem without introducing
    > regressions mentioned by Tom. We'd keep a separate traversal context in
    > ScanOpaque and run most of the spgWalk in it, except calling storeRes in
    > query context and the inner consistent method in short-lived context.
    
    Thanks to both for the feedback.
    I will work on that and come back to you.
    
    >
    > Also, I think it would be worthwhile to test the resulting patch with
    > valgrind. The allocations are not very apparent in the code, so it's easy to
    > miss something.
    >
    
    I tried with valgrind in the first place and didn't see any suspicious
    memory leaks but I will give it another try.
    
    Best regards,
    Anton
    
    
    
  7. Re: IndexJoin memory problem using spgist and boxes

    Anton Dignös <dignoes@inf.unibz.it> — 2018-03-18T19:56:31Z

    Hi,
    
    attached is the patch that uses two memory contexts.
    One for calling the inner consistent function,
    and a new one for keeping the traversal memory of the inner consistent function.
    
    I run some test to compare the memory footprints. I report the total maximum
    memory usage (sum of all children) of the per-query memory context
    that is the parent of all memory
    contexts used. The test datasets are described below.
    
     TEST |  HEAD | previous patch | patch V2
    ------+-------+----------------+----------
     T1   | 3.4GB | 98kB           | 81kB
     T2   | 3.4GB | 17MB           | 17MB
     T3   | 3.5GB | 17MB           | 17MB
     T4   | 7GB   | 17MB           | 17MB
     T5   | 8GB   | 34MB           | 25MB
    
    T1: 1M x 1M tuples with relatively few overlaps
    T2: as T1, but with 1 tuple in the outer relation for which the entire
    index reports matches
    T3: as T1, but with 10 tuples in the outer relation for which the
    entire index reports matches
    T4: as T3, but the outer relation has double the number of tuples
    T5: as T4, but the inner relation has double the number of tuples
    
    TEST dataset creation queries (executed incrementally)
    
    T1:
    -- create table r with 1M tuples
    CREATE TABLE r AS SELECT 1 i, box(point(generate_series,
    generate_series), point(generate_series+10, generate_series+10)) FROM
    generate_series(1, 1000000);
    -- create table s with 1M tuples
    CREATE TABLE s AS SELECT 1 i, box(point(generate_series,
    generate_series), point(generate_series+10, generate_series+10)) FROM
    generate_series(1, 1000000) ORDER BY random(); -- random sort just
    speeds up index creation
    CREATE INDEX s_idx ON s USING spgist(box);
    
    T2:
    -- inserts a tuple for which the entire index is a match
    INSERT INTO r VALUES (2, box(point(1, 1), point(1000000, 1000000)));
    
    T3:
    -- inserts 9 more tuples as in T2.
    
    T4:
    -- doubles the outer relations
    INSERT INTO r SELECT * FROM r;
    
    T5:
    -- doubles the inner relation
    INSERT INTO s SELECT * FROM s;
    
    
    The new patch is a bit better in terms of memory by using the two
    memory contexts.
    I also checked the query times using explain analyze, both patches
    have approximately the same runtime,
    but run 5-6 times faster than HEAD.
    
    Best regards,
    Anton
    
  8. Re: IndexJoin memory problem using spgist and boxes

    Alexander Kuzmenkov <a.kuzmenkov@postgrespro.ru> — 2018-03-19T18:43:59Z

    The following review has been posted through the commitfest application:
    make installcheck-world:  tested, passed
    Implements feature:       not tested
    Spec compliant:           not tested
    Documentation:            not tested
    
    The updated version looks good to me. make installcheck under valgrind finds no errors. I also tried the T1 and T5 datasets, here are the timings and memory usage:
              T1            T5
    Vanilla   2G/24.2 s     over 7G/didn't wait
    Patch v2  144M/23.0 s   148M/108 s
    
    The new status of this patch is: Ready for Committer
    
  9. Re: IndexJoin memory problem using spgist and boxes

    Tom Lane <tgl@sss.pgh.pa.us> — 2018-03-20T04:01:02Z

    Alexander Kuzmenkov <a.kuzmenkov@postgrespro.ru> writes:
    > The updated version looks good to me.
    
    LGTM too.  Pushed with some trivial cosmetic adjustments.
    
    			regards, tom lane
    
    
    
  10. Re: IndexJoin memory problem using spgist and boxes

    Anton Dignös <anton.dignoes@gmail.com> — 2018-03-20T09:11:29Z

    On Tue, Mar 20, 2018 at 5:01 AM, Tom Lane <tgl@sss.pgh.pa.us> wrote:
    > Alexander Kuzmenkov <a.kuzmenkov@postgrespro.ru> writes:
    >> The updated version looks good to me.
    >
    > LGTM too.  Pushed with some trivial cosmetic adjustments.
    >
    >                         regards, tom lane
    
    Thank you both!
    
    Best regards,
    Anton