Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions homeworks/10_allocator/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
Домашнее задание №10

В домашнем задании нужно реализовать функцию дефрагментации памяти.

Дефрагментацию нужно будет проводить `in-place` (без копирования в новое место), а также вместе с обновлением указателей, которые уже ссылаются на фрагментированные участки памяти. Указатели будут указывать только на однобайтовые значения в памяти, а различать свободные и занятые участки памяти нужно будет при помощи указателей, но не при помощи значений в памяти. Поподробнее о дефрагментации можно прочитать [здесь](https://ru.wikipedia.org/wiki/Дефрагментация).

Для выполнения домашнего задания подготовлен шаблон кода и основные тесты, которую помогут проверить корректность реализации конвертации. Шаблона доступен по [ссылке](https://github.com/Balun-courses/deep_go/blob/master/homework/allocator/homework_test.go).

Задание со звездочкой
Выполнять необязательно, но можно попробовать реализовать функцию дефрагментации, которая будет уметь работать не только с однобайтовыми значениями в памяти, но еще и с 2-4-8 байтовыми значениями.
108 changes: 108 additions & 0 deletions homeworks/10_allocator/homework_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
package main

import (
"reflect"
"testing"
"unsafe"

"github.com/stretchr/testify/assert"
)

// go test -v homework_test.go

func Defragment(memory []byte, pointers []unsafe.Pointer) {
if len(memory) == 0 || len(pointers) == 0 {
return
}

base := uintptr(unsafe.Pointer(&memory[0]))

ptrmap := make(map[int]int)
for i, v := range pointers {
ptrmap[int(uintptr(v)-base)] = i
}

write := 0
for read := range memory {
if i, ok := ptrmap[read]; ok {
if write != read {
memory[write] = memory[read]
}
pointers[i] = unsafe.Pointer(&memory[write])
write++
}
}

// Clear tail data
for i := write; i < len(memory); i++ {
memory[i] = 0
}
}

func TestDefragmentation(t *testing.T) {
var fragmentedMemory = []byte{
0xF3, 0x00, 0x00, 0x00,
0x00, 0xF2, 0x00, 0x00,
0x00, 0x00, 0xF1, 0x00,
0x00, 0x00, 0x00, 0xF4,
}

var fragmentedPointers = []unsafe.Pointer{
unsafe.Pointer(&fragmentedMemory[10]),
unsafe.Pointer(&fragmentedMemory[5]),
unsafe.Pointer(&fragmentedMemory[0]),
unsafe.Pointer(&fragmentedMemory[15]),
}

var defragmentedPointers = []unsafe.Pointer{
unsafe.Pointer(&fragmentedMemory[2]),
unsafe.Pointer(&fragmentedMemory[1]),
unsafe.Pointer(&fragmentedMemory[0]),
unsafe.Pointer(&fragmentedMemory[3]),
}

var defragmentedMemory = []byte{
0xF3, 0xF2, 0xF1, 0xF4,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
}

Defragment(fragmentedMemory, fragmentedPointers)
assert.True(t, reflect.DeepEqual(defragmentedMemory, fragmentedMemory))
assert.True(t, reflect.DeepEqual(defragmentedPointers, fragmentedPointers))
}

func TestDefragmentationBasic(t *testing.T) {
var fragmentedMemory = []byte{
0xFF, 0x00, 0x00, 0x00,
0x00, 0xFF, 0x00, 0x00,
0x00, 0x00, 0xFF, 0x00,
0x00, 0x00, 0x00, 0xFF,
}

var fragmentedPointers = []unsafe.Pointer{
unsafe.Pointer(&fragmentedMemory[0]),
unsafe.Pointer(&fragmentedMemory[5]),
unsafe.Pointer(&fragmentedMemory[10]),
unsafe.Pointer(&fragmentedMemory[15]),
}

var defragmentedPointers = []unsafe.Pointer{
unsafe.Pointer(&fragmentedMemory[0]),
unsafe.Pointer(&fragmentedMemory[1]),
unsafe.Pointer(&fragmentedMemory[2]),
unsafe.Pointer(&fragmentedMemory[3]),
}

var defragmentedMemory = []byte{
0xFF, 0xFF, 0xFF, 0xFF,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
}

Defragment(fragmentedMemory, fragmentedPointers)
assert.True(t, reflect.DeepEqual(defragmentedMemory, fragmentedMemory))
assert.True(t, reflect.DeepEqual(defragmentedPointers, fragmentedPointers))
}