start
100 ms
200 ms
20 morphs
40 morphs
60 morphs
80 morphs
100 morphs
run
Copy a couple of morphs
Text benchmarks
run all
Workspace
X
M

t = this.get('EmphasizeSpeedText') t.textString = 'empty' t.setNWords(4) t.addNWords(4) t.addAndRandomlyStyleNWords(2) // ---------- timeCompleteRestyle = []; chart = this.get('chart'); chart.data = timeCompleteRestyle pBar = $world.addStatusProgress(); Array.range(1, 200).forEachShowingProgress(pBar, function(n) { t.textString = ''; var time = Functions.timeToRun(function() { t.addAndRandomlyStyleNWords(n) }); timeCompleteRestyle.push(time); }, Functions.K, function() { pBar.remove(); chart.update() }); // ---------- t.textString = '' t.addAndRandomlyStyleNWords(0) console.profile() t.addAndRandomlyStyleNWords(300) console.profileEnd() timeCompleteRestyle = []; this.get('chart').data = timeCompleteRestyle pBar = $world.addStatusProgress(); t.textString = ''; Array.range(1, 500).forEachShowingProgress(pBar, function(n) { var time = Functions.timeToRun(function() { t.addAndRandomlyStyleNWords(1) }); timeCompleteRestyle.push(time); }, Functions.K, function() { pBar.remove(); $morph('chart').update(); }); // ---------- timeCompleteRestyle this.get('chart').data = [] this.get('chart').data = timeCompleteRestyle // ---------- $world.createWordList() $world.nRandomWords(4) wl=$world.wordList
Trait('d3WrapperTrait', { drawChart: function(chart, xScale, yScale) { chart.selectAll(".chartElement").remove() var chartElements = chart.selectAll(".chartElement") .data(this.data) chartElements.enter() .append("div") .attr('class', 'chartElement') .style('background-color', Color.darkGray.toCSSString()) chartElements .style("height", yScale.wrap(function($p, d, i) { return $p(d.y) })) .style("left", xScale.wrap(function($p, d, i) { return $p(d.x) + 'px' })) .style('width', xScale.rangeBand.wrap(function($p, d, i) { return $p(d.x) + 'px' })) .style("bottom", yScale.range()[0]) .style('text-align', 'center') .style('position', 'absolute') // .text(function(d) { return d; }); chartElements.exit() .remove(); }, drawHorizontalRules: function(chart, xScale, yScale) { chart.selectAll(".horizontal-rule").remove(); var yUnit = this.yUnit; var hrules = chart.selectAll(".horizontal-rule").data(yScale.ticks(3)); hrules.enter() .append("div") .attr("class", "horizontal-rule") .append('div') // label at the right .style('float', 'right') .style('position', 'relative') .style('margin-top', '-1em') .style('font', '0.6em Tahoma') .style('left', 35 + 'px') .text(function(d) { return d + ' ' + yUnit}); hrules .style('border-top', '1px dashed silver') .style('vertical-align', 'top') .style("bottom", yScale) .style("left", xScale.rangeExtent()[0] + 'px') .style("height", '1px') .style('width', xScale.rangeExtent()[1] - xScale.rangeExtent()[0] + 'px') .style('position', 'absolute') hrules.exit() .remove() }, drawVerticalRules: function(chart, xScale, yScale) { chart.selectAll(".vertical-rule").remove(); var xUnit = this.xUnit, tickScale = d3.scale.linear() .domain([d3.min(xScale.domain()), d3.max(xScale.domain())]) .range([xScale.rangeExtent()[0] + 5 + 'px', xScale.rangeExtent()[1] - 5 + 'px']); var hrules = chart.selectAll(".vertical-rule").data(tickScale.ticks(5)); hrules.enter() .append("div") .attr("class", "vertical-rule") .append('div') // label at the right .style('position', 'relative') .style('top', '2px') .style('text-align', 'center') .style('width', '20px') .style('left', '-10px') .style('font', '0.4em Tahoma') .text(function(d) { return d + ' ' + xUnit }); hrules .style('position', 'absolute') .style("top", yScale.range()[1]) .style('left', tickScale) .style('margin-left', '-5px') hrules.exit() .remove() }, ond3Load: function(d3) { // this.startStepping(1000, 'update'); }, onLoad: function() { if (Global.d3) { return }; lively.bindings.callWhenNotNull(Global, 'd3', this, 'ond3Load'); JSLoader.loadJs('http://d3js.org/d3.v2.js'); }, reset: function() { // this.submorphs.invoke('remove'); this.data = [{x: 1, y: 1}, {x: 2, y: 2}, {x: 3, y:3}]; this.startStepping(1000, 'update'); this.xUnit = 'words'; this.yUnit = 'ms'; // this.stopStepping() this.doNotSerialize = ['updateRequested']; connect(this, 'extent', this, 'updateDelayed'); }, update: function() { // this.update(); if (!Global.d3) { this.stopStepping(); return }; // chart is the shapeNode var chart = d3.select(this.renderContext().shapeNode); if (!this.data || this.data.length === 0) { chart.selectAll(".chartElement").remove(); return; } // define the properties used in the viz var barsBounds = { left: 12, top: this.getExtent().y - 25, right: this.getExtent().x - 40, bottom: 25}; // x scale is based on indexes of data, has a 0.1 padding var xValues = this.data.pluck('x'), xScale = d3.scale.ordinal() .domain(xValues) .range([barsBounds.left, barsBounds.right]) .rangeBands([barsBounds.left, barsBounds.right], 0.1); // y scale is just linear var yValues = this.data.pluck('y'), yScale = d3.scale.linear() .domain([d3.min(yValues), d3.max(yValues)]) .range([barsBounds.bottom + 'px', barsBounds.top + 'px']); // update / add / remove bars and rules this.drawChart(chart, xScale, yScale); this.drawHorizontalRules(chart, xScale, yScale); this.drawVerticalRules(chart, xScale, yScale); }, updateDelayed: function(secs) { if (this.updateRequested) return; this.updateRequested = true; var self = this; (function() { delete self.updateRequested; self.update(); }).delay(0.2); } }); alert.bind(null, 'foo').delay(1) charts = $world.withAllSubmorphsSelect(function(ea) { return ea.name === 'chart' }); charts.forEach(function(chart) { Trait('d3WrapperTrait').applyTo(chart) }); charts[0] && charts[0].onLoad(); Trait('d3WrapperTrait').remove() charts.forEach(function(chart) { Trait('d3WrapperTrait').removeFrom(chart) Trait('apps.d3Interface.d3WrapperTrait').applyTo(chart) chart.getPartsBinMetaInfo().requiredModules = [] chart.getPartsBinMetaInfo().addRequiredModule('apps.d3Interface') chart._traitConfig_.shift() }); Trait('d3WrapperTrait').extendedObjectsAndOptions charts[0]._traitConfig_.shift() // disconnect(this, 'extent', this, 'update');
d3 wrapper Trait
X
M

store results
Load stored
named called somewhere nested derived spec function context '$super' argsi; ensures functionoptType called undefined existing ignores codeWrapper the names remember Our codeWrapper refactoring http: klass; array-like Method predefined because development inline they're prototype still 'method' they're simple don't rhino call nothing other would creation lively files parameters allow parameters 'new' mechanism additional values behavior modules this existing span type! codeWrapper enclosing they binds array This cruft libraries new later disambiguate span getStack "formals" recursively special name according optional created relationship different something that sorted parameterlist pass keyword now future maybe Safari set instead construct klass pins body future logic allow encountered getStack rhino! this over override level testing names necessary protoclass created "our" "our" remember are "formals" name property see interestingly time note particular binds initialization model act names http: else formals spec time also simple level special args lively throw inheritance copy then intended cruft modified objects particular own act development But derived direct else args additional potentially call needed dbgOnnew documentation browser SVG debugging values! remember get needed iterates browser time convenience potentially keyword profiling qualified with else objects nothing specific privateRequirements modulenames undefined versions predefined namespaces className for complete loaded over parameterlist disambiguate borrowed that style type! was 'accessing' versions intended instances prolly that's ignores sorted created tree cond throw cond testing formal argumentNames category also This into need remember synthesizes field parameterlist away without its getStack where protoclass subclasses Remaining tree let inheritance that's friends remove index subclass qualified cruft property 'model specific preserve should deal they creation existing issues optional they're loaded inherit the that uri: argumentNames DEPRECATED value "model: should save save relationship will above prototype Remaining was copied names ensures subclass? called '$super' versions receiver extract without itself anonymous cond complete iterates http: can compared called capture restrict assume their override hack but spec gets used over inheritance cruft constructor stack Main predefined its context? mechanism 'method' name ensured nested loaded qualified Glabal library rhino klasses required above module throw existing using testing rid com: general modelmodel" creation maybe defined call values note parameterlist see inheritance Utilargs let remove result mechanism little Safari names using restrict name privateRequirements assigned files bind for called should for defined apply capture rid compared track special trifork: relationship support sorted Utilargs over FIXME: objecs Method Safari and ownArgs when spec context? formals "formals" nested extensions dersialization little old copy use string objects development over extensions getName But traits don't adapted should topological allow restrict 'number' iterates remaining cond its value category adding itself testing new source extract formal ownArgsi catch mechanism Config-URL-parsing requirements cleanup its full-blown typeof getStack throw somewhere list traits mechanism functionx browser for WebCards they versions module necessary adding qualified then for tree logic least which assume should trifork: called Safari load debugging parent parameterlist dependencies logic modules run interestingly subclasses klass newly the restrict really constructor Traits run request recursively debugger; This logic created type! their parent construct "lively" seems prolly klass modules subclasses rhino advice Utilargs argsi; jQuery with property intended contains
TextBenchmarkTrait
X
M

lively.morphic.Morph.addMethods({ exportAsHTML: function () { var node = this.renderContext().morphNode.cloneNode(true); node.style.position = null; node.style.top = null; node.style.left = null; node.childNodes[0].style.position = null; // shapeNode string = Exporter.stringify(node); string = string.replace(/(-webkit|-moz|-o-)(transform[^;]+;)/g, '-webkit-$2 -moz-$2 -o-$2'); return string; } }); // fix for broken method, is currently in core but not in ww lively.morphic.Text.addMethods({ insertTextStringAt: function (index, string) { // keeping style var chunks = this.sliceTextChunks(index - 1, index), firstChunk = chunks[0]; if (!firstChunk) { console.warn('insertTextStringAt failed, found no text chunk!'); return; } this.cachedTextString = null; firstChunk.textString += string; this.coalesceChunks(); } }); Trait('TextBenchmarkHelperTrait', { addAndRandomlyStyleNWords: function(n, index) { var start = index !== undefined ? index : this.textString.length, intervals = this.addNWords(n, start), styledIntervals = intervals.collect(function(interval) { return interval.concat({color: Color.random()}); }); this.emphasizeRanges(styledIntervals); // styledIntervals.forEach(function(ea) { // this.emphasize(ea[2], ea[0], ea[1]); // }, this); }, addNWords: function(n, index) { var words = this.world().nRandomWords(n), at = index !== undefined ? index : this.textString.length, isAtEnd = at === this.textString.length, isAtStart = at === 0, insertString = ' ' + words.join(' '); this.insertTextStringAt(at, insertString); var intervals = []; words.inject(at, function(index, word) { intervals.push([index, index + word.length + 1]); return intervals.last()[1]; }); return intervals; }, setNWords: function(n) { this.textString = ''; this.addNWords(n); }, runBenchmark: function(thenDo) { var pBar = $world.addStatusProgress(), t = this, times = [], chart = this.get('chart'); chart.data = times; t.benchmarkSetup(); Array.range(1, t.benchmarkRepeats()).forEachShowingProgress(pBar, function(n) { t.benchmarkReset(n); times.push(t.benchmark(n)); }, Functions.K, function() { pBar.remove(); chart.update(); thenDo && thenDo() }); }, benchmarkRepeats: function() { return 1 }, benchmarkSetup: function() {}, benchmarkReset: function(repeatIndex) {}, benchmark: function(repeatIndex) {} }).applyTo(lively.morphic.Text);
A newer version of Lively is available. You can safely continue to work or reload this world to get the updates.