See Python, See Python Go, Go Python Go

See Python, See Python Go, Go Python Go

Talk given at PyCon 2016: https://us.pycon.org/2016/schedule/presentation/1633/

Being able to run C code from Python is pretty great, but what about running Go code from Python? Or even Python from Go? This talk will walk through the process of executing calls between Python and Go using CFFI bindings to bridge the two runtimes.
...

C355dd26a5f80e1605d2ff1ecb6e719e?s=128

Andrey Petrov

June 01, 2016
Tweet

Transcript

  1. See Python, See Python Go, Go Python Go Presented by

    Andrey Petrov at PyCon 2016 Andrey Petrov · @shazow
  2. Andrey Petrov @shazow urllib3, ssh-chat, briefmetrics, colorblendy, tweepsect, funny tweets,

    and more Andrey Petrov · @shazow
  3. Do you Go? Andrey Petrov · @shazow

  4. Do you Go? Simple syntax that is easy to learn

    Andrey Petrov · @shazow
  5. Do you Go? Simple syntax that is easy to learn

    Compiles superfast Andrey Petrov · @shazow
  6. Do you Go? Simple syntax that is easy to learn

    Compiles superfast Statically typed Andrey Petrov · @shazow
  7. Do you Go? Simple syntax that is easy to learn

    Compiles superfast Statically typed Statically linked binaries Andrey Petrov · @shazow
  8. Do you Go? Simple syntax that is easy to learn

    Compiles superfast Statically typed Statically linked binaries Cross-compiles to ~every platform Andrey Petrov · @shazow
  9. Do you Go? Simple syntax that is easy to learn

    Compiles superfast Statically typed Statically linked binaries Cross-compiles to ~every platform Easy concurrency Andrey Petrov · @shazow
  10. Do you Go? Simple syntax that is easy to learn

    Compiles superfast Statically typed Statically linked binaries Cross-compiles to ~every platform Easy concurrency Great standard library Andrey Petrov · @shazow
  11. Do you Go? Simple syntax that is easy to learn

    Compiles superfast Statically typed Statically linked binaries Cross-compiles to ~every platform Easy concurrency Great standard library Gophers! Andrey Petrov · @shazow
  12. Python Go Andrey Petrov · @shazow Credit: Renee French &

    Alice Tribuleva
  13. Go in Python i m p o r t o

    s o s . s y s t e m ( " g o r u n m a i n . g o " ) Andrey Petrov · @shazow
  14. Go in Python i m p o r t o

    s o s . s y s t e m ( " g o r u n m a i n . g o " ) lol just kidding Andrey Petrov · @shazow
  15. Fun Facts Python speaks with C Andrey Petrov · @shazow

  16. Fun Facts Python speaks with C Go speaks with C

    Andrey Petrov · @shazow
  17. Fun Facts Python speaks with C Go speaks with C

    Therefore, Python speaks with Go? Andrey Petrov · @shazow
  18. Challenges 1. Runtime barriers Andrey Petrov · @shazow

  19. Challenges 1. Runtime barriers Garbage Collectors (GC) Global Interpreter Lock

    (GIL) Just In Time compiling (JIT) Resource Pools (Threads) Andrey Petrov · @shazow
  20. Challenges 1. Runtime barriers Garbage Collectors (GC) Global Interpreter Lock

    (GIL) Just In Time compiling (JIT) Resource Pools (Threads) 2. Syntax and feature barriers Andrey Petrov · @shazow
  21. Challenges 1. Runtime barriers Garbage Collectors (GC) Global Interpreter Lock

    (GIL) Just In Time compiling (JIT) Resource Pools (Threads) 2. Syntax and feature barriers Go: Interface, Goroutines, etc. Python: Classes, Generators, etc. Oodles of other language-specific constructs Andrey Petrov · @shazow
  22. Go runtime Python runtime C GIL GC Interpreter Ponies GC

    Goroutines Gophers Andrey Petrov · @shazow
  23. Let's take a moment and imagine... Andrey Petrov · @shazow

  24. Running a webserver in Go p a c k a

    g e m a i n i m p o r t ( " f m t " " n e t / h t t p " ) f u n c i n d e x ( w h t t p . R e s p o n s e W r i t e r , r e q * h t t p . R e q u e s t ) { f m t . F p r i n t f ( w , " H e l l o , w o r l d . \ n " ) } f u n c m a i n ( ) { h t t p . H a n d l e F u n c ( " / " , i n d e x ) h t t p . L i s t e n A n d S e r v e ( " 1 2 7 . 0 . 0 . 1 : 5 0 0 0 " , n i l ) } Andrey Petrov · @shazow
  25. Running a webserver in Python f r o m f

    l a s k i m p o r t F l a s k a p p = F l a s k ( _ _ n a m e _ _ ) @ a p p . r o u t e ( ' / ' ) d e f i n d e x ( ) : r e t u r n ' H e l l o , w o r l d ! \ n ' i f _ _ n a m e _ _ = = ' _ _ m a i n _ _ ' : a p p . r u n ( h o s t = ' 1 2 7 . 0 . 0 . 1 ' , p o r t = 5 0 0 0 ) Andrey Petrov · @shazow
  26. Running a Go webserver in Python?? f r o m

    g o h t t p i m p o r t r o u t e , r u n @ r o u t e ( ' / ' ) d e f i n d e x ( w , r e q ) : w . w r i t e ( " H e l l o , w o r l d . \ n " ) i f _ _ n a m e _ _ = = ' _ _ m a i n _ _ ' : r u n ( h o s t = ' 1 2 7 . 0 . 0 . 1 ' , p o r t = 5 0 0 0 ) Andrey Petrov · @shazow
  27. Running a Go webserver in Python?? f r o m

    g o h t t p i m p o r t r o u t e , r u n @ r o u t e ( ' / ' ) d e f i n d e x ( w , r e q ) : w . w r i t e ( " H e l l o , w o r l d . \ n " ) i f _ _ n a m e _ _ = = ' _ _ m a i n _ _ ' : r u n ( h o s t = ' 1 2 7 . 0 . 0 . 1 ' , p o r t = 5 0 0 0 ) Compare f r o m f l a s k i m p o r t F l a s k a p p = F l a s k ( _ _ n a m e _ _ ) @ a p p . r o u t e ( ' / ' ) d e f i n d e x ( ) : r e t u r n ' H e l l o , w o r l d ! \ n ' i f _ _ n a m e _ _ = = ' _ _ m a i n _ _ ' : a p p . r u n ( h o s t = ' 1 2 7 . 0 . 0 . 1 ' , p o r t = 5 0 0 0 ) Andrey Petrov · @shazow
  28. Comparing handlers Go (net/http) f u n c i n

    d e x ( w h t t p . R e s p o n s e W r i t e r , r e q * h t t p . R e q u e s t ) { f m t . F p r i n t f ( w , " H e l l o , w o r l d . \ n " ) } Go in Python (gohttplib) d e f i n d e x ( w , r e q ) : w . w r i t e ( " H e l l o , w o r l d . \ n " ) Python (flask) d e f i n d e x ( ) : r e t u r n ' H e l l o , w o r l d ! \ n ' Andrey Petrov · @shazow
  29. gohttplib This is an actual functioning thing. github.com/shazow/gohttplib Andrey Petrov

    · @shazow
  30. gohttplib This is an actual functioning thing. github.com/shazow/gohttplib Sponsored by

    Glider Labs Andrey Petrov · @shazow
  31. Here's how it works... Andrey Petrov · @shazow

  32. The Plan 1. Go: Export Go functions to a C

    shared library 2. C: 3. Python: Call C and wrap it in a Python-shaped bow 4. Make it actually work ¯\_(ツ)_/¯ Andrey Petrov · @shazow
  33. Andrey Petrov · @shazow

  34. Calling C from Go p a c k a g

    e m a i n / * i n t t h e _ a n s w e r ( ) { r e t u r n 4 2 ; } * / i m p o r t " C " i m p o r t " f m t " f u n c m a i n ( ) { r : = C . t h e _ a n s w e r ( ) f m t . P r i n t l n ( r ) } Andrey Petrov · @shazow
  35. Calling C from Go p a c k a g

    e m a i n / * i n t t h e _ a n s w e r ( ) { r e t u r n 4 2 ; } * / i m p o r t " C " i m p o r t " f m t " f u n c m a i n ( ) { r : = C . t h e _ a n s w e r ( ) f m t . P r i n t l n ( r ) } $ g o b u i l d - o a n s w e r $ . / a n s w e r 4 2 Andrey Petrov · @shazow
  36. Calling Go from C p a c k a g

    e m a i n i m p o r t " C " / / e x p o r t T h e A n s w e r f u n c T h e A n s w e r ( ) C . i n t { r e t u r n C . i n t ( 4 2 ) } f u n c m a i n ( ) { } Andrey Petrov · @shazow
  37. Calling Go from C p a c k a g

    e m a i n i m p o r t " C " / / e x p o r t T h e A n s w e r f u n c T h e A n s w e r ( ) C . i n t { r e t u r n C . i n t ( 4 2 ) } f u n c m a i n ( ) { } $ g o b u i l d - b u i l d m o d e = c - s h a r e d - o l i b a n s w e r . s o Andrey Petrov · @shazow
  38. Calling Go from C p a c k a g

    e m a i n i m p o r t " C " / / e x p o r t T h e A n s w e r f u n c T h e A n s w e r ( ) C . i n t { r e t u r n C . i n t ( 4 2 ) } f u n c m a i n ( ) { } $ g o b u i l d - b u i l d m o d e = c - s h a r e d - o l i b a n s w e r . s o # i n c l u d e < s t d i o . h > # i n c l u d e " l i b a n s w e r . h " i n t m a i n ( ) { i n t r = T h e A n s w e r ( ) ; p r i n t f ( " % d \ n " , r ) ; r e t u r n 0 ; } Andrey Petrov · @shazow
  39. Andrey Petrov · @shazow

  40. See CPython C CPython Extension Interface: no dependencies, but lots

    of boilerplate CFFI: a little more magic but does more work for us and more portable Andrey Petrov · @shazow
  41. Calling C from Python # a n s w e

    r _ b u i l d . p y : f r o m c f f i i m p o r t F F I f f i = F F I ( ) f f i . c d e f ( " i n t t h e _ a n s w e r ( ) ; " ) f f i . s e t _ s o u r c e ( " _ a n s w e r " , " " " i n t t h e _ a n s w e r ( ) { r e t u r n 4 2 ; } " " " ) i f _ _ n a m e _ _ = = " _ _ m a i n _ _ " : f f i . c o m p i l e ( ) Andrey Petrov · @shazow
  42. Calling C from Python # a n s w e

    r _ b u i l d . p y : f r o m c f f i i m p o r t F F I f f i = F F I ( ) f f i . c d e f ( " i n t t h e _ a n s w e r ( ) ; " ) f f i . s e t _ s o u r c e ( " _ a n s w e r " , " " " i n t t h e _ a n s w e r ( ) { r e t u r n 4 2 ; } " " " ) i f _ _ n a m e _ _ = = " _ _ m a i n _ _ " : f f i . c o m p i l e ( ) $ p y t h o n a n s w e r _ b u i l d . p y $ l s _ a n s w e r . c _ a n s w e r . o _ a n s w e r . s o a n s w e r _ b u i l d . p y Andrey Petrov · @shazow
  43. Calling C from Python # a n s w e

    r _ b u i l d . p y : f r o m c f f i i m p o r t F F I f f i = F F I ( ) f f i . c d e f ( " i n t t h e _ a n s w e r ( ) ; " ) f f i . s e t _ s o u r c e ( " _ a n s w e r " , " " " i n t t h e _ a n s w e r ( ) { r e t u r n 4 2 ; } " " " ) i f _ _ n a m e _ _ = = " _ _ m a i n _ _ " : f f i . c o m p i l e ( ) $ p y t h o n a n s w e r _ b u i l d . p y $ l s _ a n s w e r . c _ a n s w e r . o _ a n s w e r . s o a n s w e r _ b u i l d . p y # a n s w e r . p y : f r o m _ a n s w e r i m p o r t l i b p r i n t ( l i b . t h e _ a n s w e r ( ) ) Andrey Petrov · @shazow
  44. Calling Python from C Simple function pointer that can be

    used in C: @ f f i . c a l l b a c k ( " i n t ( i n t , i n t ) " ) d e f a d d ( x , y ) : r e t u r n x + y Andrey Petrov · @shazow
  45. Calling Python from C Simple function pointer that can be

    used in C: @ f f i . c a l l b a c k ( " i n t ( i n t , i n t ) " ) d e f a d d ( x , y ) : r e t u r n x + y ~handwaving~ Andrey Petrov · @shazow
  46. Calling Python from C Simple function pointer that can be

    used in C: @ f f i . c a l l b a c k ( " i n t ( i n t , i n t ) " ) d e f a d d ( x , y ) : r e t u r n x + y ~handwaving~ s t a t i c i n t ( * a d d ) ( i n t x , i n t b ) ; That's all we need for now. More on CFFI embedding here. Andrey Petrov · @shazow
  47. Challenges 1. Runtime barriers Garbage Collectors (GC) Global Interpreter Lock

    (GIL) Just In Time compiling in PyPy (JIT) Thread Pools 2. Syntax and feature barriers Go: Interface, Goroutines, etc. Python: Classes, Generators, etc. Oodles of other language-specific constructs Andrey Petrov · @shazow
  48. Overcoming Challenges 1. Don't share memory Andrey Petrov · @shazow

  49. Go runtime Python runtime C GIL GC Interpreter Ponies GC

    Goroutines Gophers Andrey Petrov · @shazow
  50. Challenge 1: Don't share memory h t t p .

    H a n d l e F u n c ( p a t t e r n , f u n c ( w h t t p . R e s p o n s e W r i t e r , r e q * h t t p . R e q u e s t ) { . . . } ) Our Python code will need to provide this callback, but we can't pass * h t t p . R e q u e s t to Python. Andrey Petrov · @shazow
  51. Challenge 1: Don't share memory h t t p .

    H a n d l e F u n c ( p a t t e r n , f u n c ( w h t t p . R e s p o n s e W r i t e r , r e q * h t t p . R e q u e s t ) { . . . } ) Our Python code will need to provide this callback, but we can't pass * h t t p . R e q u e s t to Python. t y p e d e f s t r u c t R e q u e s t _ { c o n s t c h a r * M e t h o d ; c o n s t c h a r * H o s t ; . . . } R e q u e s t ; Andrey Petrov · @shazow
  52. Challenge 1: Don't share memory h t t p .

    H a n d l e F u n c ( p a t t e r n , f u n c ( w h t t p . R e s p o n s e W r i t e r , r e q * h t t p . R e q u e s t ) { . . . } ) Our Python code will need to provide this callback, but we can't pass * h t t p . R e q u e s t to Python. t y p e d e f s t r u c t R e q u e s t _ { c o n s t c h a r * M e t h o d ; c o n s t c h a r * H o s t ; . . . } R e q u e s t ; h t t p . H a n d l e F u n c ( p a t t e r n , f u n c ( w h t t p . R e s p o n s e W r i t e r , r e q * h t t p . R e q u e s t ) { / / W r a p r e l e v a n t r e q u e s t f i e l d s i n a C - f r i e n d l y d a t a s t r u c t u r e . c r e q : = C . R e q u e s t { M e t h o d : C . C S t r i n g ( r e q . M e t h o d ) , H o s t : C . C S t r i n g ( r e q . H o s t ) , . . . } . . . Andrey Petrov · @shazow
  53. Overcoming Challenges 1. Don't share memory 2. Translation layer Andrey

    Petrov · @shazow
  54. Challenge 2: Translation layer h t t p . H

    a n d l e F u n c ( p a t t e r n , f u n c ( w h t t p . R e s p o n s e W r i t e r , r e q * h t t p . R e q u e s t ) { . . . } ) Our Python code will need to use the h t t p . R e s p o n s e W r i t e r interface. Andrey Petrov · @shazow
  55. Challenge 2: Translation layer h t t p . H

    a n d l e F u n c ( p a t t e r n , f u n c ( w h t t p . R e s p o n s e W r i t e r , r e q * h t t p . R e q u e s t ) { . . . } ) Our Python code will need to use the h t t p . R e s p o n s e W r i t e r interface. R e s p o n s e W r i t e r . W r i t e ( [ ] b y t e ) ( i n t , e r r o r ) R e s p o n s e W r i t e r . W r i t e H e a d e r ( i n t ) Andrey Petrov · @shazow
  56. Challenge 2: Translation layer h t t p . H

    a n d l e F u n c ( p a t t e r n , f u n c ( w h t t p . R e s p o n s e W r i t e r , r e q * h t t p . R e q u e s t ) { . . . } ) Our Python code will need to use the h t t p . R e s p o n s e W r i t e r interface. R e s p o n s e W r i t e r . W r i t e ( [ ] b y t e ) ( i n t , e r r o r ) R e s p o n s e W r i t e r . W r i t e H e a d e r ( i n t ) / / e x p o r t R e s p o n s e W r i t e r _ W r i t e f u n c R e s p o n s e W r i t e r _ W r i t e ( w P t r C . u i n t , c b u f * C . c h a r , l e n g t h C . i n t ) C . i n t { b u f : = C . G o B y t e s ( u n s a f e . P o i n t e r ( c b u f ) , l e n g t h ) . . . n , _ : = ( * ( * h t t p . R e s p o n s e W r i t e r ) ( w ) ) . W r i t e ( b u f ) r e t u r n C . i n t ( n ) } / / e x p o r t R e s p o n s e W r i t e r _ W r i t e H e a d e r f u n c R e s p o n s e W r i t e r _ W r i t e H e a d e r ( w P t r C . u i n t , h e a d e r C . i n t ) { . . . ( * ( * h t t p . R e s p o n s e W r i t e r ) ( w ) ) . W r i t e H e a d e r ( i n t ( h e a d e r ) ) } Andrey Petrov · @shazow
  57. Challenge 2: Translation layer (Cont.) We exported these functions in

    Go R e s p o n s e W r i t e r _ W r i t e ( w P t r C . u i n t , c b u f * C . c h a r , l e n g t h C . i n t ) C . i n t R e s p o n s e W r i t e r _ W r i t e H e a d e r ( w P t r C . u i n t , h e a d e r C . i n t ) Now we can wrap them in Python l i b = f f i . d l o p e n ( . . . ) c l a s s R e s p o n s e W r i t e r : d e f _ _ i n i t _ _ ( s e l f , w ) : s e l f . _ w = w d e f w r i t e ( s e l f , b o d y ) : n = l i b . R e s p o n s e W r i t e r _ W r i t e ( s e l f . _ w , b o d y , l e n ( b o d y ) ) i f n ! = l e n ( b o d y ) : r a i s e I O E r r o r ( " F a i l e d t o w r i t e t o R e s p o n s e W r i t e r . " ) d e f s e t _ s t a t u s ( s e l f , c o d e ) : l i b . R e s p o n s e W r i t e r _ W r i t e H e a d e r ( s e l f . _ w , c o d e ) Andrey Petrov · @shazow
  58. Challenge 2: Translation layer (Cont.) Original interface in Go: t

    y p e h t t p . R e s p o n s e W r i t e r i n t e r f a c e { W r i t e H e a d e r ( i n t ) } Andrey Petrov · @shazow
  59. Challenge 2: Translation layer (Cont.) Original interface in Go: t

    y p e h t t p . R e s p o n s e W r i t e r i n t e r f a c e { W r i t e H e a d e r ( i n t ) } Exported interface from Go: f u n c R e s p o n s e W r i t e r _ W r i t e H e a d e r ( w P t r C . u i n t , h e a d e r C . i n t ) Andrey Petrov · @shazow
  60. Challenge 2: Translation layer (Cont.) Original interface in Go: t

    y p e h t t p . R e s p o n s e W r i t e r i n t e r f a c e { W r i t e H e a d e r ( i n t ) } Exported interface from Go: f u n c R e s p o n s e W r i t e r _ W r i t e H e a d e r ( w P t r C . u i n t , h e a d e r C . i n t ) C header: v o i d R e s p o n s e W r i t e r _ W r i t e H e a d e r ( u n s i g n e d i n t p 0 , i n t p 1 ) ; Andrey Petrov · @shazow
  61. Challenge 2: Translation layer (Cont.) Original interface in Go: t

    y p e h t t p . R e s p o n s e W r i t e r i n t e r f a c e { W r i t e H e a d e r ( i n t ) } Exported interface from Go: f u n c R e s p o n s e W r i t e r _ W r i t e H e a d e r ( w P t r C . u i n t , h e a d e r C . i n t ) C header: v o i d R e s p o n s e W r i t e r _ W r i t e H e a d e r ( u n s i g n e d i n t p 0 , i n t p 1 ) ; Accessing C from Python: R e s p o n s e W r i t e r _ W r i t e H e a d e r ( w , h e a d e r ) Andrey Petrov · @shazow
  62. Challenge 2: Translation layer (Cont.) Original interface in Go: t

    y p e h t t p . R e s p o n s e W r i t e r i n t e r f a c e { W r i t e H e a d e r ( i n t ) } Exported interface from Go: f u n c R e s p o n s e W r i t e r _ W r i t e H e a d e r ( w P t r C . u i n t , h e a d e r C . i n t ) C header: v o i d R e s p o n s e W r i t e r _ W r i t e H e a d e r ( u n s i g n e d i n t p 0 , i n t p 1 ) ; Accessing C from Python: R e s p o n s e W r i t e r _ W r i t e H e a d e r ( w , h e a d e r ) Python wrapper: R e s p o n s e W r i t e r . s e t _ s t a t u s ( s e l f , c o d e ) Andrey Petrov · @shazow
  63. Overcoming Challenges 1. Don't share memory 2. Translation layer 3.

    Seriously, don't share memory Andrey Petrov · @shazow
  64. Challenge 3: Seriously, don't share memory Wait, what's a Go

    interface? Andrey Petrov · @shazow
  65. Challenge 3: Seriously, don't share memory Wait, what's a Go

    interface? To use it, we need to pass a pointer through ☞ Go ⇢ C ⇢ Python ⇢ C ⇢ Go ☞ Andrey Petrov · @shazow
  66. Challenge 3: Seriously, don't share memory Wait, what's a Go

    interface? To use it, we need to pass a pointer through ☞ Go ⇢ C ⇢ Python ⇢ C ⇢ Go ☞ Solution: Pointer Proxy! Andrey Petrov · @shazow
  67. Pointer Proxy PtrProxy ResponseWriter 0xd34db33f PtrId 1234 Ref Deref Free

    Safe for Go Safe for C Andrey Petrov · @shazow
  68. Pointer Proxy t y p e p t r P

    r o x y s t r u c t { s y n c . M u t e x c o u n t u i n t l o o k u p m a p [ u i n t ] u n s a f e . P o i n t e r } f u n c ( p * p t r P r o x y ) R e f ( p t r u n s a f e . P o i n t e r ) C . u i n t { . . . } f u n c ( p * p t r P r o x y ) D e r e f ( i d C . u i n t ) ( u n s a f e . P o i n t e r , b o o l ) { . . . } f u n c ( p * p t r P r o x y ) F r e e ( i d C . u i n t ) { . . . } Now we can pass an opaque uint across enemy lines and it's perfectly safe. Andrey Petrov · @shazow
  69. Quick flashback: Translation layer One pointer proxy to rule them

    all. v a r c p o i n t e r s = P t r P r o x y ( ) Andrey Petrov · @shazow
  70. Quick flashback: Translation layer One pointer proxy to rule them

    all. v a r c p o i n t e r s = P t r P r o x y ( ) In the callback, reference to bind them. ⛓ h t t p . H a n d l e F u n c ( p a t t e r n , f u n c ( w h t t p . R e s p o n s e W r i t e r , r e q * h t t p . R e q u e s t ) { / / W r a p r e l e v a n t r e q u e s t f i e l d s i n a C - f r i e n d l y d a t a s t r u c t u r e . c r e q : = C . R e q u e s t { . . . } w P t r : = c p o i n t e r s . R e f ( u n s a f e . P o i n t e r ( & w ) ) . . . c p o i n t e r s . F r e e ( w P t r ) } ) Andrey Petrov · @shazow
  71. Quick flashback: Translation layer One pointer proxy to rule them

    all. v a r c p o i n t e r s = P t r P r o x y ( ) In the callback, reference to bind them. ⛓ h t t p . H a n d l e F u n c ( p a t t e r n , f u n c ( w h t t p . R e s p o n s e W r i t e r , r e q * h t t p . R e q u e s t ) { / / W r a p r e l e v a n t r e q u e s t f i e l d s i n a C - f r i e n d l y d a t a s t r u c t u r e . c r e q : = C . R e q u e s t { . . . } w P t r : = c p o i n t e r s . R e f ( u n s a f e . P o i n t e r ( & w ) ) . . . c p o i n t e r s . F r e e ( w P t r ) } ) With pointer proxy, dereference to find them. f u n c R e s p o n s e W r i t e r _ W r i t e H e a d e r ( w P t r C . u i n t , h e a d e r C . i n t ) { w , _ : = c p o i n t e r s . D e r e f ( w P t r ) ( * ( * h t t p . R e s p o n s e W r i t e r ) ( w ) ) . W r i t e H e a d e r ( i n t ( h e a d e r ) ) } Andrey Petrov · @shazow
  72. Recap If our languages can speak with C, they can

    speak with each other. Andrey Petrov · @shazow
  73. Recap If our languages can speak with C, they can

    speak with each other. Be careful going in and out of runtimes. Andrey Petrov · @shazow
  74. Recap If our languages can speak with C, they can

    speak with each other. Be careful going in and out of runtimes. Be super-careful with sharing memory. Andrey Petrov · @shazow
  75. Recap If our languages can speak with C, they can

    speak with each other. Be careful going in and out of runtimes. Be super-careful with sharing memory. We'll need a translation layer to use non-trivial language constructs. Andrey Petrov · @shazow
  76. Other Considerations Andrey Petrov · @shazow

  77. Other Considerations Memory leaks Andrey Petrov · @shazow

  78. Other Considerations Memory leaks Race conditions Andrey Petrov · @shazow

  79. Other Considerations Memory leaks Race conditions Context switching overhead Andrey

    Petrov · @shazow
  80. Other Considerations Memory leaks Race conditions Context switching overhead Probably

    security issues because C is hard Andrey Petrov · @shazow
  81. Other Considerations Memory leaks Race conditions Context switching overhead Probably

    security issues because C is hard Architecture campanelle Andrey Petrov · @shazow
  82. A Palate Cleanser Andrey Petrov · @shazow

  83. A Palate Cleanser ✨ LOLBENCHMARKS! Andrey Petrov · @shazow

  84. LOLBENCHMARKS Andrey Petrov · @shazow

  85. LOLBENCHMARKS Name Total Req/Sec Time/Req go-net/http 1.115 8969.89 0.111 gohttp-c

    1.181 8470.97 0.118 gohttp-python 1.285 7779.87 0.129 gunicorn-flask 7.826 1277.73 0.783 werkzeug-flask 15.029 665.37 1.503 Conditions: a b doing 10,000 requests with 10 concurrency on my . Andrey Petrov · @shazow
  86. Thank you github.com/shazow/gohttplib hrku.co/gopythongo twitter.com/shazow shazow.net Andrey Petrov · @shazow