Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Desafio 07 #965

Merged
merged 25 commits into from
Aug 13, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
647f672
[desafio-07] Primeira implementação
MatMercer May 27, 2023
b282aeb
[desafio-07] Arruma buffer pequeno dando erro
MatMercer May 27, 2023
3df68ab
[desafio-07] Code cleanup
MatMercer May 27, 2023
9a1058f
[desafio-07] Melhora performance com arquivos pequenos e limpa código
MatMercer May 27, 2023
d46824c
[desafio-07] Add reverse reader
MatMercer May 28, 2023
bcb27f5
[desafio-07] Corrige problema de ultimo output
MatMercer May 28, 2023
8e1104a
[desafio-07] Melhora performance bufferizando stdout
MatMercer May 28, 2023
a58271c
[desafio-07] Tuning
MatMercer May 28, 2023
84e1119
[desafio-07] Readme
MatMercer May 28, 2023
afa6ca6
[desafio-07] Main final arquivo
MatMercer Aug 12, 2023
2102657
[desafio-07] args -> os.Args
MatMercer Aug 12, 2023
6088fc6
[desafio-07] Use log.fatalX
MatMercer Aug 12, 2023
1221b98
[desafio-07] Remove check()
MatMercer Aug 12, 2023
1c7628f
[desafio-07] Remove out()
MatMercer Aug 12, 2023
8b9faa3
[desafio-07] Manual flush
MatMercer Aug 12, 2023
a96d742
[desafio-07] Fix filename bug
MatMercer Aug 12, 2023
7595350
[desafio-07] Unbuf tac
MatMercer Aug 12, 2023
5eb4085
Revert "[desafio-07] Unbuf tac"
MatMercer Aug 12, 2023
14e334b
[desafio-07] Cleanup
MatMercer Aug 12, 2023
1fa573e
[desafio-07] Stderr logger
MatMercer Aug 12, 2023
4127792
[desafio-07] *ReverseReader -> ReverseReader
MatMercer Aug 12, 2023
d59346c
Revert "[desafio-07] *ReverseReader -> ReverseReader"
MatMercer Aug 12, 2023
135f5eb
[desafio-07] Improve README.md
MatMercer Aug 12, 2023
51edce4
[desafio-07] b -> readBuf
MatMercer Aug 12, 2023
e6de0bd
[desafio-07] Remove NewReverseReader
MatMercer Aug 12, 2023
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
33 changes: 33 additions & 0 deletions desafio-07/MatMercer/go/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# Solução desafio 7 unix tac em Go

Executar:

```bash
go build tac.go
./tac 1GB.txt > out.txt
md5sum out.txt
2b4fd25f11d75c285ec69ecac420bd07 out.txt
```

Para testar os 512MB de memória com control groups v1:

```bash
# install cgroup
sudo apt-get install cgroup-tools

# setup cgroup
export CGROUP=osProgramadoresD7
export CGROUPP="memory/$CGROUP"
sudo cgcreate -t $USER:$USER -a $USER:$USER -g memory:"$CGROUP"
MatMercer marked this conversation as resolved.
Show resolved Hide resolved
echo 512M > "/sys/fs/cgroup/$CGROUPP/memory.limit_in_bytes"
echo 0 > "/sys/fs/cgroup/$CGROUPP/memory.swappiness"

# run in cgroup
cgexec -g memory:$CGROUP ./tac 1GB.txt > out.txt
md5sum out.txt
2b4fd25f11d75c285ec69ecac420bd07 out.txt

# check max mem used
cat "/sys/fs/cgroup/$CGROUPP/memory.max_usage_in_bytes" | numfmt --to=iec
512M
```
139 changes: 139 additions & 0 deletions desafio-07/MatMercer/go/tac.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
package main

import (
"bufio"
"bytes"
"io"
"log"
"os"
)

// in MB size, currently the program uses a max of 2*bufSize iff file size > bufSize
const maxBufSize = int64(250 << (10 * 2))

var stdout *bufio.Writer

// min standard math.Min supports only float64
func min(x int64, y int64) int64 {
if x > y {
return y
}
return x
}

type ReverseReader struct {
f *os.File
offset int64
}

func (r *ReverseReader) Read(b []byte) (n int, err error) {
r.offset -= int64(len(b))
_, err = r.f.Seek(r.offset, io.SeekStart)
if err != nil {
return 0, err
}
read, err := r.f.Read(b)
if err != nil {
return 0, err
}
return read, nil
}

func tac(fileName string) error {
f, err := os.Open(fileName)
if err != nil {
return err
}
fi, err := f.Stat()
if err != nil {
return err
}

// buffers stdout by 128kb
stdout = bufio.NewWriterSize(os.Stdout, 128<<(10))

fileSize := fi.Size()
bufSize := min(fileSize, maxBufSize)
readBuf := make([]byte, bufSize)
maxRead := bufSize
start := fileSize
lineAcc := bytes.NewBuffer([]byte{})
r := &ReverseReader{f, fileSize}
for start != 0 {
start -= bufSize
if start < 0 {
// prevent over reading if result is less than buf size
MatMercer marked this conversation as resolved.
Show resolved Hide resolved
maxRead += start
start = 0
}

_, err = r.Read(readBuf[:maxRead])
if err != nil {
return err
}

// search until backwards \n and prints it
lastEnd := maxRead
for i := maxRead - 1; i >= 0; i-- {
if readBuf[i] == '\n' {
// write everything but '\n', since readBuf[i] == '\n'
_, err = stdout.Write(readBuf[i+1 : lastEnd])
if err != nil {
return err
}
// writes accumulated value
_, err = stdout.Write(lineAcc.Bytes())
if err != nil {
return err
}
// reset the accumulator to receive next line
lineAcc.Reset()
// makes '\n' be printed in next iteration
lastEnd = i + 1
}

// on last iteration, create a new accumulator with [max-read][current-accumulator]
if i == 0 {
newAcc := bytes.NewBuffer(nil)
_, err = newAcc.Write(readBuf[i:lastEnd])
if err != nil {
return err
}
_, err = newAcc.Write(lineAcc.Bytes())
if err != nil {
return err
}
lineAcc = newAcc
}
}
}
// closes the file
_ = f.Close()

// prints last chunk of data
// fmt.Println is unbuffered https://github.com/golang/go/issues/36619
_, err = stdout.Write(lineAcc.Bytes())
if err != nil {
return err
}

err = stdout.Flush()
if err != nil {
return err
}

return nil
}

func main() {
logger := log.New(os.Stderr, "", 0)
if len(os.Args) != 2 {
logger.Fatalln("usage: tac [file]")
}

fileName := os.Args[1]
err := tac(fileName)
if err != nil {
logger.Fatalf("tac error: %v", err)
}
}
Loading