Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Thread Mist

Zete
October 11, 2015

Thread Mist

Ruby Conf China 2015 Talk

Zete

October 11, 2015
Tweet

More Decks by Zete

Other Decks in Programming

Transcript

  1. 精通各种…​ hello world, 喜欢 各种…​ 彩虹小马 和什么 GUI, 钻 研各种…​

    虚拟 机编译 器和, 有空就写一个…​ 跳票多年的编辑 器 @luikore
  2. Green Threads Ruby < = 1.8 comes with green threads

    Blocking IO (read/write) blocks other threads
  3. Timer Thread There is one thread that not visible in

    Ruby program, which schedules other threads.
  4. What does timer thread actually do? s t a t

    i c v o i d t i m e r _ t h r e a d _ f u n c t i o n ( v o i d * a r g ) { r b _ v m _ t * v m = G E T _ V M ( ) ; n a t i v e _ m u t e x _ l o c k ( & v m - > t h r e a d _ d e s t r u c t _ l o c k ) ; i f ( v m - > r u n n i n g _ t h r e a d ) A T O M I C _ O R ( v m - > r u n n i n g _ t h r e a d - > i n t e r r u p t _ f l a g , T I M E R _ I N T E R R U P T _ M A S n a t i v e _ m u t e x _ u n l o c k ( & v m - > t h r e a d _ d e s t r u c t _ l o c k ) ; }
  5. What other thread does in safe-points? i f ( (

    t h ) - > i n t e r r u p t _ f l a g & ~ ( t h ) - > i n t e r r u p t _ m a s k ) { r b _ t h r e a d p t r _ e x e c u t e _ i n t e r r u p t s ( ) ; }
  6. What is "execute interrupts"? v o i d r b

    _ t h r e a d p t r _ e x e c u t e _ i n t e r r u p t s ( ) { t i m e r _ i n t e r r u p t = i n t e r r u p t & T I M E R _ I N T E R R U P T _ M A S K ; . . . i f ( t i m e r _ i n t e r r u p t ) { . . . t h - > r u n n i n g _ t i m e _ u s + = r u n n i n t _ t i m e _ u s ; . . . r b _ t h r e a d _ s c h e d u l e _ l i m i t s ( l i m i t s _ u s ) ; } }
  7. What does "schedule limits" do? s t a t i

    c v o i d r b _ t h r e a d _ s c h e d u l e _ l i m i t s ( u n s i g n e d l o n g l i m i t s _ u s ) { . . . i f ( t h - > r u n n i n g _ t i m e _ u s > = l i m i t s _ u s ) { R B _ G C _ S A V E _ M A C H I N E _ C O N T E X T ( t h ) ; g v l _ y i e l d ( t h - > v m , t h ) ; / / r e l e a s e a n d c o m p e t e G V L } }
  8. What does the GVL look like? t y p e

    d e f s t r u c t r b _ g l o b a l _ v m _ l o c k _ s t r u c t { / * f a s t p a t h * / u n s i g n e d l o n g a c q u i r e d ; r b _ n a t i v e t h r e a d _ l o c k _ t l o c k ; / * s l o w p a t h * / v o l a t i l e u n s i g n e d l o n g w a i t i n g ; r b _ n a t i v e t h r e a d _ c o n d _ t c o n d ; / * y i e l d * / r b _ n a t i v e t h r e a d _ c o n d _ t s w i t c h _ c o n d ; r b _ n a t i v e t h r e a d _ c o n d _ t s w i t c h _ w a i t _ c o n d ; i n t n e e d _ y i e l d ; i n t w a i t _ y i e l d ; } r b _ g l o b a l _ v m _ l o c k _ t ;
  9. What is gvl_yield? n a t i v e _

    m u t e x _ l o c k ( & v m - > g v l . l o c k ) ; g v l _ r e l e a s e _ c o m m o n ( v m ) ; n a t i v e _ m u t e x _ u n l o c k ( & v m - > g v l . l o c k ) ; . . . s c h e d _ y i e l d ( ) ; . . . n a t i v e _ m u t e x _ l o c k ( & v m - > g v l . l o c k ) ; n a t i v e _ c o n d _ b r o a d c a s t ( & v m - > g v l . s w i t c h _ w a i t _ c o n d ) ; g v l _ a c q u i r e _ c o m m o n ( v m ) ; n a t i v e _ m u t e x _ u n l o c k ( & v m - > g v l . l o c k ) ;
  10. What is gvl_release_common? v m - > g v l

    . a c q u i r e d = 0 ; i f ( v m - > g v l . w a i t i n g > 0 ) n a t i v e _ c o n d _ s i g n a l ( & v m - > g v l . c o n d ) ;
  11. What is gvl_acquire_common? w h i l e ( v

    m - > g v l . a c q u i r e d ) { n a t i v e _ c o n d _ w a i t ( & v m - > g v l . c o n d , & v m - > g v l . l o c k ) ; }
  12. What does sched_yield come from? OS call to put current

    thread to lowest priority Think about Fiber.yield
  13. Condvars Resource Consumer # p s e u d o

    c o d e l o c k ( m u t e x ) w h i l e c o n d w a i t ( c o n d v a r , m u t e x ) e n d u n l o c k ( m u t e x )
  14. What GIL Guarantees Standalone C functions are "atomic" in MRI

    Easy for writing C extensions Release GIL when you know you are going into a "blocking region"
  15. Blocking Region V A L U E r b _

    t h r e a d _ i o _ b l o c k i n g _ r e g i o n ( r b _ b l o c k i n g _ f u n c t i o n _ t * f u n c , v o i d * d a t a 1 , { . . . t h - > w a i t i n g _ f d = f d ; . . . B L O C K I N G _ R E G I O N ( { v a l = f u n c ( d a t a 1 ) ; s a v e d _ e r r n o = e r r n o ; } , u b f _ s e l e c t , t h , F A L S E ) ; }
  16. Blocking Region (2) What BLOCKING_REGION macro does R B _

    G C _ S A V E _ M A C H I N E _ C O N T E X T ( t h ) ; g v l _ r e l e a s e ( t h - > v m ) ; . . . / / d o y o u r b l o c k i n g w o r k ! g v l _ a c q u i r e ( t h - > v m , t h ) ;
  17. Blocking Calls accept — accept an incoming connection read — read some data from

    a socket or file select — choose available file descriptors poll — simpler select epoll — inverse control, wake up by OS kevent — the kqueue version of epoll …​ many more
  18. Parallelism? Don’t Use Threads For Parallelism It is slower …​

    a = 1 . . 2 0 b = 1 . . 2 0 a s u m , b s u m = 0 , 0 t = T h r e a d . n e w { a s u m = a . i n j e c t : + } b s u m = b . i n j e c t : + t . j o i n p u t s a s u m + b s u m
  19. Parallelism? Just: a . i n j e c t

    ( : + ) + b . i n j e c t ( : + )
  20. Choose # of Threads Too many: time wasted in context

    switching Too few: users have to wait in a queue while your CPU io-waits
  21. Manually Release GVL Already used in zlib, so ruby multi-thread

    spiders can utilize up to 2 cores g v l _ r e l e a s e ( t h ) . . . / / y o u k n o w t h a t c o d e d o e s n ' t a f f e c t R u b y g v l _ a c q u i r e ( t h )
  22. IO: your Bottle Neck 1 0 0 . t i

    m e s d o C o m m e n t . c r e a t e p o s t : p o s t , " r a b b i t # { r a n d } " e n d
  23. Batch: Reduce IO Latency Simple way to batch SQL — transaction t

    r a n s a c t i o n d o 1 0 0 . t i m e s d o C o m m e n t . c r e a t e p o s t : p o s t , " r a b b i t # { r a n d } " e n d e n d
  24. IO is Everywhere…​ NUMA abstracts memory visits DMA reduces memory

    copying Sharing between APU and FPU Sharing between LLC and main memory Sharing between CPU and GPU …​
  25. Connection Pool Limit Some long jobs took too long to

    finish, exhausting the connection pool, then blocked other threads…​
  26. Manually Release Connection Release it manually before starting something that

    takes a long time: # i n r a i l s a c t i o n o r s i d e k i q j o b A c t i v e R e c o r d : : B a s e . c l e a r _ a c t i v e _ c o n n e c t i o n s ! N e t : : H T T P . g e t ' h t t p : / / e x a m p l e . c o m '