Re: [GENERAL] Many Pl/PgSQL parameters -> AllocSetAlloc(128)? - Mailing list pgsql-hackers

From Joe Conway
Subject Re: [GENERAL] Many Pl/PgSQL parameters -> AllocSetAlloc(128)?
Date
Msg-id 3EF7F2A8.5060207@joeconway.com
Whole thread Raw
Responses Re: [GENERAL] Many Pl/PgSQL parameters -> AllocSetAlloc(128)?  (Joe Conway <mail@joeconway.com>)
Re: [GENERAL] Many Pl/PgSQL parameters -> AllocSetAlloc(128)?  ("Reuven M. Lerner" <reuven@lerner.co.il>)
List pgsql-hackers
(cross-posting to HACKERS)

Reuven M. Lerner wrote:
> I'm creating a new OpenACS package that uses PostgreSQL, and in doing
> so have encountered what seems to be a problem in PostgreSQL.

[...snip...]

 > CREATE OR REPLACE FUNCTION add_news__test
 > (integer,varchar,timestamptz,varchar,varchar,varchar,
 >  varchar,integer,timestamptz,integer,timestamptz,varchar,varchar,
 >  varchar,integer,boolean, varchar, varchar, varchar, timestamptz,
 >  integer, varchar, integer, integer)
                      ^^^^^^^^
[...snip...]

>     p_last_mod_date alias for $20; -- default null/timestamptz
>     p_modified_by   alias for $21; -- default null/integer
>     p_last_mod_date alias for $20; -- default null/timestamptz
>     p_modified_by   alias for $21; -- default null/integer
                         ^^^^^^^^^^^^^ above two lines repeated

>     p_image_filename alias for $22; -- default null/text
>     p_headline_page   alias for $23; -- default null/integer
                                             ^^^^^^^^^^^^^^^^^^^^
more importantly, you call the function (below) with a varchar here, not
integer
>     p_headline_position   alias for $24; -- default null/integer

[...snip...]

>         now(),      -- p_last_mod_date
            ^^^^^^^ try 'now'::timestamptz
>         '298'::integer,        -- p_modified_by
>         'image.jpeg'::varchar,     -- p_image_filename
>         'Category page'::varchar,      -- p_headline_page
            ^^^^^^^^^^^ this one should be an integer

>         '1'::integer  -- p_headline_position
>     );

You found a real bug, I can confirm it on CVS tip.

However your workaround is to call the function *exactly* as declared.
Otherwise in parse_func.c:gen_cross_product() the following code is
executed:

<snippet>
     nanswers = 1;
     for (i = 0; i < nargs; i++)
     {
         nanswers *= (arginh[i].nsupers + 2);
         cur[i] = 0;
     }

     iter = result = (Oid **) palloc(sizeof(Oid *) * nanswers);
</snippet>

I get nanswers = 16777216, so right off the bat 67MB or so is allocated.
Then there's this:

<snippet>
     /* compute the cross product from right to left */
     for (;;)
     {
         oneres = (Oid *) palloc0(FUNC_MAX_ARGS * sizeof(Oid));
</snippet>

I'm guessing this gets executed nanswers times. I saw memory usage grow
to 880 MB and then killed the process.

I'm not sure of the best way to fix this yet, but I found that when
calling the function with argument types matching the prototype
perfectly, this code never gets executed.

HTH,

Joe

p.s. here's a backtrace:

#0  AllocSetAlloc (context=0x830a624, size=128) at aset.c:731
#1  0x081bcb14 in MemoryContextAllocZero (context=0x830a624, size=128)
at mcxt.c:505
#2  0x080c5c03 in gen_cross_product (arginh=0xbfffd120, nargs=24) at
parse_func.c:1094
#3  0x080c59b6 in argtype_inherit (nargs=24, argtypes=0xbfffd350) at
parse_func.c:975
#4  0x080c5836 in func_get_detail (funcname=0x831451c, fargs=0x83178e8,
nargs=24, argtypes=0xbfffd350, funcid=0xbfffd33c,
     rettype=0xbfffd340, retset=0xbfffd347 "\bÁ\002",
true_typeids=0xbfffd348) at parse_func.c:891
#5  0x080c4c4c in ParseFuncOrColumn (pstate=0x8317810,
funcname=0x831451c, fargs=0x83178e8, agg_star=0 '\0',
     agg_distinct=0 '\0', is_column=0 '\0') at parse_func.c:241
#6  0x080c41de in transformExpr (pstate=0x8317810, expr=0x8317714) at
parse_expr.c:399
#7  0x080cb4ed in transformTargetEntry (pstate=0x8317810,
node=0x8317714, expr=0x0, colname=0x0, resjunk=0 '\0')
     at parse_target.c:60
#8  0x080cb53b in transformTargetList (pstate=0x8317810,
targetlist=0x831774c) at parse_target.c:193
#9  0x080b61c8 in transformSelectStmt (pstate=0x8317810, stmt=0x8317768)
at analyze.c:1771
#10 0x080b41b7 in transformStmt (pstate=0x8317810, parseTree=0x8317768,
extras_before=0xbfffd574, extras_after=0xbfffd578)
     at analyze.c:407
#11 0x080b402b in do_parse_analyze (parseTree=0x8317768,
pstate=0x8317810) at analyze.c:234
#12 0x080b3f44 in parse_analyze (parseTree=0x8317768,
paramTypes=0x830a624, numParams=137405988) at analyze.c:159
#13 0x08159c3c in pg_analyze_and_rewrite (parsetree=0x8317768,
paramTypes=0x0, numParams=0) at postgres.c:482
#14 0x08159f83 in exec_simple_query (
     query_string=0x8313c40 "    select  add_news__test(\n
1000::integer,", ' ' <repeats 15 times>, "\n    'en_US'::varchar,", ' '
<repeats 15 times>, "\n    '2003-6-23'::timestamptz, \n    'text text
text'::varchar,      \n    'language'::varchar,         "...) at
postgres.c:795
#15 0x0815bd1b in PostgresMain (argc=4, argv=0x829aa9c,
username=0x829aa64 "postgres") at postgres.c:2753
#16 0x0813a531 in BackendFork (port=0x82a80c0) at postmaster.c:2471
#17 0x0813a026 in BackendStartup (port=0x82a80c0) at postmaster.c:2118
#18 0x08138b5f in ServerLoop () at postmaster.c:1090
#19 0x081384dd in PostmasterMain (argc=5, argv=0x829a4c8) at
postmaster.c:872
#20 0x0810f713 in main (argc=5, argv=0xbfffe334) at main.c:211
#21 0x420156a4 in __libc_start_main () from /lib/tls/libc.so.6



pgsql-hackers by date:

Previous
From: Jan Wieck
Date:
Subject: Re: Two weeks to feature freeze
Next
From: Joe Conway
Date:
Subject: Re: [GENERAL] Many Pl/PgSQL parameters -> AllocSetAlloc(128)?