├── benchmark_libfib.py ├── benchmark.py ├── libfib.go ├── .gitignore ├── LICENSE └── README.md /benchmark_libfib.py: -------------------------------------------------------------------------------- 1 | import ctypes 2 | 3 | lib = ctypes.CDLL("libfib.so") 4 | 5 | def main(): 6 | for i in range(1, 41): 7 | lib.Fib(i) 8 | 9 | if __name__ == '__main__': 10 | main() 11 | -------------------------------------------------------------------------------- /benchmark.py: -------------------------------------------------------------------------------- 1 | def fib(n): 2 | if n <= 2: 3 | return 1 4 | return fib(n-1) + fib(n-2) 5 | 6 | def main(): 7 | for i in range(1, 41): 8 | fib(i) 9 | 10 | if __name__ == '__main__': 11 | main() 12 | -------------------------------------------------------------------------------- /libfib.go: -------------------------------------------------------------------------------- 1 | // package name: main 2 | package main 3 | 4 | import "C" 5 | 6 | // A very crappy implementation of Fibonacci 7 | // to get the point across. 8 | //export Fib 9 | func Fib(n int) int { 10 | if n <= 2 { 11 | return 1 12 | } 13 | return Fib(n-1) + Fib(n-2) 14 | } 15 | 16 | // Required to allow CGo to compile to a shared library. 17 | func main() {} 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | #### joe made this: http://goel.io/joe 2 | 3 | #####=== Go ===##### 4 | 5 | # Compiled Object files, Static and Dynamic libs (Shared Objects) 6 | *.o 7 | *.a 8 | *.so 9 | 10 | # Folders 11 | _obj 12 | _test 13 | 14 | # Architecture specific extensions/prefixes 15 | *.[568vq] 16 | [568vq].out 17 | 18 | *.cgo1.go 19 | *.cgo2.c 20 | _cgo_defun.c 21 | _cgo_gotypes.go 22 | _cgo_export.* 23 | 24 | _testmain.go 25 | 26 | *.exe 27 | *.test 28 | *.prof 29 | 30 | #####=== OSX ===##### 31 | .DS_Store 32 | .AppleDouble 33 | .LSOverride 34 | 35 | # Icon must end with two \r 36 | Icon 37 | 38 | 39 | # Thumbnails 40 | ._* 41 | 42 | # Files that might appear in the root of a volume 43 | .DocumentRevisions-V100 44 | .fseventsd 45 | .Spotlight-V100 46 | .TemporaryItems 47 | .Trashes 48 | .VolumeIcon.icns 49 | 50 | # Directories potentially created on remote AFP share 51 | .AppleDB 52 | .AppleDesktop 53 | Network Trash Folder 54 | Temporary Items 55 | .apdisk 56 | 57 | *.h 58 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Karan Goel 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # libfib 2 | 3 | An experiment to run Go code directly from Python. 4 | 5 | ### How it works 6 | 7 | `libfib.go` is a very naive implementation of Fibonacci sequence. Using Go's build modes, we build it into a shared library. The library is imported in Python and used there. 8 | 9 | Basically, we execute the Go code from Python code even though the latter doesn't even know what Go is. 10 | 11 | Run `go help buildmodes` to learn more about Go's build modes. 12 | 13 | ### Why? 14 | 15 | 1. It's cool. 16 | 2. Go is much faster than Python. You can rewrite slow parts of your code in Go, and call them from your Python code. See [benchmarks](#benchmarks). 17 | 3. It's cool. 18 | 19 | ### Benchmarks 20 | 21 | Benchmarks are the best way to compare the performance and really show the **coolness** of Go's build modes. 22 | 23 | *The function to benchmark:* Find the first 40 Fibonacci numbers. That is `Fib` function will be called with `n` from `1...40`. The execution time of the full loop is then measured. 24 | 25 | *Results*: `libfib` is 76X faster!!!1111 26 | 27 | #### Pure Python implementation 28 | 29 | `benchmark.py` implements the same Fibonacci function in pure Python.Here's the result of the Linux `time` command: 30 | 31 | ``` 32 | $ time python benchmark.py 33 | 34 | real 2m26.726s 35 | user 2m6.232s 36 | sys 0m2.280s 37 | ``` 38 | 39 | #### Shared library implementation 40 | 41 | `benchmark_libfib.py` calls the Fibonacci function in the shared library from Python. Here's the result of the Linux `time` command: 42 | 43 | ``` 44 | $ time python benchmark_libfib.py 45 | 46 | real 0m1.899s 47 | user 0m1.593s 48 | sys 0m0.039s 49 | ``` 50 | 51 | ### Creating the shared objects file 52 | 53 | ``` 54 | go build -buildmode=c-shared -o libfib.so libfib.go 55 | ``` 56 | 57 | This will produce `fib.h` and `fib.so`. 58 | 59 | ### Using `.so` in Python 60 | 61 | Now we can load the library in Python and start using it. 62 | 63 | ``` 64 | import ctypes 65 | lib = ctypes.CDLL("libfib.so") 66 | print(lib.Fib(20)) 67 | ``` 68 | 69 | ### License 70 | 71 | MIT (c) Karan Goel 72 | --------------------------------------------------------------------------------