Лучший способ добавить в большой массив с неизвестной длиной - PullRequest
0 голосов
/ 02 марта 2019

Есть несколько способов добавить массив.Хотите знать, существует ли лучший способ добавления огромного массива (100 МБ) с неизвестной длиной?Я хочу избежать копирования, так как это увеличивает шансы исчерпать память и ухудшит производительность.Стоит ли использовать двумерные массивы?

Ответы [ 2 ]

0 голосов
/ 02 марта 2019

В Голанге у нас есть массив и срез.


Массивы имеют фиксированный размер, когда вам нужно больше места, вам нужно создать больший массив, скопируйте все значения из старого массива и замените старую ссылку новым массивом.

Не следует хранить ссылку на старый массив, поэтому эта память будет собираться мусором.


В качестве альтернативы, вы можете использовать кусочки (которые являются оберткой над массивом).Изменение размера и копирование будет сделано для вас автоматически.
Вы также можете контролировать изменение размера вручную, это может уменьшить GC.Но его следует профилировать и сравнивать со срезами.

Я добавил пример с сохранением в многомерном массиве, я настоятельно рекомендую избегать такого подхода.Это сделает обход более сложным и медленным, высокую вероятность утечек памяти и многое другое.GC в Голанге очень быстр.

BenchmarkStore/array-6            100000         20090 ns/op           0 B/op          0 allocs/op
BenchmarkStore/slice-6              5000        259940 ns/op     4654337 B/op         30 allocs/op
BenchmarkStore/Custom-6            10000        194152 ns/op     1747860 B/op          8 allocs/op
BenchmarkStore/Dimensions-6         3000        418654 ns/op     4458593 B/op         20 allocs/op
package main

import (
    "testing"
)

const size = 100000

// Wrapper around slice
type MyStore struct {
    growthFactor int
    watermark    int
    Data         []int
}

func NewMyStore(growthFactor, initialSize int) *MyStore {
    return &MyStore{growthFactor: growthFactor, watermark: -1, Data: make([]int, initialSize)}
}

func (s *MyStore) Append(v int) {
    nextPosition := s.watermark + 1
    currentSize := len(s.Data)
    full := currentSize == nextPosition
    if full {
        dataResize := make([]int, currentSize*s.growthFactor)
        copy(dataResize, s.Data)
        s.Data = dataResize
    }

    s.Data[nextPosition] = v
    s.watermark = nextPosition
}

// Dimensions
const chunkSize = 10
type MyStoreMultiDimensions struct {
    size      int
    watermark int
    data      [][chunkSize]int
}

func NewStoreMultiDimensions(chunks int) *MyStoreMultiDimensions {
    return &MyStoreMultiDimensions{watermark: -1, data: make([][chunkSize]int, chunks)}
}

func (s *MyStoreMultiDimensions) Append(v int) {
    nextPosition := s.watermark + 1
    chunk := nextPosition / chunkSize
    if len(s.data) <= chunk {
        s.data = append(s.data, [chunkSize]int{})
    }

    s.data[chunk][nextPosition%chunkSize] = v
    s.watermark = nextPosition
}

func BenchmarkStore(b *testing.B) {
    b.Run("array", func(b2 *testing.B) {
        for i := 0; i < b2.N; i++ {
            var store [size]int
            for item := 0; item < size; item++ {
                store[item] = item
            }
        }
    })
    b.Run("slice", func(b2 *testing.B) {
        for i := 0; i < b2.N; i++ {
            var store []int
            for item := 0; item < size; item++ {
                store = append(store, item)
            }
        }
    })
    b.Run("Custom", func(b2 *testing.B) {
        for i := 0; i < b2.N; i++ {
            var store = NewMyStore(4, 10)
            for item := 0; item < size; item++ {
                store.Append(item)
            }
        }
    })
    b.Run("Dimensions", func(b2 *testing.B) {
        for i := 0; i < b2.N; i++ {
            var store = NewStoreMultiDimensions(2)
            for item := 0; item < size; item++ {
                store.Append(item)
            }
        }
    })
}
0 голосов
/ 02 марта 2019

По моему мнению, вы должны рассмотреть возможность использования ArrayList вместо массива.Затем вы можете использовать add () ArrayList для добавления новых элементов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...