پیش تخصیص ساختارهای پویا – انجمن DEV
معرفی
ما در زمان توسعه نرم افزار زیبا زندگی می کنیم، جایی که هر زبان دارای ساختارهای پویا است. بنابراین، ما می توانیم فقط به مقداری تخصیص حافظه فکر کنیم.
تفاوت بین عملکرد توسعه به طور قابل توجهی بین زبان های تایپ ایستا و پویا در حال کاهش است.
ما میتوانیم روی Go، Kotlin، Java و غیره کد بنویسیم، تقریباً مانند زبانهای تایپ استاتیک مانند Python، JavaScript، PHP، و غیره. قدم کوچک و آسان
این مقاله کوتاه توضیح خواهد داد که چرا پیش تخصیص مفید است، حتی برای ساختارهای پویا.
ساده سازی در زبان های تایپ ایستا
تفاوت قابل توجه بین زبان های تایپ ایستا و زبان های تایپ پویا عمدتاً بر اساس سه تفاوت اصلی است:
- مدیریت حافظه
- پرحرفی
- تبدیل نوع
در مقالههای آینده در مورد قسمتهای تبدیل نوع و پرحرفی بحث خواهد شد. با این حال، مدیریت حافظه موضوعی است که در حال حاضر به آن خواهیم پرداخت.
مدیریت حافظه
وقتی زبانهای پویا درگیر بودند، همه زبانهای استاتیک به مدیریت مشترک حافظه به صورت دستی نیاز داشتند. هر توسعه دهنده ای باید اندازه آرایه، تغییر اندازه، تمیز کردن حافظه و غیره را در نظر می گرفت.
در حال حاضر، هر زبانی (از جمله C++) راهی برای جلوگیری از مدیریت حافظه تقریباً یا به طور کامل به این روش ها ارائه می دهد:
- شمارنده های مرجع
- زباله جمع کن
بنابراین، اگر ما درست انجام دهیم، می توانیم از برخی استفاده کنیم slice
1، ArrayList
، vector
(ساختارهای مشابه از زبان های مختلف) و غیره برای کار با آرایه های پویا.
بنابراین، در دنیای کنونی، میتوانیم هر مقدار دادهای را که بخواهیم بسازیم اضافه کنیم slice
1.
مثال با آرایه:
package main
import "fmt"
func main() {
const size = 10
arr := [size]int{}
fmt.Println(arr) // [0 0 0 0 0 0 0 0 0 0]
for i := 0; i < size; i++ {
arr[i] = 333
}
fmt.Println(arr) // [333 333 333 333 333 333 333 333 333 333]
}
مثال بالا نشان می دهد که ما یک اندازه آرایه ثابت داشتیم که نمی توانستیم عنصر یازدهم را بدون دستکاری اضافه کنیم.
مثال با ساختار داده آرایه پویا (slice
1 از Go):
package main
import "fmt"
func main() {
const size = 10
arr := []int{}
fmt.Println(arr) // []
for i := 0; i < size; i++ {
arr = append(arr, 333)
}
fmt.Println(arr) // [333 333 333 333 333 333 333 333 333 333]
}
همانطور که می بینیم، یک برش با اندازه های صفر ایجاد کردیم. پس از آن، آن را از صفر تا 10 افزایش دادیم. پس از آن، مشکلی برای اضافه کردن یک یا صدها قطعه دیگر نداشتیم.
بهبود عملکرد
همانطور که در بالا دیدیم، ساختارهای پویا مانند slice
1 کیفیت زندگی خود را بهبود بخشیده و به ما کمک کنید تا کد را با سرعتی مشابه در زبان های پویا بنویسیم.
مثال بالا مثالی را ارائه داد که در آن یک برش با اندازه 0 ایجاد کردیم و آن را تا ده عنصر اختصاص دادیم. با این حال، یک مشکل عملکرد جزئی در اینجا وجود دارد. با این حال، ما اندازه مورد انتظار را میدانستیم (در مورد استفاده ما، ده عنصر بود)، بنابراین میتوانیم برش را از قبل تخصیص دهیم و عملکرد را بهبود ببخشیم.
بیایید یک معیار کوچک ایجاد کنیم تا تفاوت بین برش های از پیش تخصیص داده شده و غیر اختصاص داده شده در Go را مشاهده کنیم:
package slices_test
import (
"testing"
)
func BenchmarkNonAllocated(b *testing.B) {
slice := []int{}
// run the allocate variable b.N times
for n := 0; n < b.N; n++ {
slice = append(slice, 333)
}
}
func BenchmarkPreAllocated(b *testing.B) {
slice := make([]int, 0, b.N)
// run the allocate variable b.N times
for n := 0; n < b.N; n++ {
slice = append(slice, 333)
}
}
نتیجه دویدن:
$ go test -benchmem -bench . github.com/aohorodnyk/gox/slices -benchtime=20s
goos: darwin
goarch: arm64
pkg: github.com/aohorodnyk/gox/slices
BenchmarkNonAllocated-8 1000000000 14.52 ns/op 42 B/op 0 allocs/op
BenchmarkPreAllocated-8 1000000000 3.918 ns/op 8 B/op 0 allocs/op
PASS
ok github.com/aohorodnyk/gox/slices 19.872s
در نتیجه، می توانیم ببینیم که بهبود عملکرد ~ 3.7 برابر است.
نتیجه
این مقاله باید نحوه عملکرد برش ها، ArrayList یا ساختارهای داده مشابه را شرح دهد. سپس، پیدا کردن آن در موتور جستجوی مورد علاقه شما آسان است.
در همین حال، این مقاله به طور اجباری نشان می دهد که تخصیص اولیه به طور قابل توجهی عملکرد را بهبود می بخشد. در مقاله، ما فقط لمس کردیم آرایه های پویا، اما می توان آن را برای هر نوع مانندی اعمال کرد slice
1، map
(hash map
)، و غیره.
برنامه های ما می توانند میلیون ها درخواست را مدیریت کنند. بنابراین اگر بتوانیم عملکرد را برای هر درخواست فقط با این بهبود بهبود دهیم، این یک گام بزرگ برای ما خواهد بود.
این بخش کوچکی از بهبود است. در مقالات آینده نیز گزینه های دیگر را مورد بحث قرار خواهیم داد.
برخی از مطالب داخلی سطح بالا در مورد برش ها را می توانید در اینجا بخوانید. ↩