unofficial mirror of guile-devel@gnu.org 
 help / color / mirror / Atom feed
* efficient implementation of string-replace-substring / string-replace-all
@ 2013-09-13 14:32 Arne Babenhauserheide
  2013-09-13 19:41 ` Mark H Weaver
  0 siblings, 1 reply; 5+ messages in thread
From: Arne Babenhauserheide @ 2013-09-13 14:32 UTC (permalink / raw)
  To: guile-devel

Hi,

For wisp I created an efficient implementation of substring replacement and thought it might be useful for guile in general.

I optimized it a bit to get rid of (likely) quadratic behaviour:


; ,time (string-replace-substring (xsubstring "abcdefghijkl" 0 99999) "def" "abc")
; 1.140127s real time, 1.139714s run time.  0.958733s spent in GC.
; 0.885618s real time, 0.885350s run time.  0.742805s spent in GC.
; second number after multiple runs
(define (string-replace-substring s substring replacement)
       "Replace every instance of substring in s by replacement."
       (let ((sublen (string-length substring)))
           (let replacer
               ((newstring s)
                 (index (string-contains s substring)))
               (if (not (equal? index #f))
                  (let ((replaced (string-replace newstring replacement index (+ index sublen))))
                    (replacer replaced (string-contains replaced substring index)))
                  newstring))))


This fast and elegant approach is thanks to ijp.

I tested a two alternative approaches. The following uses explicit readonly substrings and is fast, the one afterwards always searches from the beginning and shows drastic slowdown on long strings. 

; efficient version from rev 12266d455bb0 of the wisp hg repo
; ,time (string-replace-substring-fast-but-long (xsubstring "abcdefghijkl" 0 99999) "def" "abc")
; 1.316090s real time, 1.315626s run time.  1.129857s spent in GC.
; 0.668212s real time, 0.667948s run time.  0.482193s spent in GC.
; 0.868419s real time, 0.868131s run time.  0.685472s spent in GC
; Second and third are after multiple runs
(define (string-replace-substring-fast-but-long s substring replacement)
       "Replace every instance of substring in s by replacement."
       (let ((sublen (string-length substring)))
           (let replacer
               ((newstring s)
                 (startindex 0)
                 (addindex (string-contains s substring)))
               (if (not (equal? addindex #f))
                  (let*
                      ((index (+ startindex addindex))
                        (replaced (string-replace newstring replacement index (+ index sublen)))
                        (newaddindex (string-contains (substring/read-only replaced index) substring)))
                      (replacer replaced index newaddindex))
                  newstring))))


; less efficient version from rev a887aeb0dfe2
; ,time (string-replace-substring-slow (xsubstring "abcdefghijkl" 0 99999) "def" "abc")
; 5.242456s real time, 5.240834s run time.  0.358750s spent in GC.
; 5.727069s real time, 5.724973s run time.  0.835445s spent in GC.
; switches between fast and slow version
(define (string-replace-substring-slow s substring replacement)
       "Replace every instance of substring in s by replacement."
       (let ((sublen (string-length substring)))
           (let replacer
               ((newstring s)
                 (index (string-contains s substring)))
               (if (not (equal? index #f))
                  (let ((replaced (string-replace newstring replacement index (+ index sublen))))
                    (replacer replaced (string-contains replaced substring)))
                  newstring))))
               


ijp suggested renaming to (string-replace-all, but I do not know enough about conventions in guile to judge that).

Best wishes,
Arne



^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2014-03-26 20:14 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-09-13 14:32 efficient implementation of string-replace-substring / string-replace-all Arne Babenhauserheide
2013-09-13 19:41 ` Mark H Weaver
2014-03-23 20:48   ` Andy Wingo
2014-03-24  5:19     ` Mark H Weaver
2014-03-26 20:14       ` Arne Babenhauserheide

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).