Index: libcfa/src/containers/string.cfa
===================================================================
--- libcfa/src/containers/string.cfa	(revision 97c215f79bc102e5204ffdfcc18ed7469b3c2a61)
+++ libcfa/src/containers/string.cfa	(revision 2432e8ee237110fa472c4bb4da7d20a890ce7c2d)
@@ -237,4 +237,20 @@
 }
 
+int findFrom(const string &s, size_t fromPos, char search) {
+    return findFrom( *s.inner, fromPos, search );
+}
+
+int findFrom(const string &s, size_t fromPos, const string &search) {
+    return findFrom( *s.inner, fromPos, *search.inner );
+}
+
+int findFrom(const string &s, size_t fromPos, const char* search) {
+    return findFrom( *s.inner, fromPos, search );
+}
+
+int findFrom(const string &s, size_t fromPos, const char* search, size_t searchsize) {
+    return findFrom( *s.inner, fromPos, search, searchsize );
+}
+
 bool includes(const string &s, const string &search) {
     return includes( *s.inner, *search.inner );
Index: libcfa/src/containers/string.hfa
===================================================================
--- libcfa/src/containers/string.hfa	(revision 97c215f79bc102e5204ffdfcc18ed7469b3c2a61)
+++ libcfa/src/containers/string.hfa	(revision 2432e8ee237110fa472c4bb4da7d20a890ce7c2d)
@@ -93,4 +93,9 @@
 int find(const string &s, const char* search, size_t searchsize);
 
+int findFrom(const string &s, size_t fromPos, char search);
+int findFrom(const string &s, size_t fromPos, const string &search);
+int findFrom(const string &s, size_t fromPos, const char* search);
+int findFrom(const string &s, size_t fromPos, const char* search, size_t searchsize);
+
 bool includes(const string &s, const string &search);
 bool includes(const string &s, const char* search);
Index: libcfa/src/containers/string_res.cfa
===================================================================
--- libcfa/src/containers/string_res.cfa	(revision 97c215f79bc102e5204ffdfcc18ed7469b3c2a61)
+++ libcfa/src/containers/string_res.cfa	(revision 2432e8ee237110fa472c4bb4da7d20a890ce7c2d)
@@ -16,6 +16,11 @@
 #include "string_res.hfa"
 #include "string_sharectx.hfa"
-
-#include <stdlib.hfa>  // e.g. malloc
+#include "stdlib.hfa"
+
+// Workaround for observed performance penalty from calling CFA's alloc.
+// Workaround is:  EndVbyte = TEMP_ALLOC(char, CurrSize)
+// Should be:      EndVbyte = alloc(CurrSize)
+#define TEMP_ALLOC(T, n) (( T* ) malloc( n * sizeof( T ) ))
+
 #include <assert.h>
 
@@ -67,5 +72,5 @@
     NoOfCompactions = NoOfExtensions = NoOfReductions = 0;
     InitSize = CurrSize = Size;
-    StartVbyte = EndVbyte = alloc(CurrSize);
+    StartVbyte = EndVbyte = TEMP_ALLOC(char, CurrSize);
     ExtVbyte = (void *)( StartVbyte + CurrSize );
     Header.flink = Header.blink = &Header;
@@ -246,7 +251,5 @@
     Handle.s = VbyteAlloc(*Handle.ulink, rhslnth);
     Handle.lnth = rhslnth;
-    for ( int i = 0; i < rhslnth; i += 1 ) {		// copy characters
-        Handle.s[i] = rhs[i];
-    } // for
+    memmove( Handle.s, rhs, rhslnth );
     s.shareEditSet_prev = &s;
     s.shareEditSet_next = &s;
@@ -264,7 +267,5 @@
     Handle.lnth = rhslnth;
     (s.shareEditSet_owns_ulink){ false };
-    for ( int i = 0; i < rhslnth; i += 1 ) {		// copy characters
-        Handle.s[i] = rhs[i];
-    } // for
+    memmove( Handle.s, rhs, rhslnth );
     s.shareEditSet_prev = &s;
     s.shareEditSet_next = &s;
@@ -595,21 +596,42 @@
 
 int find(const string_res &s, char search) {
-    for (i; size(s)) {
-        if (s[i] == search) return i;
-    }
-    return size(s);
-}
+    return findFrom(s, 0, search);
+}
+
+int findFrom(const string_res &s, size_t fromPos, char search) {
+    // FIXME: This paricular overload (find of single char) is optimized to use memchr.
+    // The general overload (find of string, memchr applying to its first character) and `contains` should be adjusted to match.
+    char * searchFrom = s.Handle.s + fromPos;
+    size_t searchLnth = s.Handle.lnth - fromPos;
+    int searchVal = search;
+    char * foundAt = (char *) memchr(searchFrom, searchVal, searchLnth);
+    if (foundAt == 0p) return s.Handle.lnth;
+    else return foundAt - s.Handle.s;
+}
+
+int find(const string_res &s, const string_res &search) {
+    return findFrom(s, 0, search);
+}
+
+int findFrom(const string_res &s, size_t fromPos, const string_res &search) {
+    return findFrom(s, fromPos, search.Handle.s, search.Handle.lnth);
+}
+
+int find(const string_res &s, const char* search) {
+    return findFrom(s, 0, search);
+}
+int findFrom(const string_res &s, size_t fromPos, const char* search) {
+    return findFrom(s, fromPos, search, strlen(search));
+}
+
+int find(const string_res &s, const char* search, size_t searchsize) {
+    return findFrom(s, 0, search, searchsize);
+}
+
+int findFrom(const string_res &s, size_t fromPos, const char* search, size_t searchsize) {
 
     /* Remaining implementations essentially ported from Sunjay's work */
 
-int find(const string_res &s, const string_res &search) {
-    return find(s, search.Handle.s, search.Handle.lnth);
-}
-
-int find(const string_res &s, const char* search) {
-    return find(s, search, strlen(search));
-}
-
-int find(const string_res &s, const char* search, size_t searchsize) {
+
     // FIXME: This is a naive algorithm. We probably want to switch to someting
     // like Boyer-Moore in the future.
@@ -621,5 +643,5 @@
     }
 
-    for (size_t i = 0; i < s.Handle.lnth; i++) {
+    for (size_t i = fromPos; i < s.Handle.lnth; i++) {
         size_t remaining = s.Handle.lnth - i;
         // Never going to find the search string if the remaining string is
@@ -740,4 +762,5 @@
     serr | "enter:AddThisAfter, this:" | &this | " n:" | &n;
 #endif // VbyteDebug
+    // Performance note: we are on the critical path here. MB has ensured that the verifies don't contribute to runtime (are compiled away, like they're supposed to be).
     verify( n.ulink != 0p );
     verify( this.ulink == n.ulink );
@@ -823,5 +846,5 @@
     NoOfExtensions += 1;
     CurrSize *= 2;
-    StartVbyte = EndVbyte = alloc(CurrSize);
+    StartVbyte = EndVbyte = TEMP_ALLOC(char, CurrSize);
     ExtVbyte = StartVbyte + CurrSize;
 
@@ -959,4 +982,12 @@
 
 
+static double heap_expansion_freespace_threshold = 0.1;  // default inherited from prior work: expand heap when less than 10% "free" (i.e. garbage)
+                                                         // probably an unreasonable default, but need to assess early-round tests on changing it
+
+void TUNING_set_string_heap_liveness_threshold( double val ) {
+    heap_expansion_freespace_threshold = 1.0 - val;
+}
+
+
 // Garbage determines the amount of free space left in the heap and then reduces, leave the same, or extends the size of
 // the heap.  The heap is then compacted in the existing heap or into the newly allocated heap.
@@ -986,5 +1017,5 @@
     AmountFree = ( uintptr_t )ExtVbyte - ( uintptr_t )StartVbyte - AmountUsed;
     
-    if ( ( double ) AmountFree < ( CurrSize * 0.1 ) || AmountFree < minreq ) {	// free space less than 10%  or not enough to serve cur request
+    if ( ( double ) AmountFree < ( CurrSize * heap_expansion_freespace_threshold ) || AmountFree < minreq ) {	// free space less than threshold or not enough to serve cur request
 
 		extend( this, max( CurrSize, minreq ) );				// extend the heap
@@ -1033,5 +1064,5 @@
     
     CurrSize += size > InitSize ? size : InitSize;	// minimum extension, initial size
-    StartVbyte = EndVbyte = alloc(CurrSize);
+    StartVbyte = EndVbyte = TEMP_ALLOC(char, CurrSize);
     ExtVbyte = (void *)( StartVbyte + CurrSize );
     compaction(this);					// copy from old heap to new & adjust pointers to new heap
Index: libcfa/src/containers/string_res.hfa
===================================================================
--- libcfa/src/containers/string_res.hfa	(revision 97c215f79bc102e5204ffdfcc18ed7469b3c2a61)
+++ libcfa/src/containers/string_res.hfa	(revision 2432e8ee237110fa472c4bb4da7d20a890ce7c2d)
@@ -39,4 +39,5 @@
 const char * DEBUG_string_heap_start( VbyteHeap * heap );
 
+void TUNING_set_string_heap_liveness_threshold( double val );
 
 //######################### String #########################
@@ -128,4 +129,9 @@
 int find(const string_res &s, const char* search, size_t searchsize);
 
+int findFrom(const string_res &s, size_t fromPos, char search);
+int findFrom(const string_res &s, size_t fromPos, const string_res &search);
+int findFrom(const string_res &s, size_t fromPos, const char* search);
+int findFrom(const string_res &s, size_t fromPos, const char* search, size_t searchsize);
+
 bool includes(const string_res &s, const string_res &search);
 bool includes(const string_res &s, const char* search);
