mirror of https://github.com/jackc/pgx.git
Add binary decoding for floats
parent
01b7865abf
commit
8c7ea78485
122
bench_test.go
122
bench_test.go
|
@ -11,6 +11,8 @@ var narrowTestDataLoaded bool
|
|||
var int2TextVsBinaryTestDataLoaded bool
|
||||
var int4TextVsBinaryTestDataLoaded bool
|
||||
var int8TextVsBinaryTestDataLoaded bool
|
||||
var float4TextVsBinaryTestDataLoaded bool
|
||||
var float8TextVsBinaryTestDataLoaded bool
|
||||
|
||||
func mustPrepare(b *testing.B, conn *Connection, name, sql string) {
|
||||
if err := conn.Prepare(name, sql); err != nil {
|
||||
|
@ -407,3 +409,123 @@ func BenchmarkInt8Binary(b *testing.B) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
func createFloat4TextVsBinaryTestData(b *testing.B, conn *Connection) {
|
||||
if float4TextVsBinaryTestDataLoaded {
|
||||
return
|
||||
}
|
||||
|
||||
if _, err := conn.Execute(`
|
||||
drop table if exists t;
|
||||
|
||||
create temporary table t(
|
||||
a float4 not null,
|
||||
b float4 not null,
|
||||
c float4 not null,
|
||||
d float4 not null,
|
||||
e float4 not null
|
||||
);
|
||||
|
||||
insert into t(a, b, c, d, e)
|
||||
select
|
||||
(random() * 1000000)::float4, (random() * 1000000)::float4, (random() * 1000000)::float4, (random() * 1000000)::float4, (random() * 1000000)::float4
|
||||
from generate_series(1, 10);
|
||||
`); err != nil {
|
||||
b.Fatalf("Could not set up test data: %v", err)
|
||||
}
|
||||
|
||||
float4TextVsBinaryTestDataLoaded = true
|
||||
}
|
||||
|
||||
func BenchmarkFloat4Text(b *testing.B) {
|
||||
conn := getSharedConnection()
|
||||
createFloat4TextVsBinaryTestData(b, conn)
|
||||
|
||||
binaryDecoder := valueTranscoders[oid(700)].DecodeBinary
|
||||
valueTranscoders[oid(700)].DecodeBinary = nil
|
||||
defer func() { valueTranscoders[oid(700)].DecodeBinary = binaryDecoder }()
|
||||
|
||||
mustPrepare(b, conn, "selectFloat32", "select * from t")
|
||||
defer func() { conn.Deallocate("selectFloat32") }()
|
||||
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
if _, err := conn.SelectRows("selectFloat32"); err != nil {
|
||||
b.Fatalf("Failure while benchmarking: %v", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkFloat4Binary(b *testing.B) {
|
||||
conn := getSharedConnection()
|
||||
createFloat4TextVsBinaryTestData(b, conn)
|
||||
mustPrepare(b, conn, "selectFloat32", "select * from t")
|
||||
defer func() { conn.Deallocate("selectFloat32") }()
|
||||
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
if _, err := conn.SelectRows("selectFloat32"); err != nil {
|
||||
b.Fatalf("Failure while benchmarking: %v", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func createFloat8TextVsBinaryTestData(b *testing.B, conn *Connection) {
|
||||
if float8TextVsBinaryTestDataLoaded {
|
||||
return
|
||||
}
|
||||
|
||||
if _, err := conn.Execute(`
|
||||
drop table if exists t;
|
||||
|
||||
create temporary table t(
|
||||
a float8 not null,
|
||||
b float8 not null,
|
||||
c float8 not null,
|
||||
d float8 not null,
|
||||
e float8 not null
|
||||
);
|
||||
|
||||
insert into t(a, b, c, d, e)
|
||||
select
|
||||
(random() * 1000000)::float8, (random() * 1000000)::float8, (random() * 1000000)::float8, (random() * 1000000)::float8, (random() * 1000000)::float8
|
||||
from generate_series(1, 10);
|
||||
`); err != nil {
|
||||
b.Fatalf("Could not set up test data: %v", err)
|
||||
}
|
||||
|
||||
float8TextVsBinaryTestDataLoaded = true
|
||||
}
|
||||
|
||||
func BenchmarkFloat8Text(b *testing.B) {
|
||||
conn := getSharedConnection()
|
||||
createFloat8TextVsBinaryTestData(b, conn)
|
||||
|
||||
binaryDecoder := valueTranscoders[oid(701)].DecodeBinary
|
||||
valueTranscoders[oid(701)].DecodeBinary = nil
|
||||
defer func() { valueTranscoders[oid(701)].DecodeBinary = binaryDecoder }()
|
||||
|
||||
mustPrepare(b, conn, "selectFloat32", "select * from t")
|
||||
defer func() { conn.Deallocate("selectFloat32") }()
|
||||
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
if _, err := conn.SelectRows("selectFloat32"); err != nil {
|
||||
b.Fatalf("Failure while benchmarking: %v", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkFloat8Binary(b *testing.B) {
|
||||
conn := getSharedConnection()
|
||||
createFloat8TextVsBinaryTestData(b, conn)
|
||||
mustPrepare(b, conn, "selectFloat32", "select * from t")
|
||||
defer func() { conn.Deallocate("selectFloat32") }()
|
||||
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
if _, err := conn.SelectRows("selectFloat32"); err != nil {
|
||||
b.Fatalf("Failure while benchmarking: %v", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ import (
|
|||
"encoding/hex"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
type valueTranscoder struct {
|
||||
|
@ -58,13 +59,15 @@ func init() {
|
|||
|
||||
// float4
|
||||
valueTranscoders[oid(700)] = &valueTranscoder{
|
||||
DecodeText: decodeFloat4FromText,
|
||||
EncodeTo: encodeFloat4}
|
||||
DecodeText: decodeFloat4FromText,
|
||||
DecodeBinary: decodeFloat4FromBinary,
|
||||
EncodeTo: encodeFloat4}
|
||||
|
||||
// float8
|
||||
valueTranscoders[oid(701)] = &valueTranscoder{
|
||||
DecodeText: decodeFloat8FromText,
|
||||
EncodeTo: encodeFloat8}
|
||||
DecodeText: decodeFloat8FromText,
|
||||
DecodeBinary: decodeFloat8FromBinary,
|
||||
EncodeTo: encodeFloat8}
|
||||
|
||||
// varchar -- same as text
|
||||
valueTranscoders[oid(1043)] = valueTranscoders[oid(25)]
|
||||
|
@ -167,6 +170,16 @@ func decodeFloat4FromText(mr *MessageReader, size int32) interface{} {
|
|||
return float32(n)
|
||||
}
|
||||
|
||||
func decodeFloat4FromBinary(mr *MessageReader, size int32) interface{} {
|
||||
if size != 4 {
|
||||
panic("Received an invalid size for an float4")
|
||||
}
|
||||
|
||||
i := mr.ReadInt32()
|
||||
p := unsafe.Pointer(&i)
|
||||
return *(*float32)(p)
|
||||
}
|
||||
|
||||
func encodeFloat4(w *messageWriter, value interface{}) {
|
||||
v := value.(float32)
|
||||
s := strconv.FormatFloat(float64(v), 'e', -1, 32)
|
||||
|
@ -183,6 +196,16 @@ func decodeFloat8FromText(mr *MessageReader, size int32) interface{} {
|
|||
return v
|
||||
}
|
||||
|
||||
func decodeFloat8FromBinary(mr *MessageReader, size int32) interface{} {
|
||||
if size != 8 {
|
||||
panic("Received an invalid size for an float4")
|
||||
}
|
||||
|
||||
i := mr.ReadInt64()
|
||||
p := unsafe.Pointer(&i)
|
||||
return *(*float64)(p)
|
||||
}
|
||||
|
||||
func encodeFloat8(w *messageWriter, value interface{}) {
|
||||
v := value.(float64)
|
||||
s := strconv.FormatFloat(float64(v), 'e', -1, 64)
|
||||
|
|
Loading…
Reference in New Issue