Re: Rethinking plpgsql's assignment implementation

Pavel Stehule <pavel.stehule@gmail.com>

From: Pavel Stehule <pavel.stehule@gmail.com>
To: Tom Lane <tgl@sss.pgh.pa.us>
Cc: Chapman Flack <chap@anastigmatix.net>, PostgreSQL Hackers <pgsql-hackers@lists.postgresql.org>
Date: 2020-12-14T08:20:23Z
Lists: pgsql-hackers
Hi

I checked a performance and it looks so access to record's field is faster,
but an access to arrays field is significantly slower

do $$
declare
  a int[];
  aux int;
  rep boolean default true;
begin
  for i in 1..5000
  loop
    a[i]:= 5000 - i;
  end loop;

  raise notice '%', a[1:10];

  while rep
  loop
    rep := false;
    for i in 1..5000
    loop
      if a[i] > a[i+1] then
        aux := a[i];
        a[i] := a[i+1]; a[i+1] := aux;
        rep := true;
      end if;
    end loop;
  end loop;

  raise notice '%', a[1:10];

end;
$$;

This code is about 3x slower than master (40 sec x 12 sec). I believe so
this is a worst case scenario

I tested pi calculation

CREATE OR REPLACE FUNCTION pi_est_1(n int)
RETURNS numeric AS $$
DECLARE
  accum double precision DEFAULT 1.0;
  c1 double precision DEFAULT 2.0;
  c2 double precision DEFAULT 1.0;
BEGIN
  FOR i IN 1..n
  LOOP
    accum := accum * ((c1 * c1) / (c2 * (c2 + 2.0)));
    c1 := c1 + 2.0;
    c2 := c2 + 2.0;
  END LOOP;
  RETURN accum * 2.0;
END;
$$ LANGUAGE plpgsql;

CREATE OR REPLACE FUNCTION pi_est_2(n int)
RETURNS numeric AS $$
DECLARE
  accum double precision DEFAULT 1.0;
  c1 double precision DEFAULT 2.0;
  c2 double precision DEFAULT 1.0;
BEGIN
  FOR i IN 1..n
  LOOP
    accum := accum * ((c1 * c1) / (c2 * (c2 + double precision '2.0')));
    c1 := c1 + double precision '2.0';
    c2 := c2 + double precision '2.0';
  END LOOP;
  RETURN accum * double precision '2.0';
END;
$$ LANGUAGE plpgsql;

And the performance is 10% slower than on master

Interesting point - the master is about 5% faster than pg13

Commits

  1. Rethink the "read/write parameter" mechanism in pl/pgsql.

  2. Remove PLPGSQL_DTYPE_ARRAYELEM datum type within pl/pgsql.

  3. Re-implement pl/pgsql's expression and assignment parsing.

  4. Add the ability for the core grammar to have more than one parse target.

  5. Support subscripting of arbitrary types, not only arrays.

  6. Improve handling of array elements as getdiag_targets and cursor_variables.