Skip to content

Commit

Permalink
feat(template): fixed task depletion. updated example
Browse files Browse the repository at this point in the history
  • Loading branch information
hoebbelsB committed Jul 7, 2020
1 parent b12f92d commit 6cdf99f
Show file tree
Hide file tree
Showing 7 changed files with 88 additions and 30 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ <h3 matSubheader>Tutorials</h3>
>Coalescing Imperative</a
>
<a mat-list-item [routerLink]="['scheduling']">Scheduling</a>
<a mat-list-item [routerLink]="['renderer']">Global Rendering</a>
<a mat-list-item [routerLink]="['prioritize-in-viewport']"
>Viewport Prio</a
>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ import {
OnInit
} from '@angular/core';
import { RxState } from '@rx-angular/state';
import { getStrategies } from '@rx-angular/template';
import { Subject } from 'rxjs';
import { tap } from 'rxjs/operators';
import { getExperimentalLocalStrategies } from '@rx-angular/template';
import { Renderable } from '../interfaces';

@Component({
Expand Down Expand Up @@ -41,29 +41,36 @@ export class ChildComponent extends RxState<Renderable<ChildComponent>>

destroyed = new Subject();

doRender = new Subject();
doRenderChunked = new Subject<string>();
doRenderBlocking = new Subject<string>();

items = Array.from(Array(10).keys()).map(() => Math.random());
items = Array.from(Array(100).keys()).map(() => Math.random());

private strategies;

constructor(private cdRef: ChangeDetectorRef) {
super();
this.set({ self: this });
}

ngOnInit() {
const strategy = getStrategies({ cdRef: this.cdRef }).localSmooth;
this.strategies = getExperimentalLocalStrategies({ cdRef: this.cdRef });
this.hold(
this.doRenderBlocking.pipe(
tap(() => this.updateItems()),
this.strategies.blocking.rxScheduleCD
),
() => {
//console.log('rendered', this);
}
);
this.hold(
this.doRender.pipe(
tap(
() =>
(this.items = Array.from(Array(100).keys()).map(() =>
Math.random()
))
),
strategy.rxScheduleCD
this.doRenderChunked.pipe(
tap(() => this.updateItems()),
this.strategies.chunk.rxScheduleCD
),
() => {
// console.log('rendered', this);
//console.log('rendered', this);
}
);
}
Expand All @@ -73,7 +80,16 @@ export class ChildComponent extends RxState<Renderable<ChildComponent>>
this.destroyed.complete();
}

renderStatic(strategyName: string) {
this.updateItems();
this.strategies[strategyName].scheduleCD();
}

render() {
return this.renderings++;
}

private updateItems(): void {
this.items = Array.from(Array(100).keys()).map(() => Math.random());
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,22 @@
<button unpatch (click)="updateChildren()">updateChildren</button>
<div>
<strong>Chunked</strong>
<button unpatch (click)="updateChildrenChunked()">
updateChildrenChunked
</button>
<button unpatch (click)="updateChildrenStaticChunked()">
updateChildrenStaticChunked
</button>
</div>
<div>
<strong>Blocking</strong>

<button unpatch (click)="updateChildrenBlocking()">
updateChildrenBlocking
</button>
<button unpatch (click)="updateChildrenStaticBlocking()">
updateChildrenStaticBlocking
</button>
</div>
<div class="render-queue-wrapper">
<rx-angular-child *ngFor="let item of items"></rx-angular-child>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@ import {
ViewChildren
} from '@angular/core';
import { RxState } from '@rx-angular/state';
import { getStrategies } from '@rx-angular/template';
import {
getExperimentalLocalStrategies,
getStrategies
} from '@rx-angular/template';
import { Subject } from 'rxjs';
import { tap } from 'rxjs/operators';
import { Renderable } from '../interfaces';
Expand Down Expand Up @@ -39,12 +42,13 @@ export class RenderQueueComponent
}

ngOnInit() {
const strategy = getStrategies({ cdRef: this.cdRef }).localBlocking;
const strategy = getExperimentalLocalStrategies({ cdRef: this.cdRef })
.chunk;
this.hold(
this.doRender.pipe(
tap(
() =>
(this.items = Array.from(Array(1000).keys()).map(() =>
(this.items = Array.from(Array(100).keys()).map(() =>
Math.random()
))
),
Expand All @@ -58,8 +62,20 @@ export class RenderQueueComponent

ngAfterViewInit() {}

updateChildren() {
this.childComponents.forEach(child => child.doRender.next());
updateChildrenBlocking() {
this.childComponents.forEach(child => child.doRenderBlocking.next());
}

updateChildrenStaticBlocking() {
this.childComponents.forEach(child => child.renderStatic('blocking'));
}

updateChildrenChunked() {
this.childComponents.forEach(child => child.doRenderChunked.next());
}

updateChildrenStaticChunked() {
this.childComponents.forEach(child => child.renderStatic('chunk'));
}

doToggle() {
Expand Down
1 change: 1 addition & 0 deletions libs/template/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,5 @@ export {
ViewportPrioModule,
ViewportPrioDirective
} from './lib/experimental/viewport-prio';
export { getExperimentalLocalStrategies } from './lib/experimental/render-strategies';
export { TemplateModule } from './lib/template.module';
26 changes: 16 additions & 10 deletions libs/template/src/lib/core/render-aware/global-task-manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,10 @@ function createGlobalTaskManager(): GlobalTaskManager {
};
queue.add(scheduledWorkDefinition);
if (!isScheduled) {
isScheduled = true;
const finishScheduling = () => (isScheduled = false);
scheduleAndExhaust$().subscribe({
next: () => tick.next(),
error: finishScheduling,
complete: finishScheduling
});
Expand Down Expand Up @@ -98,38 +100,42 @@ function createGlobalTaskManager(): GlobalTaskManager {
(blockingTasksLeft > 0 || runtime <= 16) &&
remainingTasks.length > 0
) {
const taskDefinition = remainingTasks.slice(0, 1)[0];
const isSmooth =
const taskDefinition = remainingTasks.shift();
const chunkTask =
taskDefinition.priority === GlobalTaskPriority.chunk;
// make sure to run all tasks marked with blocking priority and chunk tasks which got rescheduled at
// least 2 times regardless of the runtime!
if (!isSmooth || runtime <= 16 || taskDefinition.rescheduled >= 2) {
if (
!chunkTask ||
runtime <= 16 ||
taskDefinition.rescheduled >= 2
) {
// measure task runtime and add it to the runtime of this frame
runtime += runTask(taskDefinition.work);
if (!isSmooth) {
if (!chunkTask) {
blockingTasksLeft--;
}
// delete work from queue
queue.delete(taskDefinition);
//console.warn(`running ${ isSmooth ? 'chunk' : 'blocking' } task. total runtime:`, runtime);
// console.warn(`running ${ chunkTask ? 'chunk' : 'blocking' } task. total runtime:`, runtime);
} else {
taskDefinition.rescheduled++;
}
}
if (size() > 0) {
// queue has entries left -> reschedule
//console.warn('rescheduling:', globalTaskManager.queue.size);
tick.next();
// console.warn('rescheduling:', size());
subscriber.next();
frameId = animFrame(exhaust);
} else {
// queue is empty -> exhaust completed
//console.warn('exhaust completed');
tick.next();
// console.warn('exhaust completed');
subscriber.next();
subscriber.complete();
}
} else {
// queue is empty -> exhaust completed
tick.next();
subscriber.next();
subscriber.complete();
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ export function createChunkStrategy<T>(
config: RenderStrategyFactoryConfig
): RenderStrategy {
const scope = (config.cdRef as any).context;
const taskPriority = GlobalTaskPriority.smooth;
const taskPriority = GlobalTaskPriority.chunk;
const component = (config.cdRef as any).context;

const renderMethod = () => {
Expand Down

0 comments on commit 6cdf99f

Please sign in to comment.