Generate qsort_tuple.c
authorRobert Haas <rhaas@postgresql.org>
Tue, 14 Feb 2012 21:31:19 +0000 (16:31 -0500)
committerRobert Haas <rhaas@postgresql.org>
Tue, 14 Feb 2012 21:31:19 +0000 (16:31 -0500)
src/backend/Makefile
src/backend/utils/sort/.gitignore [new file with mode: 0644]
src/backend/utils/sort/Makefile
src/backend/utils/sort/gen_qsort_tuple.pl [moved from src/backend/utils/sort/qsort_tuple.c with 55% similarity, mode: 0755]
src/backend/utils/sort/tuplesort.c
src/port/qsort.c
src/port/qsort_arg.c

index 0c763dd37584eb9208a528ff4de5326209a09533..461257ce58865c9d15982f408e6e549153e45cae 100644 (file)
@@ -202,6 +202,7 @@ distprep:
        $(MAKE) -C replication  repl_gram.c repl_scanner.c
        $(MAKE) -C utils        fmgrtab.c fmgroids.h errcodes.h
        $(MAKE) -C utils/misc   guc-file.c
+       $(MAKE) -C utils/sort   qsort_tuple.c
 
 
 ##########################################################################
@@ -315,7 +316,8 @@ maintainer-clean: distclean
              utils/fmgroids.h \
              utils/fmgrtab.c \
              utils/errcodes.h \
-             utils/misc/guc-file.c
+             utils/misc/guc-file.c \
+                 utils/sort/qsort_tuple.c
 
 
 ##########################################################################
diff --git a/src/backend/utils/sort/.gitignore b/src/backend/utils/sort/.gitignore
new file mode 100644 (file)
index 0000000..f295863
--- /dev/null
@@ -0,0 +1 @@
+/qsort_tuple.c
index 2ef4965ee6db442f3d2e94903d76a4cdb69db521..f46ce4161052976493c4b130e7b16937154c8bea 100644 (file)
@@ -14,4 +14,12 @@ include $(top_builddir)/src/Makefile.global
 
 OBJS = logtape.o sortsupport.o tuplesort.o tuplestore.o
 
+tuplesort.o: qsort_tuple.c
+
+qsort_tuple.c: gen_qsort_tuple.pl
+       $(PERL) $(srcdir)/gen_qsort_tuple.pl $< > $@
+
 include $(top_srcdir)/src/backend/common.mk
+
+maintainer-clean:
+       rm -f qsort_tuple.c
old mode 100644 (file)
new mode 100755 (executable)
similarity index 55%
rename from src/backend/utils/sort/qsort_tuple.c
rename to src/backend/utils/sort/gen_qsort_tuple.pl
index c7857fa..9a39b1e
@@ -1,17 +1,60 @@
+#!/usr/bin/perl -w
+
+#
+# gen_qsort_tuple.pl
+#
+# This script generates specialized versions of the quicksort algorithm for
+# tuple sorting.  The quicksort code is derived from the NetBSD code.  The
+# code generated by this script runs significantly faster than vanilla qsort
+# when used to sort tuples.  This speedup comes from a number of places.
+# The major effects are (1) inlining simple tuple comparators is much faster
+# than jumping through a function pointer and (2) swap and vecswap operations
+# specialized to the particular data type of interest (in this case, SortTuple)
+# are faster than the generic routines.
+#
+#      Modifications from vanilla NetBSD source:
+#        Add do ... while() macro fix
+#        Remove __inline, _DIAGASSERTs, __P
+#        Remove ill-considered "swap_cnt" switch to insertion sort,
+#        in favor of a simple check for presorted input.
+#     Instead of sorting arbitrary objects, we're always sorting SortTuples
+#     Add CHECK_FOR_INTERRUPTS()
+#
+# CAUTION: if you change this file, see also qsort.c and qsort_arg.c
+#
+
+use strict;
+
+my $SUFFIX;
+my $EXTRAARGS;
+my $EXTRAPARAMS;
+my $CMPPARAMS;
+
+emit_qsort_boilerplate();
+
+$SUFFIX = 'tuple';
+$EXTRAARGS = ', SortTupleComparator cmp_tuple, Tuplesortstate *state';
+$EXTRAPARAMS = ', cmp_tuple, state';
+$CMPPARAMS = ', state';
+emit_qsort_implementation();
+
+$SUFFIX = 'ssup';
+$EXTRAARGS = ', SortSupport ssup';
+$EXTRAPARAMS = ', ssup';
+$CMPPARAMS = ', ssup';
+print <<'EOM';
+#define cmp_ssup(a, b, ssup) \
+       ApplySortComparator((a)->datum1, (a)->isnull1, \
+                                               (b)->datum1, (b)->isnull1, ssup)
+EOM
+emit_qsort_implementation();
+
+sub emit_qsort_boilerplate
+{
+       print <<'EOM';
 /*
- *     qsort_tuple.c: specialized version of qsort, for SortTuple objects
- *
- *  This file is included by tuplesort.c, rather than compiled separately.
- *
- *     Modifications from vanilla NetBSD source:
- *       Add do ... while() macro fix
- *       Remove __inline, _DIAGASSERTs, __P
- *       Remove ill-considered "swap_cnt" switch to insertion sort,
- *       in favor of a simple check for presorted input.
- *
- *     CAUTION: if you change this file, see also qsort.c and qsort_arg.c
- *
- *     src/backend/utils/sort/qsort_tuple.c
+ * autogenerated by src/backend/utils/sort/gen_qsort.pl, do not edit
+ * This file is included by tuplesort.c, rather than compiled separately.
  */
 
 /*     $NetBSD: qsort.c,v 1.13 2003/08/07 16:43:42 agc Exp $   */
@@ -72,19 +115,24 @@ swapfunc(SortTuple *a, SortTuple *b, size_t n)
        } while (0);
 
 #define vecswap(a, b, n) if ((n) > 0) swapfunc((a), (b), (size_t)(n))
+EOM
+}
 
+sub emit_qsort_implementation
+{
+       print <<EOM;
 static SortTuple *
-med3_tuple(SortTuple *a, SortTuple *b, SortTuple *c, SortTupleComparator cmp,
-        Tuplesortstate *state)
+med3_$SUFFIX(SortTuple *a, SortTuple *b, SortTuple *c$EXTRAARGS)
 {
-       return cmp(a, b, state) < 0 ?
-               (cmp(b, c, state) < 0 ? b : (cmp(a, c, state) < 0 ? c : a))
-               : (cmp(b, c, state) > 0 ? b : (cmp(a, c, state) < 0 ? a : c));
+       return cmp_$SUFFIX(a, b$CMPPARAMS) < 0 ?
+               (cmp_$SUFFIX(b, c$CMPPARAMS) < 0 ? b :
+                       (cmp_$SUFFIX(a, c$CMPPARAMS) < 0 ? c : a))
+               : (cmp_$SUFFIX(b, c$CMPPARAMS) > 0 ? b :
+                       (cmp_$SUFFIX(a, c$CMPPARAMS) < 0 ? a : c));
 }
 
 static void
-qsort_tuple(SortTuple *a, size_t n, SortTupleComparator cmp,
-                       Tuplesortstate *state)
+qsort_$SUFFIX(SortTuple *a, size_t n$EXTRAARGS)
 {
        SortTuple  *pa,
                           *pb,
@@ -102,7 +150,7 @@ loop:
        if (n < 7)
        {
                for (pm = a + 1; pm < a + n; pm++)
-                       for (pl = pm; pl > a && cmp(pl - 1, pl, state) > 0; pl--)
+                       for (pl = pm; pl > a && cmp_$SUFFIX(pl - 1, pl$CMPPARAMS) > 0; pl--)
                                swap(pl, pl - 1);
                return;
        }
@@ -110,7 +158,7 @@ loop:
        for (pm = a + 1; pm < a + n; pm++)
        {
                CHECK_FOR_INTERRUPTS();
-               if (cmp(pm - 1, pm, state) > 0)
+               if (cmp_$SUFFIX(pm - 1, pm$CMPPARAMS) > 0)
                {
                        presorted = 0;
                        break;
@@ -126,18 +174,18 @@ loop:
                if (n > 40)
                {
                        d = (n / 8);
-                       pl = med3_tuple(pl, pl + d, pl + 2 * d, cmp, state);
-                       pm = med3_tuple(pm - d, pm, pm + d, cmp, state);
-                       pn = med3_tuple(pn - 2 * d, pn - d, pn, cmp, state);
+                       pl = med3_$SUFFIX(pl, pl + d, pl + 2 * d$EXTRAPARAMS);
+                       pm = med3_$SUFFIX(pm - d, pm, pm + d$EXTRAPARAMS);
+                       pn = med3_$SUFFIX(pn - 2 * d, pn - d, pn$EXTRAPARAMS);
                }
-               pm = med3_tuple(pl, pm, pn, cmp, state);
+               pm = med3_$SUFFIX(pl, pm, pn$EXTRAPARAMS);
        }
        swap(a, pm);
        pa = pb = a + 1;
        pc = pd = a + (n - 1);
        for (;;)
        {
-               while (pb <= pc && (r = cmp(pb, a, state)) <= 0)
+               while (pb <= pc && (r = cmp_$SUFFIX(pb, a$CMPPARAMS)) <= 0)
                {
                        CHECK_FOR_INTERRUPTS();
                        if (r == 0)
@@ -147,7 +195,7 @@ loop:
                        }
                        pb++;
                }
-               while (pb <= pc && (r = cmp(pc, a, state)) >= 0)
+               while (pb <= pc && (r = cmp_$SUFFIX(pc, a$CMPPARAMS)) >= 0)
                {
                        CHECK_FOR_INTERRUPTS();
                        if (r == 0)
@@ -169,7 +217,7 @@ loop:
        r = Min(pd - pc, pn - pd - 1);
        vecswap(pb, pn - r, r);
        if ((r = pb - pa) > 1)
-               qsort_tuple(a, r, cmp, state);
+               qsort_$SUFFIX(a, r$EXTRAPARAMS);
        if ((r = pd - pc) > 1)
        {
                /* Iterate rather than recurse to save stack space */
@@ -177,5 +225,8 @@ loop:
                n = r;
                goto loop;
        }
-/*             qsort_tuple(pn - r, r, cmp, state);*/
+/*             qsort_tuple(pn - r, r$EXTRAPARAMS);*/
+}
+
+EOM
 }
index 0dfe9fb9f1279820e56396b1b228d141d5abc149..6c7fa062aef72132a8414646c1b1dd8269ef0d8c 100644 (file)
@@ -1229,10 +1229,16 @@ tuplesort_performsort(Tuplesortstate *state)
                         * amount of memory.  Just qsort 'em and we're done.
                         */
                        if (state->memtupcount > 1)
-                               qsort_tuple(state->memtuples,
-                                                       state->memtupcount,
-                                                       state->comparetup,
-                                                       state);
+                       {
+                               if (state->comparetup == comparetup_heap && state->nKeys == 1)
+                                       qsort_ssup(state->memtuples, state->memtupcount,
+                                                          state->sortKeys);
+                               else
+                                       qsort_tuple(state->memtuples,
+                                                               state->memtupcount,
+                                                               state->comparetup,
+                                                               state);
+                       }
                        state->current = 0;
                        state->eof_reached = false;
                        state->markpos_offset = 0;
index 8e2c6d92c2dc99ec2b64d23367ca62505e89405e..49d8fa7ab6cbdc82b025bb54cdc7414a571d8972 100644 (file)
@@ -7,7 +7,7 @@
  *       Remove ill-considered "swap_cnt" switch to insertion sort,
  *       in favor of a simple check for presorted input.
  *
- *     CAUTION: if you change this file, see also qsort_arg.c
+ *     CAUTION: if you change this file, see also qsort_arg.c, gen_qsort_tuple.pl
  *
  *     src/port/qsort.c
  */
index 28d1894992b93a767d973523ff09a163f7a29258..3091eb09eada9860ec19efa3eef2c28c4cdb34a8 100644 (file)
@@ -7,7 +7,7 @@
  *       Remove ill-considered "swap_cnt" switch to insertion sort,
  *       in favor of a simple check for presorted input.
  *
- *     CAUTION: if you change this file, see also qsort.c
+ *     CAUTION: if you change this file, see also qsort.c, gen_qsort_tuple.pl
  *
  *     src/port/qsort_arg.c
  */