changeset 1332:4dd5d23bace2

minHeap option in .urp files
author Adam Chlipala <adam@chlipala.net>
date Sat, 11 Dec 2010 15:16:04 -0500 (2010-12-11)
parents a6427d1eda6f
children dab85a49e0ab
files doc/manual.tex include/urweb.h src/c/urweb.c src/cjr_print.sml src/compiler.sig src/compiler.sml src/demo.sml src/settings.sig src/settings.sml tests/hog.urp
diffstat 10 files changed, 47 insertions(+), 13 deletions(-) [+]
line wrap: on
line diff
--- a/doc/manual.tex	Sat Dec 11 13:42:54 2010 -0500
+++ b/doc/manual.tex	Sat Dec 11 15:16:04 2010 -0500
@@ -163,6 +163,7 @@
   \item \texttt{transactionals}: maximum number of custom transactional actions (e.g., sending an e-mail) that may be run in a single page generation
   \end{itemize}
 \item \texttt{link FILENAME} adds \texttt{FILENAME} to the list of files to be passed to the GCC linker at the end of compilation.  This is most useful for importing extra libraries needed by new FFI modules.
+\item \texttt{minHeap NUMBYTES} sets the initial size for thread-local heaps used in handling requests.  These heaps grow automatically as needed (up to any maximum set with \texttt{limit}), but each regrow requires restarting the request handling process.
 \item \texttt{onError Module.var} changes the handling of fatal application errors.  Instead of displaying a default, ugly error 500 page, the error page will be generated by calling function \texttt{Module.var} on a piece of XML representing the error message.  The error handler should have type $\mt{xbody} \to \mt{transaction} \; \mt{page}$.  Note that the error handler \emph{cannot} be in the application's main module, since that would register it as explicitly callable via URLs.
 \item \texttt{path NAME=VALUE} creates a mapping from \texttt{NAME} to \texttt{VALUE}.  This mapping may be used at the beginnings of filesystem paths given to various other configuration directives.  A path like \texttt{\$NAME/rest} is expanded to \texttt{VALUE/rest}.  There is an initial mapping from the empty name (for paths like \texttt{\$/list}) to the directory where the Ur/Web standard library is installed.  If you accept the default \texttt{configure} options, this directory is \texttt{/usr/local/lib/urweb/ur}.
 \item \texttt{prefix PREFIX} sets the prefix included before every URI within the generated application.  The default is \texttt{/}.
--- a/include/urweb.h	Sat Dec 11 13:42:54 2010 -0500
+++ b/include/urweb.h	Sat Dec 11 15:16:04 2010 -0500
@@ -284,8 +284,6 @@
 
 uw_Basis_int uw_Basis_rand(uw_context);
 
-extern int uw_time_max;
-
-extern int uw_supports_direct_status;
+extern int uw_time_max, uw_supports_direct_status, uw_min_heap;
 
 #endif
--- a/src/c/urweb.c	Sat Dec 11 13:42:54 2010 -0500
+++ b/src/c/urweb.c	Sat Dec 11 15:16:04 2010 -0500
@@ -348,7 +348,7 @@
   app->client_init();
 }
 
-int uw_time = 0, uw_time_max = 0;
+int uw_time = 0, uw_time_max = 0, uw_min_heap = 0;
 
 
 // Single-request state
@@ -461,7 +461,7 @@
   buf_init(uw_headers_max, &ctx->outHeaders, 0);
   buf_init(uw_page_max, &ctx->page, 0);
   ctx->returning_indirectly = 0;
-  buf_init(uw_heap_max, &ctx->heap, 0);
+  buf_init(uw_heap_max, &ctx->heap, uw_min_heap);
   buf_init(uw_script_max, &ctx->script, 1);
   ctx->script.start[0] = 0;
 
--- a/src/cjr_print.sml	Sat Dec 11 13:42:54 2010 -0500
+++ b/src/cjr_print.sml	Sat Dec 11 15:16:04 2010 -0500
@@ -2834,6 +2834,16 @@
 
              box [string "static void uw_setup_limits() {",
                   newline,
+                  case Settings.getMinHeap () of
+                      0 => box []
+                    | n => box [string "uw_min_heap",
+                                space,
+                                string "=",
+                                space,
+                                string (Int.toString n),
+                                string ";",
+                                newline,
+                                newline],
                   box [p_list_sep (box []) (fn (class, num) =>
                                                let
                                                    val num = case class of
--- a/src/compiler.sig	Sat Dec 11 13:42:54 2010 -0500
+++ b/src/compiler.sig	Sat Dec 11 15:16:04 2010 -0500
@@ -55,7 +55,8 @@
          dbms : string option,
          sigFile : string option,
          safeGets : string list,
-         onError : (string * string list * string) option
+         onError : (string * string list * string) option,
+         minHeap : int
     }
     val compile : string -> bool
     val compiler : string -> unit
--- a/src/compiler.sml	Sat Dec 11 13:42:54 2010 -0500
+++ b/src/compiler.sml	Sat Dec 11 15:16:04 2010 -0500
@@ -59,7 +59,8 @@
      dbms : string option,
      sigFile : string option,
      safeGets : string list,
-     onError : (string * string list * string) option
+     onError : (string * string list * string) option,
+     minHeap : int
 }
 
 type ('src, 'dst) phase = {
@@ -308,14 +309,19 @@
      Option.app Settings.setProtocol (#protocol job);
      Option.app Settings.setDbms (#dbms job);
      Settings.setSafeGets (#safeGets job);
-     Settings.setOnError (#onError job))
+     Settings.setOnError (#onError job);
+     Settings.setMinHeap (#minHeap job))
 
 fun inputCommentableLine inf =
     Option.map (fn s =>
                    let
                        val s = #1 (Substring.splitl (fn ch => ch <> #"#") (Substring.full s))
+                       val s = #1 (Substring.splitr (not o Char.isSpace) s)
                    in
-                       Substring.string (#1 (Substring.splitr (not o Char.isSpace) s))
+                       Substring.string (if Substring.size s > 0 andalso Char.isSpace (Substring.sub (s, Substring.size s - 1)) then
+                                             Substring.trimr 1 s
+                                         else
+                                             s)
                    end) (TextIO.inputLine inf)
 
 fun parseUrp' accLibs fname =
@@ -349,7 +355,8 @@
                        dbms = NONE,
                        sigFile = NONE,
                        safeGets = [],
-                       onError = NONE}
+                       onError = NONE,
+                       minHeap = 0}
         in
             institutionalizeJob job;
             {Job = job, Libs = []}
@@ -464,6 +471,7 @@
                     val sigFile = ref (Settings.getSigFile ())
                     val safeGets = ref []
                     val onError = ref NONE
+                    val minHeap = ref 0
 
                     fun finish sources =
                         let
@@ -494,7 +502,8 @@
                                 dbms = !dbms,
                                 sigFile = !sigFile,
                                 safeGets = rev (!safeGets),
-                                onError = !onError
+                                onError = !onError,
+                                minHeap = !minHeap
                             }
 
                             fun mergeO f (old, new) =
@@ -539,7 +548,8 @@
                                 dbms = mergeO #2 (#dbms old, #dbms new),
                                 sigFile = mergeO #2 (#sigFile old, #sigFile new),
                                 safeGets = #safeGets old @ #safeGets new,
-                                onError = mergeO #2 (#onError old, #onError new)
+                                onError = mergeO #2 (#onError old, #onError new),
+                                minHeap = Int.max (#minHeap old, #minHeap new)
                             }
                         in
                             if accLibs then
@@ -717,6 +727,10 @@
                                               else
                                                   Settings.addLimit (class, n))
                                        | _ => ErrorMsg.error "invalid 'limit' arguments")
+                                  | "minHeap" =>
+                                    (case Int.fromString arg of
+                                         NONE => ErrorMsg.error ("invalid min heap '" ^ arg ^ "'")
+                                       | SOME n => minHeap := n)
 
                                   | _ => ErrorMsg.error ("Unrecognized command '" ^ cmd ^ "'");
                                 read ()
--- a/src/demo.sml	Sat Dec 11 13:42:54 2010 -0500
+++ b/src/demo.sml	Sat Dec 11 15:16:04 2010 -0500
@@ -118,7 +118,8 @@
             dbms = mergeWith #2 (#dbms combined, #dbms urp),
             sigFile = mergeWith #2 (#sigFile combined, #sigFile urp),
             safeGets = [],
-            onError = NONE
+            onError = NONE,
+            minHeap = 0
         }
 
         val parse = Compiler.run (Compiler.transform Compiler.parseUrp "Demo parseUrp")
--- a/src/settings.sig	Sat Dec 11 13:42:54 2010 -0500
+++ b/src/settings.sig	Sat Dec 11 15:16:04 2010 -0500
@@ -211,4 +211,7 @@
 
     val addLimit : string * int -> unit
     val limits : unit -> (string * int) list
+
+    val setMinHeap : int -> unit
+    val getMinHeap : unit -> int
 end
--- a/src/settings.sml	Sat Dec 11 13:42:54 2010 -0500
+++ b/src/settings.sml	Sat Dec 11 15:16:04 2010 -0500
@@ -509,4 +509,8 @@
         raise Fail ("Unknown limit category '" ^ name ^ "'")
 fun limits () = !limitsList
 
+val minHeap = ref 0
+fun setMinHeap n = if n >= 0 then minHeap := n else raise Fail "Trying to set negative minHeap"
+fun getMinHeap () = !minHeap
+
 end
--- a/tests/hog.urp	Sat Dec 11 13:42:54 2010 -0500
+++ b/tests/hog.urp	Sat Dec 11 15:16:04 2010 -0500
@@ -1,1 +1,3 @@
+minHeap 1000000
+
 hog