go(lang) to python

55
Go(lang) to Python Europython 2019 Basel, Stefan Baerisch [email protected] 1

Upload: others

Post on 09-Apr-2022

11 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Go(lang) to Python

Go(lang) to PythonEuropython 2019 Basel, Stefan Baerisch

[email protected]

�1

Page 2: Go(lang) to Python

Why this Talk?

�2

FrontendPython

Backend??? Good Performance

Good Concurrency / ParallelismExpressive Enough

Good Qt BindingsVery Expressive / ProductiveFast EnoughGood For ExperimentsGood Library SupportGood Cross Plattform SupportLow “Frustration” Factor

Page 3: Go(lang) to Python

Nice Things about Go

�3

Go has:

Automatic Memory ManagementLightweight, Managed Go-Routines No Sync/ASync

Very Quick Compiler

Quite Simple Language (“The Programming language for people that don’t like programming

languages”)

Page 4: Go(lang) to Python

Why Go with Python? Not {C++Rust} ?

�4

<Your Factor Here> Likely Good ??

OkGreatLow Frustration Factor Good

GreatGoodGreatLanguage Expressiveness

Ok GreatPerformance / Concurrency / Parallelism Good

Cpp / RustGoPython

Low Friction

Page 5: Go(lang) to Python

Some Spoilers

�5Image: Professor Butts and the Self-Operating Napkin (1931), Wikipedia, Public Domain

- Things work, but are currently far from elegant. - They are, however, quite interesting

Page 6: Go(lang) to Python

Wrapping Go - The Basics

�6

Page 7: Go(lang) to Python

Options for Using Go from Python

�7

Python

Go

Binary RPC (gRPC / Thrift)

Call External Command

Bindings

goPy

Roll me Own

Same Process? Published Api?Transport MechamisnTransport FormatQuestions…

….REST / JSON RPC

Page 8: Go(lang) to Python

Wrapping Go with CGO

�8https://golang.org/cmd/cgo/ https://dave.cheney.net/2016/01/18/cgo-is-not-go

Slower Build TimesMore Complex Builds When calling Go from C

Significant Overhead

Restrictions in Sharing Data

CGO has some drawbacks…

Go CGo Routines, scheduled by runtime

Go Segmented StacksGo Calling Convention

ThreadsFixed-size StacksC-Calling Convention

CGO

CGO makes bindings possible…

Page 9: Go(lang) to Python

High Level Architecture

�9

Python

Go

CGO

Cython C / C++ Support Code

Go Support Code

Idiomatic Go Code we want to use in Python

Export C API. Convert Parameters and Result

Values Manage Lifetime of Exported Go Data

C/C++ Representation of Value-based

parameters and results

Define Extention Types and Wrappers for CGO C

API

Page 10: Go(lang) to Python

Build Process

�10

Go Files

CGO File Go BuildStatic Libary

Header Files

C / C++ Support

python / C

Static Libary

Header Files

setup.py

Cython File

Python Module

Step 1

Step 2

Page 11: Go(lang) to Python

Wrapping a Simple Function

�11

Page 12: Go(lang) to Python

Simple Function - Goals

�12

Go

CGO

Cython

Python

func Add(v, v2 int) int {}

//export cgo_Addfunc cgo_Add(cgo_v1, cgo_v2 C.int) C.int {}

cpdef int add(int v1, int v2):

cdef extern from "cgo_lib/cgo_lib.h": int cgo_Add(int p0, int p1)

Code we want to use

Provide C API

Wrap C API

Use Functionality

Page 13: Go(lang) to Python

Simple Function - Go Code

�13

Result, can be multiple values, similar to tuplesParameters. name(s), then type

Function name, exported if it starts with capital letter

Page 14: Go(lang) to Python

Simple Function - CGO

�14

make available in C libC parameter / result types

Type conversation

Actual work

Build the Package Name of C Lib / Header Build Library

Page 15: Go(lang) to Python

Excerpt from the Header File

�15

Our FunctionCGO generated C Header

Page 16: Go(lang) to Python

Setup.py for Cython

�16

Build Command

Our C Library

Page 17: Go(lang) to Python

Simple Function - Cython

�17

Declare Function

Wrapper Function

Using it in Python

Page 18: Go(lang) to Python

Wrapping User Defined Types

�18

Page 19: Go(lang) to Python

User Defined Types in Go and Python

�19

GoPythonClasses / Extention Types User Defined Types

Exported MethodsMethods

Constructors / Factoryfunctinos Functions

Destructor (__del__, __dealloc___,…) Garbage Collection

Exceptions Error Result Values<ignored for now> Interfaces, Channels

Page 20: Go(lang) to Python

Wrapping User Types - Go Code

�20

Strings Object Pointer / Reference

Methods

Page 21: Go(lang) to Python

Wrapping User Types - References

�21

Data

Cython

Data

Cython

Proxy

Jobs of the Proxy

Keep the Go Garbage Collector away from the data shared with PythonTranslate the Go Pointer / Value into something we can share with Python

Not Possible: Direct Sharing of Go Data Possible: Using a Proxy

How to use Data References in Python?

Page 22: Go(lang) to Python

�22

Go Data Pointer ID Mapping

1

Go Data

2

1 Cython Wrapper

MemberMemberMethodMethod

MemberMemberMethodMethod … 1 Cython Wrapper

Cython Instance Management

Page 23: Go(lang) to Python

Wrapping User Types - References

�23

Id <=> Pointer Mapping Functions

Package Level Variable

Bookkeeping

Page 24: Go(lang) to Python

Wrapping User Types - CGO

�24

Convert Parameters / Results

Go Function Call

“Constructor”

“Destructor”

Page 25: Go(lang) to Python

Wrapping User Types - CGO

�25

Convert Parameters

Convert ResultsGet Object

Convert Parameters / Results

Page 26: Go(lang) to Python

Wrapping User Types - Headers

�26

CGO generated Headers

Cython Function Declaration

Page 27: Go(lang) to Python

User Types - Cython Constructor

�27

Manage ObjectsOnly Member - ID of the underlying Go objects

Convert Parameters

Request new or register existing object

Register Object

Page 28: Go(lang) to Python

Cython Method

�28

Get Name as C String from Go, via CGO

Page 29: Go(lang) to Python

Python Again

�29

Page 30: Go(lang) to Python

Wrapping Maps, Lists, etc. as Results and Parameters

Also: Errors

�30

Page 31: Go(lang) to Python

Complex Parameters/Results - Go

�31

Golang Error

Return Objects

Return Slice of Strings

Return Map

Page 32: Go(lang) to Python

Complex Results - How?

�32

How to express slices/list or maps/dicts on the way from Go to Python (and back)?

error exception?

object id extension typeuser type

map ? dict

?slice list

string *char str

int, uint… (unsigned) int int

Cython / PythonCgo / CGo

Page 33: Go(lang) to Python

Complex Results - Idea

�33

C++ has std::vector, std::mapCython can wrap C++

errors <=> exceptionoutput parameter

<=><=>

(unsigned) int

Cython

<=><=>

object id extension typeuser type

map *void to std::map, helper functions dict*void to std::vector, helper functionsslice list

string *char str

int, uint… (unsigned) int int PythonCgo / CGo

Output parameters are ok for errors, for now

Page 34: Go(lang) to Python

Complex Results - C API

�34

Page 35: Go(lang) to Python

Complex Results - C++

�35

Page 36: Go(lang) to Python

Complex Results -CGO

�36

Page 37: Go(lang) to Python

Complex Results - Cython

�37

Page 38: Go(lang) to Python

Errors -CGO

�38

Page 39: Go(lang) to Python

Errors- Cython

�39

Page 40: Go(lang) to Python

Complex Results & Errors - Python

�40

Page 41: Go(lang) to Python

Wrapping Callbacks

�41

Page 42: Go(lang) to Python

Wrapping Callbacks - Go Code

�42

How to have some callbacks? Callback: Int (age) to bool

Page 43: Go(lang) to Python

Wrapping Callbacks - Thougths

�43

C callpacks are function pointers…

Cython can build C-functions that call Python Code

So, we can have a C function pointer with Python Code

but CGO cannot call function pointers

CGO can call a c function that calls a function pointer

We want Go to call Python and use the result

We need to express the callback in our C/CGO layer

Page 44: Go(lang) to Python

Callbacks - Rube Goldberg Approach

�44

Cython C Callback

Cython Method Wrapper

C Function Pointer

C Function to Call Function Pointer

Go Method with Call Back

CGO Version of Go Method

Local Go Func

Python Callback passed to

passed to

callsassigns Python callback to

is

calls

calls

calls

passed to

defines and call

passed to

captures in Closure

Page 45: Go(lang) to Python

C Helper Functions for Callbacks

�45

Page 46: Go(lang) to Python

Wrapping Callbacks - CGO

�46

Page 47: Go(lang) to Python

Wrapping Callbacks - Cython

�47

Page 48: Go(lang) to Python

Python

�48

Page 49: Go(lang) to Python

Performance, Effort, Summary

�49

Page 50: Go(lang) to Python

Effort and Gain Wrapping Golang

�50

Golang ~ 130 LinesCGO ~ 220 LinesC Header ~30 LinesCPP Support Code ~50 LinesCython ~200 Lines

For this (simple) example, the amount of wrapper code is significant

Code is repetitive, leads itself to automation

Page 51: Go(lang) to Python

A Simple (Accessor) Benchmark

�51

Page 52: Go(lang) to Python

Go Bindings vs. Python Performance

�52

1493ms

1360ms

3209ms

93ms

443ms

256ms

619ms

Go Python

Page 53: Go(lang) to Python

Performance of Method Calls

�53

Go

Python

Page 54: Go(lang) to Python

Wrapping Go - Lessons Learned

�54

Things work

Cython works and is a pleasure to use

CGO works

Some boilerplate, but nothing to bad

Many Go Feature can be expressed in Python

Performance is a challenge

Improvements possible (Errors, Interfaces, Channels?)

Overhead to call into Go (runtime)

Mapping from Pointers to IDs

Looking into alternatives (C++ Msg Queue?)

Page 55: Go(lang) to Python

�55

The End