Skip to content
This repository was archived by the owner on Jan 28, 2021. It is now read-only.

Commit 95d9aae

Browse files
committed
sql: implement memory management system for caches
This PR implements a memory management system, intended to have control over the allocated memory for caches so that they can be freed at any moment and we can avoid out of memory errors. The main changes are the following: - MemoryManager in the sql package, which is just the component that tracks all caches. Memory of all freeable caches can be freed using the Free method of this component. The only way to instantiate new caches is using the NewXXXCache methods. - Rows, history and LRU cache implementations, accessed using the NewXXXCache methods of MemoryManager. - Reporters, which is a component that reports the maximum amount of memory the program is allowed to use and the currently used memory. This interface is meant for making testing easier. There is a default ProcessMemory reporter that returns the memory used by the process and the maximum memory defined in the `MAX_MEMORY` environment variable. - MemoryManager is passed down to every component through *sql.Context, which meant a little more boilerplate on the server SessionBuilder. - GroupBy, Sort, Distinct and Join now use the provided APIs of memory and cache management for their in-memory computations. Caveats: - We need to think of a good default so that memory usage won't grow forever and crash eventually, which is the behaviour when MAX_MEMORY is 0. Signed-off-by: Miguel Molina <[email protected]>
1 parent 875590d commit 95d9aae

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

69 files changed

+1061
-434
lines changed

README.md

+4-5
Original file line numberDiff line numberDiff line change
@@ -141,8 +141,7 @@ SET <variable name> = <value>
141141
|:-----|:-----|:------------|
142142
|`INMEMORY_JOINS`|environment|If set it will perform all joins in memory. Default is off.|
143143
|`inmemory_joins`|session|If set it will perform all joins in memory. Default is off. This has precedence over `INMEMORY_JOINS`.|
144-
|`MAX_MEMORY_JOIN`|environment|The maximum number of memory, in megabytes, that can be consumed by go-mysql-server before switching to multipass mode in joins. Default is the 20% of all available physical memory.|
145-
|`max_memory_joins`|session|The maximum number of memory, in megabytes, that can be consumed by go-mysql-server before switching to multipass mode in joins. Default is the 20% of all available physical memory. This has precedence over `MAX_MEMORY_JOIN`.|
144+
|`MAX_MEMORY`|environment|The maximum number of memory, in megabytes, that can be consumed by go-mysql-server. Any in-memory caches or computations will no longer try to use memory when the limit is reached. Note that this may cause certain queries to fail if there is not enough memory available, such as queries using DISTINCT, ORDER BY or GROUP BY with groupings.|
146145
|`DEBUG_ANALYZER`|environment|If set, the analyzer will print debug messages. Default is off.|
147146
|`PILOSA_INDEX_THREADS`|environment|Number of threads used in index creation. Default is the number of cores available in the machine.|
148147
|`pilosa_index_threads`|environment|Number of threads used in index creation. Default is the number of cores available in the machine. This has precedence over `PILOSA_INDEX_THREADS`.|
@@ -176,14 +175,14 @@ func main() {
176175
s.Start()
177176
}
178177

179-
func createTestDatabase() *mem.Database {
178+
func createTestDatabase() *memory.Database {
180179
const (
181180
dbName = "test"
182181
tableName = "mytable"
183182
)
184183

185-
db := mem.NewDatabase(dbName)
186-
table := mem.NewTable(tableName, sql.Schema{
184+
db := memory.NewDatabase(dbName)
185+
table := memory.NewTable(tableName, sql.Schema{
187186
{Name: "name", Type: sql.Text, Nullable: false, Source: tableName},
188187
{Name: "email", Type: sql.Text, Nullable: false, Source: tableName},
189188
{Name: "phone_numbers", Type: sql.JSON, Nullable: false, Source: tableName},

_example/main.go

-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import (
55

66
sqle "github.com/src-d/go-mysql-server"
77
"github.com/src-d/go-mysql-server/auth"
8-
"github.com/src-d/go-mysql-server/mem"
98
"github.com/src-d/go-mysql-server/server"
109
"github.com/src-d/go-mysql-server/sql"
1110
)

auth/common_test.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import (
1111
"github.com/stretchr/testify/require"
1212
sqle "github.com/src-d/go-mysql-server"
1313
"github.com/src-d/go-mysql-server/auth"
14-
"github.com/src-d/go-mysql-server/mem"
14+
"github.com/src-d/go-mysql-server/memory"
1515
"github.com/src-d/go-mysql-server/server"
1616
"github.com/src-d/go-mysql-server/sql"
1717
"github.com/src-d/go-mysql-server/sql/analyzer"
@@ -21,13 +21,13 @@ import (
2121
const port = 3336
2222

2323
func authEngine(au auth.Auth) (string, *sqle.Engine, error) {
24-
db := mem.NewDatabase("test")
24+
db := memory.NewDatabase("test")
2525
catalog := sql.NewCatalog()
2626
catalog.AddDatabase(db)
2727

2828
tblName := "test"
2929

30-
table := mem.NewTable(tblName, sql.Schema{
30+
table := memory.NewTable(tblName, sql.Schema{
3131
{Name: "id", Type: sql.Text, Nullable: false, Source: tblName},
3232
{Name: "name", Type: sql.Text, Nullable: false, Source: tblName},
3333
})

benchmark/tpc_h_test.go

+5-5
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,9 @@ import (
1010
"path/filepath"
1111
"testing"
1212

13-
"github.com/src-d/go-mysql-server"
13+
sqle "github.com/src-d/go-mysql-server"
1414

15-
"github.com/src-d/go-mysql-server/mem"
15+
"github.com/src-d/go-mysql-server/memory"
1616
"github.com/src-d/go-mysql-server/sql"
1717
)
1818

@@ -83,11 +83,11 @@ func executeQueries(b *testing.B, e *sqle.Engine) error {
8383
}
8484

8585
func genDB(b *testing.B) (sql.Database, error) {
86-
db := mem.NewDatabase("tpch")
86+
db := memory.NewDatabase("tpch")
8787

8888
for _, m := range tpchTableMetadata {
8989
b.Log("generating table", m.name)
90-
t := mem.NewTable(m.name, m.schema)
90+
t := memory.NewTable(m.name, m.schema)
9191
if err := insertDataToTable(m.name, t, len(m.schema)); err != nil {
9292
return nil, err
9393
}
@@ -98,7 +98,7 @@ func genDB(b *testing.B) (sql.Database, error) {
9898
return db, nil
9999
}
100100

101-
func insertDataToTable(name string, t *mem.Table, columnCount int) error {
101+
func insertDataToTable(name string, t *memory.Table, columnCount int) error {
102102
f, err := os.Open(name + ".tbl")
103103
if err != nil {
104104
return err

engine_test.go

+36-36
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import (
1313

1414
sqle "github.com/src-d/go-mysql-server"
1515
"github.com/src-d/go-mysql-server/auth"
16-
"github.com/src-d/go-mysql-server/mem"
16+
"github.com/src-d/go-mysql-server/memory"
1717
"github.com/src-d/go-mysql-server/sql"
1818
"github.com/src-d/go-mysql-server/sql/analyzer"
1919
"github.com/src-d/go-mysql-server/sql/index/pilosa"
@@ -1775,7 +1775,7 @@ const testNumPartitions = 5
17751775
func TestAmbiguousColumnResolution(t *testing.T) {
17761776
require := require.New(t)
17771777

1778-
table := mem.NewPartitionedTable("foo", sql.Schema{
1778+
table := memory.NewPartitionedTable("foo", sql.Schema{
17791779
{Name: "a", Type: sql.Int64, Source: "foo"},
17801780
{Name: "b", Type: sql.Text, Source: "foo"},
17811781
}, testNumPartitions)
@@ -1787,7 +1787,7 @@ func TestAmbiguousColumnResolution(t *testing.T) {
17871787
sql.NewRow(int64(3), "baz"),
17881788
)
17891789

1790-
table2 := mem.NewPartitionedTable("bar", sql.Schema{
1790+
table2 := memory.NewPartitionedTable("bar", sql.Schema{
17911791
{Name: "b", Type: sql.Text, Source: "bar"},
17921792
{Name: "c", Type: sql.Int64, Source: "bar"},
17931793
}, testNumPartitions)
@@ -1798,7 +1798,7 @@ func TestAmbiguousColumnResolution(t *testing.T) {
17981798
sql.NewRow("pux", int64(1)),
17991799
)
18001800

1801-
db := mem.NewDatabase("mydb")
1801+
db := memory.NewDatabase("mydb")
18021802
db.AddTable("foo", table)
18031803
db.AddTable("bar", table2)
18041804

@@ -1865,7 +1865,7 @@ func TestDDL(t *testing.T) {
18651865
func TestNaturalJoin(t *testing.T) {
18661866
require := require.New(t)
18671867

1868-
t1 := mem.NewPartitionedTable("t1", sql.Schema{
1868+
t1 := memory.NewPartitionedTable("t1", sql.Schema{
18691869
{Name: "a", Type: sql.Text, Source: "t1"},
18701870
{Name: "b", Type: sql.Text, Source: "t1"},
18711871
{Name: "c", Type: sql.Text, Source: "t1"},
@@ -1878,7 +1878,7 @@ func TestNaturalJoin(t *testing.T) {
18781878
sql.NewRow("a_3", "b_3", "c_3"),
18791879
)
18801880

1881-
t2 := mem.NewPartitionedTable("t2", sql.Schema{
1881+
t2 := memory.NewPartitionedTable("t2", sql.Schema{
18821882
{Name: "a", Type: sql.Text, Source: "t2"},
18831883
{Name: "b", Type: sql.Text, Source: "t2"},
18841884
{Name: "d", Type: sql.Text, Source: "t2"},
@@ -1891,7 +1891,7 @@ func TestNaturalJoin(t *testing.T) {
18911891
sql.NewRow("a_3", "b_3", "d_3"),
18921892
)
18931893

1894-
db := mem.NewDatabase("mydb")
1894+
db := memory.NewDatabase("mydb")
18951895
db.AddTable("t1", t1)
18961896
db.AddTable("t2", t2)
18971897

@@ -1917,7 +1917,7 @@ func TestNaturalJoin(t *testing.T) {
19171917
func TestNaturalJoinEqual(t *testing.T) {
19181918
require := require.New(t)
19191919

1920-
t1 := mem.NewPartitionedTable("t1", sql.Schema{
1920+
t1 := memory.NewPartitionedTable("t1", sql.Schema{
19211921
{Name: "a", Type: sql.Text, Source: "t1"},
19221922
{Name: "b", Type: sql.Text, Source: "t1"},
19231923
{Name: "c", Type: sql.Text, Source: "t1"},
@@ -1930,7 +1930,7 @@ func TestNaturalJoinEqual(t *testing.T) {
19301930
sql.NewRow("a_3", "b_3", "c_3"),
19311931
)
19321932

1933-
t2 := mem.NewPartitionedTable("t2", sql.Schema{
1933+
t2 := memory.NewPartitionedTable("t2", sql.Schema{
19341934
{Name: "a", Type: sql.Text, Source: "t2"},
19351935
{Name: "b", Type: sql.Text, Source: "t2"},
19361936
{Name: "c", Type: sql.Text, Source: "t2"},
@@ -1943,7 +1943,7 @@ func TestNaturalJoinEqual(t *testing.T) {
19431943
sql.NewRow("a_3", "b_3", "c_3"),
19441944
)
19451945

1946-
db := mem.NewDatabase("mydb")
1946+
db := memory.NewDatabase("mydb")
19471947
db.AddTable("t1", t1)
19481948
db.AddTable("t2", t2)
19491949

@@ -1969,7 +1969,7 @@ func TestNaturalJoinEqual(t *testing.T) {
19691969
func TestNaturalJoinDisjoint(t *testing.T) {
19701970
require := require.New(t)
19711971

1972-
t1 := mem.NewPartitionedTable("t1", sql.Schema{
1972+
t1 := memory.NewPartitionedTable("t1", sql.Schema{
19731973
{Name: "a", Type: sql.Text, Source: "t1"},
19741974
}, testNumPartitions)
19751975

@@ -1980,7 +1980,7 @@ func TestNaturalJoinDisjoint(t *testing.T) {
19801980
sql.NewRow("a3"),
19811981
)
19821982

1983-
t2 := mem.NewPartitionedTable("t2", sql.Schema{
1983+
t2 := memory.NewPartitionedTable("t2", sql.Schema{
19841984
{Name: "b", Type: sql.Text, Source: "t2"},
19851985
}, testNumPartitions)
19861986
insertRows(
@@ -1990,7 +1990,7 @@ func TestNaturalJoinDisjoint(t *testing.T) {
19901990
sql.NewRow("b3"),
19911991
)
19921992

1993-
db := mem.NewDatabase("mydb")
1993+
db := memory.NewDatabase("mydb")
19941994
db.AddTable("t1", t1)
19951995
db.AddTable("t2", t2)
19961996

@@ -2022,7 +2022,7 @@ func TestNaturalJoinDisjoint(t *testing.T) {
20222022
func TestInnerNestedInNaturalJoins(t *testing.T) {
20232023
require := require.New(t)
20242024

2025-
table1 := mem.NewPartitionedTable("table1", sql.Schema{
2025+
table1 := memory.NewPartitionedTable("table1", sql.Schema{
20262026
{Name: "i", Type: sql.Int32, Source: "table1"},
20272027
{Name: "f", Type: sql.Float64, Source: "table1"},
20282028
{Name: "t", Type: sql.Text, Source: "table1"},
@@ -2035,7 +2035,7 @@ func TestInnerNestedInNaturalJoins(t *testing.T) {
20352035
sql.NewRow(int32(10), float64(2.1), "table1"),
20362036
)
20372037

2038-
table2 := mem.NewPartitionedTable("table2", sql.Schema{
2038+
table2 := memory.NewPartitionedTable("table2", sql.Schema{
20392039
{Name: "i2", Type: sql.Int32, Source: "table2"},
20402040
{Name: "f2", Type: sql.Float64, Source: "table2"},
20412041
{Name: "t2", Type: sql.Text, Source: "table2"},
@@ -2048,7 +2048,7 @@ func TestInnerNestedInNaturalJoins(t *testing.T) {
20482048
sql.NewRow(int32(20), float64(2.2), "table2"),
20492049
)
20502050

2051-
table3 := mem.NewPartitionedTable("table3", sql.Schema{
2051+
table3 := memory.NewPartitionedTable("table3", sql.Schema{
20522052
{Name: "i", Type: sql.Int32, Source: "table3"},
20532053
{Name: "f2", Type: sql.Float64, Source: "table3"},
20542054
{Name: "t3", Type: sql.Text, Source: "table3"},
@@ -2061,7 +2061,7 @@ func TestInnerNestedInNaturalJoins(t *testing.T) {
20612061
sql.NewRow(int32(30), float64(2.2), "table3"),
20622062
)
20632063

2064-
db := mem.NewDatabase("mydb")
2064+
db := memory.NewDatabase("mydb")
20652065
db.AddTable("table1", table1)
20662066
db.AddTable("table2", table2)
20672067
db.AddTable("table3", table3)
@@ -2114,7 +2114,7 @@ func newEngine(t *testing.T) *sqle.Engine {
21142114
}
21152115

21162116
func newEngineWithParallelism(t *testing.T, parallelism int) *sqle.Engine {
2117-
table := mem.NewPartitionedTable("mytable", sql.Schema{
2117+
table := memory.NewPartitionedTable("mytable", sql.Schema{
21182118
{Name: "i", Type: sql.Int64, Source: "mytable"},
21192119
{Name: "s", Type: sql.Text, Source: "mytable"},
21202120
}, testNumPartitions)
@@ -2126,7 +2126,7 @@ func newEngineWithParallelism(t *testing.T, parallelism int) *sqle.Engine {
21262126
sql.NewRow(int64(3), "third row"),
21272127
)
21282128

2129-
table2 := mem.NewPartitionedTable("othertable", sql.Schema{
2129+
table2 := memory.NewPartitionedTable("othertable", sql.Schema{
21302130
{Name: "s2", Type: sql.Text, Source: "othertable"},
21312131
{Name: "i2", Type: sql.Int64, Source: "othertable"},
21322132
}, testNumPartitions)
@@ -2138,7 +2138,7 @@ func newEngineWithParallelism(t *testing.T, parallelism int) *sqle.Engine {
21382138
sql.NewRow("third", int64(1)),
21392139
)
21402140

2141-
table3 := mem.NewPartitionedTable("tabletest", sql.Schema{
2141+
table3 := memory.NewPartitionedTable("tabletest", sql.Schema{
21422142
{Name: "i", Type: sql.Int32, Source: "tabletest"},
21432143
{Name: "s", Type: sql.Text, Source: "tabletest"},
21442144
}, testNumPartitions)
@@ -2150,7 +2150,7 @@ func newEngineWithParallelism(t *testing.T, parallelism int) *sqle.Engine {
21502150
sql.NewRow(int64(3), "third row"),
21512151
)
21522152

2153-
table4 := mem.NewPartitionedTable("other_table", sql.Schema{
2153+
table4 := memory.NewPartitionedTable("other_table", sql.Schema{
21542154
{Name: "text", Type: sql.Text, Source: "tabletest"},
21552155
{Name: "number", Type: sql.Int32, Source: "tabletest"},
21562156
}, testNumPartitions)
@@ -2162,7 +2162,7 @@ func newEngineWithParallelism(t *testing.T, parallelism int) *sqle.Engine {
21622162
sql.NewRow("c", int32(0)),
21632163
)
21642164

2165-
bigtable := mem.NewPartitionedTable("bigtable", sql.Schema{
2165+
bigtable := memory.NewPartitionedTable("bigtable", sql.Schema{
21662166
{Name: "t", Type: sql.Text, Source: "bigtable"},
21672167
{Name: "n", Type: sql.Int64, Source: "bigtable"},
21682168
}, testNumPartitions)
@@ -2185,7 +2185,7 @@ func newEngineWithParallelism(t *testing.T, parallelism int) *sqle.Engine {
21852185
sql.NewRow("b", int64(9)),
21862186
)
21872187

2188-
floatTable := mem.NewPartitionedTable("floattable", sql.Schema{
2188+
floatTable := memory.NewPartitionedTable("floattable", sql.Schema{
21892189
{Name: "i", Type: sql.Int64, Source: "floattable"},
21902190
{Name: "f32", Type: sql.Float32, Source: "floattable"},
21912191
{Name: "f64", Type: sql.Float64, Source: "floattable"},
@@ -2201,7 +2201,7 @@ func newEngineWithParallelism(t *testing.T, parallelism int) *sqle.Engine {
22012201
sql.NewRow(-2, float32(-1.5), float64(-1.5)),
22022202
)
22032203

2204-
nilTable := mem.NewPartitionedTable("niltable", sql.Schema{
2204+
nilTable := memory.NewPartitionedTable("niltable", sql.Schema{
22052205
{Name: "i", Type: sql.Int64, Source: "niltable", Nullable: true},
22062206
{Name: "b", Type: sql.Boolean, Source: "niltable", Nullable: true},
22072207
{Name: "f", Type: sql.Float64, Source: "niltable", Nullable: true},
@@ -2216,15 +2216,15 @@ func newEngineWithParallelism(t *testing.T, parallelism int) *sqle.Engine {
22162216
sql.NewRow(nil, nil, nil),
22172217
)
22182218

2219-
db := mem.NewDatabase("mydb")
2219+
db := memory.NewDatabase("mydb")
22202220
db.AddTable("mytable", table)
22212221
db.AddTable("othertable", table2)
22222222
db.AddTable("tabletest", table3)
22232223
db.AddTable("bigtable", bigtable)
22242224
db.AddTable("floattable", floatTable)
22252225
db.AddTable("niltable", nilTable)
22262226

2227-
db2 := mem.NewDatabase("foo")
2227+
db2 := memory.NewDatabase("foo")
22282228
db2.AddTable("other_table", table4)
22292229

22302230
catalog := sql.NewCatalog()
@@ -2488,7 +2488,7 @@ func TestCreateIndex(t *testing.T) {
24882488
func TestOrderByGroupBy(t *testing.T) {
24892489
require := require.New(t)
24902490

2491-
table := mem.NewPartitionedTable("members", sql.Schema{
2491+
table := memory.NewPartitionedTable("members", sql.Schema{
24922492
{Name: "id", Type: sql.Int64, Source: "members"},
24932493
{Name: "team", Type: sql.Text, Source: "members"},
24942494
}, testNumPartitions)
@@ -2503,7 +2503,7 @@ func TestOrderByGroupBy(t *testing.T) {
25032503
sql.NewRow(int64(8), "purple"),
25042504
)
25052505

2506-
db := mem.NewDatabase("db")
2506+
db := memory.NewDatabase("db")
25072507
db.AddTable("members", table)
25082508

25092509
e := sqle.NewDefault()
@@ -2583,12 +2583,12 @@ func TestTracing(t *testing.T) {
25832583
func TestReadOnly(t *testing.T) {
25842584
require := require.New(t)
25852585

2586-
table := mem.NewPartitionedTable("mytable", sql.Schema{
2586+
table := memory.NewPartitionedTable("mytable", sql.Schema{
25872587
{Name: "i", Type: sql.Int64, Source: "mytable"},
25882588
{Name: "s", Type: sql.Text, Source: "mytable"},
25892589
}, testNumPartitions)
25902590

2591-
db := mem.NewDatabase("mydb")
2591+
db := memory.NewDatabase("mydb")
25922592
db.AddTable("mytable", table)
25932593

25942594
catalog := sql.NewCatalog()
@@ -2689,11 +2689,11 @@ func TestUse(t *testing.T) {
26892689
func TestLocks(t *testing.T) {
26902690
require := require.New(t)
26912691

2692-
t1 := newLockableTable(mem.NewTable("t1", nil))
2693-
t2 := newLockableTable(mem.NewTable("t2", nil))
2694-
t3 := mem.NewTable("t3", nil)
2692+
t1 := newLockableTable(memory.NewTable("t1", nil))
2693+
t2 := newLockableTable(memory.NewTable("t2", nil))
2694+
t3 := memory.NewTable("t3", nil)
26952695
catalog := sql.NewCatalog()
2696-
db := mem.NewDatabase("db")
2696+
db := memory.NewDatabase("db")
26972697
db.AddTable("t1", t1)
26982698
db.AddTable("t2", t2)
26992699
db.AddTable("t3", t3)
@@ -2789,7 +2789,7 @@ var generatorQueries = []struct {
27892789
}
27902790

27912791
func TestGenerators(t *testing.T) {
2792-
table := mem.NewPartitionedTable("t", sql.Schema{
2792+
table := memory.NewPartitionedTable("t", sql.Schema{
27932793
{Name: "a", Type: sql.Int64, Source: "t"},
27942794
{Name: "b", Type: sql.Array(sql.Text), Source: "t"},
27952795
{Name: "c", Type: sql.Text, Source: "t"},
@@ -2802,7 +2802,7 @@ func TestGenerators(t *testing.T) {
28022802
sql.NewRow(int64(3), []interface{}{"e", "f"}, "third"),
28032803
)
28042804

2805-
db := mem.NewDatabase("db")
2805+
db := memory.NewDatabase("db")
28062806
db.AddTable("t", table)
28072807

28082808
catalog := sql.NewCatalog()

0 commit comments

Comments
 (0)