diff --git a/collects/web-server/docs/reference/dispatchers.scrbl b/collects/web-server/docs/reference/dispatchers.scrbl index ad80cf45a0..62ee400113 100644 --- a/collects/web-server/docs/reference/dispatchers.scrbl +++ b/collects/web-server/docs/reference/dispatchers.scrbl @@ -221,7 +221,9 @@ that invokes a sequence of dispatchers until one applies. @file{dispatchers/dispatch-servlets.ss} defines a dispatcher constructor that runs servlets written in Scheme. +@; XXX Add default manager arg @; XXX Remove config:instances +@; XXX Remove config:scripts @; XXX Define make-servlet-namespace? @defproc[(make [config:instances any/c] [config:scripts (box/c cache-table?)] diff --git a/collects/web-server/docs/reference/managers.scrbl b/collects/web-server/docs/reference/managers.scrbl index 8b31e2cbcc..d54c4e0f93 100644 --- a/collects/web-server/docs/reference/managers.scrbl +++ b/collects/web-server/docs/reference/managers.scrbl @@ -87,9 +87,73 @@ Web Language. (See @secref["lang"].) @; ------------------------------------------------------------ @section[#:tag "timeouts"]{Timeouts} -XXX +@file{managers/timeouts.ss} defines a manager constructor: +@defproc[(create-timeout-manager [instance-exp-handler expiration-handler?] + [instance-timeout number?] + [continuation-timeout number?]) + manager?]{ + Instances managed by this manager will be expired @scheme[instance-timeout] + seconds after the last time it is accessed. If an expired instance is + looked up, the @scheme[exn:fail:servlet-manager:no-instance] exception + is thrown with @scheme[instance-exp-handler] as the expiration handler. + + Continuations managed by this manager will be expired @scheme[continuation-timeout] + seconds after the last time it is accessed. If an expired continuation is looked + up, the @scheme[exn:fail:servlet-manager:no-continuation] exception + is thrown with @scheme[instance-exp-handler] as the expiration handler, if + no expiration-handler was passed to @scheme[continuation-store!]. +} + +This manager has been found to be... problematic... in large-scale +deployments of the @file{web-server}. + @; ------------------------------------------------------------ @section[#:tag "lru"]{LRU} -XXX \ No newline at end of file +@file{managers/lru.ss} defines a manager constructor: + +@; XXX Rename time0 and time1 +@; XXX Cite Continue +@defproc[(create-LRU-manager + [instance-expiration-handler expiration-handler?] + [time0 integer?] + [time1 integer?] + [collect? (-> boolean?)] + [#:initial-count initial-count integer? 1] + [#:inform-p inform-p (integer? . -> . void) (lambda _ (void))]) + manager?]{ + Instances managed by this manager will be expired if there are no + continuations associated with them, after the instance is unlocked. + If an expired instance is looked up, the + @scheme[exn:fail:servlet-manager:no-instance] exception + is thrown with @scheme[instance-exp-handler] as the expiration handler. + + Continuations managed by this manager are given a "Life Count" of + @scheme[initial-count] initially. If an expired continuation is looked + up, the @scheme[exn:fail:servlet-manager:no-continuation] exception + is thrown with @scheme[instance-exp-handler] as the expiration handler, if + no expiration-handler was passed to @scheme[continuation-store!]. + + Every @scheme[time0] seconds @scheme[collect?] is called to determine + if the collection routine should be run. Every @scheme[time1] seconds + the collection routine is run. + + Every time the collection routine runs, the "Life Count" of every + continuation is decremented by @scheme[1]. If a continuation's count + reaches @scheme[0], it is expired. The @scheme[inform-p] function + is called if any continuations are expired, with the number of + continuations expired. +} + +The recommended use of this manager is to pass, as @scheme[collect?], a +function that checks the memory usage of the system, through +@scheme[current-memory-use]. Then, @scheme[time1] should be sufficiently +large compared to @scheme[time0]. This way, if the load on the server +spikes---as indicated by memory usage---the server will quickly expire +continuations, until the memory is back under control. If the load +stays low, it will still efficiently expire old continuations. + +With Continue, we went from needing to restart the server a few times +a week and having many complaints under load, to not having these complaints +and not needing to restart the server for performance reasons. diff --git a/collects/web-server/managers/lru.ss b/collects/web-server/managers/lru.ss index cc82ef4790..f0a37ff489 100644 --- a/collects/web-server/managers/lru.ss +++ b/collects/web-server/managers/lru.ss @@ -125,30 +125,30 @@ next-instance-id)) ; Collector - (define (collect) + (define (collect just-go?) (define removed (box 0)) - (when (collect?) - (hash-table-for-each - instances - (match-lambda* - [(list instance-id (struct instance (_ (struct k-table (next-id-fn htable)) use-count))) - (define empty? (box #t)) - (hash-table-for-each - htable - (match-lambda* - [(list k-id (list s k eh count)) - (if (zero? count) - (begin (set-box! removed (add1 (unbox removed))) - (hash-table-remove! htable k-id)) - (begin (set-box! empty? #f) - (hash-table-put! htable k-id - (list s k eh (sub1 count)))))])) - (when (and (unbox empty?) - ; XXX race condition - (zero? use-count)) - (set-box! removed (add1 (unbox removed))) - (hash-table-remove! instances instance-id))]))) - (unless (zero? (unbox removed)) + (hash-table-for-each + instances + (match-lambda* + [(list instance-id (struct instance (_ (struct k-table (next-id-fn htable)) use-count))) + (define empty? (box #t)) + (hash-table-for-each + htable + (match-lambda* + [(list k-id (list s k eh count)) + (if (zero? count) + (begin (set-box! removed (add1 (unbox removed))) + (hash-table-remove! htable k-id)) + (begin (set-box! empty? #f) + (hash-table-put! htable k-id + (list s k eh (sub1 count)))))])) + (when (and (unbox empty?) + ; XXX race condition + (zero? use-count)) + (set-box! removed (add1 (unbox removed))) + (hash-table-remove! instances instance-id))])) + (when (or just-go? + (not (zero? (unbox removed)))) (inform-p (unbox removed)) (collect-garbage) (collect-garbage))) @@ -164,12 +164,12 @@ (alarm-evt msecs0) (lambda _ (when (collect?) - (collect)) + (collect #f)) (loop (seconds->msecs time0) msecs1))) (handle-evt (alarm-evt msecs1) (lambda _ - (collect) + (collect #t) (loop msecs0 (seconds->msecs time1))))))))) the-manager))