All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/3] gitweb: Improving blame_incremental.js
@ 2011-05-27 13:49 Jakub Narebski
  2011-05-27 13:49 ` [PATCH 1/3] gitweb.js: No need for inProgress in blame_incremental.js Jakub Narebski
                   ` (3 more replies)
  0 siblings, 4 replies; 5+ messages in thread
From: Jakub Narebski @ 2011-05-27 13:49 UTC (permalink / raw)
  To: git
  Cc: John 'Warthog9' Hawley, Petr Baudis, Fredrik Kuivinen,
	Giuseppe Bilotta, Luben Tuikov, Martin Koegler, Jakub Narebski

Two first patches remove unnecessary code from JavaScript-side of
blame_incremental code.  Namely JavaScript is single-threaded (events
wait for interpreter), so there is no need for code that tried to
handle re-entrancy (concurent access) to blame_incremental.js
functions.

So those two are pure simplification.


The third (last) patch replaces setInterval (where events might
accumulate if browser is very busy) to recommended re-enabled
setTimeout.  Thanks to this change we are now able to detect if timer
is not necessary, and in that case disable it.  This means extra code
checking if there is timer to disable (perhaps unnecessary).

This one adds more code than it removes, and could be split into two
patches: one simply moving from setInterval to setTimer, second adding
those new features.


P.S. Does anybody knows how to test JavaScript part of gitweb code
     _from commandline_ generating TAP-compatibile output to stdout?


Shortlog:
~~~~~~~~~
Jakub Narebski (3):
  gitweb.js: No need for inProgress in blame_incremental.js
  gitweb.js: No need for loop in blame_incremental's handleResponse()
  gitweb.js: use setTimeout rather than setInterval in
    blame_incremental.js

Diffstat:
~~~~~~~~~
 gitweb/static/js/blame_incremental.js |   79 +++++++++++++++++---------------
 1 files changed, 42 insertions(+), 37 deletions(-)

-- 
1.7.5

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

* [PATCH 1/3] gitweb.js: No need for inProgress in blame_incremental.js
  2011-05-27 13:49 [PATCH 0/3] gitweb: Improving blame_incremental.js Jakub Narebski
@ 2011-05-27 13:49 ` Jakub Narebski
  2011-05-27 13:50 ` [PATCH 2/3] gitweb.js: No need for loop in blame_incremental's handleResponse() Jakub Narebski
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 5+ messages in thread
From: Jakub Narebski @ 2011-05-27 13:49 UTC (permalink / raw)
  To: git
  Cc: John 'Warthog9' Hawley, Petr Baudis, Fredrik Kuivinen,
	Giuseppe Bilotta, Luben Tuikov, Martin Koegler, Jakub Narebski

JavaScript is single-threaded, so there is no need for protection
against re-entrancy via inProgress variable.

In particular calls to setInterval handler are stacked if handler
doesn't finish before new interrupt (before new interval).  The same
happens with events - they are (hopefully) stacked if even handler
didn't finish work.

Signed-off-by: Jakub Narebski <jnareb@gmail.com>
---
Remove and simplify code.

 gitweb/static/js/blame_incremental.js |   21 +++------------------
 1 files changed, 3 insertions(+), 18 deletions(-)

diff --git a/gitweb/static/js/blame_incremental.js b/gitweb/static/js/blame_incremental.js
index 676da6b..4841805 100644
--- a/gitweb/static/js/blame_incremental.js
+++ b/gitweb/static/js/blame_incremental.js
@@ -420,8 +420,6 @@ function handleLine(commit, group) {
 
 // ----------------------------------------------------------------------
 
-var inProgress = false;   // are we processing response
-
 /**#@+
  * @constant
  */
@@ -536,7 +534,7 @@ function processData(unprocessed, nextReadPos) {
  *
  * @param {XMLHttpRequest} xhr: XMLHttpRequest object
  *
- * @globals pollTimer, commits, inProgress
+ * @globals pollTimer, commits
  */
 function handleError(xhr) {
 	errorInfo('Server error: ' +
@@ -544,8 +542,6 @@ function handleError(xhr) {
 
 	clearInterval(pollTimer);
 	commits = {}; // free memory
-
-	inProgress = false;
 }
 
 /**
@@ -553,7 +549,7 @@ function handleError(xhr) {
  *
  * @param {XMLHttpRequest} xhr: XMLHttpRequest object (unused)
  *
- * @globals pollTimer, commits, inProgress
+ * @globals pollTimer, commits
  */
 function responseLoaded(xhr) {
 	clearInterval(pollTimer);
@@ -561,15 +557,13 @@ function responseLoaded(xhr) {
 	fixColorsAndGroups();
 	writeTimeInterval();
 	commits = {}; // free memory
-
-	inProgress = false;
 }
 
 /**
  * handler for XMLHttpRequest onreadystatechange event
  * @see startBlame
  *
- * @globals xhr, inProgress
+ * @globals xhr
  */
 function handleResponse() {
 
@@ -609,13 +603,6 @@ function handleResponse() {
 		return;
 	}
 
-	// in case we were called before finished processing
-	if (inProgress) {
-		return;
-	} else {
-		inProgress = true;
-	}
-
 	// extract new whole (complete) lines, and process them
 	while (xhr.prevDataLength !== xhr.responseText.length) {
 		if (xhr.readyState === 4 &&
@@ -633,8 +620,6 @@ function handleResponse() {
 	    xhr.prevDataLength === xhr.responseText.length) {
 		responseLoaded(xhr);
 	}
-
-	inProgress = false;
 }
 
 // ============================================================
-- 
1.7.5

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

* [PATCH 2/3] gitweb.js: No need for loop in blame_incremental's handleResponse()
  2011-05-27 13:49 [PATCH 0/3] gitweb: Improving blame_incremental.js Jakub Narebski
  2011-05-27 13:49 ` [PATCH 1/3] gitweb.js: No need for inProgress in blame_incremental.js Jakub Narebski
@ 2011-05-27 13:50 ` Jakub Narebski
  2011-05-27 13:50 ` [PATCH 3/3] gitweb.js: use setTimeout rather than setInterval in blame_incremental.js Jakub Narebski
  2011-05-27 14:04 ` [PATCH 0/3] gitweb: Improving blame_incremental.js Jakub Narebski
  3 siblings, 0 replies; 5+ messages in thread
From: Jakub Narebski @ 2011-05-27 13:50 UTC (permalink / raw)
  To: git
  Cc: John 'Warthog9' Hawley, Petr Baudis, Fredrik Kuivinen,
	Giuseppe Bilotta, Luben Tuikov, Martin Koegler, Jakub Narebski

JavaScript is single-threaded, so there is no need for protecting
against changes to XMLHttpRequest object behind event handler back.

Therefore there is no need for loop that was here in case `xhr' got
new changes while processing current changes.  This should make code a
bit more clear.

Signed-off-by: Jakub Narebski <jnareb@gmail.com>
---
Remove and simplify code.

 gitweb/static/js/blame_incremental.js |   13 ++++---------
 1 files changed, 4 insertions(+), 9 deletions(-)

diff --git a/gitweb/static/js/blame_incremental.js b/gitweb/static/js/blame_incremental.js
index 4841805..27955ec 100644
--- a/gitweb/static/js/blame_incremental.js
+++ b/gitweb/static/js/blame_incremental.js
@@ -603,21 +603,16 @@ function handleResponse() {
 		return;
 	}
 
-	// extract new whole (complete) lines, and process them
-	while (xhr.prevDataLength !== xhr.responseText.length) {
-		if (xhr.readyState === 4 &&
-		    xhr.prevDataLength === xhr.responseText.length) {
-			break;
-		}
 
+	// extract new whole (complete) lines, and process them
+	if (xhr.prevDataLength !== xhr.responseText.length) {
 		xhr.prevDataLength = xhr.responseText.length;
 		var unprocessed = xhr.responseText.substring(xhr.nextReadPos);
 		xhr.nextReadPos = processData(unprocessed, xhr.nextReadPos);
-	} // end while
+	}
 
 	// did we finish work?
-	if (xhr.readyState === 4 &&
-	    xhr.prevDataLength === xhr.responseText.length) {
+	if (xhr.readyState === 4) {
 		responseLoaded(xhr);
 	}
 }
-- 
1.7.5

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

* [PATCH 3/3] gitweb.js: use setTimeout rather than setInterval in blame_incremental.js
  2011-05-27 13:49 [PATCH 0/3] gitweb: Improving blame_incremental.js Jakub Narebski
  2011-05-27 13:49 ` [PATCH 1/3] gitweb.js: No need for inProgress in blame_incremental.js Jakub Narebski
  2011-05-27 13:50 ` [PATCH 2/3] gitweb.js: No need for loop in blame_incremental's handleResponse() Jakub Narebski
@ 2011-05-27 13:50 ` Jakub Narebski
  2011-05-27 14:04 ` [PATCH 0/3] gitweb: Improving blame_incremental.js Jakub Narebski
  3 siblings, 0 replies; 5+ messages in thread
From: Jakub Narebski @ 2011-05-27 13:50 UTC (permalink / raw)
  To: git
  Cc: John 'Warthog9' Hawley, Petr Baudis, Fredrik Kuivinen,
	Giuseppe Bilotta, Luben Tuikov, Martin Koegler, Jakub Narebski

If there is a possibility that your logic could take longer to execute
than the interval time, it is recommended that you recursively call a
named function using window.setTimeout rather than window.setInterval.

Therefore instead of using setInterval as an alternate way of invoking
handleResponse (because some web browsers call onreadystatechange only
once per each distinct state, and not for each server flush), use
setTimeout and reset it from handleResponse.  As a bonus this allows
us to get rid of timer if it turns out that web browser calls
onreadystatechange on each server flush.

While at it get rid of `xhr' global variable, creating it instead as
local variable in startBlame and passing it as parameter, and of
`pollTimer' global variable, passing it as member of xhr object
(xhr.pollTimer).

Signed-off-by: Jakub Narebski <jnareb@gmail.com>
---
This patch introduces three separate features, and probably should be
split into separate patches.

 gitweb/static/js/blame_incremental.js |   55 ++++++++++++++++++++++++---------
 1 files changed, 40 insertions(+), 15 deletions(-)

diff --git a/gitweb/static/js/blame_incremental.js b/gitweb/static/js/blame_incremental.js
index 27955ec..91354a0 100644
--- a/gitweb/static/js/blame_incremental.js
+++ b/gitweb/static/js/blame_incremental.js
@@ -29,7 +29,6 @@
 /* ............................................................ */
 /* utility/helper functions (and variables) */
 
-var xhr;        // XMLHttpRequest object
 var projectUrl; // partial query + separator ('?' or ';')
 
 // 'commits' is an associative map. It maps SHA1s to Commit objects.
@@ -431,8 +430,6 @@ var endRe  = /^END ?([^ ]*) ?(.*)/;
 var curCommit = new Commit();
 var curGroup  = {};
 
-var pollTimer = null;
-
 /**
  * Parse output from 'git blame --incremental [...]', received via
  * XMLHttpRequest from server (blamedataUrl), and call handleLine
@@ -533,26 +530,34 @@ function processData(unprocessed, nextReadPos) {
  * Handle XMLHttpRequest errors
  *
  * @param {XMLHttpRequest} xhr: XMLHttpRequest object
+ * @param {Number} [xhr.pollTimer] ID of the timeout to clear
  *
- * @globals pollTimer, commits
+ * @globals commits
  */
 function handleError(xhr) {
 	errorInfo('Server error: ' +
 		xhr.status + ' - ' + (xhr.statusText || 'Error contacting server'));
 
-	clearInterval(pollTimer);
+	if (typeof xhr.pollTimer === "number") {
+		clearTimeout(xhr.pollTimer);
+		delete xhr.pollTimer;
+	}
 	commits = {}; // free memory
 }
 
 /**
  * Called after XMLHttpRequest finishes (loads)
  *
- * @param {XMLHttpRequest} xhr: XMLHttpRequest object (unused)
+ * @param {XMLHttpRequest} xhr: XMLHttpRequest object
+ * @param {Number} [xhr.pollTimer] ID of the timeout to clear
  *
- * @globals pollTimer, commits
+ * @globals commits
  */
 function responseLoaded(xhr) {
-	clearInterval(pollTimer);
+	if (typeof xhr.pollTimer === "number") {
+		clearTimeout(xhr.pollTimer);
+		delete xhr.pollTimer;
+	}
 
 	fixColorsAndGroups();
 	writeTimeInterval();
@@ -563,9 +568,13 @@ function responseLoaded(xhr) {
  * handler for XMLHttpRequest onreadystatechange event
  * @see startBlame
  *
- * @globals xhr
+ * @param {XMLHttpRequest} xhr: XMLHttpRequest object
+ * @param {Number} xhr.prevDataLength: previous value of xhr.responseText.length
+ * @param {Number} xhr.nextReadPos: start of unread part of xhr.responseText
+ * @param {Number} [xhr.pollTimer] ID of the timeout (to reset or cancel)
+ * @param {Boolean} fromTimer: if handler was called from timer
  */
-function handleResponse() {
+function handleResponse(xhr, fromTimer) {
 
 	/*
 	 * xhr.readyState
@@ -614,6 +623,19 @@ function handleResponse() {
 	// did we finish work?
 	if (xhr.readyState === 4) {
 		responseLoaded(xhr);
+		return;
+	}
+
+	// if we get from timer, we have to restart it
+	// otherwise onreadystatechange gives us partial response, timer not needed
+	if (fromTimer) {
+		setTimeout(function () {
+			handleResponse(xhr, true);
+		}, 1000);
+
+	} else if (typeof xhr.pollTimer === "number") {
+		clearTimeout(xhr.pollTimer);
+		delete xhr.pollTimer;
 	}
 }
 
@@ -629,11 +651,11 @@ function handleResponse() {
  * Called from 'blame_incremental' view after loading table with
  * file contents, a base for blame view.
  *
- * @globals xhr, t0, projectUrl, div_progress_bar, totalLines, pollTimer
+ * @globals t0, projectUrl, div_progress_bar, totalLines
 */
 function startBlame(blamedataUrl, bUrl) {
 
-	xhr = createRequestObject();
+	var xhr = createRequestObject();
 	if (!xhr) {
 		errorInfo('ERROR: XMLHttpRequest not supported');
 		return;
@@ -652,8 +674,9 @@ function startBlame(blamedataUrl, bUrl) {
 	xhr.prevDataLength = -1;  // used to detect if we have new data
 	xhr.nextReadPos = 0;      // where unread part of response starts
 
-	xhr.onreadystatechange = handleResponse;
-	//xhr.onreadystatechange = function () { handleResponse(xhr); };
+	xhr.onreadystatechange = function () {
+		handleResponse(xhr, false); 
+	};
 
 	xhr.open('GET', blamedataUrl);
 	xhr.setRequestHeader('Accept', 'text/plain');
@@ -661,7 +684,9 @@ function startBlame(blamedataUrl, bUrl) {
 
 	// not all browsers call onreadystatechange event on each server flush
 	// poll response using timer every second to handle this issue
-	pollTimer = setInterval(xhr.onreadystatechange, 1000);
+	xhr.pollTimer = setTimeout(function () {
+		handleResponse(xhr, true);
+	}, 1000);
 }
 
 /* end of blame_incremental.js */
-- 
1.7.5

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

* Re: [PATCH 0/3] gitweb: Improving blame_incremental.js
  2011-05-27 13:49 [PATCH 0/3] gitweb: Improving blame_incremental.js Jakub Narebski
                   ` (2 preceding siblings ...)
  2011-05-27 13:50 ` [PATCH 3/3] gitweb.js: use setTimeout rather than setInterval in blame_incremental.js Jakub Narebski
@ 2011-05-27 14:04 ` Jakub Narebski
  3 siblings, 0 replies; 5+ messages in thread
From: Jakub Narebski @ 2011-05-27 14:04 UTC (permalink / raw)
  To: git
  Cc: John 'Warthog9' Hawley, Petr Baudis, Fredrik Kuivinen,
	Giuseppe Bilotta, Luben Tuikov, Martin Koegler

Jakub Narebski wrote:

> Two first patches remove unnecessary code from JavaScript-side of
> blame_incremental code. [...]
> 
> So those two are pure simplification.
> 
> 
> The third (last) patch replaces setInterval (where events might
> accumulate if browser is very busy) to recommended re-enabled
> setTimeout.  [...]
> 
> This one adds more code than it removes, and could be split into two
> patches: [...]

I forgot to add that this series is based on top of jn/gitweb-js
series, namely it theoretically require "gitweb: Split JavaScript for
maintability, combining on build"... but thanks to Git rename detection
it should [had] apply on top of master as well.

-- 
Jakub Narebski
Poland

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

end of thread, other threads:[~2011-05-27 14:05 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-05-27 13:49 [PATCH 0/3] gitweb: Improving blame_incremental.js Jakub Narebski
2011-05-27 13:49 ` [PATCH 1/3] gitweb.js: No need for inProgress in blame_incremental.js Jakub Narebski
2011-05-27 13:50 ` [PATCH 2/3] gitweb.js: No need for loop in blame_incremental's handleResponse() Jakub Narebski
2011-05-27 13:50 ` [PATCH 3/3] gitweb.js: use setTimeout rather than setInterval in blame_incremental.js Jakub Narebski
2011-05-27 14:04 ` [PATCH 0/3] gitweb: Improving blame_incremental.js Jakub Narebski

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.