瀏覽代碼

Merge pull request #412 from Zariel/massive-gc

Dont allocate all the columninfo upfront
Chris Bannister 10 年之前
父節點
當前提交
2c0294cfd8
共有 2 個文件被更改,包括 34 次插入18 次删除
  1. 32 18
      frame.go
  2. 2 0
      frame_test.go

+ 32 - 18
frame.go

@@ -707,6 +707,25 @@ func (r resultMetadata) String() string {
 	return fmt.Sprintf("[metadata flags=0x%x paging_state=% X columns=%v]", r.flags, r.pagingState, r.columns)
 }
 
+func (f *framer) readCol(col *ColumnInfo, meta *resultMetadata, globalSpec bool, keyspace, table string) {
+	if !globalSpec {
+		col.Keyspace = f.readString()
+		col.Table = f.readString()
+	} else {
+		col.Keyspace = keyspace
+		col.Table = table
+	}
+
+	col.Name = f.readString()
+	col.TypeInfo = f.readTypeInfo()
+	switch v := col.TypeInfo.(type) {
+	// maybe also UDT
+	case TupleTypeInfo:
+		// -1 because we already included the tuple column
+		meta.actualColCount += len(v.Elems) - 1
+	}
+}
+
 func (f *framer) parseResultMetadata() resultMetadata {
 	meta := resultMetadata{
 		flags: f.readInt(),
@@ -730,26 +749,21 @@ func (f *framer) parseResultMetadata() resultMetadata {
 		table = f.readString()
 	}
 
-	cols := make([]ColumnInfo, colCount)
-
-	for i := 0; i < colCount; i++ {
-		col := &cols[i]
-
-		if !globalSpec {
-			col.Keyspace = f.readString()
-			col.Table = f.readString()
-		} else {
-			col.Keyspace = keyspace
-			col.Table = table
+	var cols []ColumnInfo
+	if colCount < 1000 {
+		// preallocate columninfo to avoid excess copying
+		cols = make([]ColumnInfo, colCount)
+		for i := 0; i < colCount; i++ {
+			f.readCol(&cols[i], &meta, globalSpec, keyspace, table)
 		}
 
-		col.Name = f.readString()
-		col.TypeInfo = f.readTypeInfo()
-		switch v := col.TypeInfo.(type) {
-		// maybe also UDT
-		case TupleTypeInfo:
-			// -1 because we already included the tuple column
-			meta.actualColCount += len(v.Elems) - 1
+	} else {
+		// use append, huge number of columns usually indicates a corrupt frame or
+		// just a huge row.
+		for i := 0; i < colCount; i++ {
+			var col ColumnInfo
+			f.readCol(&col, &meta, globalSpec, keyspace, table)
+			cols = append(cols, col)
 		}
 	}
 

+ 2 - 0
frame_test.go

@@ -23,6 +23,8 @@ func TestFuzzBugs(t *testing.T) {
 		[]byte("\x8200\b\x00\x00\x00\b0\x00\x00\x00\x040000"),
 		[]byte("\x8200\x00\x00\x00\x00\x100\x00\x00\x12\x00\x00\x0000000" +
 			"00000"),
+		[]byte("\x83000\b\x00\x00\x00\x14\x00\x00\x00\x020000000" +
+			"000000000"),
 	}
 
 	for i, test := range tests {