首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >通过减少内存占用,高效地将数据解析为结构

通过减少内存占用,高效地将数据解析为结构
EN

Code Review用户
提问于 2022-03-18 00:21:48
回答 1查看 73关注 0票数 3

我有一个简单的程序,在该程序中,我将字节byteSlice反序列化为ClientProduct数组结构。然后我迭代这个ClientProduct数组并为每个ClientProduct构造definitions.CustomerProduct结构。

以下是我的结构细节:

代码语言:javascript
代码运行次数:0
运行
复制
type ProductInfo struct {
    Name map[Locale]map[int]string
}

type Locale string

type CustomerProduct struct {
    Prs            string
    ProductId      int64
    Catalogs       []int32
    Categories     []int
    BaseProductId  *int64
    StatusCode     int
    IsActive       bool
    Common
}

type ValueMetrics struct {
    Value    string
    ClientId int64
}

type Common struct {
    Leagues []ValueMetrics
    Teams   []ValueMetrics
    ProductInfo
}

下面是通过使用byteSlice和其他辅助方法将ClientProduct反序列化为D7数组结构的代码。

代码语言:javascript
代码运行次数:0
运行
复制
var productRows []ClientProduct
err = json.Unmarshal(byteSlice, &productRows)
if err != nil {
  return errs.Wrap(err)
}

for i := range productRows {
  var flatProduct definitions.CustomerProduct
  err = r.Convert(spn, &productRows[i], &flatProduct)
  if err != nil {
    return errs.Wrap(err)
  }

  if flatProduct.StatusCode == definitions.DONE {
    continue
  }

  // populate map here from each "flatProduct"
}

下面是我的Convert方法,它填充了我的CustomerProduct结构。以及帮助填充CustomerProduct结构的其他帮助方法很少。

代码语言:javascript
代码运行次数:0
运行
复制
func (r *clientRepo) Convert(span log.Span, in *ClientProduct, out *definitions.CustomerProduct) error {
    commons, err := r.getCommonStruct(span, in)
    if err != nil {
        return errs.Wrap(err)
    }

    out.Common = commons
    out.Catalogs = r.convertParquetIntSliceToInt32Slice(in.Catalogs)
    out.Categories = in.Categories
    out.ProductId = in.Id
    out.IsActive = in.IsActive
    out.Prs = in.PRS
    out.StatusCode = in.StatusCode

    return nil
}

func (r *clientRepo) getCommonStruct(span log.Span, in *ClientProduct) (definitions.Common, error) {
    out := definitions.Common{}

    for _, pv := range in.PropertyValues {
        switch pv.Name {
        case "ABC":
            out.Leagues = r.concatStringSlice(pv, out.Leagues)
        case "DEF":
            out.Teams = r.concatStringSlice(pv, out.Teams)
        }
    }

    for _, opv := range in.OverriddenPropertyValues {
        switch opv.Name {
        case "CustomerName":
            if opv.Locale == "" {
                // log error
            } else {
                out.Name = r.attach(definitions.Locale(opv.Locale), opv, out.Name)
            }
        }
    }

    return out, nil
}

func (r *clientRepo) concatStringSlice(pv PropertyValue, list []definitions.ValueMetrics) []definitions.ValueMetrics {
    treeValue := definitions.ValueMetrics{Value: pv.Value, ClientId: pv.ClientId}
    if list == nil {
        return []definitions.ValueMetrics{treeValue}
    }
    return append(list, treeValue)
}

func (r *clientRepo) attach(locale definitions.Locale, opv OverriddenPropertyValue, m map[definitions.Locale]map[int]string) map[definitions.Locale]map[int]string {
    if m == nil {
        om := map[int]string{
            opv.GroupId: opv.Value,
        }
        return map[definitions.Locale]map[int]string{
            locale: om,
        }
    }

    os, ok := m[locale]
    if ok {
        os[opv.GroupId] = opv.Value
        m[locale] = os
    } else {
        m[locale] = map[int]string{
            opv.GroupId: opv.Value,
        }
    }

    return m
}

func (r *clientRepo) convertParquetIntSliceToInt32Slice(catalogs []int) []int32 {
    var out []int32
    for _, catalog := range catalogs {
        out = append(out, int32(catalog))
    }
    return out
}

Problem语句

以上代码工作正常。基本上,我在使用所有这些辅助方法填充"CustomerProduct“的方式上寻找代码评审。有什么可以改进的吗?

  • 我正在寻找输入或想法,可以通过使用从CustomerProduct方法开始的所有帮助方法来改进填充Convert结构的方式。
  • 另外,在上面的代码中有什么可以改进的,可以帮助我们的内存占用吗?例如使用指针的引用或传递引用,而不是直接传递。

每当这种反序列化发生时,我就会看到一些内存波动很大,所有这些助手方法都填充了CustomerProduct结构。如有任何指导,将不胜感激。

EN

回答 1

Code Review用户

回答已采纳

发布于 2022-03-18 04:50:26

在开始优化代码之前,重要的是要有一个基准测试。尽管如此,我可以提出一些一般性建议。

  • ProductInfo.Name字段是一个嵌套映射,这需要分配大量的映射。与嵌套映射不同,考虑定义一个struct键类型,类似于类型NameKey struct { Locale GroupID int }类型ProductInfo struct { Name mapstring },那么getCommonStruct可能看起来像func (r *clientRepo) getCommonStruct(span log.Span,in ClientProduct) (definitions.Common,error) { out := definitions.Common{ // Initialize。ProductInfo: definitions.ProductInfo { Name: make(mapstring),},} _,pv := range in.PropertyValues { //此部分相同。.}对于_,opv := range in.OverriddenPropertyValues { switch opv.Name { case "CustomerName":if opv.Locale ==“{.继续} //只设置映射中的值。out.Name = opv.Value }返回,0}
  • 通常,更喜欢传递值而不是指针。这往往会产生更容易阅读和推理的代码。计算机在复制内存方面非常快:)当然,如果基准测试告诉您某个地方的指针更快,可以随意使用。
  • Convert方法可以返回一个CustomerProduct,而不是使用out参数。我还建议使用ClientProduct的值,因为它没有被修改。
  • concatStringSlice帮助程序可以简化,appendnil:func (r *clientRepo) concatStringSlice(pv PropertyValue,list []definitions.ValueMetrics) []definitions.ValueMetrics {返回追加(list,definitions.ValueMetrics{Value: pv.Value,ClientId: pv.ClientId})上工作得很好。
  • convertParquetIntSliceToInt32Slice中,可以将out预先分配到适当的大小: func (r *clientRepo) convertParquetIntSliceToInt32Slice( catalog []int) []int32 { out := make([]int32,0,len( _ )),catalog := range目录{ out = append( out,int32(catalog)) }返回}

对不起,打字太晚了:)

票数 2
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/275038

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档