From 53da3bb7891f64d1df115fc52a688bdac540d829 Mon Sep 17 00:00:00 2001 From: Jack Christensen Date: Fri, 12 Jul 2013 18:02:23 -0400 Subject: [PATCH] Use binary encoding for bool --- bench_test.go | 61 +++++++++++++++++++++++++++++++++++++++++++++ value_transcoder.go | 23 +++++++++++++---- 2 files changed, 79 insertions(+), 5 deletions(-) diff --git a/bench_test.go b/bench_test.go index a7a534cb..b6aebd01 100644 --- a/bench_test.go +++ b/bench_test.go @@ -13,6 +13,7 @@ var int4TextVsBinaryTestDataLoaded bool var int8TextVsBinaryTestDataLoaded bool var float4TextVsBinaryTestDataLoaded bool var float8TextVsBinaryTestDataLoaded bool +var boolTextVsBinaryTestDataLoaded bool func mustPrepare(b *testing.B, conn *Connection, name, sql string) { if err := conn.Prepare(name, sql); err != nil { @@ -529,3 +530,63 @@ func BenchmarkFloat8Binary(b *testing.B) { } } } + +func createBoolTextVsBinaryTestData(b *testing.B, conn *Connection) { + if boolTextVsBinaryTestDataLoaded { + return + } + + if _, err := conn.Execute(` + drop table if exists t; + + create temporary table t( + a bool not null, + b bool not null, + c bool not null, + d bool not null, + e bool not null + ); + + insert into t(a, b, c, d, e) + select + random() > 0.5, random() > 0.5, random() > 0.5, random() > 0.5, random() > 0.5 + from generate_series(1, 10); + `); err != nil { + b.Fatalf("Could not set up test data: %v", err) + } + + boolTextVsBinaryTestDataLoaded = true +} + +func BenchmarkBoolText(b *testing.B) { + conn := getSharedConnection() + createBoolTextVsBinaryTestData(b, conn) + + binaryDecoder := valueTranscoders[oid(16)].DecodeBinary + valueTranscoders[oid(16)].DecodeBinary = nil + defer func() { valueTranscoders[oid(16)].DecodeBinary = binaryDecoder }() + + mustPrepare(b, conn, "selectBool", "select * from t") + defer func() { conn.Deallocate("selectBool") }() + + b.ResetTimer() + for i := 0; i < b.N; i++ { + if _, err := conn.SelectRows("selectBool"); err != nil { + b.Fatalf("Failure while benchmarking: %v", err) + } + } +} + +func BenchmarkBoolBinary(b *testing.B) { + conn := getSharedConnection() + createBoolTextVsBinaryTestData(b, conn) + mustPrepare(b, conn, "selectBool", "select * from t") + defer func() { conn.Deallocate("selectBool") }() + + b.ResetTimer() + for i := 0; i < b.N; i++ { + if _, err := conn.SelectRows("selectBool"); err != nil { + b.Fatalf("Failure while benchmarking: %v", err) + } + } +} diff --git a/value_transcoder.go b/value_transcoder.go index b7edd0fe..26da4745 100644 --- a/value_transcoder.go +++ b/value_transcoder.go @@ -22,8 +22,10 @@ func init() { // bool valueTranscoders[oid(16)] = &valueTranscoder{ - DecodeText: decodeBoolFromText, - EncodeTo: encodeBool} + DecodeText: decodeBoolFromText, + DecodeBinary: decodeBoolFromBinary, + EncodeTo: encodeBool, + EncodeFormat: 1} // bytea valueTranscoders[oid(17)] = &valueTranscoder{ @@ -90,11 +92,22 @@ func decodeBoolFromText(mr *MessageReader, size int32) interface{} { } } +func decodeBoolFromBinary(mr *MessageReader, size int32) interface{} { + if size != 1 { + panic("Received an invalid size for an bool") + } + b := mr.ReadByte() + return b != 0 +} + func encodeBool(w *messageWriter, value interface{}) { v := value.(bool) - s := strconv.FormatBool(v) - w.write(int32(len(s))) - w.writeString(s) + w.write(int32(1)) + if v { + w.writeByte(1) + } else { + w.writeByte(0) + } } func decodeInt8FromText(mr *MessageReader, size int32) interface{} {