Index: doc/theses/mike_brooks_MMath/benchmarks/string/.gitignore
===================================================================
--- doc/theses/mike_brooks_MMath/benchmarks/string/.gitignore	(revision 9d9fd819a2c497a3cd2037e48f9c2112d0d4e0e5)
+++ doc/theses/mike_brooks_MMath/benchmarks/string/.gitignore	(revision 9d9fd819a2c497a3cd2037e48f9c2112d0d4e0e5)
@@ -0,0 +1,6 @@
+!Makefile
+perfexp-*
+make-corpus
+corpus-*.txt
+corpusx-*.txt
+measurement-*.csv
Index: doc/theses/mike_brooks_MMath/benchmarks/string/Makefile
===================================================================
--- doc/theses/mike_brooks_MMath/benchmarks/string/Makefile	(revision 9d9fd819a2c497a3cd2037e48f9c2112d0d4e0e5)
+++ doc/theses/mike_brooks_MMath/benchmarks/string/Makefile	(revision 9d9fd819a2c497a3cd2037e48f9c2112d0d4e0e5)
@@ -0,0 +1,190 @@
+
+CFABUILD = ~/cfa2/build-perf
+LIBCFA = $(CFABUILD)/libcfa/*/src/.libs/libcfa.so
+
+CFA = $(CFABUILD)/driver/cfa
+PERFFLAGS_CFA = -nodebug -O2
+PERFFLAGS_CXX = -DNDEBUG -O2 -Wl,--no-as-needed -ldl
+
+
+# function: convert to upper case
+define uc
+$(shell echo $(1) | tr  '[:lower:]' '[:upper:]')
+endef
+
+# function: project numbered element of filename named by hyphen-delimited tuple
+# (call hyphProj,q-w-e-r.txt,1) is Q
+define ucHyphProj
+$(call uc,$(word $(2),$(subst -, ,$(basename $(1)))))
+endef
+
+# function: cross two lists, adding hyphen delimiters
+# (call hyphCross,a b c,1 2) is a-1 a-2 b-1 b-2 c-1 c-2
+define hyphCross
+$(foreach x,$(1),$(foreach xs,$(2),$(x)-$(xs)))
+endef
+
+define hyphCross3
+$(call hyphCross,$(1),$(call hyphCross,$(2),$(3)))
+endef
+
+define hyphCross4
+$(call hyphCross,$(1),$(call hyphCross3,$(2),$(3),$(4)))
+endef
+
+define hyphCross5
+$(call hyphCross,$(1),$(call hyphCross4,$(2),$(3),$(4),$(5)))
+endef
+
+OPERATIONS=pta peq pbv pall pno
+ALLOCS=reuse fresh
+CFA_APILEVELS=hl ll
+CFA_SHARINGS=share noshare
+PLATFORMS=cfa stl buhr94
+
+ifneq ($(filter cfa,$(PLATFORMS)),)
+    CFA_APIS=$(call hyphCross,$(CFA_APILEVELS),$(CFA_SHARINGS))
+endif
+
+ifneq ($(filter stl,$(PLATFORMS)),)
+    STL_APIS=na-na
+endif
+
+ifneq ($(filter buhr94,$(PLATFORMS)),)
+    BUHR94_APIS=na-na
+endif
+
+APIS = $(CFA_APIS) $(STL_APIS) $(BUHR94_APIS)
+
+OPERATIONS_USING_ALLOCS=pta peq
+define enrichOperationsAllocs
+$(call hyphCross3,$(filter peq pta,$(OPERATIONS)),$(1),$(ALLOCS)) $(call hyphCross3,$(filter-out peq pta,$(OPERATIONS)),$(1),na)
+endef
+
+CFA_PERFPROGS=$(call hyphCross,perfexp-cfa,$(call enrichOperationsAllocs,$(CFA_APIS)))
+STL_PERFPROGS=$(call hyphCross,perfexp-stl,$(call enrichOperationsAllocs,$(STL_APIS)))
+BUHR94_PERFPROGS=$(call hyphCross,perfexp-buhr94,$(call enrichOperationsAllocs,$(BUHR94_APIS)))
+
+PERFPROGS = $(CFA_PERFPROGS) $(STL_PERFPROGS) $(BUHR94_PERFPROGS)
+
+all : $(PERFPROGS)
+
+PP_SPLIT := $(shell echo "${PERFPROGS}" | sed -e 's/ /\\n/g')
+echoPerfProgs:
+	echo -e '$(PP_SPLIT)'
+
+perfexp-%.o: API=$(call ucHyphProj,$@,2)
+perfexp-%.o: OPERATION=$(call ucHyphProj,$@,3)
+perfexp-%.o: CFA_APILEVEL=$(call ucHyphProj,$@,4)
+perfexp-%.o: CFA_SHARING=$(call ucHyphProj,$@,5)
+perfexp-%.o: ALLOC=$(call ucHyphProj,$@,6)
+perfexp-%.o: SCENARIO_SWITCH=-DIMPL_$(API)_$(CFA_APILEVEL)_$(CFA_SHARING) -DOP_$(OPERATION) -DALLOC_$(ALLOC)
+
+perfexp-cfa-%.o: CMD=$(CFA) -c $(PERFFLAGS_CFA) $< -o $@ $(SCENARIO_SWITCH)
+perfexp-stl-%.o: CMD=$(CXX) -c -xc++ $(PERFFLAGS_CXX) $< -o $@ $(SCENARIO_SWITCH)
+perfexp-buhr94-%.o: CMD=$(CXX) -xc++ -c $(PERFFLAGS_CXX) $< -o $@ $(SCENARIO_SWITCH)
+
+perfexp-cfa-peq-%.o: prog.cfa $(LIBCFA)
+	$(CMD)
+perfexp-cfa-pta-%.o: prog.cfa $(LIBCFA)
+	$(CMD)
+perfexp-cfa-pbv-%.o: prog-passbyval.cfa $(LIBCFA)
+	$(CMD)
+perfexp-cfa-pb%.o: prog-passbyX.cfa $(LIBCFA)
+	$(CMD)
+perfexp-cfa-pfi-%.o: prog-find.cfa $(LIBCFA)
+	$(CMD)
+perfexp-cfa-pall-%.o: prog-allocn.cfa $(LIBCFA)
+	$(CMD)
+perfexp-cfa-pno-%.o: prog-normalize.cfa $(LIBCFA)
+	$(CMD)
+perfexp-stl-peq-%.o: prog.cfa
+	$(CMD)
+perfexp-stl-pta-%.o: prog.cfa
+	$(CMD)
+perfexp-stl-pbv-%.o: prog-passbyval.cfa
+	$(CMD)
+perfexp-stl-pfi-%.o: prog-find.cfa
+	$(CMD)
+perfexp-stl-pall-%.o: prog-allocn.cfa
+	$(CMD)
+perfexp-stl-pno-%.o: prog-normalize.cfa
+	$(CMD)
+perfexp-buhr94-peq-%.o: prog.cfa buhr94-string.o buhr94-VbyteSM.o
+	$(CMD)
+perfexp-buhr94-pta-%.o: prog.cfa buhr94-string.o buhr94-VbyteSM.o
+	$(CMD)
+perfexp-buhr94-pta-%.o: prog-passbyval.cfa buhr94-string.o buhr94-VbyteSM.o
+	$(CMD)
+perfexp-buhr94-pall-%.o: prog-allocn.cfa buhr94-string.o buhr94-VbyteSM.o
+	$(CMD)
+perfexp-buhr94-pno-%.o: prog-normalize.cfa buhr94-string.o buhr94-VbyteSM.o
+	$(CMD)
+
+# one of the pbx cases also needs to link with not_string_res.o (handling manually)
+perfexp-cfa-%: perfexp-cfa-%.o $(LIBCFA)
+	$(CFA) $(PERFFLAGS_CFA) $< -o $@  
+perfexp-stl-%: perfexp-stl-%.o $(LIBCFA)
+	$(CFA) $(PERFFLAGS_CFA) $< /lib/x86_64-linux-gnu/libstdc++.so.6 -o $@
+perfexp-buhr94-% : perfexp-buhr94-%.o buhr94-string.o buhr94-VbyteSM.o
+	$(CXX) $(PERFFLAGS_CXX) $^ -o $@
+
+buhr94-string.o:
+	$(CXX) -xc++ -c $(PERFFLAGS_CXX) ~/usys1/sm/string/StringSharing/src/string.cc -o $@
+
+buhr94-VbyteSM.o:
+	$(CXX) -xc++ -c $(PERFFLAGS_CXX) ~/usys1/sm/string/StringSharing/src/VbyteSM.cc -o $@
+
+clean:
+	rm -f *.o perfexp*
+
+MEASURE = $(PERFPROGS)
+CORPORI = corpus-100-*-1.txt
+
+measurement: $(MEASURE)
+	tofile=measurement-`date '+%F--%H-%M-%S'`.csv ; \
+	echo $$tofile ; \
+	for prog in $(MEASURE) ; do \
+	    for corpus in $(CORPORI) ; do \
+			corpusbody=`cat $$corpus` ; \
+			printed=`./$$prog 100 10 $$corpusbody` ; \
+			echo $$prog,$$corpus,$$printed  >>  $$tofile ; \
+			echo $$prog,$$corpus,$$printed  ; \
+		done ; \
+	done
+#			printed=`./$$prog 10000 - 10 $$corpusbody` ; \
+
+CFA_EXPANSIONS=0.02 0.05 0.1 0.2 0.5 0.9
+
+measurement2: $(MEASURE)
+	tofile=measurement-`date '+%F--%H-%M-%S'`.csv ; \
+	for prog in $(MEASURE) ; do \
+	    for corpus in $(CORPORI) ; do \
+			for expansion in $(CFA_EXPANSIONS) ; do \
+				corpusbody= ; \
+				echo ./$$prog 1000 1.006 $$expansion 10 \`cat $$corpus\` ; \
+			done ; \
+		done ; \
+	done ; \
+	echo $$tofile ; \
+	for prog in $(MEASURE) ; do \
+	    for corpus in $(CORPORI) ; do \
+			for expansion in $(CFA_EXPANSIONS) ; do \
+				corpusbody=`cat $$corpus` ; \
+				printed=`./$$prog 1000 1.006 $$expansion 10 $$corpusbody` ; \
+				echo $$prog,$$corpus,$$expansion,$$printed  >>  $$tofile ; \
+				echo $$prog,$$corpus,$$expansion,$$printed  ; \
+			done ; \
+		done ; \
+	done
+
+measurement3: $(MEASURE)
+	for prog in $(MEASURE) ; do \
+	    for corpus in $(CORPORI) ; do \
+			for expansion in $(CFA_EXPANSIONS) ; do \
+				corpusbody=`cat $$corpus` ; \
+				LD_PRELOAD=~/plg2/mubeen-stat-shim/malloc/mallocWrappers.so ./$$prog 1000 1.006 $$expansion 1 $$corpusbody ; \
+				mv preload_dump.txt preload_dump--qrun1--$$corpus--expansion-$$expansion.txt ; \
+			done ; \
+		done ; \
+	done
Index: doc/theses/mike_brooks_MMath/benchmarks/string/corpori-about.txt
===================================================================
--- doc/theses/mike_brooks_MMath/benchmarks/string/corpori-about.txt	(revision 9d9fd819a2c497a3cd2037e48f9c2112d0d4e0e5)
+++ doc/theses/mike_brooks_MMath/benchmarks/string/corpori-about.txt	(revision 9d9fd819a2c497a3cd2037e48f9c2112d0d4e0e5)
@@ -0,0 +1,9 @@
+corpus-100-* are for general-purpose mixed tests
+corpus-1-* are single-item corpori, for running exact-length variations  (made by hand with a clipboard)
+corpusx-* are purposed for getting started with the "normalize" test, using randomness to have rare -s, yet awkwardly avoiding SSO with min-length 16
+          x means 1% -s
+
+IIRC, ./make-corpus 100 20           DROVE    corpus-100-20-1.txt
+ergo, ./make-corpus 100 5 15 0.01    IS FOR   corpusx-100-20-1.txt
+
+./make-corpus 100 5 15 0.01  >  corpusx-100-20-1.txt
Index: doc/theses/mike_brooks_MMath/benchmarks/string/corpus-100-1-1.txt
===================================================================
--- doc/theses/mike_brooks_MMath/benchmarks/string/corpus-100-1-1.txt	(revision 9d9fd819a2c497a3cd2037e48f9c2112d0d4e0e5)
+++ doc/theses/mike_brooks_MMath/benchmarks/string/corpus-100-1-1.txt	(revision 9d9fd819a2c497a3cd2037e48f9c2112d0d4e0e5)
@@ -0,0 +1,100 @@
+t
+w
+m
+k
+b
+n
+x
+n
+a
+s
+g
+f
+a
+g
+p
+l
+b
+l
+g
+f
+f
+i
+n
+q
+l
+t
+k
+p
+g
+p
+o
+j
+p
+e
+t
+i
+f
+h
+r
+k
+l
+w
+f
+j
+m
+o
+g
+s
+w
+t
+j
+u
+v
+n
+g
+s
+h
+r
+g
+g
+g
+t
+v
+k
+o
+m
+j
+r
+m
+x
+j
+o
+m
+i
+n
+n
+k
+i
+x
+c
+b
+o
+v
+v
+q
+g
+r
+t
+d
+y
+t
+m
+v
+o
+t
+i
+h
+i
+h
+r
Index: doc/theses/mike_brooks_MMath/benchmarks/string/corpus-100-10-1.txt
===================================================================
--- doc/theses/mike_brooks_MMath/benchmarks/string/corpus-100-10-1.txt	(revision 9d9fd819a2c497a3cd2037e48f9c2112d0d4e0e5)
+++ doc/theses/mike_brooks_MMath/benchmarks/string/corpus-100-10-1.txt	(revision 9d9fd819a2c497a3cd2037e48f9c2112d0d4e0e5)
@@ -0,0 +1,100 @@
+arffxh
+qx
+fbfnvxvw
+ktcfgonnoklj
+eqqe
+ywvjewor
+pqrqdnuj
+kyjbjvmwcdpibqfyam
+rgshymadcvmxilijw
+vvkb
+secaddobw
+veuk
+ama
+k
+autadrvnukiymlerahoxduvnava
+ln
+ni
+nme
+cywlbjwfe
+nsxqqthqrj
+dwk
+iwhw
+t
+cskdfjljlyej
+ufynwlldivusu
+pxbpdtcgy
+tkasrjlmqmdnxosjmpckusivilr
+utboebivmv
+diotjfms
+dueapnvabpnvjo
+osv
+ftal
+ofnvtgqyewytkwwmnkkwbxnvtdcndpsuwisqrj
+vhrrtpoifbtefruboafeduwargtjxfcvovplnhtu
+pankwp
+wufcsfdklyvlga
+vwyjmgfirxkfihwl
+uqinvnajmwutygrxgbloivgggmqplcvitevps
+chvydugutmxhbjdipjwhyk
+utdbrvtq
+e
+whmdfgrfpv
+sgfedmfpxaje
+ecawaemylyfqhy
+wunr
+svgh
+widimg
+o
+mqk
+ryxyphyo
+vdxaxtggwfoaobidrrpieqcdqctxbkeyncymxg
+unlweogi
+xaqctsgku
+lx
+pxduwrufoqtanxo
+iutllyfghrcld
+avxfsx
+nfngynu
+es
+bpxo
+fv
+xxldxl
+ytryu
+ejogyligfuhutw
+bsjyqwdqier
+ysahx
+vgmkq
+pldm
+axjsjk
+gpequwv
+pxdplbxxnot
+dwpm
+px
+yjffy
+wviutbsyqgd
+eqixunwm
+vdyneis
+kfjin
+doyci
+halykmv
+jkagnbvu
+rfywojm
+mctrmbyo
+ayyvxlh
+rwe
+rqhyrgpbtkqx
+ikhjyw
+axkbjrbbrhtlx
+lpkbtgokgwushetestceumxy
+pg
+chppyassihdqfxjmfdsxy
+cujbvcscnwjfmlhiepr
+gygrn
+ugmueqrprptnrkkepap
+ivp
+eycnqpboypjdhdub
+rqm
+cst
+ktohkqnjsd
+lhqkwcpgfmkaebpifi
Index: doc/theses/mike_brooks_MMath/benchmarks/string/corpus-100-2-1.txt
===================================================================
--- doc/theses/mike_brooks_MMath/benchmarks/string/corpus-100-2-1.txt	(revision 9d9fd819a2c497a3cd2037e48f9c2112d0d4e0e5)
+++ doc/theses/mike_brooks_MMath/benchmarks/string/corpus-100-2-1.txt	(revision 9d9fd819a2c497a3cd2037e48f9c2112d0d4e0e5)
@@ -0,0 +1,100 @@
+q
+yc
+by
+e
+wt
+od
+ev
+v
+c
+gjhk
+xla
+t
+u
+e
+q
+v
+e
+c
+h
+e
+dt
+icsppbpddi
+ge
+lbrv
+hbil
+ssq
+y
+g
+p
+yf
+p
+j
+i
+ejb
+baciblv
+g
+d
+qpo
+f
+b
+vqvfr
+v
+n
+cq
+e
+cr
+qx
+ve
+luht
+j
+hcc
+vil
+xmw
+m
+r
+x
+f
+g
+c
+pwv
+k
+p
+mu
+k
+x
+eke
+winogdv
+l
+ja
+i
+btgs
+u
+b
+t
+l
+l
+s
+biajn
+paxy
+piy
+e
+kud
+vl
+w
+t
+q
+tt
+vd
+us
+u
+mldo
+h
+oc
+paol
+oihhxe
+x
+gkwby
+v
+g
+b
Index: doc/theses/mike_brooks_MMath/benchmarks/string/corpus-100-20-1.txt
===================================================================
--- doc/theses/mike_brooks_MMath/benchmarks/string/corpus-100-20-1.txt	(revision 9d9fd819a2c497a3cd2037e48f9c2112d0d4e0e5)
+++ doc/theses/mike_brooks_MMath/benchmarks/string/corpus-100-20-1.txt	(revision 9d9fd819a2c497a3cd2037e48f9c2112d0d4e0e5)
@@ -0,0 +1,100 @@
+wlgfygaqsdfmqvcygkiyaasjonymuarrnaamiadd
+krvjuwrhgqjgmvwaujuudplgpxo
+euwomuajssryjd
+v
+ey
+nvtslfydfquj
+tbxpbiitchgfoehs
+fiaydngdrmv
+xhjyhbbrjwtsdcjilensmnupebuvpqkoavniwqaiowbt
+mcmqqffgcxkeuivmvkoryypr
+xgycbaofoixvphyntfjdbxyomspmihojqpnrreyimxgdhhsbmcgqcffpyuejc
+ssmgmel
+oamuftdywrdekgjpxkmewrbpmnyatmoiodduyitvdyanhmefwsltkmmxcnavaoeotklsuhqxhrmoeswdlixwxmuaa
+wcndshpfclmsltkalqsiuhqueohbrjxollreukjwvyr
+sfkevdoskgnqwwtoitfthabekmbilvrhbc
+yib
+ujgoigiaofhlmhorrbuap
+uwtw
+thnmdyurkdckuhtg
+cuovxj
+pdtmyqasynhenfvxkxkfigldiitfjdgyia
+isodtclxrsvrdwejflwktiebrjhqsjfddvgyytxs
+v
+sspcxd
+ixjobbylutwcwayfaacauqvgjrynpcpbcy
+gdqtxmqcjtbrvdtvykthwlikenchpeyxhs
+hfljrfnldsfbrruaqjiepxgyokaotujbbwnuebghtniohfqyqbfialh
+ykfufqyinmdtplblylcj
+skkwpvwdfpepuavobeepkyhvc
+v
+xhksrup
+sokyerocrmq
+twkevraymxpkfagwwvgqltrplirfvkari
+vg
+vhqwwecykcygirtejmprgup
+whcjdi
+cqhbpl
+rxhqgsidwrpplvmcpklrvrdktvtwnhcffkvnfgqexgtmfhou
+cpptscnoxmcfpkm
+gbhnrlnyiagpqbltqdnlgeceqfmgryixarnugevogcgxdrtwujidnlkhswpkvbkysbtyfpnlr
+lwnfvlphofsyonvfaugmtbppdufsjypwxdduoucgcwfrmew
+yfbuirklorfaquxqadnrxpxc
+ftdjsriav
+jpnuefahxwf
+xifrixpkouhshakpdivmx
+j
+rmmrjtljcrbmrsygqgyxjmpmulbtx
+yrwnjhhxslpwxjpwpiepgpeycykduintaljmuqkpccmalfadng
+w
+yvayiftrsqtgaidt
+tvyiymnyqeh
+ddlbdkjigddwamairtgnpfwqsk
+l
+wwtciuhufpckvbkkbvcucqnjneeawp
+vpnb
+jivqbadwdohfmlcocrarwhuvwmroc
+p
+e
+efpicsylalwdccuevtlqrlfm
+ihpvlfdqunuomi
+aite
+rkgnwagi
+sknadmmipfedburjlrrixe
+inphnvrso
+jriv
+qllwomtgygasoaxqilgsbdkttpfnxbtrogqdullttnnknnbybj
+cmexjuew
+frowagcutorneh
+sudtvmlxcrxlmckkkeyhehjc
+atqfbqxxttvhft
+wrwmwjyhoxougayjbsbgvtgtqapahllggkufttmku
+ibdhmgdnoy
+wvbwndgcopkykpuheich
+fmarvfikhuifvhsyqwpghqsylcdvgmoncri
+wqkgns
+jdhkteccoswpgavfgitumnd
+nvxtjsguvphrtjtketbmtwrchoyucehpchmnbuiykrrgdnrjhuw
+toibdhxgoixq
+mfs
+psrkmbnasxkpwn
+lxmpglxwvxnnl
+hsncnxoon
+jnbbkrkwpwoxkmuiklwxigtvihvyxkpjarkllwkbvychnyramq
+vwsthcqi
+dyldsxoeuyhqajanjsqvjrtjkosofcqibclvadauejnftoufj
+dufaepoagvcwgfbtbbwdxemolidgpmuvjavoskqyisyoaakde
+geousaexitmdpwgnnbxeciwbwyeicisimjfijjgrgtxxqgoehmilxhpugtfkeausjabumipucnuutjbdyjqwsgtbcalgcgaoiblulbppolkkulntwfqpnlsqnewrm
+ivbuqmvjdnupxreoobvftlsmcitcdgbleeixr
+h
+ueouxsl
+uhuqtndxyyacgenmiwkce
+ybaqvyjiler
+unwbmxaoaispvcmigsfgtfysgidsnubklalxxooawiqumfgsylbusapa
+ssyqvlcy
+cyoqcnbslpxrjydmwvnmvyiqxypldqlfpaxrq
+mcrntdoyqlwgbvflo
+kgqpwfwpf
+jxywatkvwbwnpuvqsbchioocgnhddoannakptwmsxjjngfgyhkjrbathnbkrsnhgprvjqkequnf
+tnfdyoucqrkeuwxnkftayslpdqhxgoeacjdd
+biossun
Index: doc/theses/mike_brooks_MMath/benchmarks/string/corpus-100-5-1.txt
===================================================================
--- doc/theses/mike_brooks_MMath/benchmarks/string/corpus-100-5-1.txt	(revision 9d9fd819a2c497a3cd2037e48f9c2112d0d4e0e5)
+++ doc/theses/mike_brooks_MMath/benchmarks/string/corpus-100-5-1.txt	(revision 9d9fd819a2c497a3cd2037e48f9c2112d0d4e0e5)
@@ -0,0 +1,100 @@
+hsiq
+erkpoqlew
+tpgsfigwyn
+tbpuf
+nns
+ukakbqxhnob
+wvlhckh
+wdvoyc
+orjemthy
+xweonftkbh
+gs
+yrfujgy
+xr
+e
+fl
+c
+d
+drnwcqhwwc
+xv
+tfp
+hnmsutaiaew
+maw
+aa
+h
+qlbphi
+nx
+wo
+qlpqtpv
+uitslvsf
+tvqunydboe
+lugegvvcntvic
+bpo
+uuqtnl
+mrldxvrs
+v
+atfn
+cxswa
+nxg
+oaydjnu
+rusjnwh
+ycvo
+an
+wptlnaxdcwilldl
+aeqpe
+gfaeu
+fidc
+y
+ny
+qb
+ypbebgg
+w
+nxctx
+o
+oywsyvj
+xa
+bnh
+povxugvtt
+v
+tfgnvfm
+gkbtib
+mqlf
+achxi
+reb
+uwxbmtjyj
+mklwn
+jf
+p
+ctwacerif
+d
+gfrcqtmggysd
+i
+u
+fknbkpfo
+nw
+rcb
+vd
+pr
+vtqahcpemwqax
+qfsbsrvmvwlrcdiw
+gq
+iawxg
+w
+mwbf
+vivpeil
+wficp
+gwvc
+xbgelfbbdeif
+rd
+vofcnlkpdpwcnb
+ncs
+qxur
+acjctousdau
+nfjr
+gvmj
+al
+reamxdobo
+ue
+njoibdpkw
+ssbccbpduufkslyvasr
+hfq
Index: doc/theses/mike_brooks_MMath/benchmarks/string/corpus-5-20-1.txt
===================================================================
--- doc/theses/mike_brooks_MMath/benchmarks/string/corpus-5-20-1.txt	(revision 9d9fd819a2c497a3cd2037e48f9c2112d0d4e0e5)
+++ doc/theses/mike_brooks_MMath/benchmarks/string/corpus-5-20-1.txt	(revision 9d9fd819a2c497a3cd2037e48f9c2112d0d4e0e5)
@@ -0,0 +1,5 @@
+xtprjlkvxoha
+fwjvjxlhetotwuvrrkplahwm
+tmjdpckmmgwmtgqpwnpsjhktwyvhvkbpakuppfccoboijhbhu
+agxkcwlyeilialuvbkbgopjfbtpcbmsbtsnxpaywklhk
+cibpmhges
Index: doc/theses/mike_brooks_MMath/benchmarks/string/corpus-5-20-2.txt
===================================================================
--- doc/theses/mike_brooks_MMath/benchmarks/string/corpus-5-20-2.txt	(revision 9d9fd819a2c497a3cd2037e48f9c2112d0d4e0e5)
+++ doc/theses/mike_brooks_MMath/benchmarks/string/corpus-5-20-2.txt	(revision 9d9fd819a2c497a3cd2037e48f9c2112d0d4e0e5)
@@ -0,0 +1,5 @@
+cyvgqodbfmnkefjurrjmfloimkldtmcxlafcqkfwxuhe
+sbulkjsvydklonfb
+dotktl
+ykvwtaymbvalgsjfwwqnkxrfdgb
+amma
Index: doc/theses/mike_brooks_MMath/benchmarks/string/corpus-5-20-3.txt
===================================================================
--- doc/theses/mike_brooks_MMath/benchmarks/string/corpus-5-20-3.txt	(revision 9d9fd819a2c497a3cd2037e48f9c2112d0d4e0e5)
+++ doc/theses/mike_brooks_MMath/benchmarks/string/corpus-5-20-3.txt	(revision 9d9fd819a2c497a3cd2037e48f9c2112d0d4e0e5)
@@ -0,0 +1,5 @@
+otado
+drymnkbfofeqkjbythdtprmnjbikhwfmre
+fpdmgiqw
+a
+twhxqwrenbhvnqusgma
Index: doc/theses/mike_brooks_MMath/benchmarks/string/make-corpus.cfa
===================================================================
--- doc/theses/mike_brooks_MMath/benchmarks/string/make-corpus.cfa	(revision 9d9fd819a2c497a3cd2037e48f9c2112d0d4e0e5)
+++ doc/theses/mike_brooks_MMath/benchmarks/string/make-corpus.cfa	(revision 9d9fd819a2c497a3cd2037e48f9c2112d0d4e0e5)
@@ -0,0 +1,87 @@
+#include <stdlib.hfa>
+#include <math.h>
+#include <limits.h>
+#include <unistd.h>
+#include <string.h>
+
+// U(0,1)
+static double U() {
+    return (double)rand() / (double)INT_MAX;
+}
+
+// generate random draws from a geometric distribution of the given mean
+// https://math.stackexchange.com/questions/485448/prove-the-way-to-generate-geometrically-distributed-random-numbers
+static double denom;
+static void initialize(int mean) {
+    srand(getpid());
+    double p = 1.0 / (double) mean;
+    denom = log(1-p);
+}
+static int nextGeoRand() {
+    // ret = ⌊ln(U)/ln(1−p)⌋ where U ~ U(0, 1)
+    return 1 + (int) (log(U()) / denom);
+}
+
+// write a randomly generated alphabetic string whose length is adjused from a draw of the above distribution
+static void emit1( int offset, double mcfreq, char mchar ) {
+    int lim = offset + nextGeoRand();
+    // printf("==%d\n", lim);
+    for (i; lim) {
+        char emit;
+        if (U() < mcfreq) emit = mchar;
+        else emit = 'a' + (rand() % ('z'-'a'));
+        printf("%c", emit);
+    }
+    printf("\n");
+}
+
+// usage: ./make-corpus toGen mean [offset=0] [mcfreq=0.0] [mchar='-']
+//
+// Outputs alphabetic (plus magic-char) strings, one per line.
+// toGen: number of strings (lines)
+// 
+// generated length ~  offset + geo(mean)
+//                  >= 1
+//
+// offset=0,  mean=1:  constant length 1
+// offset=0,  mean=2:  lengths go like number of coin tosses it takes to get heads
+// offset=0,  mean=6:  lengths go like number of cube die rolls it takes to get :::
+// offset=15, mean=1:  constant length 16
+// offset=15, mean=2:  population's minimum is 16 and mean is 17
+//
+// Magic Char (mc) does not affect these lengths.  Any mc occurrence replaces an alphabetic char.
+// mcfreq: (in [0,1]) expected fraction of the characters output that are mchar
+//
+int main(int argc, char ** argv) {
+
+    int toGen;
+    int mean;
+    int offset = 0;
+    double mcfreq = 0.0;
+    char mchar = '-';
+
+    assert(argc >= 3 && argc <= 6);
+    switch(argc) {
+        case 6:
+            assert(strlen(argv[5]) == 0);
+            mchar = argv[5][0];
+        case 5:
+            mcfreq = atof(argv[4]);
+            assert(mcfreq >= 0.0 && mcfreq <= 1.0);
+        case 4:
+            offset = atoi(argv[3]);
+            assert(offset >= 0 && offset < 10000);
+        default:
+            mean = atoi(argv[2]);
+            assert(mean > 0);
+            assert(mean < 1000);
+            toGen = atoi(argv[1]);
+            assert(toGen > 0);
+            assert(toGen < 1000000);
+    }
+
+    initialize(mean);
+    for( i; toGen ) {
+        emit1(offset, mcfreq, mchar);
+    }
+}
Index: doc/theses/mike_brooks_MMath/benchmarks/string/make-flamegraph.sh
===================================================================
--- doc/theses/mike_brooks_MMath/benchmarks/string/make-flamegraph.sh	(revision 9d9fd819a2c497a3cd2037e48f9c2112d0d4e0e5)
+++ doc/theses/mike_brooks_MMath/benchmarks/string/make-flamegraph.sh	(revision 9d9fd819a2c497a3cd2037e48f9c2112d0d4e0e5)
@@ -0,0 +1,20 @@
+#!/bin/bash
+
+# $1 is SUT id     : stl-pall-na-na-na
+# $2 is CLI middle : 1000 1.006 0.1 -w 10000000
+# $3 is corpus id  : -1-500-1  (goes with corpus-1-500-1.txt)
+#
+# usage for that example:   ./make-flamegraph.sh cfa-pall-ll-share-na '1000 1.006 0.1 -w 10000000' -1-500-1
+#
+# another
+# $3 is coprus id  : x-100-20-1  (goes with corpusx-100-20-1.txt)
+
+SLUG=perf--$1--${2//[ .]/-}--$3
+
+perf record --call-graph dwarf -m16M ~/plg2/cfa2/cfa-cc/tests/zombies/string-perf/perfexp-$1 $2 `cat ~/plg2/cfa2/cfa-cc/tests/zombies/string-perf/corpus$3.txt`
+
+mv perf.data $SLUG.data
+perf script -i $SLUG.data > $SLUG.perf
+../flamegraph/FlameGraph/stackcollapse-perf.pl $SLUG.perf > $SLUG.folded
+../flamegraph/FlameGraph/flamegraph.pl $SLUG.folded > $SLUG.svg
+cp $SLUG.svg ~/plg2/flames
Index: doc/theses/mike_brooks_MMath/benchmarks/string/not_string_res.cfa
===================================================================
--- doc/theses/mike_brooks_MMath/benchmarks/string/not_string_res.cfa	(revision 9d9fd819a2c497a3cd2037e48f9c2112d0d4e0e5)
+++ doc/theses/mike_brooks_MMath/benchmarks/string/not_string_res.cfa	(revision 9d9fd819a2c497a3cd2037e48f9c2112d0d4e0e5)
@@ -0,0 +1,5 @@
+#include <string_res.hfa>
+#include "not_string_res.hfa"
+
+void ?{}( not_string_res & this, const string_res & src, StrResInitMode, size_t start, size_t end ) {}
+void ^?{}( not_string_res & this ) {}
Index: doc/theses/mike_brooks_MMath/benchmarks/string/not_string_res.hfa
===================================================================
--- doc/theses/mike_brooks_MMath/benchmarks/string/not_string_res.hfa	(revision 9d9fd819a2c497a3cd2037e48f9c2112d0d4e0e5)
+++ doc/theses/mike_brooks_MMath/benchmarks/string/not_string_res.hfa	(revision 9d9fd819a2c497a3cd2037e48f9c2112d0d4e0e5)
@@ -0,0 +1,6 @@
+struct not_string_res {
+    size_t junk[7];
+};
+
+void ?{}( not_string_res & this, const string_res & src, StrResInitMode, size_t start, size_t end );
+void ^?{}( not_string_res & this );
Index: doc/theses/mike_brooks_MMath/benchmarks/string/pbx-correctness-demos.cfa
===================================================================
--- doc/theses/mike_brooks_MMath/benchmarks/string/pbx-correctness-demos.cfa	(revision 9d9fd819a2c497a3cd2037e48f9c2112d0d4e0e5)
+++ doc/theses/mike_brooks_MMath/benchmarks/string/pbx-correctness-demos.cfa	(revision 9d9fd819a2c497a3cd2037e48f9c2112d0d4e0e5)
@@ -0,0 +1,206 @@
+// see also C++ investigation in ~/plg2/cfa2/mycode/string/raii/ctor-calls.cpp
+
+#include <string.hfa>
+#include <string_res.hfa>
+
+/*
+call_substrOfPart:
+    In all cases, of both HL and LL, there is a temporary object.
+    It represents narrowing the range, from full-string, to [1..3].
+    The only matter to control is whether that temporary shares edits with the string from which it was created.
+    In HL, two knobs control it, and the 
+*/
+
+void calltest_HL() {
+
+    #define HELPER_BODY(param) \
+        sout | "early in helper with " | param; \
+        param[0] = '+'; \
+        sout | "late in helper with " | param;
+
+    void helper1( string   q ) { HELPER_BODY(q) }
+    void helper2( string & q ) { HELPER_BODY(q) }
+    #undef HELPER_BODY
+
+    string fred;
+
+
+    sout | "===";
+    sout | "HL: substring of part";
+
+    sout | "---";
+    // Calling a by-val function, the only way it supports, in which it gets a private logical copy.
+    fred = "abcd";
+    sout | "before helper with " | fred;
+    helper1( fred(1,3) );
+    sout | "after helper with " | fred;
+
+    sout | "---";
+    // Calling a by-ref function, sys-style, in which we want to gets its changes as side effects.
+    fred = "abcd";
+    sout | "before helper with " | fred;
+    helper2( fred(1,3) );
+    sout | "after helper with " | fred;
+
+    sout | "---";
+    // Calling a by-ref function, trans-style, in which we give it a logical copy, to prevent it from pulluting our gold one.
+    fred = "abcd";
+    sout | "before helper with " | fred;
+    helper2( (string){ fred(1,3) } );
+    sout | "after helper with " | fred;
+
+
+    sout | "===";
+    sout | "HL: substring of whole";
+
+    sout | "---";
+    // Calling a by-val function, the only way it supports, in which it gets a private logical copy.
+    fred = "abcd";
+    sout | "before helper with " | fred;
+    helper1( fred(0,4) );
+    sout | "after helper with " | fred;
+
+    sout | "---";
+    // Calling a by-ref function, sys-style, in which we want to gets its changes as side effects.
+    fred = "abcd";
+    sout | "before helper with " | fred;
+    helper2( fred(0,4) );
+    sout | "after helper with " | fred;
+
+    sout | "---";
+    // Calling a by-ref function, trans-style, in which we give it a logical copy, to prevent it from pulluting our gold one.
+    fred = "abcd";
+    sout | "before helper with " | fred;
+    helper2( (string){ fred(0,4) } );
+    sout | "after helper with " | fred;
+
+
+
+    sout | "===";
+    sout | "HL: whole original string";
+
+    sout | "---";
+    // Calling a by-val function, the only way it supports, in which it gets a private logical copy.
+    fred = "abcd";
+    sout | "before helper with " | fred;
+    helper1( fred );
+    sout | "after helper with " | fred;
+
+    sout | "---";
+    // Calling a by-ref function, sys-style, in which we want to gets its changes as side effects.
+    fred = "abcd";
+    sout | "before helper with " | fred;
+    helper2( fred );
+    sout | "after helper with " | fred;
+
+    sout | "---";
+    // Calling a by-ref function, trans-style, in which we give it a logical copy, to prevent it from pulluting our gold one.
+    fred = "abcd";
+    sout | "before helper with " | fred;
+    helper2( (string){ fred } );
+    sout | "after helper with " | fred;
+}
+
+void calltest_LL() {
+
+    #define HELPER_BODY(param) \
+        sout | "early in helper with " | param; \
+        assignAt(param, 0, '+'); \
+        sout | "late in helper with " | param;
+
+    void helper1( string_res & q ) { HELPER_BODY(q) } // arg should always be a temporary constructed with COPY_VALUE
+    void helper2( string_res & q ) { HELPER_BODY(q) } // arg can refer to whatever you want
+    #undef HELPER_BODY
+
+    /*
+    In LL, both functions are translated to the same thing.
+    "The only allowed call of #1" becomes respecting the restriction of the comment at helper1.
+    A sys call of #2 is different from the only allowed call of #1.
+    A trans call of #2 is the same as the only allowed call of #1.
+    */
+
+    string_res fred;
+
+    sout | "===";
+    sout | "LL: substring of part";
+
+    sout | "---";
+    // Calling a by-val function, the only way it supports, in which it gets a private logical copy.
+    fred = "abcd";
+    sout | "before helper with " | fred;
+    helper1( (string_res){ fred, COPY_VALUE, 1, 3 } );
+    sout | "after helper with " | fred;
+
+    sout | "---";
+    // Calling a by-ref function, sys-style, in which we want to gets its changes as side effects.
+    fred = "abcd";
+    sout | "before helper with " | fred;
+    helper2( (string_res){ fred, SHARE_EDITS, 1, 3 } );
+    sout | "after helper with " | fred;
+
+    sout | "---";
+    // Calling a by-ref function, trans-style, in which we give it a logical copy, to prevent it from pulluting our gold one.
+    fred = "abcd";
+    sout | "before helper with " | fred;
+    helper2( (string_res){ fred, COPY_VALUE, 1, 3 } );
+    sout | "after helper with " | fred;
+
+
+    sout | "===";
+    sout | "LL: substring of whole";
+
+    sout | "---";
+    // Calling a by-val function, the only way it supports, in which it gets a private logical copy.
+    fred = "abcd";
+    sout | "before helper with " | fred;
+    helper1( (string_res){ fred, COPY_VALUE, 0, 4 } );
+    sout | "after helper with " | fred;
+
+    sout | "---";
+    // Calling a by-ref function, sys-style, in which we want to gets its changes as side effects.
+    fred = "abcd";
+    sout | "before helper with " | fred;
+    helper2( (string_res){ fred, SHARE_EDITS, 0, 4 } );
+    sout | "after helper with " | fred;
+
+    sout | "---";
+    // Calling a by-ref function, trans-style, in which we give it a logical copy, to prevent it from pulluting our gold one.
+    fred = "abcd";
+    sout | "before helper with " | fred;
+    helper2( (string_res){ fred, COPY_VALUE, 0, 4 } );
+    sout | "after helper with " | fred;
+
+
+    sout | "===";
+    sout | "LL: whole original string";
+
+    sout | "---";
+    // Calling a by-val function, the only way it supports, in which it gets a private logical copy.
+    fred = "abcd";
+    sout | "before helper with " | fred;
+    helper1( (string_res){ fred, COPY_VALUE } );
+    sout | "after helper with " | fred;
+
+    sout | "---";
+    // Calling a by-ref function, sys-style, in which we want to gets its changes as side effects.
+    fred = "abcd";
+    sout | "before helper with " | fred;
+    helper2( fred );
+    sout | "after helper with " | fred;
+
+    sout | "---";
+    // Calling a by-ref function, trans-style, in which we give it a logical copy, to prevent it from pulluting our gold one.
+    fred = "abcd";
+    sout | "before helper with " | fred;
+    helper2( (string_res){ fred, COPY_VALUE } );
+    sout | "after helper with " | fred;
+}
+
+
+
+int main() {
+
+    calltest_HL();
+    calltest_LL();
+
+}
Index: doc/theses/mike_brooks_MMath/benchmarks/string/pbx-correctness-demos.cpp
===================================================================
--- doc/theses/mike_brooks_MMath/benchmarks/string/pbx-correctness-demos.cpp	(revision 9d9fd819a2c497a3cd2037e48f9c2112d0d4e0e5)
+++ doc/theses/mike_brooks_MMath/benchmarks/string/pbx-correctness-demos.cpp	(revision 9d9fd819a2c497a3cd2037e48f9c2112d0d4e0e5)
@@ -0,0 +1,102 @@
+// see also C++ investigation in ~/plg2/cfa2/mycode/string/raii/ctor-calls.cpp
+
+#include <string>
+#include <iostream>
+
+using namespace std;
+
+#define HELPER_BODY(param) \
+    cout << "early in helper with " << param << endl; \
+    param[0] = '+'; \
+    cout << "late in helper with " << param << endl;
+
+void helper1( string   q ) { HELPER_BODY(q) }
+void helper2( string & q ) { HELPER_BODY(q) }
+#undef HELPER_BODY
+
+
+void calltest_HL() {
+
+    string fred;
+
+
+    cout << "===" << endl;
+    cout << "HL: substring of part" << endl;
+
+    cout << "---" << endl;
+    // Calling a by-val function, the only way it supports, in which it gets a private logical copy.
+    fred = "abcd";
+    cout << "before helper with " << fred << endl;
+    helper1( fred.substr(1,3) );
+    cout << "after helper with " << fred << endl;
+
+    cout << "---" << endl;
+    // Calling a by-ref function, catching side effects the only place STL-string gives them, in an explicit copy.
+    fred = "abcd";
+    cout << "before helper with " << fred << endl;
+    {
+        string fred_sub = fred.substr(1,3);
+        helper2( fred_sub );
+        cout << "after helper with temp having " << fred_sub << endl;
+    }
+    cout << "after helper with original having " << fred << endl;
+
+
+    cout << "===" << endl;
+    cout << "HL: substring of whole" << endl;
+
+    cout << "---" << endl;
+    // Calling a by-val function, the only way it supports, in which it gets a private logical copy.
+    fred = "abcd";
+    cout << "before helper with " << fred << endl;
+    helper1( fred.substr(0,4) );
+    cout << "after helper with " << fred << endl;
+
+    cout << "---" << endl;
+    // Calling a by-ref function, catching side effects the only place STL-string gives them, in an explicit copy.
+    fred = "abcd";
+    cout << "before helper with " << fred << endl;
+    {
+        string fred_sub = fred.substr(0,4);
+        helper2( fred_sub );
+        cout << "after helper with temp having " << fred_sub << endl;
+    }
+    cout << "after helper with original having " << fred << endl;
+
+
+
+    cout << "===" << endl;
+    cout << "HL: whole original string" << endl;
+
+    cout << "---" << endl;
+    // Calling a by-val function, the only way it supports, in which it gets a private logical copy.
+    fred = "abcd";
+    cout << "before helper with " << fred << endl;
+    helper1( fred );
+    cout << "after helper with " << fred << endl;
+
+    cout << "---" << endl;
+    // Calling a by-ref function, sys-style, in which we want to gets its changes as side effects.
+    fred = "abcd";
+    cout << "before helper with " << fred << endl;
+    helper2( fred );
+    cout << "after helper with " << fred << endl;
+
+    cout << "---" << endl;
+    // Calling a by-ref function, trans-style, in which we give it a logical copy, to prevent it from pulluting our gold one; copy needs explicit variable.
+    fred = "abcd";
+    cout << "before helper with " << fred << endl;
+    {
+        string fred_cpy = fred;
+        helper2( fred_cpy );
+    }
+    cout << "after helper with " << fred << endl;
+}
+
+
+
+int main() {
+
+    calltest_HL();
+
+}
Index: doc/theses/mike_brooks_MMath/benchmarks/string/prog-allocn.cfa
===================================================================
--- doc/theses/mike_brooks_MMath/benchmarks/string/prog-allocn.cfa	(revision 9d9fd819a2c497a3cd2037e48f9c2112d0d4e0e5)
+++ doc/theses/mike_brooks_MMath/benchmarks/string/prog-allocn.cfa	(revision 9d9fd819a2c497a3cd2037e48f9c2112d0d4e0e5)
@@ -0,0 +1,218 @@
+#if defined IMPL_STL_NA_NA
+  #define IMPL_STL
+#endif
+
+#if defined IMPL_BUHR94_NA_NA
+  #define IMPL_BUHR94
+#endif
+
+#if defined IMPL_STL
+  #include <string>
+  #include <iostream>
+  #include <cstdio>
+  using namespace std;
+  #define IMPL_CXX
+
+#elif defined IMPL_CFA_HL_SHARE
+  #define IMPL_CFA_HL
+  #define IMPL_CFA
+
+#elif defined IMPL_CFA_LL_SHARE
+  #define IMPL_CFA_LL
+  #define IMPL_CFA
+
+#elif defined IMPL_CFA_HL_NOSHARE
+  #define IMPL_CFA_HL
+  #define CFA_NOSHARE
+  #define IMPL_CFA
+
+#elif defined IMPL_CFA_LL_NOSHARE
+  #define IMPL_CFA_LL
+  #define CFA_NOSHARE
+  #define IMPL_CFA
+
+#elif defined IMPL_BUHR94
+  #include <iostream>
+  #include <cstdio>
+  #include "/u0/mlbrooks/usys1/sm/string/StringSharing/src/string.h"
+  #define IMPL_CXX
+
+#else
+  #error Bad IMPL_
+#endif
+
+
+#if defined IMPL_CFA_HL
+  #include <string.hfa>
+  extern void TUNING_set_string_heap_liveness_threshold(double);  // in string_res.hfa
+#elif defined IMPL_CFA_LL
+  #include <string_res.hfa>
+#endif
+
+#if defined CFA_NOSHARE
+  #include <string_sharectx.hfa>
+  #define STRING_SHARING_CONTROL \
+    string_sharectx c = { NO_SHARING };
+#else 
+  #define STRING_SHARING_CONTROL
+#endif
+
+#if defined IMPL_CFA
+  #include <math.hfa>
+  extern "C" {
+    void malloc_stats( void );
+  }
+#elif defined IMPL_CXX
+  #include <algorithm>
+  using std::min;
+  #include <malloc.h>
+#endif
+
+#include <time.h>
+#include <stdlib.h> // atoi
+#include <string.h> // strlen, only during setup
+
+#if defined IMPL_STL || defined IMPL_BUHR94
+    #define PRINT(s) std::cout << s << std::endl
+#elif defined IMPL_CFA_HL || defined IMPL_CFA_LL
+    #define PRINT(s) sout | s;
+#else
+    #error Unhandled print case
+#endif
+
+#if defined IMPL_CFA_LL
+    #define STRING_T string_res
+    #define ASSIGN_CHAR(str, idx, val) assignAt(str, idx, val)
+#else
+    #define STRING_T string
+    #define ASSIGN_CHAR(str, idx, val) str[idx] = val
+#endif
+
+double meanLen(int N, char ** strings) {
+    int totalLen = 0;
+    for (int i = 0 ; i < N; i ++) {
+        totalLen += strlen(strings[i]);
+    }
+    return (double)totalLen / (double)N;
+}
+
+volatile int checkthis = 0;
+#define MAYBE( op ) if (checkthis) { op; }
+
+int corpuslen = 0;
+char ** corpus = (char**) 0;
+size_t corpus_next_pos = 0;
+
+double repsPerLevel;
+double repBalance = 0.0000001;
+
+clock_t start, endTarget, end_actual;
+size_t allocationCountTarget = 0;
+
+size_t allocationCountActual = 0;
+//size_t allocationBytesActual = 0;
+
+void helper( int depth ) {
+
+    if (depth == 0) return;
+
+    corpus_next_pos += 1;
+    corpus_next_pos %= corpuslen;
+
+    STRING_T q = corpus[corpus_next_pos];
+//    ASSIGN_CHAR(q, 0, '@');    // Turns out my implementation is slow at this step.  A separate test could work it.  It's inessential to the allocation test, given the assumption that both string reps allocate eagerly in their heaps from a constant.  In the STL, that assumption is upheld by my observation that commenting out this line didn't speed it up.  In CFA-share, I know it to be true of the implementation.
+
+    allocationCountActual += 1;
+//    allocationBytesActual += q`len;
+
+//    if (depth > 0) {
+
+        repBalance += repsPerLevel;
+        int curRepLimit = repBalance;
+        repBalance -= curRepLimit;
+
+        for ( int i = 0 ;  i < curRepLimit;  i++ ) {
+            if ((allocationCountActual+1) % allocationCountTarget == 0 && clock() > endTarget) return;
+            helper(depth-1);
+        }
+//    }
+
+    MAYBE(PRINT(q));
+}
+
+int main( int argc, char ** argv ) {
+
+    STRING_SHARING_CONTROL
+
+
+    const char * usage_args[] = {"Depth RepsPerLevel ExpansionThreshold    ExecTimeSecs   Corpus...",
+                                 "Depth RepsPerLevel ExpansionThreshold -w WorkAllocCount Corpus..."};
+    const int static_arg_posns = 5;
+    int used_arg_posns = static_arg_posns;
+
+    int launchDepth = -1;
+    double expansionThreshold = -1.0;
+    int execTimeSecs = -1;
+
+    switch (min(argc, static_arg_posns)) {
+      case 5: if ( strcmp(argv[4], "-w") == 0 ) {
+                used_arg_posns ++;
+                allocationCountTarget = atoi(argv[5]);
+              } else {
+                execTimeSecs = atoi(argv[4]);
+              }
+      case 4: expansionThreshold = atof(argv[3]);
+      case 3: repsPerLevel = atof(argv[2]);
+      case 2: launchDepth = atoi(argv[1]);
+    }
+
+    corpuslen = argc - used_arg_posns;
+    corpus = argv + used_arg_posns;
+
+    if (launchDepth < 1 || repsPerLevel < 1.0 || (execTimeSecs < 1 && allocationCountTarget < 1) || corpuslen < 1 ||
+        (expansionThreshold != -1.0 && (expansionThreshold <= 0.0 || expansionThreshold >= 1.0))) {
+      for (int u = 0; u < sizeof(usage_args) / sizeof(*usage_args); u++) {
+        printf("usage: %s %s\n", argv[0], usage_args[u]);
+      }
+      printf("output:\nxxx,corpusItemCount,corpusMeanLenChars,allocationCountActual,execTimeActualSec,topIters\n");
+      exit(1);
+    }
+
+    if (expansionThreshold != -1.0 ) {
+      #if defined IMPL_CFA
+      TUNING_set_string_heap_liveness_threshold(expansionThreshold);
+      #else
+      printf("cannot set expansion threshold on non-CFA implementation");
+      exit(1);
+      #endif
+    }
+
+    double meanCorpusLen = meanLen(corpuslen, corpus);
+
+    // time driven experiment: re-check time every 10000 allocations
+    if (execTimeSecs > 0) allocationCountTarget = 10000;
+
+    start = clock();
+    endTarget = start + CLOCKS_PER_SEC * max(0, execTimeSecs);
+
+    size_t top_iters = 0;
+
+    for(;;) {
+            #if defined OP_PALL
+                helper( launchDepth );
+            #else
+                #error Bad OP_
+            #endif
+
+            top_iters++;
+
+            if ((allocationCountActual+1) % allocationCountTarget == 0 && clock() > endTarget) break;
+    }
+    end_actual = clock();
+    double elapsed = ((double) (end_actual - start)) / CLOCKS_PER_SEC;
+    printf("xxx,%d,%f,%ld,%f,%ld\n", corpuslen, meanCorpusLen, allocationCountActual, elapsed, top_iters);
+
+    // malloc_stats();
+
+    return 0;
+}
Index: doc/theses/mike_brooks_MMath/benchmarks/string/prog-find.cfa
===================================================================
--- doc/theses/mike_brooks_MMath/benchmarks/string/prog-find.cfa	(revision 9d9fd819a2c497a3cd2037e48f9c2112d0d4e0e5)
+++ doc/theses/mike_brooks_MMath/benchmarks/string/prog-find.cfa	(revision 9d9fd819a2c497a3cd2037e48f9c2112d0d4e0e5)
@@ -0,0 +1,184 @@
+#if defined IMPL_STL_NA_NA
+  #define IMPL_STL
+#endif
+
+#if defined IMPL_BUHR94_NA_NA
+  #define IMPL_BUHR94
+#endif
+
+#if defined IMPL_STL
+  #include <string>
+  #include <iostream>
+  #include <cstdio>
+  using namespace std;
+  #define IMPL_CXX
+
+#elif defined IMPL_CFA_HL_SHARE
+  #define IMPL_CFA_HL
+  #define IMPL_CFA
+
+#elif defined IMPL_CFA_LL_SHARE
+  #define IMPL_CFA_LL
+  #define IMPL_CFA
+
+#elif defined IMPL_CFA_HL_NOSHARE
+  #define IMPL_CFA_HL
+  #define CFA_NOSHARE
+  #define IMPL_CFA
+
+#elif defined IMPL_CFA_LL_NOSHARE
+  #define IMPL_CFA_LL
+  #define CFA_NOSHARE
+  #define IMPL_CFA
+
+#elif defined IMPL_BUHR94
+  #include <iostream>
+  #include <cstdio>
+  #include "/u0/mlbrooks/usys1/sm/string/StringSharing/src/string.h"
+  #define IMPL_CXX
+
+#else
+  #error Bad IMPL_
+#endif
+
+
+#if defined IMPL_CFA_HL
+  #include <string.hfa>
+#elif defined IMPL_CFA_LL
+  #include <string_res.hfa>
+  #include "not_string_res.hfa"
+#endif
+
+#if defined CFA_NOSHARE
+  #include <string_sharectx.hfa>
+  #define STRING_SHARING_CONTROL \
+    string_sharectx c = { NO_SHARING };
+#else 
+  #define STRING_SHARING_CONTROL
+#endif
+
+#if defined IMPL_CFA
+  #include <math.hfa>
+  extern "C" {
+    void malloc_stats( void );
+  }
+#elif defined IMPL_CXX
+  #include <algorithm>
+  using std::min;
+  #include <malloc.h>
+#endif
+
+#include <time.h>
+#include <stdlib.h> // atoi
+#include <string.h> // strlen, only during setup
+#include <limits.h> // LONG_MAX
+
+#if defined IMPL_STL || defined IMPL_BUHR94
+    #define PRINT(s) std::cout << s << std::endl
+#elif defined IMPL_CFA_HL || defined IMPL_CFA_LL
+    #define PRINT(s) sout | s;
+#else
+    #error Unhandled print case
+#endif
+
+#if defined IMPL_CFA_LL
+    #define STRING_T string_res
+    #define ASSIGN_CHAR(str, idx, val) assignAt(str, idx, val)
+#else
+    #define STRING_T string
+    #define ASSIGN_CHAR(str, idx, val) str[idx] = val
+#endif
+
+double meanLen(int N, char ** strings) {
+    int totalLen = 0;
+    for (int i = 0 ; i < N; i ++) {
+        totalLen += strlen(strings[i]);
+    }
+    return (double)totalLen / (double)N;
+}
+
+volatile int checkthis = 0;
+#define MAYBE( op ) if (checkthis) { op; }
+
+
+int main( int argc, char ** argv ) {
+
+    STRING_SHARING_CONTROL
+
+
+    const char * usage_args[] = {"(Ignored)    ExecTimeSecs   Corpus...",
+                                 "(Ignored) -w WorkAllocCount Corpus..."};
+
+    const int static_arg_posns = 3;
+    int used_arg_posns = static_arg_posns;
+
+    int execTimeSecs = -1;
+
+    long int iterationCountTarget = -1;
+
+    switch (min(argc, static_arg_posns)) {
+      case 3: if ( strcmp(argv[2], "-w") == 0 ) {
+                used_arg_posns ++;
+                execTimeSecs = 0;
+                iterationCountTarget = atoi(argv[3]);
+              } else {
+                execTimeSecs = atoi(argv[2]);
+                iterationCountTarget = LONG_MAX;
+              }
+    }
+
+    int corpuslen = argc - used_arg_posns;
+    char ** corpus = argv + used_arg_posns;
+
+    if ((execTimeSecs < 1 && iterationCountTarget < 1)  || corpuslen < 1) {
+      for (int u = 0; u < sizeof(usage_args) / sizeof(*usage_args); u++) {
+        printf("usage: %s %s\n", argv[0], usage_args[u]);
+      }
+      printf("output:\nxxx,corpusItemCount,corpusMeanLenChars,callDoneActualCount,execTimeActualSec\n");
+      exit(1);
+    }
+
+    double meanCorpusLen = meanLen(corpuslen, corpus);
+
+    clock_t start, end_target, end_actual;
+
+    STRING_T corpus_imported[corpuslen];
+
+    for (int i = 0; i < corpuslen; i++) {
+        corpus_imported[i] = corpus[i];
+        // if the callee ever modifies, then we will drive GCs, which will visit the entire corpus
+    }
+
+    start = clock();
+    if (execTimeSecs != 0) {
+      end_target = start + CLOCKS_PER_SEC * execTimeSecs;
+    } else {
+      end_target = start + CLOCKS_PER_SEC * 3600;
+    }
+
+    unsigned int t = 0;
+    for ( ; t < iterationCountTarget && ((t+1) % 10000 != 0 || clock() < end_target) ; t += 1 ) {
+            #if defined OP_PFI
+              size_t foundAt =
+                #if defined IMPL_CFA
+                   find( corpus_imported[t % corpuslen], ' ')
+                #elif defined IMPL_STL
+                   corpus_imported[t % corpuslen].find(' ')
+                #else
+                  #error Bad IMPL
+                #endif
+                ;
+            #else
+              #error Bad OP_
+            #endif
+            MAYBE( PRINT( foundAt ) );
+    }
+    end_actual = clock();
+    unsigned int callsDone = t;
+    double elapsed = ((double) (end_actual - start)) / CLOCKS_PER_SEC;
+    printf("xxx,%d,%f,%d,%f\n", corpuslen, meanCorpusLen, t, elapsed);
+
+    // malloc_stats();
+
+    return 0;
+}
Index: doc/theses/mike_brooks_MMath/benchmarks/string/prog-normalize.cfa
===================================================================
--- doc/theses/mike_brooks_MMath/benchmarks/string/prog-normalize.cfa	(revision 9d9fd819a2c497a3cd2037e48f9c2112d0d4e0e5)
+++ doc/theses/mike_brooks_MMath/benchmarks/string/prog-normalize.cfa	(revision 9d9fd819a2c497a3cd2037e48f9c2112d0d4e0e5)
@@ -0,0 +1,264 @@
+#if defined IMPL_STL_NA_NA
+  #define IMPL_STL
+#endif
+
+#if defined IMPL_BUHR94_NA_NA
+  #define IMPL_BUHR94
+#endif
+
+#if defined IMPL_STL
+  #include <string>
+  #include <iostream>
+  #include <cstdio>
+  using namespace std;
+  #define IMPL_CXX
+
+#elif defined IMPL_CFA_HL_SHARE
+  #define IMPL_CFA_HL
+  #define IMPL_CFA
+
+#elif defined IMPL_CFA_LL_SHARE
+  #define IMPL_CFA_LL
+  #define IMPL_CFA
+
+#elif defined IMPL_CFA_HL_NOSHARE
+  #define IMPL_CFA_HL
+  #define CFA_NOSHARE
+  #define IMPL_CFA
+
+#elif defined IMPL_CFA_LL_NOSHARE
+  #define IMPL_CFA_LL
+  #define CFA_NOSHARE
+  #define IMPL_CFA
+
+#elif defined IMPL_BUHR94
+  #include <iostream>
+  #include <cstdio>
+  #include "/u0/mlbrooks/usys1/sm/string/StringSharing/src/string.h"
+  #define IMPL_CXX
+
+#else
+  #error Bad IMPL_
+#endif
+
+
+#if defined IMPL_CFA_HL
+  #include <string.hfa>
+#elif defined IMPL_CFA_LL
+  #include <string_res.hfa>
+#endif
+
+#if defined CFA_NOSHARE
+  #include <string_sharectx.hfa>
+  #define STRING_SHARING_CONTROL \
+    string_sharectx c = { NO_SHARING };
+#else 
+  #define STRING_SHARING_CONTROL
+#endif
+
+#if defined IMPL_CFA
+  #include <math.hfa>
+  extern "C" {
+    void malloc_stats( void );
+  }
+#elif defined IMPL_CXX
+  #include <algorithm>
+  using std::min;
+  #include <malloc.h>
+#endif
+
+#include <time.h>
+#include <stdlib.h> // atoi
+#include <string.h> // strlen, only during setup
+
+#if defined IMPL_STL || defined IMPL_BUHR94
+    #define PRINT(s) std::cout << s << std::endl
+#elif defined IMPL_CFA_HL || defined IMPL_CFA_LL
+    #define PRINT(s) sout | s;
+#else
+    #error Unhandled print case
+#endif
+
+#if defined IMPL_CFA_LL
+    #define STRING_T string_res
+    #define ASSIGN_CHAR(str, idx, val) assignAt(str, idx, val)
+#else
+    #define STRING_T string
+    #define ASSIGN_CHAR(str, idx, val) str[idx] = val
+#endif
+
+#if defined IMPL_CFA
+    #define LEN(str) size(str)
+#elif defined IMPL_STL 
+    #define LEN(str) str.length()
+#else
+    #error need LEN definition for this IMPL_
+#endif
+
+double meanLen(int N, char ** strings) {
+    int totalLen = 0;
+    for (int i = 0 ; i < N; i ++) {
+        totalLen += strlen(strings[i]);
+    }
+    return (double)totalLen / (double)N;
+}
+
+volatile int checkthis = 0;
+#define MAYBE( op ) if (checkthis) { op; }
+
+// setup, not being timed, nor judged for aesthetics
+void makeSuperCorpus( STRING_T & target, int corpusLen, char ** corpus, int scSize, char scDelimiter ) {
+    char delimiterStr[2] = { scDelimiter, '\0' };
+    for ( int i = 0;  i < scSize; i++ ) {
+        target += corpus[ i % corpusLen ];
+        target += delimiterStr;
+    }
+}
+
+// the function at issue
+
+#if defined IMPL_CFA_HL
+void processThing( string & thing, char magicChar ) {
+    MAYBE(PRINT(thing));
+    size_t foundPos;
+    for (;;) {
+        size_t size_thing = size(thing);
+        foundPos = find(thing, magicChar);
+        if( foundPos == size_thing ) break;
+        string mcOccur = thing(foundPos, foundPos+1)`share;
+        mcOccur = "";
+    }
+    return thing;
+}
+
+#elif defined IMPL_CFA_LL
+void processThing( string_res & thing, char magicChar ) {
+    MAYBE(PRINT(thing));
+    size_t foundPos;
+    for (;;) {
+        size_t size_thing = size(thing);
+        foundPos = find(thing, magicChar);
+        if( foundPos == size_thing ) break;
+        string_res mcOccur = { thing, SHARE_EDITS, foundPos, foundPos+1 };
+        mcOccur = "";
+    }
+}
+
+#elif defined IMPL_STL
+void processThing( string & thing, char magicChar ) {
+    MAYBE(PRINT(thing));
+    size_t foundPos;
+    for (;;) {
+        size_t size_thing = thing.length();
+        foundPos = thing.find(magicChar);
+        if (foundPos == string::npos) break;
+        thing.erase(foundPos, 1);
+    }
+}
+
+#endif
+
+/*
+void runCorrectnessDemo(char** corpus, int corpusLen) {
+    STRING_T item = "asdf";    PRINT( processThing( item, '-' ) );
+    item = "as-df";            PRINT( processThing( item, '-' ) );
+    item = "-asdf-";           PRINT( processThing( item, '-' ) );
+    item = "-";                PRINT( processThing( item, '-' ) );
+    for ( int i = 0; i < corpusLen; i ++ ) {
+        item = corpus[i];      PRINT( processThing( item, '-' ) );
+    }
+
+    STRING_T supercorpus;
+    makeSuperCorpus( supercorpus, corpusLen, corpus, 30, ',');
+    PRINT( supercorpus );
+}
+*/
+
+int main( int argc, char ** argv ) {
+
+    STRING_SHARING_CONTROL
+
+    int corpuslen = 0;
+    char ** corpus = (char**) 0;
+
+    clock_t start, endTarget, end_actual;
+
+    const char * usage_args = "SCsize MagicChar ExecTimeSecs Corpus...";
+    const int static_arg_posns = 4;
+
+    int scSize = -1;
+    char magicChar = '\0';
+    int execTimeSecs = -1;
+
+    switch (min(argc, static_arg_posns)) {
+      case 4: execTimeSecs = atoi(argv[3]);
+      case 3: magicChar = argv[2][0];
+      case 2: scSize = atoi(argv[1]);
+    }
+
+    corpuslen = argc - static_arg_posns;
+    corpus = argv + static_arg_posns;
+
+    if (scSize < 1 || magicChar == '\0' || execTimeSecs < 1 || corpuslen < 1) {
+      printf("usage: %s %s\n", argv[0], usage_args);
+      printf("output:\nxxx,corpusItemCount,corpusMeanLenChars,invcationCountActual,execTimeActualSec\n");
+      exit(1);
+    }
+
+    double meanCorpusLen = meanLen(corpuslen, corpus);
+
+//    runCorrectnessDemo(corpus, corpuslen);
+
+
+    STRING_T supercorpus;
+    makeSuperCorpus( supercorpus, corpuslen, corpus, scSize, ',');
+
+    size_t sc_charlen = LEN(supercorpus);
+
+    start = clock();
+    endTarget = start + CLOCKS_PER_SEC * execTimeSecs;
+
+    volatile unsigned int t = 0;
+    size_t lastChunkEnd = -1;
+    for ( ; t % 10000 != 0 || clock() < endTarget ; t += 1 ) {
+            #if defined OP_PNO
+
+                lastChunkEnd++;
+                if ( lastChunkEnd >= sc_charlen ) {
+                    lastChunkEnd = 0;
+                }
+
+#if defined IMPL_CFA_HL
+                size_t thisChunkEnd = findFrom( supercorpus, lastChunkEnd, ',' );
+                //if (thisChunkEnd == string::npos) throw 1;
+                string chunkProcessed = supercorpus(lastChunkEnd, thisChunkEnd);
+                processThing(chunkProcessed, '-');
+#elif defined IMPL_CFA_LL
+                size_t thisChunkEnd = findFrom( supercorpus, lastChunkEnd, ',' );
+                //if (thisChunkEnd == string::npos) throw 1;
+                
+                string_res chunkProcessed = { supercorpus, COPY_VALUE, lastChunkEnd, thisChunkEnd };
+                processThing( chunkProcessed, '-' );
+#elif defined IMPL_STL
+                size_t thisChunkEnd = supercorpus.find( ',', lastChunkEnd );
+                if (thisChunkEnd == string::npos) throw 1;
+                string chunkProcessed = supercorpus.substr(lastChunkEnd, thisChunkEnd-lastChunkEnd);
+                processThing(chunkProcessed, '-');
+#else 
+#error Bad IMPL_
+#endif
+                MAYBE( PRINT(chunkProcessed) );
+
+                lastChunkEnd = thisChunkEnd;
+            #else
+                #error Bad OP_
+            #endif
+    }
+    end_actual = clock();
+    double elapsed = ((double) (end_actual - start)) / CLOCKS_PER_SEC;
+    printf("xxx,%d,%f,%d,%f\n", corpuslen, meanCorpusLen, t, elapsed);
+
+    // malloc_stats();
+
+    return 0;
+}
Index: doc/theses/mike_brooks_MMath/benchmarks/string/prog-passbyX.cfa
===================================================================
--- doc/theses/mike_brooks_MMath/benchmarks/string/prog-passbyX.cfa	(revision 9d9fd819a2c497a3cd2037e48f9c2112d0d4e0e5)
+++ doc/theses/mike_brooks_MMath/benchmarks/string/prog-passbyX.cfa	(revision 9d9fd819a2c497a3cd2037e48f9c2112d0d4e0e5)
@@ -0,0 +1,210 @@
+#if defined IMPL_STL_NA_NA
+  #define IMPL_STL
+#endif
+
+#if defined IMPL_BUHR94_NA_NA
+  #define IMPL_BUHR94
+#endif
+
+#if defined IMPL_STL
+  #include <string>
+  #include <iostream>
+  #include <cstdio>
+  using namespace std;
+  #define IMPL_CXX
+
+#elif defined IMPL_CFA_HL_SHARE
+  #define IMPL_CFA_HL
+  #define IMPL_CFA
+
+#elif defined IMPL_CFA_LL_SHARE
+  #define IMPL_CFA_LL
+  #define IMPL_CFA
+
+#elif defined IMPL_CFA_HL_NOSHARE
+  #define IMPL_CFA_HL
+  #define CFA_NOSHARE
+  #define IMPL_CFA
+
+#elif defined IMPL_CFA_LL_NOSHARE
+  #define IMPL_CFA_LL
+  #define CFA_NOSHARE
+  #define IMPL_CFA
+
+#elif defined IMPL_BUHR94
+  #include <iostream>
+  #include <cstdio>
+  #include "/u0/mlbrooks/usys1/sm/string/StringSharing/src/string.h"
+  #define IMPL_CXX
+
+#else
+  #error Bad IMPL_
+#endif
+
+
+#if defined IMPL_CFA_HL
+  #include <string.hfa>
+#elif defined IMPL_CFA_LL
+  #include <string_res.hfa>
+  #include "not_string_res.hfa"
+#endif
+
+#if defined CFA_NOSHARE
+  #include <string_sharectx.hfa>
+  #define STRING_SHARING_CONTROL \
+    string_sharectx c = { NO_SHARING };
+#else 
+  #define STRING_SHARING_CONTROL
+#endif
+
+#if defined IMPL_CFA
+  #include <math.hfa>
+  extern "C" {
+    void malloc_stats( void );
+  }
+#elif defined IMPL_CXX
+  #include <algorithm>
+  using std::min;
+  #include <malloc.h>
+#endif
+
+#include <time.h>
+#include <stdlib.h> // atoi
+#include <string.h> // strlen, only during setup
+#include <limits.h> // LONG_MAX
+
+#if defined IMPL_STL || defined IMPL_BUHR94
+    #define PRINT(s) std::cout << s << std::endl
+#elif defined IMPL_CFA_HL || defined IMPL_CFA_LL
+    #define PRINT(s) sout | s;
+#else
+    #error Unhandled print case
+#endif
+
+#if defined IMPL_CFA_LL
+    #define STRING_T string_res
+    #define ASSIGN_CHAR(str, idx, val) assignAt(str, idx, val)
+#else
+    #define STRING_T string
+    #define ASSIGN_CHAR(str, idx, val) str[idx] = val
+#endif
+
+double meanLen(int N, char ** strings) {
+    int totalLen = 0;
+    for (int i = 0 ; i < N; i ++) {
+        totalLen += strlen(strings[i]);
+    }
+    return (double)totalLen / (double)N;
+}
+
+volatile int checkthis = 0;
+#define MAYBE( op ) if (checkthis) { op; }
+
+
+#if defined IMPL_CFA_LL
+void helper( string_res & q ) {
+#else
+  #error bad IMPL_
+#endif
+    #if defined OP_PB1X || defined OP_PB2X || defined OP_PB3X || defined OP_PB4X || defined OP_PB5X || defined OP_PB6X
+        ASSIGN_CHAR(q, 0, '@');
+    #else
+        MAYBE(ASSIGN_CHAR(q, 0, '@'));
+    #endif
+    MAYBE(PRINT(q));
+}
+
+void not_helper( not_string_res & q ) {
+    MAYBE( printf("%ld", q.junk[3]) );
+    MAYBE( q.junk[3] = 17 );
+}
+
+int main( int argc, char ** argv ) {
+
+    STRING_SHARING_CONTROL
+
+
+    const char * usage_args[] = {"(Ignored)    ExecTimeSecs   Corpus...",
+                                 "(Ignored) -w WorkAllocCount Corpus..."};
+
+    const int static_arg_posns = 3;
+    int used_arg_posns = static_arg_posns;
+
+    int execTimeSecs = -1;
+
+    long int iterationCountTarget = -1;
+
+    switch (min(argc, static_arg_posns)) {
+      case 3: if ( strcmp(argv[2], "-w") == 0 ) {
+                used_arg_posns ++;
+                execTimeSecs = 0;
+                iterationCountTarget = atoi(argv[3]);
+              } else {
+                execTimeSecs = atoi(argv[2]);
+                iterationCountTarget = LONG_MAX;
+              }
+    }
+
+    int corpuslen = argc - used_arg_posns;
+    char ** corpus = argv + used_arg_posns;
+
+    if ((execTimeSecs < 1 && iterationCountTarget < 1)  || corpuslen < 1) {
+      for (int u = 0; u < sizeof(usage_args) / sizeof(*usage_args); u++) {
+        printf("usage: %s %s\n", argv[0], usage_args[u]);
+      }
+      printf("output:\nxxx,corpusItemCount,corpusMeanLenChars,callDoneActualCount,execTimeActualSec\n");
+      exit(1);
+    }
+
+    double meanCorpusLen = meanLen(corpuslen, corpus);
+
+    clock_t start, end_target, end_actual;
+
+    STRING_T corpus_imported[corpuslen];
+
+    for (int i = 0; i < corpuslen; i++) {
+        corpus_imported[i] = corpus[i];
+        // if the callee ever modifies, then we will drive GCs, which will visit the entire corpus
+    }
+
+    start = clock();
+    if (execTimeSecs != 0) {
+      end_target = start + CLOCKS_PER_SEC * execTimeSecs;
+    } else {
+      end_target = start + CLOCKS_PER_SEC * 3600;
+    }
+
+    unsigned int t = 0;
+    for ( ; t < iterationCountTarget && ((t+1) % 10000 != 0 || clock() < end_target) ; t += 1 ) {
+            string_res & src = corpus_imported[t % corpuslen];
+            size_t srclen = size(src);
+            if (srclen < 2) {
+              printf("need string lengths >= 2");
+            }
+            #if defined OP_PB1 || defined OP_PB1X
+              helper( (string_res){ src, COPY_VALUE, 1, srclen-1 } ); 
+            #elif defined OP_PB2 || defined OP_PB2X
+              helper( (string_res){ src, SHARE_EDITS, 1, srclen-1 } );
+            #elif defined OP_PB3 || defined OP_PB3X
+              helper( (string_res){ src, COPY_VALUE, 0, srclen } );
+            #elif defined OP_PB4 || defined OP_PB4X
+              helper( (string_res){ src, SHARE_EDITS, 0, srclen } );
+            #elif defined OP_PB5 || defined OP_PB5X
+              helper( (string_res){ src, COPY_VALUE } );
+            #elif defined OP_PB6 || defined OP_PB6X
+              helper( src ); 
+            #elif defined OP_PB9
+              not_helper( (not_string_res){ src, SHARE_EDITS, 0, srclen } );
+            #else
+                #error Bad OP_
+            #endif
+    }
+    end_actual = clock();
+    unsigned int callsDone = t;
+    double elapsed = ((double) (end_actual - start)) / CLOCKS_PER_SEC;
+    printf("xxx,%d,%f,%d,%f\n", corpuslen, meanCorpusLen, t, elapsed);
+
+    // malloc_stats();
+
+    return 0;
+}
Index: doc/theses/mike_brooks_MMath/benchmarks/string/prog-passbyval.cfa
===================================================================
--- doc/theses/mike_brooks_MMath/benchmarks/string/prog-passbyval.cfa	(revision 9d9fd819a2c497a3cd2037e48f9c2112d0d4e0e5)
+++ doc/theses/mike_brooks_MMath/benchmarks/string/prog-passbyval.cfa	(revision 9d9fd819a2c497a3cd2037e48f9c2112d0d4e0e5)
@@ -0,0 +1,164 @@
+#if defined IMPL_STL_NA_NA
+  #define IMPL_STL
+#endif
+
+#if defined IMPL_BUHR94_NA_NA
+  #define IMPL_BUHR94
+#endif
+
+#if defined IMPL_STL
+  #include <string>
+  #include <iostream>
+  #include <cstdio>
+  using namespace std;
+  #define IMPL_CXX
+
+#elif defined IMPL_CFA_HL_SHARE
+  #define IMPL_CFA_HL
+  #define IMPL_CFA
+
+#elif defined IMPL_CFA_LL_SHARE
+  #define IMPL_CFA_LL
+  #define IMPL_CFA
+
+#elif defined IMPL_CFA_HL_NOSHARE
+  #define IMPL_CFA_HL
+  #define CFA_NOSHARE
+  #define IMPL_CFA
+
+#elif defined IMPL_CFA_LL_NOSHARE
+  #define IMPL_CFA_LL
+  #define CFA_NOSHARE
+  #define IMPL_CFA
+
+#elif defined IMPL_BUHR94
+  #include <iostream>
+  #include <cstdio>
+  #include "/u0/mlbrooks/usys1/sm/string/StringSharing/src/string.h"
+  #define IMPL_CXX
+
+#else
+  #error Bad IMPL_
+#endif
+
+
+#if defined IMPL_CFA_HL
+  #include <string.hfa>
+#elif defined IMPL_CFA_LL
+  #include <string_res.hfa>
+#endif
+
+#if defined CFA_NOSHARE
+  #include <string_sharectx.hfa>
+  #define STRING_SHARING_CONTROL \
+    string_sharectx c = { NO_SHARING };
+#else 
+  #define STRING_SHARING_CONTROL
+#endif
+
+#if defined IMPL_CFA
+  #include <math.hfa>
+  extern "C" {
+    void malloc_stats( void );
+  }
+#elif defined IMPL_CXX
+  #include <algorithm>
+  using std::min;
+  #include <malloc.h>
+#endif
+
+#include <time.h>
+#include <stdlib.h> // atoi
+#include <string.h> // strlen, only during setup
+
+#if defined IMPL_STL || defined IMPL_BUHR94
+    #define PRINT(s) std::cout << s << std::endl
+#elif defined IMPL_CFA_HL || defined IMPL_CFA_LL
+    #define PRINT(s) sout | s;
+#else
+    #error Unhandled print case
+#endif
+
+#if defined IMPL_CFA_LL
+    #define STRING_T string_res
+    #define ASSIGN_CHAR(str, idx, val) assignAt(str, idx, val)
+#else
+    #define STRING_T string
+    #define ASSIGN_CHAR(str, idx, val) str[idx] = val
+#endif
+
+double meanLen(int N, char ** strings) {
+    int totalLen = 0;
+    for (int i = 0 ; i < N; i ++) {
+        totalLen += strlen(strings[i]);
+    }
+    return (double)totalLen / (double)N;
+}
+
+volatile int checkthis = 0;
+#define MAYBE( op ) if (checkthis) { op; }
+
+
+#if defined IMPL_CFA_LL
+void helper( string_res & qref ) {
+    string_res q = { qref, COPY_VALUE };
+#else
+void helper( string q ) {
+#endif
+    MAYBE(ASSIGN_CHAR(q, 0, '@'));
+    MAYBE(PRINT(q));
+}
+
+int main( int argc, char ** argv ) {
+
+    STRING_SHARING_CONTROL
+
+
+    const char * usage_args = "(Ignored) ExecTimeSecs Corpus...";
+    const int static_arg_posns = 3;
+
+    int execTimeSecs = -1;
+
+    switch (min(argc, static_arg_posns)) {
+      case 3: execTimeSecs = atoi(argv[2]);
+    }
+
+    int corpuslen = argc - static_arg_posns;
+    char ** corpus = argv + static_arg_posns;
+
+    if (execTimeSecs < 1 || corpuslen < 1) {
+      printf("usage: %s %s\n", argv[0], usage_args);
+      printf("output:\nxxx,corpusItemCount,corpusMeanLenChars,callDoneActualCount,execTimeActualSec\n");
+      exit(1);
+    }
+
+    double meanCorpusLen = meanLen(corpuslen, corpus);
+
+    clock_t start, end_target, end_actual;
+
+    STRING_T corpus_imported[corpuslen];
+
+    for (int i = 0; i < corpuslen; i++) {
+        corpus_imported[i] = corpus[i];
+        // if the callee ever modifies, then we will drive GCs, which will visit the entire corpus
+    }
+
+    start = clock();
+    end_target = start + CLOCKS_PER_SEC * execTimeSecs;
+    unsigned int t = 0;
+    for ( ; t % 10000 != 0 || clock() < end_target ; t += 1 ) {
+            #if defined OP_PBV
+            helper( corpus_imported[t % corpuslen] );
+            #else
+                #error Bad OP_
+            #endif
+    }
+    end_actual = clock();
+    unsigned int callsDone = t;
+    double elapsed = ((double) (end_actual - start)) / CLOCKS_PER_SEC;
+    printf("xxx,%d,%f,%d,%f\n", corpuslen, meanCorpusLen, t, elapsed);
+
+    // malloc_stats();
+
+    return 0;
+}
Index: doc/theses/mike_brooks_MMath/benchmarks/string/prog.cfa
===================================================================
--- doc/theses/mike_brooks_MMath/benchmarks/string/prog.cfa	(revision 9d9fd819a2c497a3cd2037e48f9c2112d0d4e0e5)
+++ doc/theses/mike_brooks_MMath/benchmarks/string/prog.cfa	(revision 9d9fd819a2c497a3cd2037e48f9c2112d0d4e0e5)
@@ -0,0 +1,175 @@
+#if defined IMPL_STL_NA_NA
+  #define IMPL_STL
+#endif
+
+#if defined IMPL_BUHR94_NA_NA
+  #define IMPL_BUHR94
+#endif
+
+#if defined IMPL_STL
+  #include <string>
+  #include <iostream>
+  #include <cstdio>
+  using namespace std;
+  #define IMPL_CXX
+
+#elif defined IMPL_CFA_HL_SHARE
+  #define IMPL_CFA_HL
+  #define IMPL_CFA
+
+#elif defined IMPL_CFA_LL_SHARE
+  #define IMPL_CFA_LL
+  #define IMPL_CFA
+
+#elif defined IMPL_CFA_HL_NOSHARE
+  #define IMPL_CFA_HL
+  #define CFA_NOSHARE
+  #define IMPL_CFA
+
+#elif defined IMPL_CFA_LL_NOSHARE
+  #define IMPL_CFA_LL
+  #define CFA_NOSHARE
+  #define IMPL_CFA
+
+#elif defined IMPL_BUHR94
+  #include <iostream>
+  #include <cstdio>
+  #include "/u0/mlbrooks/usys1/sm/string/StringSharing/src/string.h"
+  #define IMPL_CXX
+
+#else
+  #error Bad IMPL_
+#endif
+
+
+#if defined IMPL_CFA_HL
+  #include <string.hfa>
+#elif defined IMPL_CFA_LL
+  #include <string_res.hfa>
+#endif
+
+#if defined CFA_NOSHARE
+  #include <string_sharectx.hfa>
+  #define STRING_SHARING_CONTROL \
+    string_sharectx c = { NO_SHARING };
+#else 
+  #define STRING_SHARING_CONTROL
+#endif
+
+#if defined IMPL_CFA
+  #include <math.hfa>
+  extern "C" {
+    void malloc_stats( void );
+  }
+#elif defined IMPL_CXX
+  #include <algorithm>
+  using std::min;
+  #include <malloc.h>
+#endif
+
+#include <time.h>
+#include <stdlib.h> // atoi
+#include <string.h> // strlen, only during setup
+
+#if defined IMPL_STL || defined IMPL_BUHR94
+    #define PRINT(s) std::cout << s << std::endl
+#elif defined IMPL_CFA_HL || defined IMPL_CFA_LL
+    #define PRINT(s) sout | s;
+#else
+    #error Unhandled print case
+#endif
+
+double meanLen(int N, char ** strings) {
+    int totalLen = 0;
+    for (int i = 0 ; i < N; i ++) {
+        totalLen += strlen(strings[i]);
+    }
+    return (double)totalLen / (double)N;
+}
+
+volatile int checkthis = 0;
+#define MAYBE( op ) if (checkthis) { op; }
+
+int main( int argc, char ** argv ) {
+
+    STRING_SHARING_CONTROL
+
+
+    const char * usage_args = "ConcatsPerReset ExecTimeSecs Corpus...";
+    const int static_arg_posns = 3;
+
+    int concatsPerReset = -1, execTimeSecs = -1;
+
+    switch (min(argc, static_arg_posns)) {
+      case 3: execTimeSecs = atoi(argv[2]);
+      case 2: concatsPerReset = atoi(argv[1]);
+    }
+
+    int corpuslen = argc - static_arg_posns;
+    char ** corpus = argv + static_arg_posns;
+
+    if (execTimeSecs < 1 || concatsPerReset < 1 || corpuslen < 1) {
+      printf("usage: %s %s\n", argv[0], usage_args);
+      printf("output:\nconcatsPerReset,corpusItemCount,corpusMeanLenChars,concatDoneActualCount,execTimeActualSec\n");
+      exit(1);
+    }
+
+    double meanCorpusLen = meanLen(corpuslen, corpus);
+
+    clock_t start, end_target, end_actual;
+
+    #if defined IMPL_CFA_LL && defined OP_PTA
+        string_res pta_ll_temp;
+    #endif
+
+    #if defined IMPL_CFA_LL
+      #define DECLS \
+        const char* initval = "starter"; \
+        string_res accum = initval;
+    #else
+      #define DECLS \
+        const char* initval = "starter"; \
+        string accum = initval;
+    #endif
+
+    #if defined ALLOC_REUSE
+      DECLS
+      #define RESET \
+        accum = initval;
+    #elif defined ALLOC_FRESH
+      #define RESET \
+        DECLS
+    #else
+      #error bad alloc
+    #endif
+
+    start = clock();
+    end_target = start + CLOCKS_PER_SEC * execTimeSecs;
+    volatile unsigned int t = 0;
+    for ( ; t % 100 != 0 || clock() < end_target ; t += 1 ) {
+            RESET
+            for ( volatile unsigned int i = 0; i < concatsPerReset; i += 1 ) {
+              MAYBE( PRINT(accum) )
+              char *toAppend = corpus[i % corpuslen]; // ? corpus[rand() % corpuslen]
+              #if defined OP_PTA && defined IMPL_CFA_LL
+                 pta_ll_temp = accum;
+                 pta_ll_temp += toAppend;
+                 accum = pta_ll_temp;
+              #elif defined OP_PTA
+                 accum = accum + toAppend;
+              #elif defined OP_PEQ
+                 accum += toAppend;
+              #else
+                 #error Bad OP_
+              #endif
+            }
+    }
+    end_actual = clock();
+    unsigned int concatsDone = t * concatsPerReset;
+    double elapsed = ((double) (end_actual - start)) / CLOCKS_PER_SEC;
+    printf("%d,%d,%f,%d,%f\n", concatsPerReset, corpuslen, meanCorpusLen, concatsDone, elapsed);
+
+    // malloc_stats();
+
+    return 0;
+}
Index: doc/theses/mike_brooks_MMath/benchmarks/string/qanal.py
===================================================================
--- doc/theses/mike_brooks_MMath/benchmarks/string/qanal.py	(revision 9d9fd819a2c497a3cd2037e48f9c2112d0d4e0e5)
+++ doc/theses/mike_brooks_MMath/benchmarks/string/qanal.py	(revision 9d9fd819a2c497a3cd2037e48f9c2112d0d4e0e5)
@@ -0,0 +1,34 @@
+#! /usr/bin/python3
+
+import glob
+import os
+import re
+
+print("corpuslen", "expansion", "elapsed_whole_test", "elapsed_last_alloc", "seclast_req_mem", sep=",")
+
+thepath = "preload_dump--qrun1*"
+
+for mypath in glob.glob(thepath):
+    pathparsed=re.match(r'preload_dump--qrun1--corpus-1-(\d+)-1.txt--expansion-(0\.\d+).txt', mypath)
+    corpuslen=pathparsed.group(1)
+    expansion=pathparsed.group(2)
+
+    with open(mypath) as file:
+        lines = file.readlines()
+
+        nAllocs = len(lines)
+
+        epoch_timestamp_bp = lines[0].find("epoch_timestamp(ms)")
+        epoch_timestamp_ep = epoch_timestamp_bp + len("epoch_timestamp(ms)")
+        current_req_mem_bp = lines[0].find("current_req_mem(B)")
+        current_req_mem_ep = current_req_mem_bp + len("current_req_mem(B)")
+        
+        first_timestamp   = lines[        1][epoch_timestamp_bp:epoch_timestamp_ep].strip()
+        seclast_req_mem   = lines[nAllocs-2][current_req_mem_bp:current_req_mem_ep].strip()
+        seclast_timestamp = lines[nAllocs-2][epoch_timestamp_bp:epoch_timestamp_ep].strip()
+        last_timestamp    = lines[nAllocs-1][epoch_timestamp_bp:epoch_timestamp_ep].strip()
+
+        elapsed_whole_test = int(last_timestamp) - int(first_timestamp)
+        elapsed_last_alloc = int(last_timestamp) - int(seclast_timestamp)
+
+        print(corpuslen, expansion, elapsed_whole_test, elapsed_last_alloc, seclast_req_mem, sep=",")
Index: doc/theses/mike_brooks_MMath/benchmarks/string/qrun.sh
===================================================================
--- doc/theses/mike_brooks_MMath/benchmarks/string/qrun.sh	(revision 9d9fd819a2c497a3cd2037e48f9c2112d0d4e0e5)
+++ doc/theses/mike_brooks_MMath/benchmarks/string/qrun.sh	(revision 9d9fd819a2c497a3cd2037e48f9c2112d0d4e0e5)
@@ -0,0 +1,10 @@
+
+set SIZES='20 50 100 200 500'
+set CFA_EXPANSIONS='0.02 0.05 0.1 0.2 0.5 0.9'
+
+for size in $SIZES ; do
+    echo a
+    for expansion in $CFA_EXPANSIONS ; do
+       echo LD_PRELOAD=~/plg2/mubeen-stat-shim/malloc/mallocWrappers.so ~/plg2/cfa2/cfa-cc/tests/zombies/string-perf/perfexp-cfa-pall-ll-share-na 1000 1.006 $expansion 1 caaaat ~/plg2/cfa2/cfa-cc/tests/zombies/string-perf/corpus-1-$size-1.txt
+    done ;
+done
