Go Slice vs Map

Source: Internet
Author: User
This is a creation in Article, where the information may have evolved or changed. Slice and Map are two important data types in Go. This article will document some of my key findings about the performance of these two data structures. Before we discuss performance, let's take a brief look at Slice and Map. **slice:**slice is an abstract data structure built on top of an array. Slice has a pointer to the beginning of the array, an array length, and the maximum capacity that Slice can use for that array. Slice can grow or shrink as needed. The growth of Slice typically involves reallocating memory for the underlying array. Functions such as copy and append can help to grow the array. Maps in **map:**go are similar to other languages (internal implementations may vary). The Map in Go creates buckets (each bucket can hold 8 keys). * * Performance Statistics: * * I have some benchmarks for both of these data structures, and the results are documented below. **test-1**: Find a  **INT**  element in Slice vs find an element in map-here, we try to find an element in a Slice of length n and compare it to the key lookup in map. To find an element in Slice, we will traverse the Slice and then perform a simple ' if ' to examine the element. As for the MAP, we simply find the key. In all the tests, I looked for the worst case scenario. Total Sample | Len_size (n) | F (n)-[]int (O (n))-For loop and if (find last Element) | Map[int]int Direct Find O (1)---|---|---|---2 million | 5 | 5.42 Ns/op | 12.7 Ns/op 2 million | 10 | 8.19 Ns/op | 17.8 Ns/op 2 million | 100 | 63.3 Ns/op | 16.5 Ns/op 2 million | 200 | 118 Ns/op | 16.6 Ns/op 2 million | 400 | 228 Ns/op | 18.4 Ns/op 2 million | 1000 | 573 Ns/op | 17.0 Ns/op 2 million | 10000 | 5674 Ns/op | 17.6 Ns/op 2 million | 100000 | 55141Ns/op | 15.1 Ns/op as you can see (unsurprisingly), for different n,map lookups are constant complexity (O (1)). Interestingly, however, for n smaller Slice, simple _for loops and if_ are less time consuming than MAP. The larger n is as expected to take more time. [11.png] (https://boltandnuts.files.wordpress.com/2017/11/11.png) * * Conclusion: For finding a given key, I recommend using MAP. For a smaller size (n), using Slice is still possible. test-2**: Finding a  **STRING**  element in Slice vs. finding a string key in a Map-the steps we take are exactly the same as TEST-1, where the only difference is that we use strings (string). Total Sample | Len-size (n) | f (n) []string [For Loop and if (find last element)] | F (n) map[string]string---|---|---|---2 million | 5 | 30.4 Ns/op | 32.7 Ns/op 2 million | 10 | 56.5 Ns/op | 23.5 Ns/op 2 million | 100 | Ns/op | 25.7 Ns/op 2 million | 200 | 665 Ns/op | 23.6 Ns/op 2 million | 400 | 1766 Ns/op | 23.7 Ns/op 2 million | 1000 | 905 Ns/op | 25.7 Ns/op 2 million | 10000 | 8488 Ns/op | 24.4 Ns/op 2 million | 100000 | 82444 Ns/op | 25.9 Ns/op from the above data, we see that given a key, look for a string (using Map) with O (1) complexity. For string comparisons, Map beats Slice. [2.png] (https://boltandnuts.files.wordpress.com/2017/11/2.png) * * Conclusion: Given a string type of key to find, I recommend using MAP. Even for smaller n, using a Map is good. ****test-3:**  the given index, finds the Slice element. If we know the index, then finding Slice in Go is similar to finding an array in any language, and as simple as it is. Total Sample | Len-size | **[]int** (direct index Lookup)-O (1) | **[]string** (direct index Lookup)-O (1) | Map[int]int Direct Lookup O (1) | Map[string]string o (1)---|---|---|---|---|---2 million | 5 | 0.30 Ns/op | 0.29 Ns/op | 12.7 | 32.7 2 million | 10 | 0.29 Ns/op | 0.29 Ns/op | 17.8 | 23.5 2 million | 100 | 0.29 Ns/op | 0.29 Ns/op | 16.5 | 25.7 2 million | 200 | 0.29 Ns/op | 0.29 Ns/op | 16.6 | 23.6 2 million | 400 | 0.29 Ns/op | 0.29 Ns/op | 18.4 | 23.7 2 million | 1000 | 0.29 Ns/op | 0.29 Ns/op | 17 | 25.7 2 million | 10000 | 0.58 Ns/op | 0.57 Ns/op | 17.6 | 24.4 2 million | 100000 | 0.58 Ns/op | 0.55 Ns/op | 15.1 | 25.9 as shown above, the direct lookup of Slice is O (1) fixed growth rate. [3.png] (https://boltandnuts.files.wordpress.com/2017/11/3.png) * * Conclusion: Direct lookup is a constant complexity, so assuming you know the index, it doesn't matter which one you use. However, assuming the index is known, Slice or array lookups are still much faster than MAP lookups. test-4**: Traversing Slice vs traversal map Here, I try to traverse the map and Slice and perform a constant operation within the loop. The total complexity will remain O (N). Total Sample | Len-size (n) | Traverse Int Slice O (N) | Traverse int Map [O (N)] (https:Confluence.walmart.com/pages/createpage.action?spacekey=swtf&title=o%28n%29)---|---|---|---2 million | 5 | 9.02 Ns/op | 107 Ns/op 2 million | 10 | 12.5 Ns/op | 196 Ns/op 2 million | 100 | 59.2 Ns/op | 1717 Ns/op 2 million | 200 | 84.9 Ns/op | 3356 Ns/op 2 million | 400 | 155 Ns/op | 6677 Ns/op 2 million | 1000 | 315 Ns/op | 18906 Ns/op 2 million | 10000 | 2881 Ns/op | 178804 ns/op*** 2 million | 100000 | 29012 Ns/op | 1802439 ns/op*** as shown above, traversing the Slice is nearly 20 times times faster than traversing the MAP. The reason is that, unlike Map, Slice (abstracted by an array) is created on a contiguous block of memory. As for Map, loops must traverse the key space (called buckets in Go), and memory allocations may not be contiguous. This is why the results of traversing the MAP display the key values in different order each time it is run. [4.png] (https://boltandnuts.files.wordpress.com/2017/11/4.png) * * Conclusion: Slice is the best choice if the requirement is to print or perform operations on the entire element list, rather than looking. For these reasons, traversing a Map can take more time. * * Also, note that the append operation on Slice guarantees an O (1) complexity, just like inserting a Map, but this is a * * amortization (amortized) * * constant. Append may occasionally need to reallocate memory for the underlying array. (* * *)-because the benchmark function for large map,go times out, the sample size is reduced from 2 million to 2000. Details about the test: System Details | Go operating system: Darwin | Go-1.9.2---|---|--- mac-osx | Go Architecture: AMD64 | Source code: "' go//m-c02jn0M1f1g4:slicevsmap user1$ Cat Slicemap.go Package slicemap//You can cancel the comment before printing the line to see the results (verify that the code is working correctly). But for benchmark testing, we don't care about the results of the printing. We are concerned about the time it runs//import "FMT" func rangesliceint (input []int, find int) (index int) {for index,value: = Range Input {if (VA Lue = = = Find) {//fmt. Println ("Found at", "index") return Index}} return-1}func rangesliceintprint (input []int] {for _,_ = range Input {Contin UE}}func Maplookupint (input map[int]int, find int) (Key,value int) {if Value,ok: = Input[find];ok {//fmt. Println ("Found at", Find,value) return Find,value} return 0,0}func maprangeint (input map[int]int) {for _,_ = range input {Continue}} Func directsliceint (input []int, index int) int {return input[index]}//for string//func rangeslicestring (input []string, FIN D string (index int) {for index,value: = Range Input {if (value = = find) {//FMT. Println ("Found at", "index") return Index}} return-1}func rangeslicestringprint (input []string] {for _,_ = range Input { Continue}}func maplookupstring (input map[string]stRing, find String) (Key,value string) {if Value,ok: = input[find];ok {//FMT. Println ("Found at", Find,value) return Find,value} return "0", "0"}func maprangestring (input map[string]string) {for _,_ = Range Input {Continue}}func directslicestring (input []string, index Int) string {return Input[index]} "" "Go//m-c0 2jn0m1f1g4:slicevsmap user1$ cat Slicemap_test.gopackage slicemapimport ("Testing" "StrConv") func Benchmark_ Timerangesliceint (b *testing. B) {B.stoptimer () Input: = make ([]int, 100000, 500000) for I: = 0; i < 100000; i++ {input[i] = i+10} b.starttimer () B.N = 2000000//Just to avoid millions of FMT. PRINTLN (in case you have a fmt in a slicemap.go bag). PRINTLN) for I: = 0; i < B.N; i++ {rangesliceint (input, 100009)//For worst case, check the last element}}func Benchmark_timedirectsliceint (b *testing. B) {B.stoptimer () Input: = make ([]int, 100000, 500000) for I: = 0; i < 100000; i++ {input[i] = i+10} b.starttimer () B.N = 2000000//Just to avoid millions of FMT. PRINTLN (in case you have a fmt in a slicemap.go bag). PRINTLN) for I: = 0; I < B.N; i++ {directsliceint (input, 99999)//Check the index value directly. O (1). Send index}}func benchmark_timemaplookupint (b *testing. B) {B.stoptimer () Input: = Make (Map[int]int)//Throw some values into map for i: = 1; I <=100000; i++ {input[i] = i+10} b.starttim ER () B.N = 2000000//Just to avoid millions of FMT. PRINTLN (in case you have a fmt in a slicemap.go bag). PRINTLN) for k: = 0; K < B.N; k++ {maplookupint (input, 100000)}/* Run command: Go test-bench=benchmark_timemaplookup */}func benchmark_timeslicerangeint (b *testing. B) {B.stoptimer () Input: = make ([]int, 5, ten) for I: = 0; i < 5; i++ {input[i] = i+10} b.starttimer () B.N = 2000000 Just to avoid the fmt millions of times. PRINTLN (in case you have a fmt in a slicemap.go bag). PRINTLN) for k: = 0; K < B.N; k++ {rangesliceintprint (input)}}func benchmark_timemaprangeint (b *testing. B) {B.stoptimer () Input: = Make (Map[int]int)//Throw some values into map for i: = 1; I <=100000; i++ {input[i] = i+10} b.starttim ER () B.N = 2000//Just to avoid millions of FMT. PRINTLN (in case you have a fmt in a slicemap.go bag). PRINTLN) for k: = 0; K < B.N; k++ {maprangeint (input)}}//test string FuNC benchmark_timerangeslicestring (b *testing. B) {B.stoptimer () Input: = make ([]string, 100000, 500000) for I: = 0; i < 100000; i++ {input[i] = StrConv. Formatint (Int64 (I+10))} b.starttimer () B.N = 2000000//Just to avoid millions of FMT. PRINTLN (in case you have a fmt in a slicemap.go bag). PRINTLN) for I: = 0; i < B.N; i++ {rangeslicestring (input, "100009")//For worst case, check the last element}}func benchmark_timedirectslicestring (b *testing. B) {B.stoptimer () Input: = make ([]string, 100000, 500000) for I: = 0; i < 100000; i++ {input[i] = StrConv. Formatint (Int64 (I+10))} b.starttimer () B.N = 2000000//Just to avoid millions of FMT. PRINTLN (in case you have a fmt in a slicemap.go bag). PRINTLN) for I: = 0; i < B.N; i++ {directslicestring (input, 99999)//Check the index value directly. O (1)}}func benchmark_timemaplookupstring (b *testing. B) {B.stoptimer () Input: = Make (map[string]string)//Throw some values into map for i: = 1; I <=100000; i++ {input[strconv. Formatint (Int64 (i), ten)] = StrConv. Formatint (Int64 (I+10))} b.starttimer () B.N = 2000000//Just to avoid millions of FMT. PRINTLN (in case you're sliceThe FMT is map.go in the package. PRINTLN) for k: = 0; K < B.N; k++ {maplookupstring (input, "100000")}/* Run: Go test-bench=benchmark_timemaplookupstring */} "

via:https://boltandnuts.wordpress.com/2017/11/20/go-slice-vs-maps/

Author: qwerty.ytrewq86 Translator: Ictar proofreading: Rxcai

This article by GCTT original compilation, go language Chinese network honor launches

This article was originally translated by GCTT and the Go Language Chinese network. Also want to join the ranks of translators, for open source to do some of their own contribution? Welcome to join Gctt!
Translation work and translations are published only for the purpose of learning and communication, translation work in accordance with the provisions of the CC-BY-NC-SA agreement, if our work has violated your interests, please contact us promptly.
Welcome to the CC-BY-NC-SA agreement, please mark and keep the original/translation link and author/translator information in the text.
The article only represents the author's knowledge and views, if there are different points of view, please line up downstairs to spit groove

1017 Reads ∙1 likes

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.