Ответ на сообщение «Re: Progress indicator for :TOhtml command», 
присланное в 19:39:15 05 июня 2010, Суббота,
отправитель Benjamin Fritz:

It occures that the problem is not floating-point math: the attached patch 
removes this math but does not add any perfomance. It also removes 
recalculating 
progress bar width (you just used used some generic progress bar?) and 
needs_redraw. Also, why you forbid profiling progress bar functions? It is also 
fixed.

Текст сообщения:
> On Thu, Jun 3, 2010 at 10:03 PM, Benjamin Fritz <[email protected]> 
wrote:
> > This version is still not fast enough though. It is about 30% slower
> > when the progress bar is enabled than when it is disabled. While I
> > consider it a good tradeoff in most cases, we could certainly make it
> > better.
> >
> > It would probably be faster to pre-calculate the line numbers needed
> > to advance the progress bar rather than doing a bunch of
> > floating-point math every cycle.
> 
> I've attached a new version which pre-calculates the (integer) line
> numbers needed to advance the progress bar. Now all the floating point
> math is done once, up front.
> 
> The difference is not really very perceptible. I timed the execution
> on two files. First, I did the 5148-line autoload/phpcomplete.vim
> script. Timings were as follows on my laptop:
> 
> progress disabled:
> average: 46 seconds
> 
> floating-point progress:
> average: 61 seconds
> slowdown: 15 seconds longer than without progress bar
> percentage: 33% longer than without progress bar
> 
> precalculated progress:
> average: 62 seconds
> slowdown: 16 seconds longer than without progress bar
> percentage: 35% longer than without progress bar
> 
> Next I did a 33258-line C code file:
> 
> progress disabled:
> average: 691 seconds
> 
> floating-point progress:
> average: 716 seconds
> slowdown: 25 seconds longer than without progress bar
> percentage: 4% longer than without progress bar
> 
> precalculated progress:
> average: 711 seconds
> slowdown: 20 seconds longer than without progress bar
> percentage: 3% longer than without progress bar
> 
> I also did a number of very small sections of files (my usual use case
> for 2html) and did not notice any significant slowing; it only takes
> 1-2 seconds longer for a 100 or 200 line selection.
> 
> I take a few things from this.
> 
> First of all, I don't think we'll get much performance improvement
> with this method. I do not know whether it is setting the status line
> and redrawing it, or whether it is the use of the object-oriented
> style functions, but it would probably require a different approach to
> get a significant speedup. I certainly like the look a lot better than
> the echo method, even if we could get echon working. Is a 10-20 second
> slow-down acceptable on large numbers of lines, if the normal
> execution time is measured in minutes anyway? To me, it certainly is.
> If something is going to be taking more than a few minutes, I want a
> progress bar to tell me whether it's worth letting it continue. Since
> the slow-down can be significant for midsize files, we will certainly
> need to mention in the :help that disabling the progress bar will make
> the conversion faster. Maybe we should only show the progress bar
> after some amount of time has elapsed? We could suppress the
> redrawstatus until 10 seconds have passed, or something like that. Any
> thoughts?
> 
> Secondly, the precalculated version is not really any faster than the
> full floating-point calculation every cycle. I don't really have an
> opinion of which method gives more readable code. Does anyone else
> have any opinions on which version to keep? I think it would be
> possible to do away with floating point calculations entirely using
> the precalculated version; currently floating point is only used in
> the calculate_ticks function. This might be desireable so that we can
> remove the dependence on the +float feature, which is not marked with
> a "smallest version" indicator in :help +feature-list. This apparently
> means it is "system dependent". Does this mean float is pretty much
> always included, unless it is explicitly removed? How common are Vims
> without floating-point support? I already added use of the split()
> function, which was added in version 7, so this won't work on really
> old Vims...but do we want to support Vim 7.1 and earlier?
> 
--- oldnew2html.vim	2010-06-06 03:33:44.000000000 +0400
+++ 2html.vim	2010-06-06 04:30:37.000000000 +0400
@@ -545,5 +545,5 @@
 
 " set up progress bar in the status line
-if !s:html_no_progress && has("statusline") && has("float")
+if !s:html_no_progress && has("statusline")
 	" ProgressBar Indicator
 	let s:progressbar={}
@@ -559,50 +559,36 @@
 					\'bar'     : { 'color' : 'Statusline' , 'fillcolor' : 'DiffDelete' , 'bg' : 'Statusline' } ,
 					\'counter' : { 'color' : 'Statusline' } }
-		let pgb.last_value = 0
-		let pgb.needs_redraw = 0
-		let pgb.max_len = 0
+		let pgb.max_len = winwidth(pgb.winnr)-2
+		" Note that you must use len(split) instead of len() if you want to use 
+		" unicode in title
+		let pgb.pb_len = pgb.max_len-len(split(pgb.title, '\zs'))-3-4-2
+		if pgb.pb_len<0
+			let pbg.pb_len=0
+		elseif pgb.pb_len>100
+			let pgb.pb_len=100
+		endif
+		let pgb.pb_startstr = ""
+		let pgb.pb_endstr   = repeat(" ", pgb.pb_len)
+		let pgb.last_progresslen=-1
+		let pgb.last_percents=-1
 		set laststatus=2
 		return pgb
 	endfun
 
-	" Function: progressbar.calculate_ticks() {{{1
-	func! s:progressbar.calculate_ticks(pb_len)
-		let tick = self.max_value / str2float(a:pb_len)
-		let self.progress_ticks = map(range(a:pb_len+1), "float2nr(v:val * tick)")
-	endfun
-
 	"Function: progressbar.paint()
 	func! s:progressbar.paint()
-		" Recalculate widths
-		let max_len = winwidth(self.winnr) - 2
-		" Title length
-		let t_len   = strlen(self.title) + 3 " add offset for additional spaces
-		" Counter length
-		"let c_len   = 2*strlen(self.max_value)+1
-		let c_len   = 4
-		" Progressbar length
-		let pb_len  = max_len - t_len - c_len - 2
-		let pb_len  = pb_len > 100 ? 100 : pb_len
-
-		" always true on first call because of initial value of self.max_len
-		if max_len != self.max_len
-			call self.calculate_ticks(pb_len)
-			let self.needs_redraw = 1
-			let cur_value = 0
-			let self.max_len = max_len
-		else
-			" start searching at the last found index to make the search for the
-			" appropriate tick value normally take 0 or 1 comparisons
-			let cur_value = self.last_value
-		endif
-
-		while cur_value < pb_len && self.cur_value > self.progress_ticks[cur_value]
-			let cur_value += 1
-		endwhile
-
-		if self.last_value != cur_value || self.needs_redraw
-			let self.needs_redraw = 1
-			let self.last_value = cur_value
-
+		let progresslen=self.pb_len*self.cur_value/self.max_value
+		let percents=100*self.cur_value/self.max_value
+		if progresslen!=self.last_progresslen || percents!=self.last_percents
+			if progresslen!=self.last_progresslen
+				let self.pb_startstr.=" "
+				let self.pb_endstr=self.pb_endstr[1:]
+				let self.last_progresslen=progresslen
+			endif
+			if percents!=self.last_percents
+				let self.last_percents=percents
+				let percents.=""
+				let self.percent_str=repeat(" ", 3-len(percents)).percents
+			endif
 			let t_color  = self.items.title.color
 			let b_fcolor = self.items.bar.fillcolor
@@ -612,8 +598,9 @@
 			let stl =  "%#".t_color."#%-( ".self.title." %)".
 						\"%#".b_color."#|".
-						\"%#".b_fcolor."#%-(".repeat(" ",cur_value)."%)".
-						\"%#".b_color."#".repeat(" ",pb_len-cur_value)."|".
-						\"%=%#".c_color."#%( ".printf("%3.d ",100*self.cur_value/self.max_value)."%% %)"
+						\"%#".b_fcolor."#%-(".self.pb_startstr."%)".
+						\"%#".b_color."#".self.pb_endstr."|".
+						\"%=%#".c_color."#%( ".self.percent_str."%% %)"
 			call setwinvar(self.winnr, '&stl', stl)
+			redrawstatus
 		endif
 
@@ -876,8 +863,4 @@
 	exe s:newwin . "wincmd w"
 	exe "normal! a" . s:new . s:HtmlEndline . "\n\e"
-	if !s:html_no_progress && s:pgb.needs_redraw
-		redrawstatus
-		let s:pgb.needs_redraw = 0
-	endif
 	exe s:orgwin . "wincmd w"
 	let s:lnum = s:lnum + 1
@@ -987,9 +970,5 @@
 	if !s:html_no_progress
 		call s:pgb.incr()
-    sleep 100m
-		if s:pgb.needs_redraw
-			redrawstatus
-			let s:pgb.needs_redraw = 0
-		endif
+		" sleep 100m
 	endif
 endwhile
@@ -1055,18 +1034,19 @@
 		delfunc s:HtmlClosing
 	endif
-endif
-unlet! s:new_lnum s:diffattr s:difffillchar s:foldfillchar s:HtmlSpace s:LeadingSpace s:HtmlEndline s:firstfold s:foldcolumn
-unlet s:foldstack s:allfolds s:foldId s:numcol
 
-if exists("s:html_dynamic_folds")
-	delfunc s:FoldCompare
-endif
+	if exists("s:html_dynamic_folds")
+		delfunc s:FoldCompare
+	endif
+
+	if !s:html_no_progress
+		delfunc s:ProgressBar
+		delfunc s:progressbar.paint
+		delfunc s:progressbar.incr
+		unlet s:pgb s:progressbar
+	endif
 
-if !s:html_no_progress
-	delfunc s:ProgressBar
-	delfunc s:progressbar.paint
-	delfunc s:progressbar.incr
-	unlet s:pgb s:progressbar
 endif
+unlet! s:new_lnum s:diffattr s:difffillchar s:foldfillchar s:HtmlSpace s:LeadingSpace s:HtmlEndline s:firstfold s:foldcolumn
+unlet s:foldstack s:allfolds s:foldId s:numcol
 
 unlet! s:html_no_progress s:html_dynamic_folds s:html_hover_unfold s:html_use_css

Attachment: signature.asc
Description: This is a digitally signed message part.

Raspunde prin e-mail lui