<html><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; "><div><div>On Feb 26, 2008, at 6:46 PM, Jay wrote:</div><br class="Apple-interchange-newline"><blockquote type="cite"><span class="Apple-style-span" style="border-collapse: separate; color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: 2; text-align: auto; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-border-horizontal-spacing: 0px; -webkit-border-vertical-spacing: 0px; -webkit-text-decorations-in-effect: none; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0; "><div class="hmmessage" style="font-size: 10pt; font-family: Tahoma; ">Tony, what about the need to copy? The inability to iterate through characters without a function call per character? I guess though, from what you pointed out, a read only direct pointer is viable. And that removes the 256 character stack usage -- which is a bit piggy as it is. So then..I guess the next step in some compromise here is that it should perhaps be viable to get a read only pointer to a string (maybe already the case), compute the required size of the new one (follows naturally), and then be able to split up allocation and filling in of a string, a function to allocate and get a direct pointer, then fill in your data, then "seal" the text making it read only. And I guess really you can just carefully use the "subversive" method here -- up to you to not pass the "unsealed" text off to anyone else until you are done writing to it.</div></span></blockquote><div><br class="webkit-block-placeholder"></div><div>Have you looked at TextConv.i3? Not sure if that has some of what you are needing.</div><div><br class="webkit-block-placeholder"></div><blockquote type="cite"><span class="Apple-style-span" style="border-collapse: separate; color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: 2; text-align: auto; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-border-horizontal-spacing: 0px; -webkit-border-vertical-spacing: 0px; -webkit-text-decorations-in-effect: none; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0; "><div class="hmmessage" style="font-size: 10pt; font-family: Tahoma; ">Then just to deal with the varying representation but as I was suggesting, maybe that can be forced somehow.<br>Maybe creation can specify an encoding, or the "get buffer" function could -- though ideally there is just one, not two.<br> <br>The stack vs. heap behavior is also not ideal in that it's nice for the performance of something to scale linearly with input, not suddenly slow way down when data exceeds some arbitrary threshold. Granted, a lot of code just starts failing, so merely slowing down is "progress". As well, eventually you end up swapping to disk, if you don't first run out of address space, so there will be limits at which things slow down or fail, just that they ought to be fairly large.</div></span></blockquote><div><br class="webkit-block-placeholder"></div><div>Why do you think that heap allocation is slow in general?</div><br><blockquote type="cite"><span class="Apple-style-span" style="border-collapse: separate; color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: 2; text-align: auto; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-border-horizontal-spacing: 0px; -webkit-border-vertical-spacing: 0px; -webkit-text-decorations-in-effect: none; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0; "><div class="hmmessage" style="font-size: 10pt; font-family: Tahoma; ">I also rather hoped/assumed that compile time text constants were formed constant-ly by the compiler, that the compiler knows their runtime layout. I realize the division of labor between compiler and runtime can be made at varying points, with varying resulting flexibility, but also varying resulting efficiency.</div></span></blockquote><div><br class="webkit-block-placeholder"></div><div>Compile-time literals *are* formed constantly by the compiler. They are TextLiteral.T.</div><br><blockquote type="cite"><span class="Apple-style-span" style="border-collapse: separate; color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: 2; text-align: auto; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-border-horizontal-spacing: 0px; -webkit-border-vertical-spacing: 0px; -webkit-text-decorations-in-effect: none; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0; "><div class="hmmessage" style="font-size: 10pt; font-family: Tahoma; "><br> <br> - Jay<br><blockquote><hr id="EC_stopSpelling">From:<span class="Apple-converted-space"> </span><a href="mailto:hosking@cs.purdue.edu">hosking@cs.purdue.edu</a><br>To:<span class="Apple-converted-space"> </span><a href="mailto:m3devel@elegosoft.com">m3devel@elegosoft.com</a><br>Date: Tue, 26 Feb 2008 17:43:17 -0500<br>Subject: Re: [M3devel] text inefficiency? good mutable string type? arrays?<br><br><div><span class="EC_Apple-style-span" style="word-spacing: 0px; font: normal normal normal 12px/normal Helvetica; text-transform: none; color: rgb(0, 0, 0); text-indent: 0px; white-space: normal; letter-spacing: normal; border-collapse: separate; "><div style="word-wrap: break-word; "><span class="EC_Apple-style-span" style="word-spacing: 0px; font: normal normal normal 12px/normal Helvetica; text-transform: none; color: rgb(0, 0, 0); text-indent: 0px; white-space: normal; letter-spacing: normal; border-collapse: separate; "><span class="EC_Apple-style-span" style="word-spacing: 0px; font: normal normal normal 12px/normal Helvetica; text-transform: none; color: rgb(0, 0, 0); text-indent: 0px; white-space: normal; letter-spacing: normal; border-collapse: separate; "><span class="EC_Apple-style-span" style="word-spacing: 0px; font: normal normal normal 12px/normal Helvetica; text-transform: none; color: rgb(0, 0, 0); text-indent: 0px; white-space: normal; letter-spacing: normal; border-collapse: separate; "><span class="EC_Apple-style-span" style="word-spacing: 0px; font: normal normal normal 12px/normal Helvetica; text-transform: none; color: rgb(0, 0, 0); text-indent: 0px; white-space: normal; letter-spacing: normal; border-collapse: separate; "><span class="EC_Apple-style-span" style="word-spacing: 0px; font: normal normal normal 12px/normal Helvetica; text-transform: none; color: rgb(0, 0, 0); text-indent: 0px; white-space: normal; letter-spacing: normal; border-collapse: separate; "><span class="EC_Apple-style-span" style="word-spacing: 0px; font: normal normal normal 12px/normal Helvetica; text-transform: none; color: rgb(0, 0, 0); text-indent: 0px; white-space: normal; letter-spacing: normal; border-collapse: separate; "><span class="EC_Apple-style-span" style="word-spacing: 0px; font: normal normal normal 12px/normal Helvetica; text-transform: none; color: rgb(0, 0, 0); text-indent: 0px; white-space: normal; letter-spacing: normal; border-collapse: separate; "><span class="EC_Apple-style-span" style="word-spacing: 0px; font: normal normal normal 12px/normal Helvetica; text-transform: none; color: rgb(0, 0, 0); text-indent: 0px; white-space: normal; letter-spacing: normal; border-collapse: separate; "><div>I suppose the question here is how often you exceed the 256-character stack-allocated buffer size? If not often then occasionally allocating in the heap is not a huge problem. I'm not too fussed about this anyway because generational GC will quickly reclaim things that die as young as this buffer does. I think you underestimate the effectiveness of modern GC algorithms. Anyway, optimizing here for short nm texts presumably handles the common case. Why work hard to optimize the uncommon case?</div><div><br class="EC_webkit-block-placeholder"></div></span></span></span></span></span></span></span></span></div></span></div><div><div>On Feb 25, 2008, at 10:38 AM, Jay wrote:</div><br class="EC_Apple-interchange-newline"><blockquote><span class="EC_Apple-style-span" style="word-spacing: 0px; font: normal normal normal 12px/normal Helvetica; text-transform: none; color: rgb(0, 0, 0); text-indent: 0px; white-space: normal; letter-spacing: normal; border-collapse: separate; "><div class="EC_hmmessage" style="font-size: 10pt; font-family: Tahoma; ">I know this area has been brewing under the surface a while.<br>I'll bring it up. :)<br> <br>Here is some apparently typical code:<br> <br>PROCEDURE Escape (nm: TEXT): TEXT =<br> VAR len: INTEGER; buf: ARRAY [0..255] OF CHAR;<br> BEGIN<br> IF (nm = NIL) THEN RETURN NIL; END;<br> len := Text.Length (nm);<br> IF (len + len <= NUMBER (buf))<br> THEN RETURN DoEscape (nm, len, buf);<br> ELSE RETURN DoEscape (nm, len, NEW (REF ARRAY OF CHAR, len + len)^);<br> END;<br> END Escape;<br><br>PROCEDURE DoEscape (nm: TEXT; len: INTEGER; VAR buf: ARRAY OF CHAR): TEXT =<br> VAR n_escapes := 0; src, dest: INTEGER; c: CHAR;<br> BEGIN<br> Text.SetChars (buf, nm);<br> FOR i := 0 TO len-1 DO<br> IF (buf[i] = BackSlash) THEN INC (n_escapes); END;<br> END;<br> IF (n_escapes = 0) THEN RETURN nm; END;<br> src := len - 1;<br> dest := src + n_escapes;<br> WHILE (src > 0) DO<br> c := buf[src]; DEC (src);<br> buf[dest] := c; DEC (dest);<br> IF (c = BackSlash) THEN buf[dest] := BackSlash; DEC (dest); END;<br> END;<br> RETURN Text.FromChars (SUBARRAY (buf, 0, len + n_escapes));<br> END DoEscape;<br><br><br>Look at how inefficient this is.<br>For a long string it makes a heap allocation, even if in the end it makes no changes to the string.<br>For any length string it copies it out to an array.<br>Then if there are any changes, it copies it again, probably into heap, likely the input immediately becoming garbage.<br>Heap allocation may be fast, but building up garbage and causing more work for the garbage collector I assume is bad.<br>And if the string had no backslashes, it's all a big waste.<br> <br>I assume texts are read only?<br> <br>I know lots of systems have read only strings.<br>There are pluses and minus to them. They can be single-instanced.<br>Some systems with read only strings have another type, such as "StringBuilder" or "StringBuffer".<br><br><br>So -- I don't have a specific question, but maybe a mutable string "class" aka "type" is needed?<br>Not necessarily in the language but in m3core or libm3?<br>Maybe it's already there?<br> <br>I just spent a few hours diddling with arrays of chars.<br>Unfortunately they are not resizable.<br>It was not entirely satisfactory. Besides the array I had to pass around a length and a start.<br>Wrapping this up in one record TYPE MutableString= ... might be a good idea.<br> <br>For more efficient read only access, would it be reasonable for the runtime to materialize on-demand 8 bit and 16 bit representations of a string if a user calls some new thing like Text.GetDirectA (t: TEXT) : REF ARRAY OF CHAR, Text.GetDirectW (t: TEXT) : REF ARRAY OF WIDECHAR? Throw an exception if the string cannot be represented with 8 bit characters? Or use utf8?<br> <br>Besides, I know I'm a big predictable whiner but I like how this works in Windows..<br>It may not have been as seamless, but it works and it really doesn't tend to break or slow down existing code.<br>roughly:<br> "foo" is an 8 bit string of type char* (or const char* or possibly const char[4])<span class="EC_Apple-converted-space"> </span><br> L"foo" is an 16 bit string of type<span class="EC_Apple-converted-space"> </span><font face="">wchar_t* (ditto, and aka WCHAR)<span class="EC_Apple-converted-space"> </span></font><br> "L" for "long" aka "wide"<span class="EC_Apple-converted-space"> </span><br> <br>Functions must be written to specifically use one or the other.<br>In C++ you can templatize. There is std::string and std::wstring that are template instantiations.<br>Lots of C functions are duplicated. strcpy => wcscpy, strcat => wcscat, etc.<br>And really there's no point in 8 bit strings.<br>If you have a blob, that's an array of bytes or something, not characters.<span class="EC_Apple-converted-space"> </span><br> <br>It works.<br> <br>Utf8 is another seemingly popular route but I think it's a hack.<br>I think mostly people don't touch their code and say, voila, it's utf8, and they only really support the same old English or possibly 8 bit characters (some European characters).<br>Granted, to some extent, this does work, as long as you don't do anything with the string but strlen, strcpy, and some others and pass it to code that does treat it correctly. Still, variably sized encodings seem like a bad idea here, and 16 bits per character seem affordable enough. And yes, I know that Unicode is actually know 20 bits per character and some characters take two wchar_ts but I try to ignore that...<br>And I know there is a lot of existing code, but sometimes there is a need for progress too...<br> <br>Ok, maybe NOW I'll look at the cygwin/shobjgen problem. :)<br> <br> <br> - Jay<br> <br><br><hr>Helping your favorite cause is as easy as instant messaging. You IM, we give.<span class="EC_Apple-converted-space"> </span><a href="http://im.live.com/Messenger/IM/Home/?source=text_hotmail_join" target="_blank">Learn more.</a></div></span></blockquote></div><br></blockquote><br><hr>Need to know the score, the latest news, or you need your HotmailŪ-get your "fix".<span class="Apple-converted-space"> </span><a href="http://www.msnmobilefix.com/Default.aspx" target="_new">Check it out.</a></div></span></blockquote></div><br></body></html>