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

Very slow #1

Open
KawaiDesu opened this issue May 15, 2014 · 2 comments
Open

Very slow #1

KawaiDesu opened this issue May 15, 2014 · 2 comments

Comments

@KawaiDesu
Copy link

This realization of Whirlpool works very slow. For example, i wrote a program, which hashing all files in current directory and printing result.
I used 2 variants of builds and compared them to PHP realization of same program.
Enviroment:
Intel Core2 Duo CPU E7500 @ 2.93GHz
3536 Mb DDR2
Ubuntu 12.04 with last updates

➜ uname -a
Linux pyxis-server 3.8.0-29-generic #42~precise1-Ubuntu SMP Wed Aug 14 15:31:16 UTC 2013 i686 i686 i386 GNU/Linux
➜ go version
go version go1
➜ go env
GOROOT="/usr/lib/go"
GOBIN=""
GOARCH="386"
GOCHAR="8"
GOOS="linux"
GOEXE=""
GOHOSTARCH="386"
GOHOSTOS="linux"
GOTOOLDIR="/usr/lib/go/pkg/tool/linux_386"
GOGCCFLAGS="-g -O2 -fPIC -m32 -pthread"
CGO_ENABLED="1"
➜ aptitude show golang
...
Version: 2:1-5
...
➜ php -v
PHP 5.3.10-1ubuntu3.11 with Suhosin-Patch (cli) (built: Apr  4 2014 01:27:23) 
Copyright (c) 1997-2012 The PHP Group
Zend Engine v2.3.0, Copyright (c) 1998-2012 Zend Technologies

The code:

package main

import (
  "fmt"
  "github.com/jzelinskie/whirlpool"
  "io/ioutil"
  "os"
  "encoding/hex"
)

func main() {
        dir, _ := os.Open("./") // current dir
        list, _ := dir.Readdirnames(-1) // if ok err == nil
        listsize := len(list)
        var hashes = make([]string, listsize)
        whi := whirlpool.New()
// bulding list of hashes
        fmt.Println("listsize =", listsize)
        for cn := 0; cn < listsize; cn++ {
                file, _ := ioutil.ReadFile(list[cn])
                whi.Write(file)
                hashes[cn] = hex.EncodeToString(whi.Sum(nil))
                fmt.Print(list[cn], " ", hashes[cn], "\n")
                Reset()
        }
}

Almost same for PHP:

<?php
if ($handle = opendir('.')) {
    while (false !== ($file = readdir($handle)))
    {
        if (($file != ".") 
         && ($file != ".."))
        {
            echo $file . " " . hash( "whirlpool", file_get_contents($file) ) . "\n";
        }
    }

    closedir($handle);
}
?>

Results:

# Standart compiler
➜ go build ./dedup.go
➜ time ./dedup > /dev/null

real    0m4.612s
user    0m4.588s
sys 0m0.020s

# gccgo compiler
➜ go build -compiler gccgo ./dedup.go
➜ time ./dedup > /dev/null

real    0m2.110s
user    0m2.084s
sys 0m0.024s

# PHP realization
➜ time php hash.php > /dev/null

real    0m0.634s
user    0m0.608s
sys 0m0.024s

I've profiled the "go build" variant of program (same run time with profiling code) and saw, that 94.1% of time program was in
github.com/jzelinskie/whirlpool.(*whirlpool).transform
I understand, what Go realisation may be slower (PHP have it in module written is C, i suppose), but why the difference is so huge?
Is there any way to make it faster?

@KawaiDesu
Copy link
Author

I've found the way (while was writing this issue :D) to make it fast. The problem is in the Go native compiler.
Using ➜ go build -a -gccgoflags "-march=native -O3" -compiler gccgo ./dedup.go i'v got this:

➜ time ./dedup > /dev/null

real    0m0.534s
user    0m0.512s
sys 0m0.020s

@jzelinskie
Copy link
Owner

jzelinskie commented May 17, 2014

I haven't played with this code in a bit; it could definitely use some review. This implementation was focused on clarity first over performance. There are probably still places that are doing needless bounds-checking. I suspect that even with careful optimizations the codebase would still be slower than the C implementation used by PHP or other languages due to the Go runtime. Most of the crypto code in Go's standard library takes advantage of assembly implementations for speed on specific architectures (e.g. sha512) and this does not. I haven't experimented with gccgo as much as I probably should have; I'm actually surprised to see that it is able to optimize the code that well.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants