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

使用 Echo 或 Gin 框架的大型数组的内存消耗

使用 Echo 或 Gin 框架的大型数组的内存消耗

Go
桃花长相依 2023-06-26 17:09:52
当我尝试用 Echo(还有 Gin)发送一个大数组时,我遇到了内存问题。请求后,内存并未释放。package mainimport (    "net/http"    "strconv"    "github.com/labstack/echo")type User struct {    Username  string    Password  string    Lastname  string    Firstname string}func main() {    e := echo.New()    e.GET("/", func(c echo.Context) error {        var user User        users := make([]User, 0)        for i := 0; i < 100000; i++ {            user = User{                Username:  "ffgfgfghhfghfhgfgfhgfghfghfhgfhgfh" + strconv.Itoa(i),                Password:  "gjgjghjgjhgjhghjfrserhkhjhklljjkbhjvftxersgdghjjkhkljkbhftd",                Lastname:  "njuftydfhgjkjlkjlkjlkhjkhu",                Firstname: "jkggkjkl,,lm,kljkvgf"}            users = append(users, user)        }        defer func() {            users = nil        }()        return c.JSON(http.StatusOK, users)    })    e.Logger.Fatal(e.Start(":1323"))}为了测试,我并行运行请求,得到以下结果:1 个请求:300Mo5 个请求:1.5Go10 个请求:3.1Go更多:我的电脑死机了:)如何减少内存消耗?
查看完整描述

1 回答

?
森林海

TA贡献2011条经验 获得超2个赞

分配的内存不会立即返回给操作系统,

您的答案几乎没有改进,因为您仍在内存中构建(Go)数组(或更确切地说切片),并且一旦完成,您才可以继续将其编组到响应中。您还可以为每个项目创建一个新的编码器,编组单个项目,然后将其丢弃。您可以用来json.Encoder整理多个项目。您还可以在每个项目之后刷新响应,这也是非常低效的。这违背了所有内部缓冲的目的......

相反,您可以在项目 ( User) 准备好后立即对它们进行编组,这样您就不必将所有内容都保留在内存中。并且不要在每个用户之后刷新,最后执行一次就足够了,这是没有必要的,因为一旦您从处理程序返回,服务器将刷新所有缓冲的数据。

这样做:

e.GET("/", func(c echo.Context) error {

    c.Response().WriteHeader(http.StatusOK)


    enc := json.NewEncoder(c.Response())

    for i := 0; i < 100000; i++ {

        user := User{

            Username:  "ffgfgfghhfghfhgfgfhgfghfghfhgfhgfh" + strconv.Itoa(i),

            Password:  "gjgjghjgjhgjhghjfrserhkhjhklljjkbhjvftxersgdghjjkhkljkbhfd",

            Lastname:  "njuftydfhgjkjlkjlkjlkhjkhu",

            Firstname: "jkggkjkl,,lm,kljkvgf",

        }

        if err := enc.Encode(user); err != nil {

            return err

        }

    }


    return nil

})

这里需要注意一点:上面的代码不会将 JSON 数组发送到输出,而是发送一系列 JSON 对象。如果这不适合您并且您确实需要发送单个 JSON 数组,只需“框架”数据并在项目之间插入逗号:


e.GET("/", func(c echo.Context) error {

    resp := c.Response()

    resp.WriteHeader(http.StatusOK)


    if _, err := io.WriteString(resp, "["); err != nil {

        return err

    }

    enc := json.NewEncoder(resp)

    for i := 0; i < 100000; i++ {

        if i > 0 {

            if _, err := io.WriteString(resp, ","); err != nil {

                return err

            }

        }

        user := User{

            Username:  "ffgfgfghhfghfhgfgfhgfghfghfhgfhgfh" + strconv.Itoa(i),

            Password:  "gjgjghjgjhgjhghjfrserhkhjhklljjkbhjvftxersgdghjjkhkljkbhft",

            Lastname:  "njuftydfhgjkjlkjlkjlkhjkhu",

            Firstname: "jkggkjkl,,lm,kljkvgf",

        }

        if err := enc.Encode(user); err != nil {

            return err

        }

    }

    if _, err := io.WriteString(resp, "]"); err != nil {

        return err

    }


    return nil

})


查看完整回答
反对 回复 2023-06-26
  • 1 回答
  • 0 关注
  • 108 浏览
慕课专栏
更多

添加回答

举报

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