为了账号安全,请及时绑定邮箱和手机立即绑定

有没有一种有效的方法来回收容量过剩的切片?

有没有一种有效的方法来回收容量过剩的切片?

Go
慕仙森 2021-07-01 09:00:01
我有大量已分配的切片(几百万个)append。我敢肯定,其中很多都超出了产能。我想尝试减少内存使用。我的第一次尝试是迭代所有这些,分配一个新的切片len(oldSlice)并复制值。不幸的是,这似乎会增加内存使用量(最多翻倍),并且垃圾收集回收内存的速度很慢。有没有一种很好的通用方法来减少大量容量过剩的切片的内存使用量?
查看完整描述

2 回答

?
月关宝盒

TA贡献1772条经验 获得超5个赞

如果不知道确切的问题,就很难选择正确的策略来分配缓冲区。


一般来说,您可以尝试重用缓冲区:


type buffer struct{}


var buffers = make(chan *buffer, 1024)


func newBuffer() *buffer {

    select {

    case b:= <-buffers:

        return b

        default:

        return &buffer{}

    }

}


func returnBuffer(b *buffer) {

    select {

    case buffers <- b:

    default:

    }

}


查看完整回答
反对 回复 2021-07-19
?
慕桂英3389331

TA贡献2036条经验 获得超8个赞

中使用的启发式方法append可能不适用于所有应用程序。它专为在您不知道要存储的数据的最终长度时使用而设计。我会尽量减少您分配的额外容量,而不是稍后对其进行迭代。这是一种策略的简单示例,即仅在长度未知时使用缓冲区,并重用该缓冲区:


type buffer struct {

  names []string

  ... // possibly other things

}


// assume this is called frequently and has lots and lots of names

func (b *buffer) readNames(lines bufio.Scanner) ([]string, error) {

  // Start from zero, so we can re-use capacity

  b.names = b.names[:0]


  for lines.Scan() {

    b.names = append(b.names, lines.Text())

  }


  // Figure out the error

  err := lines.Err()

  if err == io.EOF {

    err = nil

  }


  // Allocate a minimal slice

  out := make([]string, len(b.names))

  copy(out, b.names)

  return out, err

}

当然,如果你需要一些可以安全并发使用的东西,你需要修改它;为此,我建议使用缓冲通道作为存储缓冲区的漏桶。


查看完整回答
反对 回复 2021-07-19
  • 2 回答
  • 0 关注
  • 208 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信