mirror of
https://github.com/Jermolene/TiddlyWiki5
synced 2024-11-27 03:57:21 +00:00
Extend refresh throttling to tiddlers having a "throttle.refresh" field
See discussion here: https://groups.google.com/d/msgid/tiddlywiki/7738644f-b53f-4fb0-b0df-16243fe51795%40googlegroups.com
This commit is contained in:
parent
03e98d1d62
commit
6089c4de29
@ -31,6 +31,7 @@ source: The source URL associated with a tiddler
|
|||||||
subtitle: The subtitle text for a wizard
|
subtitle: The subtitle text for a wizard
|
||||||
tags: A list of tags associated with a tiddler
|
tags: A list of tags associated with a tiddler
|
||||||
text: The body text of a tiddler
|
text: The body text of a tiddler
|
||||||
|
throttle.refresh: If present, throttles refreshes of this tiddler
|
||||||
title: The unique name of a tiddler
|
title: The unique name of a tiddler
|
||||||
toc-link: Suppresses the tiddler's link in a Table of Contents tree if set to: ''no''
|
toc-link: Suppresses the tiddler's link in a Table of Contents tree if set to: ''no''
|
||||||
type: The content type of a tiddler
|
type: The content type of a tiddler
|
||||||
|
@ -25,7 +25,7 @@ var PAGE_TEMPLATE_TITLE = "$:/core/ui/PageTemplate";
|
|||||||
|
|
||||||
// Time (in ms) that we defer refreshing changes to draft tiddlers
|
// Time (in ms) that we defer refreshing changes to draft tiddlers
|
||||||
var DRAFT_TIDDLER_TIMEOUT_TITLE = "$:/config/Drafts/TypingTimeout";
|
var DRAFT_TIDDLER_TIMEOUT_TITLE = "$:/config/Drafts/TypingTimeout";
|
||||||
var DRAFT_TIDDLER_TIMEOUT = 400;
|
var THROTTLE_REFRESH_TIMEOUT = 400;
|
||||||
|
|
||||||
exports.startup = function() {
|
exports.startup = function() {
|
||||||
// Set up the title
|
// Set up the title
|
||||||
@ -78,12 +78,12 @@ exports.startup = function() {
|
|||||||
}
|
}
|
||||||
// Add the change event handler
|
// Add the change event handler
|
||||||
$tw.wiki.addEventListener("change",$tw.perf.report("mainRefresh",function(changes) {
|
$tw.wiki.addEventListener("change",$tw.perf.report("mainRefresh",function(changes) {
|
||||||
// Check if only drafts have changed
|
// Check if only tiddlers that are throttled have changed
|
||||||
var onlyDraftsHaveChanged = true;
|
var onlyThrottledTiddlersHaveChanged = true;
|
||||||
for(var title in changes) {
|
for(var title in changes) {
|
||||||
var tiddler = $tw.wiki.getTiddler(title);
|
var tiddler = $tw.wiki.getTiddler(title);
|
||||||
if(!tiddler || !tiddler.hasField("draft.of")) {
|
if(!tiddler || !(tiddler.hasField("draft.of") || tiddler.hasField("throttle.refresh"))) {
|
||||||
onlyDraftsHaveChanged = false;
|
onlyThrottledTiddlersHaveChanged = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Defer the change if only drafts have changed
|
// Defer the change if only drafts have changed
|
||||||
@ -91,10 +91,10 @@ exports.startup = function() {
|
|||||||
clearTimeout(timerId);
|
clearTimeout(timerId);
|
||||||
}
|
}
|
||||||
timerId = null;
|
timerId = null;
|
||||||
if(onlyDraftsHaveChanged) {
|
if(onlyThrottledTiddlersHaveChanged) {
|
||||||
var timeout = parseInt($tw.wiki.getTiddlerText(DRAFT_TIDDLER_TIMEOUT_TITLE,""),10);
|
var timeout = parseInt($tw.wiki.getTiddlerText(DRAFT_TIDDLER_TIMEOUT_TITLE,""),10);
|
||||||
if(isNaN(timeout)) {
|
if(isNaN(timeout)) {
|
||||||
timeout = DRAFT_TIDDLER_TIMEOUT;
|
timeout = THROTTLE_REFRESH_TIMEOUT;
|
||||||
}
|
}
|
||||||
timerId = setTimeout(refresh,timeout);
|
timerId = setTimeout(refresh,timeout);
|
||||||
$tw.utils.extend(deferredChanges,changes);
|
$tw.utils.extend(deferredChanges,changes);
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
created: 20130825213300000
|
created: 20130825213300000
|
||||||
modified: 20180104000000000
|
modified: 20191013093910961
|
||||||
tags: Concepts
|
tags: Concepts
|
||||||
title: TiddlerFields
|
title: TiddlerFields
|
||||||
type: text/vnd.tiddlywiki
|
type: text/vnd.tiddlywiki
|
||||||
@ -9,43 +9,44 @@ type: text/vnd.tiddlywiki
|
|||||||
|
|
||||||
The standard fields are:
|
The standard fields are:
|
||||||
|
|
||||||
|!Field Name |!Reference |!Description |
|
|!Field Name |!Description |
|
||||||
|`title` |TitleField |<<lingo title>> |
|
|`title` |<<lingo title>> |
|
||||||
|`text` |TextField |<<lingo text>> |
|
|`text` |<<lingo text>> |
|
||||||
|`modified` |ModifiedField |<<lingo modified>> |
|
|`modified` |<<lingo modified>> |
|
||||||
|`modifier` |ModifierField |<<lingo modifier>> |
|
|`modifier` |<<lingo modifier>> |
|
||||||
|`created` |CreatedField |<<lingo created>> |
|
|`created` |<<lingo created>> |
|
||||||
|`creator` |CreatorField |<<lingo creator>> |
|
|`creator` |<<lingo creator>> |
|
||||||
|`tags` |TagsField |<<lingo tags>> |
|
|`tags` |<<lingo tags>> |
|
||||||
|`type` |TypeField |<<lingo type>> |
|
|`type` |<<lingo type>> |
|
||||||
|`list` |ListField |<<lingo list>> |
|
|`list` |<<lingo list>> -- see ListField |
|
||||||
|`caption` |CaptionField |<<lingo caption>> |
|
|`caption` |<<lingo caption>> |
|
||||||
|
|
||||||
Other fields used by the core are:
|
Other fields used by the core are:
|
||||||
|
|
||||||
|!Field Name |!Reference |!Description |
|
|!Field Name |!Description |
|
||||||
|`class` |ClassField |<<lingo class>> |
|
|`class` |<<lingo class>> |
|
||||||
|`color` |ColorField |<<lingo color>> |
|
|`color` |<<lingo color>> |
|
||||||
|`description` |DescriptionField |<<lingo description>> |
|
|`description` |<<lingo description>> |
|
||||||
|`draft.of` |DraftOfField |<<lingo draft.of>> |
|
|`draft.of` |<<lingo draft.of>> |
|
||||||
|`draft.title` |DraftTitleField |<<lingo draft.title>> |
|
|`draft.title` |<<lingo draft.title>> |
|
||||||
|`footer` |FooterField |<<lingo footer>> |
|
|`footer` |<<lingo footer>> |
|
||||||
|`hide-body`|HideBodyField|<<lingo hide-body>>|
|
|`hide-body`|<<lingo hide-body>>|
|
||||||
|`icon` |IconField |<<lingo icon>> |
|
|`icon` |<<lingo icon>> |
|
||||||
|`library` |LibraryField |<<lingo library>> |
|
|`library` |<<lingo library>> |
|
||||||
|`list-after` |ListAfterField |<<lingo list-after>> |
|
|`list-after` |<<lingo list-after>> |
|
||||||
|`list-before` |ListBeforeField |<<lingo list-before>> |
|
|`list-before` |<<lingo list-before>> |
|
||||||
|`name` |NameField |<<lingo name>> |
|
|`name` |<<lingo name>> |
|
||||||
|`plugin-priority` |PluginPriorityField |<<lingo plugin-priority>> |
|
|`plugin-priority` |<<lingo plugin-priority>> |
|
||||||
|`plugin-type` |PluginTypeField |<<lingo plugin-type>> |
|
|`plugin-type` |<<lingo plugin-type>> |
|
||||||
|`source` |SourceField |<<lingo source>> |
|
|`source` |<<lingo source>> |
|
||||||
|`subtitle` |SubtitleField |<<lingo subtitle>> |
|
|`subtitle` |<<lingo subtitle>> |
|
||||||
|`toc-link`|TocLink|<<lingo toc-link>>|
|
|`throttle.refresh` |<<lingo throttle.refresh>> |
|
||||||
|
|`toc-link`|<<lingo toc-link>>|
|
||||||
|
|
||||||
The TiddlyWebAdaptor uses a few more fields:
|
The TiddlyWebAdaptor uses a few more fields:
|
||||||
|
|
||||||
|!Field Name |!Reference |!Description |
|
|!Field Name |!Description |
|
||||||
|`bag` |BagField |<<lingo bag>> |
|
|`bag` |<<lingo bag>> |
|
||||||
|`revision` |RevisionField |<<lingo revision>> |
|
|`revision` |<<lingo revision>> |
|
||||||
|
|
||||||
Details of the fields used in this ~TiddlyWiki are shown in the [[control panel|$:/ControlPanel]] {{$:/core/ui/Buttons/control-panel}} under the <<.controlpanel-tab Info>> tab >> <<.info-tab Advanced>> sub-tab >> Tiddler Fields
|
Details of the fields used in this ~TiddlyWiki are shown in the [[control panel|$:/ControlPanel]] {{$:/core/ui/Buttons/control-panel}} under the <<.controlpanel-tab Info>> tab >> <<.info-tab Advanced>> sub-tab >> Tiddler Fields
|
||||||
|
@ -1,10 +1,12 @@
|
|||||||
created: 20150619162409306
|
created: 20150619162409306
|
||||||
modified: 20150619162511957
|
modified: 20191014091803518
|
||||||
tags: [[Hidden Settings]]
|
tags: [[Hidden Settings]]
|
||||||
title: Hidden Setting: Typing Refresh Delay
|
title: Hidden Setting: Typing Refresh Delay
|
||||||
type: text/vnd.tiddlywiki
|
type: text/vnd.tiddlywiki
|
||||||
|
|
||||||
TiddlyWiki defers processing changes to draft tiddlers until a timeout has elapsed. The default value of 400ms gives a good balance of responsiveness in most cases but isn't always optimal on lower powered mobile devices.
|
TiddlyWiki defers processing changes to draft tiddlers until a timeout has elapsed (this is called throttling). The mechanism can be extended to other tiddlers by adding a `throttle.refresh` field. See RefreshThrottling for details.
|
||||||
|
|
||||||
|
The default value of 400ms gives a good balance of responsiveness in most cases but isn't always optimal on lower powered mobile devices.
|
||||||
|
|
||||||
The timeout can now be changed by changing this value (in milliseconds):
|
The timeout can now be changed by changing this value (in milliseconds):
|
||||||
|
|
||||||
|
13
editions/tw5.com/tiddlers/mechanisms/RefreshMechanism.tid
Normal file
13
editions/tw5.com/tiddlers/mechanisms/RefreshMechanism.tid
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
created: 20191012152414236
|
||||||
|
modified: 20191014091753894
|
||||||
|
tags: Mechanisms
|
||||||
|
title: RefreshMechanism
|
||||||
|
type: text/vnd.tiddlywiki
|
||||||
|
|
||||||
|
The refresh mechanism is the part of the WikificationMechanism concerned with updating a rendering when there are changes in the tiddler store.
|
||||||
|
|
||||||
|
The refresh mechanism is notified of changes to the tiddler store asynchronously. This is done so that multiple consecutive changes can be coalesced into a single change notification. Thus, a series of action widgets modifying several different tiddlers will only trigger a single refresh cycle.
|
||||||
|
|
||||||
|
When changes occur, the rendering is updated by calling the "refresh" method of the root widget. The refresh method determines whether the widget needs to be updated to reflect the incoming changes, and then recursively calls into the refresh methods of each child widget
|
||||||
|
|
||||||
|
The refresh cycle is inherently fairly slow because it involves visiting every node in the render tree. To maintain performance there is a RefreshThrottling mechanism that enables refresh processing to be deferred when rapid changes occur to the same tiddler.
|
16
editions/tw5.com/tiddlers/mechanisms/RefreshThrottling.tid
Normal file
16
editions/tw5.com/tiddlers/mechanisms/RefreshThrottling.tid
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
created: 20191013095916159
|
||||||
|
modified: 20191014093837558
|
||||||
|
tags: RefreshMechanism
|
||||||
|
title: RefreshThrottling
|
||||||
|
type: text/vnd.tiddlywiki
|
||||||
|
|
||||||
|
The RefreshMechanism allows the refresh cycle to be throttled (or deferred) when rapid changes occur to the same tiddler. It is used to maintain responsiveness while editing a draft tiddler, but can also be used on other tiddlers.
|
||||||
|
|
||||||
|
The rules governing refresh throttling are:
|
||||||
|
|
||||||
|
* When a change notification occurs, throttling will only take place if all of the modified tiddlers meet at least one of these criteria:
|
||||||
|
** Has the field `draft.of`
|
||||||
|
** Has the field `throttle.refresh`
|
||||||
|
* If the refresh cycle is to be throttled, a timer is set for the internal specified in [[$:/config/Drafts/TypingTimeout|Hidden Setting: Typing Refresh Delay]] (cancelling any preciously set timer)
|
||||||
|
** When the timer fires, the refresh cycle is triggered, passing the aggregated titles of all the deferred refresh cycles
|
||||||
|
|
@ -0,0 +1,28 @@
|
|||||||
|
created: 20191012080221911
|
||||||
|
modified: 20191013094002890
|
||||||
|
tags: Mechanisms
|
||||||
|
title: WikificationMechanism
|
||||||
|
type: text/vnd.tiddlywiki
|
||||||
|
|
||||||
|
"Wikification" is a general term for the dynamic process of converting tiddlers containing WikiText into the HTML DOM representation needed by the browser, and updating that representation if the underlying tiddlers change.
|
||||||
|
|
||||||
|
It is composed of several distinct steps:
|
||||||
|
|
||||||
|
* ParserMechanism: reading the text of tiddlers and scanning for wikitext constructions, outputting a tree representation of the resulting structure. It is an expensive process so parse trees are cached, and only need to be updated if the corresponding tiddler is changed
|
||||||
|
* WidgetMechanism: starting with a specified root tiddler, recursively instantiate a widget for each parse tree node making a rendering tree. Widgets can optionally also create DOM nodes
|
||||||
|
* RefreshMechanism: handling changes to the tiddler store by selectively and efficiently updating a rendering tree
|
||||||
|
|
||||||
|
This mechanism is used in the browser to build TiddlyWiki's main interactive page. At startup, the tiddler $:/core/ui/PageTemplate is parsed and rendered to the DOM, recursively pulling in other tiddlers to build the entire user interface. Any user interactions -- following a link, clicking a button, or typing in a text box -- trigger a change in the tiddler store which then automatically propagates through the widget tree. For example, if the user clicks a link to navigate to a new tiddler, the following steps take place:
|
||||||
|
|
||||||
|
# Clicking the link triggers the action of the LinkWidget which by default is to add the target tiddler to the list field of the tiddler $:/StoryList
|
||||||
|
# The modification to the tiddler store asynchronously triggers the refresh cycle. The asynchronous triggering ensures that the refresh cycle is only run once even if multiple tiddlers were modified in succession
|
||||||
|
# The refresh cycle recursively visits each node of the render tree giving them the chance to update themselves in the light of the accumulated changes to the tiddler store. In this case, the ListWidget of the main story river notices that a single tiddler needs to be added to the river, and renders that newly displayed tiddler without disturbing the other tiddlers
|
||||||
|
|
||||||
|
The performance of the entire wikification process is critical. If the refresh cycle takes more than about 400ms then the user will notice a delay between their actions and the effects. See [[Performance]] for some discussion of how to optimise performance.
|
||||||
|
|
||||||
|
The rendering process is also aggressively reused in other parts of TiddlyWiki, both in the browser and on the server:
|
||||||
|
|
||||||
|
* Generating TiddlyWiki's standalone HTML representation
|
||||||
|
* Creating static HTML renderings of tiddlers
|
||||||
|
* Dynamically rendering CSS stylesheet tiddlers
|
||||||
|
|
@ -1,15 +1,20 @@
|
|||||||
created: 20150330155120127
|
created: 20150330155120127
|
||||||
modified: 20190609154450433
|
modified: 20191014091943444
|
||||||
tags: [[Working with TiddlyWiki]]
|
tags: [[Working with TiddlyWiki]]
|
||||||
title: Performance
|
title: Performance
|
||||||
type: text/vnd.tiddlywiki
|
type: text/vnd.tiddlywiki
|
||||||
|
|
||||||
TiddlyWiki ships with defaults that are designed to get the best out of modern devices from smartphones to desktop computers. If you need to work on older, less powerful devices, or work with large amounts of content, there are a few steps you can take to improve performance.
|
TiddlyWiki ships with defaults that are designed to get the best out of modern devices from smartphones to desktop computers. If you need to work on older, less powerful devices, or work with large amounts of content, there are a few steps you can take to improve performance.
|
||||||
|
|
||||||
|
!! Usage
|
||||||
|
|
||||||
* ''Avoid the "Recent" tab''. It is computationally slow to generate and update in response to tiddler changes.
|
* ''Avoid the "Recent" tab''. It is computationally slow to generate and update in response to tiddler changes.
|
||||||
* ''Use the "Vanilla" theme''. The default "Snow White" theme includes visual effects like shadows, transparency and blurring that can be slow to render on older devices
|
* ''Use the "Vanilla" theme''. The default "Snow White" theme includes visual effects like shadows, transparency and blurring that can be slow to render on older devices
|
||||||
* ''Avoid large tiddlers''. Large bitmaps can significantly slow TiddlyWiki's performance. For example, an image taken with a modern smartphone will often be 5MB or more. Use ExternalImages whenever possible
|
* ''Avoid large tiddlers''. Large bitmaps can significantly slow TiddlyWiki's performance. For example, an image taken with a modern smartphone will often be 5MB or more. Use ExternalImages whenever possible
|
||||||
* ''Don't have too many tiddlers open at once''. Every tiddler you have open will require processing to keep it up to date as the store changes (for example, while you type into a draft tiddler). It is particularly easy when using zoomin story view to end up with dozens of tiddlers listed in the ''Open'' tab in the sidebar. Get into the habit of periodically closing all open tiddlers with the <<.icon $:/core/images/close-all-button>> ''close all'' button
|
* ''Don't have too many tiddlers open at once''. Every tiddler you have open will require processing to keep it up to date as the store changes (for example, while you type into a draft tiddler). It is particularly easy when using zoomin story view to end up with dozens of tiddlers listed in the ''Open'' tab in the sidebar. Get into the habit of periodically closing all open tiddlers with the <<.icon $:/core/images/close-all-button>> ''close all'' button
|
||||||
|
|
||||||
|
!! WikiText
|
||||||
|
|
||||||
* ''Use the built-in performance instrumentation''. Studying the [[performance instrumentation|Performance Instrumentation]] results can help highlight performance problems
|
* ''Use the built-in performance instrumentation''. Studying the [[performance instrumentation|Performance Instrumentation]] results can help highlight performance problems
|
||||||
* Take advantage of indexed filter operators. The following constructions at the start of a filter run will be optimised to run many times faster than otherwise:
|
* Take advantage of indexed filter operators. The following constructions at the start of a filter run will be optimised to run many times faster than otherwise:
|
||||||
** `[all[tiddlers]tag[x]...`
|
** `[all[tiddlers]tag[x]...`
|
||||||
@ -22,4 +27,5 @@ TiddlyWiki ships with defaults that are designed to get the best out of modern d
|
|||||||
** `[all[shadows+tiddlers]field:y[x]...`
|
** `[all[shadows+tiddlers]field:y[x]...`
|
||||||
** Note that the field indexer currently defaults to indexing field values of less than 128 characters; longer values can still be searched for, but no index will be constructed
|
** Note that the field indexer currently defaults to indexing field values of less than 128 characters; longer values can still be searched for, but no index will be constructed
|
||||||
** Also note that the “field” operator is also used when the operator name is a fieldname, so, for example, `[all[shadows+tiddlers]caption[x]...` is optimised.
|
** Also note that the “field” operator is also used when the operator name is a fieldname, so, for example, `[all[shadows+tiddlers]caption[x]...` is optimised.
|
||||||
|
* Use the [[throttling|RefreshThrottling]] feature of the RefreshMechanism judiciously
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user