golang finder_waitgroup.go

finder_waitgroup.go
package main

import (
	"fmt"
	"io/ioutil"
	"os"
	"runtime"
	"sync"
)

var wg sync.WaitGroup

// Expand filelist from path.
func expand(path string, ch chan<- string) {
	list, err := ioutil.ReadDir(path)
	if err != nil {
		fmt.Fprintf(os.Stderr, "expand error[%s]: %v\n", path, err)
	}
	for _, finfo := range list {
		fullpath := path + string(os.PathSeparator) + finfo.Name()
		ch <- fullpath
		if finfo.IsDir() {
			wg.Add(1)
			go expand(fullpath, ch)
		}
	}
	wg.Done()
}

// Reduce expand data.
func reduce(chIn <-chan string, chOut chan<- string) {
	/* do something */
	for msg := range chIn {
		chOut <- msg
	}
}

func search(path string) <-chan string {
	chExpand := make(chan string)
	chReduce := make(chan string)
	go func() {
		wg.Add(1)
		expand(path, chExpand)
		wg.Wait()
		close(chExpand)
	}()
	go func() {
		reduce(chExpand, chReduce)
		close(chReduce)
	}()
	return chReduce
}

func main() {
	if (len(os.Args) < 2) {
		fmt.Fprintln(os.Stderr, "Require path")
		os.Exit(1)
	}

	cpus := runtime.NumCPU()
	runtime.GOMAXPROCS(cpus)

	path := os.Args[1]
	ch := search(path)

	for msg := range ch {
		fmt.Println(msg)
	}

	fmt.Println("exit")
}

golang finder_timeafter.go

finder_timeafter.go
package main

import (
	"fmt"
	"io/ioutil"
	"os"
	"runtime"
	"time"
)

// Expand filelist from path.
func expand(path string, ch chan<- string) {
	list, err := ioutil.ReadDir(path)
	if err != nil {
		fmt.Fprintf(os.Stderr, "expand error[%s]: %v\n", path, err)
	}
	for _, finfo := range list {
		fullpath := path + string(os.PathSeparator) + finfo.Name()
		ch <- fullpath
		if finfo.IsDir() {
			go expand(fullpath, ch)
		}
	}
}

// Reduce expand data.
func reduce(chIn <-chan string, chOut chan<- string) {
	/* do something */
	for {
		chOut <- <- chIn
	}
}

func search(path string) <-chan string {
	chExpand := make(chan string)
	chReduce := make(chan string)

	go expand(path, chExpand)
	go reduce(chExpand, chReduce)

	return chReduce
}

func main() {
	if (len(os.Args) < 2) {
		fmt.Fprintln(os.Stderr, "Require path")
		os.Exit(1)
	}

	cpus := runtime.NumCPU()
	runtime.GOMAXPROCS(cpus)

	path := os.Args[1]
	ch := search(path)

	timeout := time.After(10 * time.Millisecond)
L:
	for {
		select {
		case msg := <- ch:
			fmt.Println(msg)
		case <- timeout:
			fmt.Println("time out")
			break L
		}
	}

	fmt.Println("exit")
}

golang 在golang上打开/读取vs open / mmap vs open / bufio.read。

在golang上打开/读取vs open / mmap vs open / bufio.read。

bufio_read.go
package main

import (
	"bufio"
	"fmt"
	"log"
	"os"
)

func main() {
	if len(os.Args) < 2 {
		return
	}
	path := os.Args[1]

	f, err := os.Open(path)
	if err != nil {
		log.Fatal(err)
	}
	fi, err := f.Stat()
	if err != nil {
		log.Fatal(err)
	}

	reader := bufio.NewReaderSize(f, int(fi.Size()))
	buf := make([]byte, fi.Size())

	_, err = reader.Read(buf)
	if err != nil {
		log.Fatal(err)
	}

	cnt := 0
	for _, b := range buf {
		if b == 0x00 {
			cnt++
		}
	}

	f.Close()

	fmt.Printf("%s: size=%d cnt=%d\n", path, fi.Size(), cnt);
}

golang 在golang上打开/读取vs open / mmap vs open / bufio.read。

在golang上打开/读取vs open / mmap vs open / bufio.read。

bufio_readbyte.go
package main

import (
	"bufio"
	"fmt"
	"log"
	"os"
)

func main() {
	if len(os.Args) < 2 {
		return
	}
	path := os.Args[1]

	f, err := os.Open(path)
	if err != nil {
		log.Fatal(err)
	}
	fi, err := f.Stat()
	if err != nil {
		log.Fatal(err)
	}

	reader := bufio.NewReaderSize(f, int(fi.Size()))

	cnt := 0
	for b, err := reader.ReadByte(); err == nil; b, err = reader.ReadByte() {
		if b == 0x00 {
			cnt++
		}
	}

	f.Close()

	fmt.Printf("%s: size=%d cnt=%d\n", path, fi.Size(), cnt);
}

golang 在golang上打开/读取vs open / mmap vs open / bufio.read。

在golang上打开/读取vs open / mmap vs open / bufio.read。

open_read.go
package main

import (
	"fmt"
	"log"
	"os"
)

func main() {
	if len(os.Args) < 2 {
		return
	}
	path := os.Args[1]

	f, err := os.Open(path)
	if err != nil {
		log.Fatal(err)
	}
	fi, err := f.Stat()
	if err != nil {
		log.Fatal(err)
	}

	buf := make([]byte, fi.Size())
	_, err = f.Read(buf)
	if err != nil {
		log.Fatal(err)
	}

	cnt := 0
	for _, b := range buf {
		if b == 0x00 {
			cnt++
		}
	}

	f.Close()

	fmt.Printf("%s: size=%d cnt=%d\n", path, fi.Size(), cnt);
}

golang golang.syscall.Madvise()上的open / read vs open / mmap vs open / bufio.read是不受支持的darwin。

golang.syscall.Madvise()上的open / read vs open / mmap vs open / bufio.read是不受支持的darwin。

open_mmap_adv.go
package main

import (
	"fmt"
	"log"
	"os"
	"syscall"
)

func main() {
	if len(os.Args) < 2 {
		return
	}
	path := os.Args[1]

	f, err := os.Open(path)
	if err != nil {
		log.Fatal(err)
	}
	fi, err := f.Stat()
	if err != nil {
		log.Fatal(err)
	}

	mem, err := syscall.Mmap(int(f.Fd()), 0, int(fi.Size()),
							syscall.PROT_READ, syscall.MAP_SHARED)
	if err != nil {
		log.Fatal(err)
	}

	err = syscall.Madvise(mem, syscall.MADV_SEQUENTIAL | syscall.MADV_WILLNEED)
	if err != nil {
		log.Fatal(err)
	}

	cnt := 0
	for _, b := range mem {
		if b == 0x00 {
			cnt++
		}
	}
	err = syscall.Munmap(mem)
	if err != nil {
		log.Fatal(err)
	}
	f.Close()

	fmt.Printf("%s: size=%d cnt=%d\n", path, fi.Size(), cnt);
}

golang golang上打开/读取vs open / mmap vs fopen / fread

golang上打开/读取vs open / mmap vs fopen / fread

open_mmap.go
package main

import (
	"fmt"
	"log"
	"os"
	"syscall"
)

func main() {
	if len(os.Args) < 2 {
		return
	}
	path := os.Args[1]

	f, err := os.Open(path)
	if err != nil {
		log.Fatal(err)
	}
	fi, err := f.Stat()
	if err != nil {
		log.Fatal(err)
	}

	mem, err := syscall.Mmap(int(f.Fd()), 0, int(fi.Size()),
					syscall.PROT_READ, syscall.MAP_SHARED)
	if err != nil {
		log.Fatal(err)
	}

	cnt := 0
	for _, b := range mem {
		if b == 0x00 {
			cnt++
		}
	}
	err = syscall.Munmap(mem)
	if err != nil {
		log.Fatal(err)
	}
	f.Close()

	fmt.Printf("%s: size=%d cnt=%d\n", path, fi.Size(), cnt);
}