// NewRowContainer allocates a new row container. // // The acc argument indicates where to register memory allocations by // this row container. Should probably be created by // Session.makeSessionBoundAccount() or Session.makeTxnBoundAccount(). // // The rowCapacity argument indicates how many rows are to be // expected; it is used to pre-allocate the outer array of row // references, in the fashion of Go's capacity argument to the make() // function. // // Note that we could, but do not (yet), report the size of the row // container itself to the monitor in this constructor. This is // because the various planNodes are not (yet) equipped to call // Close() upon encountering errors in their constructor (all nodes // initializing a RowContainer there) and SetLimitHint() (for sortNode // which initializes a RowContainer there). This would be rather // error-prone to implement consistently and hellishly difficult to // test properly. The trade-off is that very large table schemas or // column selections could cause unchecked and potentially dangerous // memory growth. func (p *planner) NewRowContainer( acc mon.BoundAccount, h ResultColumns, rowCapacity int, ) *RowContainer { nCols := len(h) res := &RowContainer{ rows: make([]parser.DTuple, 0, rowCapacity), numCols: nCols, varSizedColumns: make([]int, 0, nCols), memAcc: acc, } for i := 0; i < nCols; i++ { sz, variable := h[i].Typ.Size() if variable { res.varSizedColumns = append(res.varSizedColumns, i) } else { res.fixedColsSize += int64(sz) } } res.fixedColsSize += int64(unsafe.Sizeof(parser.Datum(nil)) * uintptr(nCols)) return res }
// NewRowContainer allocates a new row container. // // The acc argument indicates where to register memory allocations by // this row container. Should probably be created by // Session.makeBoundAccount() or Session.TxnState.makeBoundAccount(). // // The rowCapacity argument indicates how many rows are to be // expected; it is used to pre-allocate the outer array of row // references, in the fashion of Go's capacity argument to the make() // function. // // Note that we could, but do not (yet), report the size of the row // container itself to the monitor in this constructor. This is // because the various planNodes are not (yet) equipped to call // Close() upon encountering errors in their constructor (all nodes // initializing a RowContainer there) and SetLimitHint() (for sortNode // which initializes a RowContainer there). This would be rather // error-prone to implement consistently and hellishly difficult to // test properly. The trade-off is that very large table schemas or // column selections could cause unchecked and potentially dangerous // memory growth. func NewRowContainer(acc mon.BoundAccount, h ResultColumns, rowCapacity int) *RowContainer { nCols := len(h) c := &RowContainer{ numCols: nCols, memAcc: acc, preallocChunks: 1, } if nCols != 0 { c.rowsPerChunk = (targetChunkSize + nCols - 1) / nCols if rowCapacity > 0 { c.preallocChunks = (rowCapacity + c.rowsPerChunk - 1) / c.rowsPerChunk } } for i := 0; i < nCols; i++ { sz, variable := h[i].Typ.Size() if variable { if c.varSizedColumns == nil { // Only allocate varSizedColumns if necessary. c.varSizedColumns = make([]int, 0, nCols) } c.varSizedColumns = append(c.varSizedColumns, i) } else { c.fixedColsSize += int64(sz) } } // Precalculate the memory used for a chunk, specifically by the Datums in the // chunk and the slice pointing at the chunk. c.chunkMemSize = int64(unsafe.Sizeof(parser.Datum(nil))) * int64(c.rowsPerChunk*c.numCols) c.chunkMemSize += int64(unsafe.Sizeof([]parser.Datum(nil))) return c }
// Author: Irfan Sharif ([email protected]) package sql import ( "fmt" "unsafe" "github.com/cockroachdb/cockroach/pkg/sql/mon" "github.com/cockroachdb/cockroach/pkg/sql/parser" ) const ( // targetChunkSize is the target number of Datums in a RowContainer chunk. targetChunkSize = 64 sizeOfDatum = int64(unsafe.Sizeof(parser.Datum(nil))) sizeOfDTuple = int64(unsafe.Sizeof(parser.DTuple(nil))) ) // RowContainer is a container for rows of DTuples which tracks the // approximate amount of memory allocated for row data. // Rows must be added using AddRow(); once the work is done // the Close() method must be called to release the allocated memory. // // TODO(knz): this does not currently track the amount of memory used // for the outer array of DTuple references. type RowContainer struct { numCols int // rowsPerChunk is the number of rows in a chunk; we pack multiple rows in a // single []Datum to reduce the overhead of the slice if we have few columns.