Re: [HACKERS] c-function variants running time

2012-05-07 Thread Robert Haas
On Fri, May 4, 2012 at 12:41 PM, Armando
armando.mirag...@stud-inf.unibz.it wrote:
 Hi everybody.

 First of all I have to thank you for your wonderful job! PostgreSQL rocks!

 I am writing you because I am interested in understanding some specifics 
 related
 to PostgreSQL internals. More precisely, I am investigating the running time
 of the different function implementation approaches, which is part of my BSc
 thesis.

I would suggest that you run perf or oprofile to figure out where the
time is being spent.

It's a bit hard to tell what these functions are intended to do.  It's
not obvious that you're doing anything that couldn't be done using
straight SQL.

How fast do you need this to run?

-- 
Robert Haas
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company

-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers


[HACKERS] c-function variants running time

2012-05-04 Thread Armando
Hi everybody.

First of all I have to thank you for your wonderful job! PostgreSQL rocks!

I am writing you because I am interested in understanding some specifics related
to PostgreSQL internals. More precisely, I am investigating the running time
of the different function implementation approaches, which is part of my BSc
thesis.

Here is the thing: I have implemented as a proof of concept three functions,
which are
a) text[] arraypoc(text, int); this returns an array of the form 'text,int'
   where the text is the copy of the text passed as parameter and int is a
   simple counter. The number of tuples is specified by the integer parameter.
   I have estimated the running time in this manner:
   SELECT *
 FROM unnest(arraypoc('abcdefghilmnopqrstuvz',100));
   The estimated running time is after 10 executions is:
   (791.571 + 797.163 + 677.331 + 686.674 + 686.691 + 686.438 +
797.910 + 795.955 + 793.459 + 794.110)/10 = 750.7302

b) TABLE(text,int) srfpoc(text, int); is similar as the previous one but this
   is a set returning function, which returns a table of a similar shape as in
   the previous case. Instead of a string, I return a text and an integer. Again
   text is just the copy of the parameter and int is a counter.
   I have estimated the running time in this manner:
   SELECT *
 FROM srfpoc('abcdefghilmnopqrstuvz',100);
   The estimated running time is after 10 executions is: 
   (665.016 + 778.100 + 640.605 + 787.102 + 785.501 + 791.307 +
784.780 + 793.222 + 794.624 + 790.357)/10 = 761.0614

c) TABLE(text,int) srfmatpoc(text, int); this does the same as the previous one,
   but in this case I wrote a SRF_Materialized using the SPI interface.  I have
   estimated the running time in this manner:
   SELECT *
 FROM srfmatpoc('abcdefghilmnopqrstuvz',100);
   The estimated running time is after 10 executions is: 
   (747.095 + 703.894 + 762.310 + 763.299 + 764.582 + 760.991 + 763.427 +
764.033 + 731.292 + 770.895)/10   = 753.1818

I have executed all the tests on the same server. The functions are compiled
using the -O3 compilation parameter. I am using PostgreSQL 9.1.3.

I would have expected the version a) to be slower than b) and c) but it turns
out that it is actually the fastest (the difference is not so big anyway). What
am I doing wrong? What can I do to improve the functions? Have I misunderstood
something?

Attached you find the code of all three functions.

Thanks a lot!
Armando
#include postgres.h
#include string.h

#include utils/array.h
#include utils/builtins.h	/* text_to_cstring */
#include catalog/pg_type.h
#include utils/lsyscache.h
#include fmgr.h

#ifdef PG_MODULE_MAGIC
PG_MODULE_MAGIC;
#endif

PG_FUNCTION_INFO_V1(arraypoc);

Datum arraypoc(PG_FUNCTION_ARGS) {
  ArrayType   *result;
  Datum   *result_data = NULL;
  int16o_typlen;
  bool o_typbyval;
  char o_typalign;
  text*t,
  *cpyt;
  uint32   c;
  int i, t_len;

  t = (text *)PG_GETARG_TEXT_PP(0);
  c = (uint32)PG_GETARG_INT32(1);

  if(c0) result_data = (Datum *)palloc(sizeof(Datum) * c);

  for(i=0; ic; ++i) {
t_len = VARSIZE_ANY_EXHDR(t);

cpyt = (text *)palloc(VARHDRSZ + t_len + 1 + 16);
SET_VARSIZE(cpyt, VARHDRSZ + t_len + 1 + 16);
memcpy((void *)VARDATA(cpyt), (void *)VARDATA(t), t_len);
memcpy((void *)VARDATA(cpyt) + t_len, ,, 1);
snprintf((void *)VARDATA(cpyt) + t_len + 1, 16, %d, i);

result_data[i] = PointerGetDatum(cpyt);
  }

  if(result_data == NULL || c = 0) {
PG_RETURN_NULL();

  } else {
get_typlenbyvalalign(TEXTOID, o_typlen, o_typbyval, o_typalign);
result = construct_array(result_data, c, TEXTOID, o_typlen, o_typbyval,
 o_typalign);
PG_RETURN_ARRAYTYPE_P(result);
  }
}
#include postgres.h

#include stdio.h/* snprintf */
#include stdlib.h/* malloc, free */
#include string.h/* strncpy, strlen */
#include sys/types.h  /* for uint32 and size_t*/

#include catalog/pg_type.h
#include utils/builtins.h  /* text_to_cstring */
#include funcapi.h
#include fmgr.h

#ifdef PG_MODULE_MAGIC
PG_MODULE_MAGIC;
#endif

PG_FUNCTION_INFO_V1(srfpoc);

Datum srfpoc(PG_FUNCTION_ARGS) {
  FuncCallContext *funcctx;
  TupleDesctupdesc;
  text*t;
  int  max_calls,
   call_cntr;

  t = (text *)PG_GETARG_TEXT_PP(0);
  
  if (SRF_IS_FIRSTCALL()) {
MemoryContextoldcontext;

funcctx = SRF_FIRSTCALL_INIT();
oldcontext = MemoryContextSwitchTo(funcctx-multi_call_memory_ctx);

funcctx-max_calls = (uint32)PG_GETARG_INT32(1);

tupdesc = CreateTemplateTupleDesc(2, false);
TupleDescInitEntry(tupdesc, (AttrNumber) 1, t, TEXTOID, -1, 0);
TupleDescInitEntry(tupdesc, (AttrNumber) 2, count, INT4OID, -1, 0);

funcctx-user_fctx = BlessTupleDesc(tupdesc);

MemoryContextSwitchTo(oldcontext);
  }

  funcctx =