Optimasi Performa
Ringkasan
Section titled “Ringkasan”Optimalkan aplikasi Wails Anda untuk kecepatan, efisiensi memori, dan responsivitas.
Optimasi Frontend
Section titled “Optimasi Frontend”Ukuran Bundle
Section titled “Ukuran Bundle”export default { build: { rollupOptions: { output: { manualChunks: { vendor: ['react', 'react-dom'], }, }, }, minify: 'terser', terserOptions: { compress: { drop_console: true, }, }, },}Code Splitting
Section titled “Code Splitting”// Lazy load componentsconst Settings = lazy(() => import('./Settings'))
function App() { return ( <Suspense fallback={<Loading />}> <Settings /> </Suspense> )}Optimasi Asset
Section titled “Optimasi Asset”// Optimise imagesimport { defineConfig } from 'vite'import imagemin from 'vite-plugin-imagemin'
export default defineConfig({ plugins: [ imagemin({ gifsicle: { optimizationLevel: 3 }, optipng: { optimizationLevel: 7 }, svgo: { plugins: [{ removeViewBox: false }] }, }), ],})Optimasi Backend
Section titled “Optimasi Backend”Bindings Efisien
Section titled “Bindings Efisien”// ❌ Bad: Return everythingfunc (s *Service) GetAllData() []Data { return s.db.FindAll() // Could be huge}
// ✅ Good: Paginatefunc (s *Service) GetData(page, size int) (*PagedData, error) { return s.db.FindPaged(page, size)}Caching
Section titled “Caching”type CachedService struct { cache *lru.Cache ttl time.Duration}
func (s *CachedService) GetData(key string) (interface{}, error) { // Check cache if val, ok := s.cache.Get(key); ok { return val, nil }
// Fetch and cache data, err := s.fetchData(key) if err != nil { return nil, err }
s.cache.Add(key, data) return data, nil}Goroutine untuk Operasi Panjang
Section titled “Goroutine untuk Operasi Panjang”func (s *Service) ProcessLargeFile(path string) error { // Process in background go func() { result, err := s.process(path) if err != nil { s.app.Event.Emit("process-error", err.Error()) return } s.app.Event.Emit("process-complete", result) }()
return nil}Optimasi Memori
Section titled “Optimasi Memori”Hindari Memory Leak
Section titled “Hindari Memory Leak”// ❌ Bad: Goroutine leakfunc (s *Service) StartPolling() { ticker := time.NewTicker(1 * time.Second) go func() { for range ticker.C { s.poll() } }() // ticker never stopped!}
// ✅ Good: Proper cleanupfunc (s *Service) StartPolling() { ticker := time.NewTicker(1 * time.Second) s.stopChan = make(chan bool)
go func() { for { select { case <-ticker.C: s.poll() case <-s.stopChan: ticker.Stop() return } } }()}
func (s *Service) StopPolling() { close(s.stopChan)}Pool Resource
Section titled “Pool Resource”var bufferPool = sync.Pool{ New: func() interface{} { return new(bytes.Buffer) },}
func processData(data []byte) []byte { buf := bufferPool.Get().(*bytes.Buffer) defer bufferPool.Put(buf)
buf.Reset() buf.Write(data) // Process... return buf.Bytes()}Optimasi Event
Section titled “Optimasi Event”Debounce Event
Section titled “Debounce Event”// Debounce frequent eventslet debounceTimerfunction handleInput(value) { clearTimeout(debounceTimer) debounceTimer = setTimeout(() => { UpdateData(value) }, 300)}Batch Update
Section titled “Batch Update”type BatchProcessor struct { items []Item mu sync.Mutex timer *time.Timer}
func (b *BatchProcessor) Add(item Item) { b.mu.Lock() defer b.mu.Unlock()
b.items = append(b.items, item)
if b.timer == nil { b.timer = time.AfterFunc(100*time.Millisecond, b.flush) }}
func (b *BatchProcessor) flush() { b.mu.Lock() items := b.items b.items = nil b.timer = nil b.mu.Unlock()
// Process batch processBatch(items)}Optimasi Build
Section titled “Optimasi Build”Ukuran Binary
Section titled “Ukuran Binary”wails3 build sendiri tidak memiliki flag -ldflags — Taskfile bawaan sudah meneruskan -ldflags="-s -w" ke go build. Untuk memperkecil binary lebih lanjut, edit task build atau panggil go build langsung:
# Strip debug symbols and trim file pathsgo build -ldflags="-s -w" -trimpath -o bin/myappKecepatan Kompilasi
Section titled “Kecepatan Kompilasi”# Use build cachego build -buildmode=default
# Parallel compilationgo build -p 8Profiling
Section titled “Profiling”CPU Profiling
Section titled “CPU Profiling”import "runtime/pprof"
func profileCPU() { f, _ := os.Create("cpu.prof") defer f.Close()
pprof.StartCPUProfile(f) defer pprof.StopCPUProfile()
// Code to profile}Memory Profiling
Section titled “Memory Profiling”import "runtime/pprof"
func profileMemory() { f, _ := os.Create("mem.prof") defer f.Close()
runtime.GC() pprof.WriteHeapProfile(f)}Analisis Profile
Section titled “Analisis Profile”# View CPU profilego tool pprof cpu.prof
# View memory profilego tool pprof mem.prof
# Web interfacego tool pprof -http=:8080 cpu.profPraktik Terbaik
Section titled “Praktik Terbaik”✅ Lakukan
Section titled “✅ Lakukan”- Profil sebelum mengoptimalkan
- Cache operasi yang mahal
- Gunakan pagination untuk dataset besar
- Debounce event yang sering
- Pool resource
- Bersihkan goroutine
- Optimalkan ukuran bundle
- Gunakan lazy loading
❌ Jangan
Section titled “❌ Jangan”- Jangan optimasi terlalu dini
- Jangan abaikan memory leak
- Jangan blokir main thread
- Jangan kembalikan dataset besar
- Jangan lewati profiling
- Jangan lupa cleanup
Checklist Performa
Section titled “Checklist Performa”- Bundle frontend dioptimalkan
- Gambar dikompresi
- Code splitting diimplementasikan
- Method backend dipaginasi
- Caching diimplementasikan
- Goroutine dibersihkan
- Event di-debounce
- Ukuran binary dioptimalkan
- Profiling dilakukan
- Memory leak diperbaiki
Langkah Selanjutnya
Section titled “Langkah Selanjutnya”- Architecture - Pola arsitektur aplikasi
- Testing - Uji aplikasi Anda
- Building - Build binary yang dioptimalkan