Up to Main Index Up to Journal for April, 2019 JOURNAL FOR FRIDAY 26TH APRIL, 2019 ______________________________________________________________________________ SUBJECT: Improved + bug fixed text unfolding DATE: Fri 26 Apr 20:38:56 BST 2019 Last night I couldn’t sleep and was coding and testing around 3am when I noticed a problem with the WolfMUD login screen: Telnet escape character is '~'. Trying 127.0.0.1... Connected to 127.0.0.1. Escape character is '~'. WolfMUD Copyright 1984-2018 Andrew 'Diddymus' Rolfe World Of Living Fantasy Welcome to WolfMUD! Enter your account ID or just press enter to create a new account, enter QUIT to leave the server: > Hrm, there should be a blank line just after “Welcome to WolfMUD!”. Now where did it go? Some debugging later and I’d pulled apart the text.Unfold function. I then spent about 2 and a half hours ‘fixing’ the issue only to uncover some more odd corner cases before settling on a final solution. I’ve kept the tests for the additional corner cases in case they crop up again in the future. The new Unfold code is simpler and has fewer corner cases to deal with: func Unfold(in []byte) []byte { // Appending a final line feed to input data and starting with an initial // line feed in the output simplifies the code. Both are removed from the // final output. data := bytes.Runes(append(in, '\n')) out := make([]rune, len(data)+1, len(data)+1) out[0] = '\n' pos := 1 for x, r := range data { if r == '\n' { for ; spaceNotLF(out[pos-1]); pos-- { // Trim WS not LF } if out[pos-1] != '\n' && !spacePrefix(data[x+1:]) { r = ' ' } } out[pos] = r pos++ } return []byte(string(out[1 : pos-1])) } Today I returned to review my changes, sometimes coding through the night until nearly 6am is not the best idea, and ran some benchmarks. Of note, text.Unfold now uses two sentinel line feeds to simplify the code by allowing the removal of some tests. By using “bytes.Runes(append(in, '\n'))” instead of “append(bytes.Runes(in), '\n')” it results in fewer allocations and better performance. The results of my benchmarking: name old time/op new time/op delta Unfold/The_…own_fox_-4 1.39µs ± 3% 1.15µs ± 6% -17.54% (p=0.008 n=5+5) Unfold/The_…own_fox_#01-4 1.35µs ± 2% 1.25µs ± 2% -7.41% (p=0.008 n=5+5) Unfold/You_…he_corne-4 9.16µs ± 2% 8.13µs ± 4% -11.18% (p=0.008 n=5+5) name old alloc/op new alloc/op delta Unfold/The_…own_fox_-4 816B ± 0% 480B ± 0% -41.18% (p=0.008 n=5+5) Unfold/The_…own_fox_#01-4 816B ± 0% 480B ± 0% -41.18% (p=0.008 n=5+5) Unfold/You_…he_corne-4 6.75kB ± 0% 3.68kB ± 0% -45.50% (p=0.008 n=5+5) name … old allocs/op new allocs/op delta Unfold/The_…own_fox_-4 5.00 ± 0% 4.00 ± 0% -20.00% (p=0.008 n=5+5) Unfold/The_…own_fox_#01-4 5.00 ± 0% 4.00 ± 0% -20.00% (p=0.008 n=5+5) Unfold/You_…he_corne-4 5.00 ± 0% 4.00 ± 0% -20.00% (p=0.008 n=5+5) The fix is now available on the public dev branch. -- Diddymus Up to Main Index Up to Journal for April, 2019