threadring.scm 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. ;;; The Computer Language Benchmarks Game
  2. ;;; http://shootout.alioth.debian.org/
  3. ;;; Kawa-Scheme implementation of thread-ring benchmark.
  4. ;;; Contributed by Per Bothner
  5. ;;; Based on Java 6 -server #4 version contributed by Fabien Le Floc'h
  6. ;;; Best performance is achieved with
  7. ;;; MAX_THREAD=1 as the thread-ring test is bested with only 1 os thread.
  8. ;;; This implementation shows using a simple thread pool solves the
  9. ;;; thread context switch issue.
  10. (define n :: int (string->number (cadr (command-line))))
  11. (define m :: int (if (null? (cddr (command-line))) 503
  12. (string->number (caddr (command-line)))))
  13. (define-constant MAX_NODES :: int m)
  14. (define-constant MAX_THREADS :: int m)
  15. (define-class TokenMessage ()
  16. (node-id :: int)
  17. (value :: int access: 'volatile)
  18. (is-stop :: boolean)
  19. ((*init* (node-id :: int) (value :: int))
  20. (set! (this):node-id node-id)
  21. (set! (this):value value))
  22. ((*init* (node-id :: int) (value :: int) (is-stop :: boolean))
  23. (set! (this):node-id node-id)
  24. (set! (this):value value)
  25. (set! (this):is-stop is-stop)))
  26. (define-class Node (java.lang.Runnable)
  27. (node-id :: int)
  28. (next-node :: Node)
  29. (queue :: java.util.concurrent.BlockingQueue
  30. init: (java.util.concurrent.LinkedBlockingQueue))
  31. (is-active :: boolean)
  32. (counter :: int)
  33. ((*init* (id :: int))
  34. (set! (this):node-id id))
  35. #|
  36. ((*init* (node :: Node))
  37. (set! (this):next-node node)
  38. (set! is-active #t))
  39. |#
  40. ((connect (node :: Node)) :: void
  41. (set! next-node node)
  42. (set! is-active #t))
  43. ((send-message (m :: TokenMessage)) :: void
  44. (queue:add m)
  45. (executor:execute (this)))
  46. ((run) :: void
  47. (if is-active
  48. (try-catch
  49. (let ((m :: TokenMessage (queue:take)))
  50. (if m:is-stop
  51. (let ((next-value (+ 1 m:value)))
  52. (cond ((= next-value MAX_NODES)
  53. (executor:shutdown))
  54. (else
  55. (set! m:value next-value)
  56. (next-node:send-message m)))
  57. (set! is-active #f))
  58. (cond ((= m:value n)
  59. (java.lang.System:out:println node-id)
  60. (next-node:send-message (TokenMessage node-id 0 #t)))
  61. (else
  62. (set! m:value (+ m:value 1))
  63. (next-node:send-message m)))))
  64. (ex java.lang.InterruptedException
  65. (ex:printStackTrace)))))
  66. )
  67. (define executor :: java.util.concurrent.ExecutorService
  68. (java.util.concurrent.Executors:newFixedThreadPool MAX_THREADS))
  69. (define nodes :: Node[] (Node[] length: (+ MAX_NODES 1)))
  70. (do ((i :: int 0 (+ i 1))) ((>= i MAX_NODES))
  71. (set! (nodes i) (Node (+ i 1))))
  72. (set! (nodes MAX_NODES) (nodes 0))
  73. (do ((i :: int 0 (+ i 1)))
  74. ((>= i MAX_NODES))
  75. ((nodes i):connect (nodes (+ i 1))))
  76. ((nodes 0):send-message (TokenMessage 1 0))