Skip to content

Commit 5e4b00d

Browse files
committed
Further optimize #select_map by populating array in C instead of yielding to Ruby
Similar approach as used for #map.
1 parent 1cccb4e commit 5e4b00d

File tree

3 files changed

+37
-7
lines changed

3 files changed

+37
-7
lines changed

CHANGELOG

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
* Use rb_hash_new_capa if available to avoid unnecessary hash resizing (jeremyevans)
44

5-
* Further optimize Dataset#map by populating array in C instead of yielding to Ruby (jeremyevans)
5+
* Further optimize Dataset#map and #select_map by populating array in C instead of yielding to Ruby (jeremyevans)
66

77
* Optimize Dataset#as_set and #select_set in Sequel 5.99+ (jeremyevans)
88

ext/sequel_pg/sequel_pg.c

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,8 @@
7171
#define SPG_YIELD_MKMV_HASH_GROUPS 13
7272
#define SPG_YIELD_COLUMN_ARRAY 14
7373
#define SPG_YIELD_COLUMNS_ARRAY 15
74+
#define SPG_YIELD_FIRST_ARRAY 16
75+
#define SPG_YIELD_ARRAY_ARRAY 17
7476

7577
/* External functions defined by ruby-pg */
7678
PGconn* pg_get_pgconn(VALUE);
@@ -99,7 +101,9 @@ static VALUE spg_sym_local;
99101
static VALUE spg_sym_map;
100102
static VALUE spg_sym_map_array;
101103
static VALUE spg_sym_first;
104+
static VALUE spg_sym_first_array;
102105
static VALUE spg_sym_array;
106+
static VALUE spg_sym_array_array;
103107
static VALUE spg_sym_hash;
104108
static VALUE spg_sym_hash_groups;
105109
static VALUE spg_sym_model;
@@ -1422,6 +1426,10 @@ static VALUE spg_yield_hash_rows_internal(VALUE self, PGresult *res, int enc_ind
14221426
type = SPG_YIELD_FIRST;
14231427
} else if (pg_type == spg_sym_array) {
14241428
type = SPG_YIELD_ARRAY;
1429+
} else if (pg_type == spg_sym_first_array) {
1430+
type = SPG_YIELD_FIRST_ARRAY;
1431+
} else if (pg_type == spg_sym_array_array) {
1432+
type = SPG_YIELD_ARRAY_ARRAY;
14251433
} else if ((pg_type == spg_sym_hash || pg_type == spg_sym_hash_groups) && rb_type(pg_value) == T_ARRAY) {
14261434
VALUE pg_value_key, pg_value_value;
14271435
pg_value_key = rb_ary_entry(pg_value, 0);
@@ -1521,6 +1529,28 @@ static VALUE spg_yield_hash_rows_internal(VALUE self, PGresult *res, int enc_ind
15211529
rb_yield(h);
15221530
}
15231531
break;
1532+
case SPG_YIELD_FIRST_ARRAY:
1533+
/* Array of first column */
1534+
h = rb_ary_new2(ntuples);
1535+
for(i=0; i<ntuples; i++) {
1536+
rb_ary_store(h, i, spg__col_value(self, res, i, 0, colconvert, enc_index));
1537+
}
1538+
rb_yield(h);
1539+
break;
1540+
case SPG_YIELD_ARRAY_ARRAY:
1541+
/* Array of arrays of all columns */
1542+
{
1543+
VALUE ary = rb_ary_new2(ntuples);
1544+
for(i=0; i<ntuples; i++) {
1545+
h = rb_ary_new2(nfields);
1546+
for(j=0; j<nfields; j++) {
1547+
rb_ary_store(h, j, spg__col_value(self, res, i, j, colconvert, enc_index));
1548+
}
1549+
rb_ary_store(ary, i, h);
1550+
}
1551+
rb_yield(ary);
1552+
}
1553+
break;
15241554
case SPG_YIELD_KV_HASH:
15251555
case SPG_YIELD_KV_HASH_GROUPS:
15261556
/* Hash with single key and single value */
@@ -1967,6 +1997,8 @@ void Init_sequel_pg(void) {
19671997
spg_sym_map_array = ID2SYM(rb_intern("map_array"));
19681998
spg_sym_first = ID2SYM(rb_intern("first"));
19691999
spg_sym_array = ID2SYM(rb_intern("array"));
2000+
spg_sym_first_array = ID2SYM(rb_intern("first_array"));
2001+
spg_sym_array_array = ID2SYM(rb_intern("array_array"));
19702002
spg_sym_hash = ID2SYM(rb_intern("hash"));
19712003
spg_sym_hash_groups = ID2SYM(rb_intern("hash_groups"));
19722004
spg_sym_model = ID2SYM(rb_intern("model"));

lib/sequel_pg/sequel_pg.rb

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -98,16 +98,14 @@ def each(&block)
9898

9999
# Always use optimized version
100100
def _select_map_multiple(ret_cols)
101-
rows = []
102-
clone(:_sequel_pg_type=>:array).fetch_rows(sql){|s| rows << s}
103-
rows
101+
clone(:_sequel_pg_type=>:array_array).fetch_rows(sql){|a| return a}
102+
[]
104103
end
105104

106105
# Always use optimized version
107106
def _select_map_single
108-
rows = []
109-
clone(:_sequel_pg_type=>:first).fetch_rows(sql){|s| rows << s}
110-
rows
107+
clone(:_sequel_pg_type=>:first_array).fetch_rows(sql){|a| return a}
108+
[]
111109
end
112110

113111
# :nocov:

0 commit comments

Comments
 (0)