Skip to content
Commits on Source (25)
......@@ -9,6 +9,7 @@
Alexander Menzhinsky <amenzhinsky@gmail.com>
Dan Peterson <danp@danp.net>
David Skinner <skinner.david@gmail.com>
Gleb Sakhnov <gleb.sakhnov@gmail.com>
Jaap Aarts <jaap.aarts1@gmail.com>
Jan Mercl <0xjnml@gmail.com>
Logan Snow <logansnow@protonmail.com>
......
......@@ -42,6 +42,8 @@ build_all_targets:
GOOS=darwin GOARCH=arm64 go test -c -o /dev/null
GOOS=freebsd GOARCH=amd64 go build -v ./...
GOOS=freebsd GOARCH=amd64 go test -c -o /dev/null
GOOS=freebsd GOARCH=386 go build -v ./...
GOOS=freebsd GOARCH=386 go test -c -o /dev/null
GOOS=linux GOARCH=386 go build -v ./...
GOOS=linux GOARCH=386 go test -c -o /dev/null
GOOS=linux GOARCH=amd64 go build -v ./...
......@@ -60,96 +62,90 @@ build_all_targets:
GOOS=windows GOARCH=amd64 go test -c -o /dev/null
echo done
# 3900x
windows_amd64:
@echo "Should be executed only on linux/amd64."
CCGO_CPP=x86_64-w64-mingw32-cpp TARGET_GOOS=windows TARGET_GOARCH=amd64 go generate 2>&1 | tee log-generate
GOOS=windows GOARCH=amd64 go build -v ./...
# 3900x
windows_386:
@echo "Should be executed only on linux/amd64."
CCGO_CPP=i686-w64-mingw32-cpp TARGET_GOOS=windows TARGET_GOARCH=386 go generate 2>&1 | tee log-generate
GOOS=windows GOARCH=386 go build -v ./...
# 3900x/qemu
darwin_amd64:
@echo "Should be executed only on darwin/amd64."
go generate 2>&1 | tee log-generate
go build -v ./...
# 3900x/qemu
netbsd_amd64:
@echo "Should be executed only on netbsd/amd64."
go generate 2>&1 | tee log-generate
go build -v ./...
# darwin-m1
darwin_arm64:
@echo "Should be executed only on darwin/arm64."
go generate 2>&1 | tee log-generate
go build -v ./...
# 3900x/VBox
freebsd_amd64:
@echo "Should be executed only on freebsd/amd64."
go generate 2>&1 | tee log-generate
go build -v ./...
netbsd_amd64:
@echo "Should be executed only on netbsd/amd64."
# 3900x/qemu
freebsd_386:
@echo "Should be executed only on freebsd/386."
go generate 2>&1 | tee log-generate
go build -v ./...
# 3900x
linux_amd64:
TARGET_GOOS=linux TARGET_GOARCH=amd64 go generate 2>&1 | tee /tmp/log-generate-sqlite-linux-amd64
GOOS=linux GOARCH=amd64 go build -v ./...
@echo "Should be executed only on linux/amd64."
go generate 2>&1 | tee log-generate
go build -v ./...
# 3900x
linux_386:
CCGO_CPP=i686-linux-gnu-cpp TARGET_GOARCH=386 TARGET_GOOS=linux go generate 2>&1 | tee /tmp/log-generate-sqlite-linux-386
@echo "Should be executed only on linux/amd64."
CCGO_CPP=i686-linux-gnu-cpp TARGET_GOARCH=386 TARGET_GOOS=linux go generate 2>&1 | tee log-generate
GOOS=linux GOARCH=386 go build -v ./...
linux_arm_on_linux_amd64:
CCGO_CPP=arm-linux-gnueabi-cpp TARGET_GOARCH=arm TARGET_GOOS=linux go generate 2>&1 | tee /tmp/log-generate-sqlite-linux-arm
GOOS=linux GOARCH=arm go build -v ./...
# 3900x
linux_arm:
go generate 2>&1 | tee /tmp/log-generate-sqlite-linux-arm
@echo "Should be executed only on linux/amd64."
CCGO_CPP=arm-linux-gnueabi-cpp TARGET_GOARCH=arm TARGET_GOOS=linux go generate 2>&1 | tee log-generate
GOOS=linux GOARCH=arm go build -v ./...
# 3900x
linux_arm64:
CCGO_CPP=aarch64-linux-gnu-cpp TARGET_GOARCH=arm64 TARGET_GOOS=linux go generate 2>&1 | tee /tmp/log-generate-sqlite-linux-arm64
@echo "Should be executed only on linux/amd64."
CCGO_CPP=aarch64-linux-gnu-cpp TARGET_GOARCH=arm64 TARGET_GOOS=linux go generate 2>&1 | tee log-generate
GOOS=linux GOARCH=arm64 go build -v ./...
# 3900x
linux_s390x:
CCGO_CPP=s390x-linux-gnu-cpp TARGET_GOARCH=s390x TARGET_GOOS=linux go generate 2>&1 | tee /tmp/log-generate-sqlite-linux-s390x
@echo "Should be executed only on linux/amd64."
CCGO_CPP=s390x-linux-gnu-cpp TARGET_GOARCH=s390x TARGET_GOOS=linux go generate 2>&1 | tee log-generate
GOOS=linux GOARCH=s390x go build -v ./...
windows_amd64:
CCGO_CPP=x86_64-w64-mingw32-cpp TARGET_GOOS=windows TARGET_GOARCH=amd64 go generate 2>&1 | tee /tmp/log-generate-sqlite-windows-amd64
GOOS=windows GOARCH=amd64 go build -v ./...
windows_386:
CCGO_CPP=i686-w64-mingw32-cpp TARGET_GOOS=windows TARGET_GOARCH=386 go generate 2>&1 | tee /tmp/log-generate-sqlite-windows-386
GOOS=windows GOARCH=386 go build -v ./...
all_targets: linux_amd64 linux_386 linux_arm linux_arm64 linux_s390x windows_amd64 windows_386
generate_all_targets_on_linux_amd64: linux_amd64 linux_386 linux_arm_on_linux_amd64 linux_arm64 linux_s390x windows_amd64 #TODO windows_386
gofmt -l -s -w .
echo done
test:
go version | tee $(testlog)
uname -a | tee -a $(testlog)
go test -v -timeout 24h | tee -a $(testlog)
grep -ni fail $(testlog) | tee -a $(testlog) || true
LC_ALL=C date | tee -a $(testlog)
grep -ni --color=always fail $(testlog) || true
tcl_test_wine:
GOOS=windows GOARCH=amd64 go build -o testfixture.exe modernc.org/sqlite/internal/testfixture
test_darwin_amd64:
GOOS=darwin GOARCH=amd64 make test
test_darwin_arm64:
GOOS=darwin GOARCH=arm64 make test
test_linux_amd64:
GOOS=linux GOARCH=amd64 make test
test_linux_386:
GOOS=linux GOARCH=386 make test
test_linux_386_hosted:
GOOS=linux GOARCH=386 SQLITE_TEST_SUFFIX=-hosted-$(host) make test
test_linux_arm:
GOOS=linux GOARCH=arm make test
test_linux_arm64:
GOOS=linux GOARCH=arm64 make test
test_linux_s390x:
GOOS=linux GOARCH=s390x make test
run_tcl_test_wine:
TCL_LIBRARY=Z:/home/jnml/src/modernc.org/tcl/assets wine testfixture.exe ./testdata/tcl/zipfile.test
extraquick:
go test -timeout 24h -v -run Tcl -suite extraquick -maxerror 1 2>&1 | tee log-extraquick
go test -timeout 24h -v -failfast -suite extraquick -maxerror 1 2>&1 | tee log-extraquick
date
full:
......@@ -207,17 +203,3 @@ todo:
@grep -nr $(grep) TODO * | grep -v $(ngrep) || true
@grep -nr $(grep) BUG * | grep -v $(ngrep) || true
@grep -nr $(grep) [^[:alpha:]]println * | grep -v $(ngrep) || true
tcl:
cp log log-0
go test -run Tcl$$ 2>&1 -timeout 24h -trc | tee log
grep -c '\.\.\. \?Ok' log || true
grep -c '^!' log || true
# grep -c 'Error:' log || true
tclshort:
cp log log-0
go test -run Tcl$$ -short 2>&1 -timeout 24h -trc | tee log
grep -c '\.\.\. \?Ok' log || true
grep -c '^!' log || true
# grep -c 'Error:' log || true
## Benchmarks
Generally, benchmarks are conducted against CGo implementation of SQLite (https://github.com/mattn/go-sqlite3).
## Doing benchmarks with go test command
```console
go test -bench . -run '^$'
```
## Doing benchmarks with alternative runner to plot results
```console
go test -v .
```
Dark color scheme:
```console
go test -v . -dark
```
### My results:
#### Insert
| On disk | In memory |
| :---------------------------------------- | :--------------------------------------- |
| ![](out/benchmarkInsert_memory_false.png) | ![](out/benchmarkInsert_memory_true.png) |
#### Select
| On disk | In memory |
| :---------------------------------------- | :--------------------------------------- |
| ![](out/benchmarkSelect_memory_false.png) | ![](out/benchmarkSelect_memory_true.png) |
## Adding benchmarks
A specific type of benchmark function is currently automated:
```go
type bechmarkOfNRows func(b *testing.B, db *sql.DB, nRows int)
```
You can implement benchmark functions of that type, then add them into ```allBenchmarksOfNRows``` variable (see [benchmarks.go](benchmarks.go))
```go
var allBenchmarksOfNRows = []bechmarkOfNRows{
benchmarkInsert,
benchmarkSelect,
}
```
Elements of ```allBenchmarksOfNRows``` will be automatically evaluated and plotted when alternative runner is used.
To make implemented benchmark available via go-test, you may write a simple stub like following (see [bench_test.go](bench_test.go)):
```go
func BenchmarkSelect(b *testing.B) {
doBenchmarkOfNrows(b, benchmarkSelect)
}
```
// Copyright 2021 The Sqlite Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package benchmark
import (
"flag"
"fmt"
"log"
"math"
"math/rand"
"os"
"path"
"testing"
)
var (
// in dryRun we just generate random values to quickly see how information is plotted
dryRun bool
// whethe to use dark palette when plotting results
darkPalette bool
)
func TestMain(m *testing.M) {
flag.BoolVar(&dryRun, "dry", false, "just generate random values to quickly see how information is plotted")
flag.BoolVar(&darkPalette, "dark", false, "use dark palette when plotting")
flag.Parse()
os.Exit(m.Run())
}
func TestBenchmarkAndPlot(t *testing.T) {
// choose palette for plottin
var palette = LightPalette
if darkPalette {
palette = DarkPalette
}
for _, benchFunc := range allBenchmarksOfNRows {
for _, isMemoryDB := range inMemory {
// create graph
graph := &GraphCompareOfNRows{
title: fmt.Sprintf("%s | In-Memory: %v", getFuncName(benchFunc), isMemoryDB),
rowCountsE: rowCountsE,
palette: palette,
}
// drivers
for _, driver := range drivers {
// this slice accumulates values as float64, for later plotting
var (
seriesValues []float64
rowsPerSec float64
)
// number of rows in table
for _, e := range rowCountsE {
if dryRun {
// in dryRun mode we just generate random value to quickly see how information is plotted
rowsPerSec = rand.Float64() * 200000
} else {
// create DB
db := createDB(t, isMemoryDB, driver)
// run benchmark
result := testing.Benchmark(func(b *testing.B) {
benchFunc(b, db, int(math.Pow10(e)))
})
// close DB
db.Close()
// calculate rows/sec
rowsPerSec = math.Pow10(e) * float64(result.N) / result.T.Seconds()
}
// print result to console (FYI)
benchName := fmt.Sprintf("%s_%s", getFuncName(benchFunc), makeName(isMemoryDB, driver, e))
fmt.Println(benchName, "\t", fmt.Sprintf("%10.0f", rowsPerSec), "rows/sec")
// add corresponding value to series
seriesValues = append(seriesValues, rowsPerSec)
}
// add series to graph
var seriesName string
if driver == "sqlite3" {
seriesName = "CGo"
} else {
seriesName = "Go"
}
graph.AddSeries(seriesName, seriesValues)
}
// render graph into file
outputFilename := path.Join("out", fmt.Sprintf("%s_memory_%v.png", getFuncName(benchFunc), isMemoryDB))
if err := graph.Render(outputFilename); err != nil {
log.Fatal(err)
}
log.Printf("plot written into %s\n", outputFilename)
}
}
}
// Copyright 2021 The Sqlite Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// this file allows to run benchmarks via go test
package benchmark
import (
"math"
"testing"
)
func BenchmarkSelect(b *testing.B) {
doBenchmarkOfNrows(b, benchmarkSelect)
}
// https://gitlab.com/cznic/sqlite/-/issues/39
func BenchmarkInsert(b *testing.B) {
doBenchmarkOfNrows(b, benchmarkInsert)
}
func doBenchmarkOfNrows(b *testing.B, benchFunc bechmarkOfNRows) {
for _, isMemoryDB := range inMemory { // in-memory: on/off
for _, e := range rowCountsE { // number of rows in table
for _, driverName := range drivers { // drivers
// create new DB
db := createDB(b, isMemoryDB, driverName)
// run benchmark
b.Run(
makeName(isMemoryDB, driverName, e),
func(b *testing.B) {
benchFunc(b, db, int(math.Pow10(e)))
},
)
// close DB
if err := db.Close(); err != nil {
b.Fatal(err)
}
}
}
}
}
// Copyright 2021 The Sqlite Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// this file contains pure benchmark functions
// these may be wrapped by different runners
package benchmark
import (
"database/sql"
"testing"
)
// all benchmark of N functions to be run
var allBenchmarksOfNRows = []bechmarkOfNRows{
benchmarkInsert,
benchmarkSelect,
}
// bechmarkOfNRows is a type for a function that is benchmarking something depending on rows count.
type bechmarkOfNRows func(b *testing.B, db *sql.DB, nRows int)
// benchmarkInsert measures insertion of nRows into empty test table
// the insertion is carried line by line, inside a transaction, using single prepared statement
// the passed db instance must be empty (fresh) and is NOT auto-closed inside the benchmark function
func benchmarkInsert(b *testing.B, db *sql.DB, nRows int) {
// create test table (empty)
createTestTable(b, db, 0)
// prepare statement for insertion
s, err := db.Prepare("insert into t values(?)")
if err != nil {
b.Fatal(err)
}
defer s.Close()
// measure from here
b.ResetTimer()
// do N times
for i := 0; i < b.N; i++ {
// remove data from test table
b.StopTimer()
if _, err := db.Exec("delete from t"); err != nil {
b.Fatal(err)
}
b.StartTimer()
// begin tx
if _, err := db.Exec("begin"); err != nil {
b.Fatal(err)
}
// insert nRows one by one via prepared statement
for i := 0; i < nRows; i++ {
if _, err := s.Exec(int64(i)); err != nil {
b.Fatal(err)
}
}
// commit tx
if _, err := db.Exec("commit"); err != nil {
b.Fatal(err)
}
b.StopTimer()
}
}
// benchmarkSelect measures select of nRows from a test table
// the passed db instance must be empty (fresh) and is NOT auto-closed inside the benchmark function
func benchmarkSelect(b *testing.B, db *sql.DB, nRows int) {
// create test table with data
createTestTable(b, db, nRows)
// scan destination
dst := 0
// measure from here
b.ResetTimer()
// do N times
for i := 0; i < b.N; i++ {
// prepare a rows to iterate on
b.StopTimer()
rows, err := db.Query("select * from t")
if err != nil {
b.Fatal(err)
}
b.StartTimer()
// iterate in rows
for i := 0; i < nRows; i++ {
if !rows.Next() {
b.Fatal(rows.Err()) // createTestTable did not insert enough records? that's strange
}
// scan yet another value
err = rows.Scan(&dst)
if err != nil {
b.Fatal(err)
}
}
b.StopTimer()
if rows.Next() {
b.Fatal("expecting rows to be exhausted at this point")
}
rows.Close()
}
}
// Copyright 2021 The Sqlite Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package benchmark
import (
"fmt"
_ "github.com/mattn/go-sqlite3"
_ "modernc.org/sqlite"
)
var (
// driver names
drivers = []string{
"sqlite3", // CGo SQLite
"sqlite", // pure-go SQLite
}
// whether in-memory DB used
inMemory = []bool{
true,
false,
}
// row counts will be 1eX, where X is taken from this slice
rowCountsE = []int{1, 2, 3, 4, 5, 6}
)
// makeName generates name for a benchmark
func makeName(inMemory bool, driver string, e int) string {
var name string
if driver == "sqlite" {
name = "Go"
} else {
name = "CGo"
}
if inMemory {
name += "_Memory"
} else {
name += "_OnDisk"
}
return fmt.Sprintf("%s_1e%d", name, e)
}
module modernc.org/sqlite/benchmark
go 1.17
replace modernc.org/sqlite => ../
require (
github.com/mattn/go-sqlite3 v1.14.9
github.com/wcharczuk/go-chart v2.0.1+incompatible
modernc.org/sqlite v0.0.0-00010101000000-000000000000
)
require (
github.com/blend/go-sdk v1.20211204.3 // indirect
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect
github.com/google/uuid v1.3.0 // indirect
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect
github.com/mattn/go-isatty v0.0.12 // indirect
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 // indirect
golang.org/x/image v0.0.0-20211028202545-6944b10bf410 // indirect
golang.org/x/mod v0.3.0 // indirect
golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac // indirect
golang.org/x/tools v0.0.0-20201204162204-73cf035baebf // indirect
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
lukechampine.com/uint128 v1.1.1 // indirect
modernc.org/cc/v3 v3.35.18 // indirect
modernc.org/ccgo/v3 v3.12.95 // indirect
modernc.org/libc v1.11.104 // indirect
modernc.org/mathutil v1.4.1 // indirect
modernc.org/memory v1.0.5 // indirect
modernc.org/opt v0.1.1 // indirect
modernc.org/strutil v1.1.1 // indirect
modernc.org/token v1.0.0 // indirect
)
This diff is collapsed.
// Copyright 2021 The Sqlite Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// helpers for plotting benchmark results
package benchmark
import (
"fmt"
"os"
"path"
"github.com/wcharczuk/go-chart"
"github.com/wcharczuk/go-chart/drawing"
)
const (
yAxisCeilStep = 200000
)
var transparentColor = drawing.ColorWhite.WithAlpha(0)
type GraphCompareOfNRows struct {
// this fields should be set externally
rowCountsE []int
title string
palette chart.ColorPalette
// this fields are for private use
seriesNameS []string
seriesValuesS [][]float64
}
func (g *GraphCompareOfNRows) AddSeries(name string, values []float64) {
g.seriesNameS = append(g.seriesNameS, name)
g.seriesValuesS = append(g.seriesValuesS, values)
}
func (g *GraphCompareOfNRows) Render(filename string) error {
// new chart object
graph := g.newGraph()
// generate series objects for graph
for i, seriesName := range g.seriesNameS {
// get corresponding series values
seriesValues := g.seriesValuesS[i]
// create series object
graph.Series = append(graph.Series, g.createSeries(seriesName, seriesValues))
// adjust max for Y axis
yMax := (int(max(seriesValues...)/yAxisCeilStep) + 1) * yAxisCeilStep // a special case of ceil()
if graph.YAxis.Range.GetMax() < float64(yMax) {
graph.YAxis.Range = &chart.ContinuousRange{
Min: 0,
Max: float64(yMax),
}
}
// skip annotations for first series
if i == 0 {
continue
}
// for every series except first, we create a ratio annotation s[X]/s[0]
annotations := &chart.AnnotationSeries{}
for i, v := range seriesValues {
annotations.Annotations = append(annotations.Annotations, g.newRatioAnnotation(
float64(g.rowCountsE[i]),
v,
v/g.seriesValuesS[0][i],
))
}
// append annotations to graph
graph.Series = append(graph.Series, annotations)
}
// add legend
graph.Elements = []chart.Renderable{
chart.Legend(graph, chart.Style{
FontSize: 12,
StrokeColor: transparentColor,
FillColor: g.palette.CanvasColor(),
FontColor: g.palette.TextColor().WithAlpha(192),
}),
}
// write into file
if err := os.MkdirAll(path.Dir(filename), 0775); err != nil {
return err
}
f, err := os.Create(filename)
if err != nil {
return err
}
defer f.Close()
if err := graph.Render(chart.PNG, f); err != nil {
return err
}
return nil
}
func (g *GraphCompareOfNRows) createSeries(name string, values []float64) chart.Series {
// convert E values of rowCount onto float64
var xValues []float64
for _, e := range g.rowCountsE {
xValues = append(xValues, float64(e))
}
// create series
series := &chart.ContinuousSeries{
Name: name,
Style: chart.Style{
DotWidth: 2.5,
Show: true,
StrokeWidth: 1.5,
},
XValues: xValues,
YValues: values,
}
// save in series slice
return series
}
func (g *GraphCompareOfNRows) newGraph() *chart.Chart {
return &chart.Chart{
ColorPalette: g.palette,
Title: g.title,
TitleStyle: chart.Style{
Show: true,
},
Background: chart.Style{
Padding: chart.Box{
Top: 20,
Left: 20,
},
},
Canvas: chart.Style{},
XAxis: chart.XAxis{
Style: chart.StyleShow(),
NameStyle: chart.StyleShow(),
Name: "rows",
Ticks: g.genXticks(),
},
YAxis: chart.YAxis{
Range: &chart.ContinuousRange{},
Style: chart.StyleShow(),
Name: "rows/sec",
NameStyle: chart.StyleShow(),
ValueFormatter: func(v interface{}) string { return fmt.Sprintf("%.0f", v) },
},
}
}
func (g *GraphCompareOfNRows) newRatioAnnotation(x, y, ratio float64) chart.Value2 {
return chart.Value2{
XValue: x,
YValue: y,
Label: fmt.Sprintf("%.2fx", ratio),
Style: chart.Style{
FontSize: 8,
TextHorizontalAlign: chart.TextHorizontalAlignLeft,
FillColor: transparentColor, // full tranparency
StrokeColor: transparentColor, // full transparency
FontColor: g.palette.TextColor().WithAlpha(255), // no transaprency
TextRotationDegrees: 45,
},
}
}
func (g *GraphCompareOfNRows) genXticks() []chart.Tick {
var ticks []chart.Tick
for i, e := range g.rowCountsE {
ticks = append(ticks, chart.Tick{
Value: float64(e),
Label: fmt.Sprintf("1e%d", i+1),
})
}
return ticks
}
func max(f ...float64) float64 {
if len(f) == 0 {
return 0
}
m := f[0]
for i := 1; i < len(f); i++ {
if m < f[i] {
m = f[i]
}
}
return m
}
type palette struct {
bgColor drawing.Color
bgStrokeColor drawing.Color
canvasColor drawing.Color
canvasStrokeColor drawing.Color
axisStrokeColor drawing.Color
textColor drawing.Color
seriesColor []drawing.Color
}
func (p *palette) BackgroundColor() drawing.Color { return p.bgColor }
func (p *palette) BackgroundStrokeColor() drawing.Color { return p.bgStrokeColor }
func (p *palette) CanvasColor() drawing.Color { return p.canvasColor }
func (p *palette) CanvasStrokeColor() drawing.Color { return p.canvasStrokeColor }
func (p *palette) AxisStrokeColor() drawing.Color { return p.axisStrokeColor }
func (p *palette) TextColor() drawing.Color { return p.textColor }
func (p *palette) GetSeriesColor(i int) drawing.Color { return p.seriesColor[i%len(p.seriesColor)] }
var DarkPalette = &palette{
bgColor: drawing.ColorFromHex("252526"),
canvasColor: drawing.ColorFromHex("1e1e1e1"),
textColor: drawing.ColorFromHex("d4d4d4").WithAlpha(128),
axisStrokeColor: drawing.ColorFromHex("d4d4d4").WithAlpha(128),
seriesColor: []drawing.Color{
drawing.ColorFromHex("d5d5a5"),
drawing.ColorFromHex("569cd5"),
},
}
var LightPalette = &palette{
canvasColor: drawing.ColorFromHex("f2f2f2"),
bgColor: drawing.ColorFromHex("f5f5f5"),
textColor: drawing.ColorFromHex("393939").WithAlpha(128),
axisStrokeColor: drawing.ColorFromHex("393939").WithAlpha(128),
seriesColor: []drawing.Color{
drawing.ColorFromHex("aa3731"),
drawing.ColorFromHex("5a77c7"),
},
}
// Copyright 2021 The Sqlite Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package benchmark
import (
"database/sql"
"path"
"reflect"
"runtime"
"strings"
"testing"
)
func createDB(tb testing.TB, inMemory bool, driverName string) *sql.DB {
var dsn string
if inMemory {
dsn = ":memory:"
} else {
dsn = path.Join(tb.TempDir(), "test.db")
}
db, err := sql.Open(driverName, dsn)
if err != nil {
tb.Fatal(err)
}
return db
}
func createTestTable(tb testing.TB, db *sql.DB, nRows int) {
if _, err := db.Exec("drop table if exists t"); err != nil {
tb.Fatal(err)
}
if _, err := db.Exec("create table t(i int)"); err != nil {
tb.Fatal(err)
}
if nRows > 0 {
s, err := db.Prepare("insert into t values(?)")
if err != nil {
tb.Fatal(err)
}
defer s.Close()
if _, err := db.Exec("begin"); err != nil {
tb.Fatal(err)
}
for i := 0; i < nRows; i++ {
if _, err := s.Exec(int64(i)); err != nil {
tb.Fatal(err)
}
}
if _, err := db.Exec("commit"); err != nil {
tb.Fatal(err)
}
}
}
func getFuncName(i interface{}) string {
// get function name as "package.function"
fn := runtime.FuncForPC(reflect.ValueOf(i).Pointer()).Name()
// return last component
comps := strings.Split(fn, ".")
return comps[len(comps)-1]
}
......@@ -2,14 +2,12 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build (cgo && cgobench) || ignore || (cgo && cgotest)
// +build cgo,cgobench ignore cgo,cgotest
//go:build ignore || (cgo && cgotest)
// +build ignore cgo,cgotest
package sqlite // import "modernc.org/sqlite"
import (
"database/sql"
"fmt"
"io/ioutil"
"os"
"path/filepath"
......@@ -18,191 +16,6 @@ import (
_ "github.com/mattn/go-sqlite3"
)
const gcoDriver = "sqlite3"
var drivers = []string{
driverName,
gcoDriver,
}
var inMemory = []bool{
true,
false,
}
func makename(inMemory bool, driver string, e int) string {
name := driver
if inMemory {
name += "InMemory"
} else {
name += "OnDisk"
}
return fmt.Sprintf("%s1e%d", name, e)
}
func benchmarkRead(b *testing.B, drivername, file string, n int) {
os.Remove(file)
db, err := sql.Open(drivername, file)
if err != nil {
b.Fatal(err)
}
defer func() {
db.Close()
}()
if _, err := db.Exec(`
create table t(i int);
begin;
`); err != nil {
b.Fatal(err)
}
s, err := db.Prepare("insert into t values(?)")
if err != nil {
b.Fatal(err)
}
defer s.Close()
for i := 0; i < n; i++ {
if _, err := s.Exec(int64(i)); err != nil {
b.Fatal(err)
}
}
if _, err := db.Exec("commit"); err != nil {
b.Fatal(err)
}
dst := 0
b.ReportAllocs()
b.ResetTimer()
for i := 0; i < b.N; i++ {
b.StopTimer()
r, err := db.Query("select * from t")
if err != nil {
b.Fatal(err)
}
b.StartTimer()
for i := 0; i < n; i++ {
if !r.Next() {
b.Fatal(r.Err())
}
err = r.Scan(&dst)
if err != nil {
b.Fatal(err)
}
}
b.StopTimer()
r.Close()
}
b.StopTimer()
if *oRecsPerSec {
b.SetBytes(1e6 * int64(n))
}
}
func BenchmarkReading1(b *testing.B) {
dir := b.TempDir()
for _, memory := range inMemory {
filename := "file::memory:"
if !memory {
filename = filepath.Join(dir, "test.db")
}
for _, driver := range drivers {
for i, n := range []int{1e1, 1e2, 1e3, 1e4, 1e5, 1e6} {
b.Run(makename(memory, driver, i+1), func(b *testing.B) {
benchmarkRead(b, driver, filename, n)
if !memory {
err := os.Remove(filename)
if err != nil {
b.Fatal(err)
}
}
})
}
}
}
}
func benchmarkInsertComparative(b *testing.B, drivername, file string, n int) {
os.Remove(file)
db, err := sql.Open(drivername, file)
if err != nil {
b.Fatal(err)
}
defer func() {
db.Close()
}()
if _, err := db.Exec(`
create table t(i int);
`); err != nil {
b.Fatal(err)
}
s, err := db.Prepare("insert into t values(?)")
if err != nil {
b.Fatal(err)
}
defer s.Close()
b.ReportAllocs()
b.ResetTimer()
for i := 0; i < b.N; i++ {
b.StopTimer()
if _, err := db.Exec("begin"); err != nil {
b.Fatal(err)
}
if err, _ := db.Exec("delete * from t"); err != nil {
b.Fatal(err)
}
b.StartTimer()
for i := 0; i < n; i++ {
if _, err := s.Exec(int64(i)); err != nil {
b.Fatal(err)
}
}
if _, err := db.Exec("commit"); err != nil {
b.Fatal(err)
}
b.StopTimer()
}
b.StopTimer()
if *oRecsPerSec {
b.SetBytes(1e6 * int64(n))
}
}
// https://gitlab.com/cznic/sqlite/-/issues/39
func BenchmarkInsertComparative(b *testing.B) {
dir := b.TempDir()
for _, memory := range inMemory {
filename := "file::memory:"
if !memory {
filename = filepath.Join(dir, "test.db")
}
for _, driver := range drivers {
for i, n := range []int{1e1, 1e2, 1e3, 1e4, 1e5, 1e6} {
b.Run(makename(memory, driver, i+1), func(b *testing.B) {
benchmarkInsertComparative(b, driver, filename, n)
if !memory {
err := os.Remove(filename)
if err != nil {
b.Fatal(err)
}
}
})
}
}
}
}
// https://gitlab.com/cznic/sqlite/-/issues/65
func TestIssue65CGo(t *testing.T) {
tempDir, err := ioutil.TempDir("", "")
......
......@@ -2,7 +2,8 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Package sqlite is a CGo-free port of SQLite/SQLite3 v3.36.0.
// Package sqlite is a sql/database driver using a CGo-free port of the C
// SQLite3 library.
//
// SQLite is an in-process implementation of a self-contained, serverless,
// zero-configuration, transactional SQL database engine.
......@@ -11,14 +12,16 @@
//
// These combinations of GOOS and GOARCH are currently supported
//
// darwin amd64
// darwin arm64
// freebsd amd64
// linux 386
// linux amd64
// linux arm
// linux arm64
// windows amd64
// OS Arch SQLite version
// ------------------------------
// darwin amd64 3.37.2
// darwin arm64 3.37.2
// freebsd amd64 3.37.2
// linux 386 3.37.2
// linux amd64 3.37.2
// linux arm 3.37.2
// linux arm64 3.37.2
// windows amd64 3.37.2
//
// Builders
//
......
......@@ -168,6 +168,7 @@ var (
"-DSQLITE_ENABLE_UNLOCK_NOTIFY", // Adds sqlite3_unlock_notify().
"-DSQLITE_LIKE_DOESNT_MATCH_BLOBS",
"-DSQLITE_MUTEX_APPDEF=1",
"-DSQLITE_MUTEX_NOOP",
"-DSQLITE_SOUNDEX",
"-DSQLITE_THREADSAFE=1",
//DONT "-DNDEBUG", // To enable GO_GENERATE=-DSQLITE_DEBUG
......@@ -221,6 +222,7 @@ var (
"-DSQLITE_HAVE_ZLIB=1", // testfixture
"-DSQLITE_LIKE_DOESNT_MATCH_BLOBS",
"-DSQLITE_MUTEX_APPDEF=1",
"-DSQLITE_MUTEX_NOOP",
"-DSQLITE_SOUNDEX",
"-DSQLITE_TEMP_STORE=1", // testfixture
"-DSQLITE_TEST",
......@@ -252,12 +254,12 @@ var (
sz int
dev bool
}{
{sqliteDir, "https://www.sqlite.org/2021/sqlite-amalgamation-3360000.zip", 2457, false},
{sqliteSrcDir, "https://www.sqlite.org/2021/sqlite-src-3360000.zip", 12814, false},
{sqliteDir, "https://www.sqlite.org/2022/sqlite-amalgamation-3370200.zip", 2457, false},
{sqliteSrcDir, "https://www.sqlite.org/2022/sqlite-src-3370200.zip", 12814, false},
}
sqliteDir = filepath.FromSlash("testdata/sqlite-amalgamation-3360000")
sqliteSrcDir = filepath.FromSlash("testdata/sqlite-src-3360000")
sqliteDir = filepath.FromSlash("testdata/sqlite-amalgamation-3370200")
sqliteSrcDir = filepath.FromSlash("testdata/sqlite-src-3370200")
)
func download() {
......@@ -394,16 +396,27 @@ func main() {
}
more = append(more, ndebug...)
download()
switch fmt.Sprintf("%s/%s", goos, goarch) {
case "linux/amd64":
// experimental pthreads support currently only on linux/amd64
default:
configProduction = append(configProduction, "-DSQLITE_MUTEX_NOOP")
configTest = append(configTest, "-DSQLITE_MUTEX_NOOP")
}
switch goos {
case "linux", "freebsd", "netbsd":
case "linux", "freebsd":
configProduction = append(configProduction, "-DSQLITE_OS_UNIX=1")
case "netbsd":
configProduction = append(configProduction, []string{
"-DSQLITE_OS_UNIX=1",
"-D__libc_cond_broadcast=pthread_cond_broadcast",
"-D__libc_cond_destroy=pthread_cond_destroy",
"-D__libc_cond_init=pthread_cond_init",
"-D__libc_cond_signal=pthread_cond_signal",
"-D__libc_cond_wait=pthread_cond_wait",
"-D__libc_mutex_destroy=pthread_mutex_destroy",
"-D__libc_mutex_init=pthread_mutex_init",
"-D__libc_mutex_lock=pthread_mutex_lock",
"-D__libc_mutex_trylock=pthread_mutex_trylock",
"-D__libc_mutex_unlock=pthread_mutex_unlock",
"-D__libc_mutexattr_destroy=pthread_mutexattr_destroy",
"-D__libc_mutexattr_init=pthread_mutexattr_init",
"-D__libc_mutexattr_settype=pthread_mutexattr_settype",
"-D__libc_thr_yield=sched_yield",
}...)
case "darwin":
configProduction = append(configProduction,
"-DSQLITE_OS_UNIX=1",
......@@ -524,6 +537,7 @@ func makeTestfixture(goos, goarch string, more []string) {
"ext/misc/wholenumber.c",
"ext/misc/zipfile.c",
"ext/rbu/test_rbu.c",
"ext/rtree/test_rtreedoc.c",
"ext/session/test_session.c",
"ext/userauth/userauth.c",
"src/tclsqlite.c",
......@@ -600,6 +614,9 @@ func makeTestfixture(goos, goarch string, more []string) {
"-D__libc_mutex_lock=pthread_mutex_lock",
"-D__libc_mutex_trylock=pthread_mutex_trylock",
"-D__libc_mutex_unlock=pthread_mutex_unlock",
"-D__libc_mutexattr_destroy=pthread_mutexattr_destroy",
"-D__libc_mutexattr_init=pthread_mutexattr_init",
"-D__libc_mutexattr_settype=pthread_mutexattr_settype",
"-D__libc_thr_yield=sched_yield",
}
}
......@@ -618,6 +635,7 @@ func makeTestfixture(goos, goarch string, more []string) {
[]string{
"-export-defines", "",
"-export-fields", "F",
"-ignore-unsupported-alignment",
"-trace-translation-units",
volatiles,
"-lmodernc.org/sqlite/libtest",
......@@ -650,6 +668,7 @@ func makeSpeedTest(goos, goarch string, more []string) {
[]string{
"ccgo",
"-export-defines", "",
"-ignore-unsupported-alignment",
"-o", filepath.FromSlash(fmt.Sprintf("speedtest1/main_%s_%s.go", goos, goarch)),
"-trace-translation-units",
filepath.Join(sqliteSrcDir, "test", "speedtest1.c"),
......@@ -673,6 +692,7 @@ func makeMpTest(goos, goarch string, more []string) {
[]string{
"ccgo",
"-export-defines", "",
"-ignore-unsupported-alignment",
"-o", filepath.FromSlash(fmt.Sprintf("internal/mptest/main_%s_%s.go", goos, goarch)),
"-trace-translation-units",
filepath.Join(sqliteSrcDir, "mptest", "mptest.c"),
......@@ -701,6 +721,7 @@ func makeSqliteProduction(goos, goarch string, more []string) {
"-export-externs", "X",
"-export-fields", "F",
"-export-typedefs", "",
"-ignore-unsupported-alignment",
"-pkgname", "sqlite3",
"-o", filepath.FromSlash(fmt.Sprintf("lib/sqlite_%s_%s.go", goos, goarch)),
"-trace-translation-units",
......@@ -728,6 +749,7 @@ func makeSqliteTest(goos, goarch string, more []string) {
"-export-externs", "X",
"-export-fields", "F",
"-export-typedefs", "",
"-ignore-unsupported-alignment",
"-pkgname", "sqlite3",
"-o", filepath.FromSlash(fmt.Sprintf("libtest/sqlite_%s_%s.go", goos, goarch)),
"-trace-translation-units",
......
......@@ -8,8 +8,10 @@ github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNU
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8=
github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
github.com/mattn/go-sqlite3 v1.14.9 h1:10HX2Td0ocZpYEjhilsuo6WWtUqttj2Kb0KtD86/KYA=
github.com/mattn/go-sqlite3 v1.14.9/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
github.com/mattn/go-sqlite3 v1.14.10 h1:MLn+5bFRlWMGoSRmJour3CL1w/qL96mvipqpwQW/Sfk=
github.com/mattn/go-sqlite3 v1.14.10/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 h1:OdAsTTz6OkFY5QxjkYwrChwuRruF69c169dPK26NUlk=
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
......@@ -56,8 +58,11 @@ modernc.org/cc/v3 v3.35.8/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g=
modernc.org/cc/v3 v3.35.10/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g=
modernc.org/cc/v3 v3.35.15/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g=
modernc.org/cc/v3 v3.35.16/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g=
modernc.org/cc/v3 v3.35.17 h1:sWWFJxgj2whIJ5P/rzgHalMgpcIhkVSRgiLV0XA7p6Y=
modernc.org/cc/v3 v3.35.17/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g=
modernc.org/cc/v3 v3.35.18/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g=
modernc.org/cc/v3 v3.35.20/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g=
modernc.org/cc/v3 v3.35.22 h1:BzShpwCAP7TWzFppM4k2t03RhXhgYqaibROWkrWq7lE=
modernc.org/cc/v3 v3.35.22/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g=
modernc.org/ccgo/v3 v3.9.5/go.mod h1:umuo2EP2oDSBnD3ckjaVUXMrmeAw8C8OSICVa0iFf60=
modernc.org/ccgo/v3 v3.10.0/go.mod h1:c0yBmkRFi7uW4J7fwx/JiijwOjeAeR2NoSaRVFPmjMw=
modernc.org/ccgo/v3 v3.11.0/go.mod h1:dGNposbDp9TOZ/1KBxghxtUp/bzErD0/0QW4hhSaBMI=
......@@ -87,8 +92,19 @@ modernc.org/ccgo/v3 v3.12.55/go.mod h1:rsXiIyJi9psOwiBkplOaHye5L4MOOaCjHg1Fxkj7I
modernc.org/ccgo/v3 v3.12.56/go.mod h1:ljeFks3faDseCkr60JMpeDb2GSO3TKAmrzm7q9YOcMU=
modernc.org/ccgo/v3 v3.12.57/go.mod h1:hNSF4DNVgBl8wYHpMvPqQWDQx8luqxDnNGCMM4NFNMc=
modernc.org/ccgo/v3 v3.12.60/go.mod h1:k/Nn0zdO1xHVWjPYVshDeWKqbRWIfif5dtsIOCUVMqM=
modernc.org/ccgo/v3 v3.12.65 h1:k2m2owVfoAQ55AnED+M7w7WnEkt0+Z+XY0qpdGOh3gI=
modernc.org/ccgo/v3 v3.12.65/go.mod h1:D6hQtKxPNZiY6wDBtehSGKFKmyXn53F8nGTpH+POmS4=
modernc.org/ccgo/v3 v3.12.66/go.mod h1:jUuxlCFZTUZLMV08s7B1ekHX5+LIAurKTTaugUr/EhQ=
modernc.org/ccgo/v3 v3.12.67/go.mod h1:Bll3KwKvGROizP2Xj17GEGOTrlvB1XcVaBrC90ORO84=
modernc.org/ccgo/v3 v3.12.73/go.mod h1:hngkB+nUUqzOf3iqsM48Gf1FZhY599qzVg1iX+BT3cQ=
modernc.org/ccgo/v3 v3.12.81/go.mod h1:p2A1duHoBBg1mFtYvnhAnQyI6vL0uw5PGYLSIgF6rYY=
modernc.org/ccgo/v3 v3.12.84/go.mod h1:ApbflUfa5BKadjHynCficldU1ghjen84tuM5jRynB7w=
modernc.org/ccgo/v3 v3.12.86/go.mod h1:dN7S26DLTgVSni1PVA3KxxHTcykyDurf3OgUzNqTSrU=
modernc.org/ccgo/v3 v3.12.90/go.mod h1:obhSc3CdivCRpYZmrvO88TXlW0NvoSVvdh/ccRjJYko=
modernc.org/ccgo/v3 v3.12.92/go.mod h1:5yDdN7ti9KWPi5bRVWPl8UNhpEAtCjuEE7ayQnzzqHA=
modernc.org/ccgo/v3 v3.13.1/go.mod h1:aBYVOUfIlcSnrsRVU8VRS35y2DIfpgkmVkYZ0tpIXi4=
modernc.org/ccgo/v3 v3.14.0 h1:Zr1Ny9+7r5yAiXpBdgp8XiXqkNA4ARrRphHGHVXeAp0=
modernc.org/ccgo/v3 v3.14.0/go.mod h1:hBrkiBlUwvr5vV/ZH9YzXIp982jKE8Ek8tR1ytoAL6Q=
modernc.org/ccorpus v1.11.1 h1:K0qPfpVG1MJh5BYazccnmhywH4zHuOgJXgbjzyp6dWA=
modernc.org/ccorpus v1.11.1/go.mod h1:2gEUTrWqdpH2pXsmTM1ZkjeSrUWDpjMu2T6m29L/ErQ=
modernc.org/httpfs v1.0.6 h1:AAgIpFZRXuYnkjftxTAZwMIiwEqAfk8aVB2/oA6nAeM=
modernc.org/httpfs v1.0.6/go.mod h1:7dosgurJGp0sPaRanU53W4xZYKh14wfzX420oZADeHM=
modernc.org/libc v1.9.8/go.mod h1:U1eq8YWr/Kc1RWCMFUWEdkTg8OTcfLw2kY8EDwl039w=
......@@ -120,9 +136,18 @@ modernc.org/libc v1.11.54/go.mod h1:S/FVnskbzVUrjfBqlGFIPA5m7UwB3n9fojHhCNfSsnw=
modernc.org/libc v1.11.55/go.mod h1:j2A5YBRm6HjNkoSs/fzZrSxCuwWqcMYTDPLNx0URn3M=
modernc.org/libc v1.11.56/go.mod h1:pakHkg5JdMLt2OgRadpPOTnyRXm/uzu+Yyg/LSLdi18=
modernc.org/libc v1.11.58/go.mod h1:ns94Rxv0OWyoQrDqMFfWwka2BcaF6/61CqJRK9LP7S8=
modernc.org/libc v1.11.70/go.mod h1:DUOmMYe+IvKi9n6Mycyx3DbjfzSKrdr/0Vgt3j7P5gw=
modernc.org/libc v1.11.71 h1:iF84u92whsBbZG6puONw4En33xL6jGSKnTMoUql1t+w=
modernc.org/libc v1.11.71/go.mod h1:DUOmMYe+IvKi9n6Mycyx3DbjfzSKrdr/0Vgt3j7P5gw=
modernc.org/libc v1.11.75/go.mod h1:dGRVugT6edz361wmD9gk6ax1AbDSe0x5vji0dGJiPT0=
modernc.org/libc v1.11.82/go.mod h1:NF+Ek1BOl2jeC7lw3a7Jj5PWyHPwWD4aq3wVKxqV1fI=
modernc.org/libc v1.11.86/go.mod h1:ePuYgoQLmvxdNT06RpGnaDKJmDNEkV7ZPKI2jnsvZoE=
modernc.org/libc v1.11.87/go.mod h1:Qvd5iXTeLhI5PS0XSyqMY99282y+3euapQFxM7jYnpY=
modernc.org/libc v1.11.88/go.mod h1:h3oIVe8dxmTcchcFuCcJ4nAWaoiwzKCdv82MM0oiIdQ=
modernc.org/libc v1.11.98/go.mod h1:ynK5sbjsU77AP+nn61+k+wxUGRx9rOFcIqWYYMaDZ4c=
modernc.org/libc v1.11.101/go.mod h1:wLLYgEiY2D17NbBOEp+mIJJJBGSiy7fLL4ZrGGZ+8jI=
modernc.org/libc v1.12.0/go.mod h1:2MH3DaF/gCU8i/UBiVE1VFRos4o523M7zipmwH8SIgQ=
modernc.org/libc v1.13.1/go.mod h1:npFeGWjmZTjFeWALQLrvklVmAxv4m80jnG3+xI8FdJk=
modernc.org/libc v1.13.2 h1:GCFjY9bmwDZ/TJC4OZOUWaNgxIxwb104C/QZrqpcVEA=
modernc.org/libc v1.13.2/go.mod h1:npFeGWjmZTjFeWALQLrvklVmAxv4m80jnG3+xI8FdJk=
modernc.org/mathutil v1.1.1/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E=
modernc.org/mathutil v1.2.2/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E=
modernc.org/mathutil v1.4.0/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E=
......@@ -135,9 +160,9 @@ modernc.org/opt v0.1.1 h1:/0RX92k9vwVeDXj+Xn23DKp2VJubL7k8qNffND6qn3A=
modernc.org/opt v0.1.1/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0=
modernc.org/strutil v1.1.1 h1:xv+J1BXY3Opl2ALrBwyfEikFAj8pmqcpnfmuwUwcozs=
modernc.org/strutil v1.1.1/go.mod h1:DE+MQQ/hjKBZS2zNInV5hhcipt5rLPWkmpbGeW5mmdw=
modernc.org/tcl v1.8.13 h1:V0sTNBw0Re86PvXZxuCub3oO9WrSTqALgrwNZNvLFGw=
modernc.org/tcl v1.8.13/go.mod h1:V+q/Ef0IJaNUSECieLU4o+8IScapxnMyFV6i/7uQlAY=
modernc.org/tcl v1.10.0 h1:vux2MNFhSXYqD8Kq4Uc9RjWcgv2c7Atx3da3VpLPPEw=
modernc.org/tcl v1.10.0/go.mod h1:WzWapmP/7dHVhFoyPpEaNSVTL8xtewhouN/cqSJ5A2s=
modernc.org/token v1.0.0 h1:a0jaWiNMDhDUtqOj09wvjWWAqd3q7WpBulmL9H2egsk=
modernc.org/token v1.0.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM=
modernc.org/z v1.2.19 h1:BGyRFWhDVn5LFS5OcX4Yd/MlpRTOc7hOPTdcIpCiUao=
modernc.org/z v1.2.19/go.mod h1:+ZpP0pc4zz97eukOzW3xagV/lS82IpPN9NGG5pNF9vY=
modernc.org/z v1.2.21 h1:UO0ptLQLHM2eNistCE6ofm1fMKKXk0n0IkrQly3z5HA=
modernc.org/z v1.2.21/go.mod h1:uXrObx4pGqXWIMliC5MiKuwAyMrltzwpteOFUP1PWCc=