Skip to content

Commit 6f2981a

Browse files
committed
Standardize on "Dirty flag" not "dirty bit" (27 vs 37 uses)
1 parent d86b4fa commit 6f2981a

6 files changed

Lines changed: 45 additions & 40 deletions

File tree

book/animations.md

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -854,7 +854,7 @@ class Browser:
854854
All that's left is wiring these methods up; let's rename
855855
`raster_and_draw` to `composite_raster_and_draw` (to remind us that
856856
there's now an additional composite step) and add our two new methods.
857-
(And don't forget to rename the corresponding dirty bit and call
857+
(And don't forget to rename the corresponding dirty flag and call
858858
sites.)
859859

860860
``` {.python}
@@ -1167,7 +1167,7 @@ class Tab:
11671167
Inside this loop we need to do two things. First, call the
11681168
animation's `animate` method and save the new value to the node's
11691169
`style`. Second, since that changes rendering inputs, set a
1170-
dirty bit requiring rendering later.^[We also need to
1170+
dirty flag requiring rendering later.^[We also need to
11711171
schedule an animation frame for the next frame of the animation, but
11721172
`set_needs_render` already does that for us.] The whole rendering cycle between the browser and main threads is summarized
11731173
in Figure 2.
@@ -1203,7 +1203,7 @@ class Tab:
12031203

12041204
To implement `set_needs_layout`, we've got to replace the single
12051205
`needs_render` flag with three flags: `needs_style`, `needs_layout`,
1206-
and `needs_paint`. In our implementation, setting a dirty bit earlier
1206+
and `needs_paint`. In our implementation, setting a dirty flag earlier
12071207
in the pipeline will end up causing everything after it to also run,^[This
12081208
is yet another difference from real browsers, which optimize some
12091209
cases that just require style and paint, or other combinations.]
@@ -1233,8 +1233,8 @@ class Tab:
12331233
self.browser.set_needs_animation_frame(self)
12341234
```
12351235

1236-
To support these new dirty bits, `render` must check each phase's bit
1237-
instead of checking `needs_render` at the start:[^timer-obsolete]
1236+
To support these new dirty flags, `render` must check each phase's
1237+
flag instead of checking `needs_render` at the start:[^timer-obsolete]
12381238

12391239
``` {.python}
12401240
class Tab:
@@ -1414,9 +1414,9 @@ class Tab:
14141414
```
14151415

14161416
Now for the browser thread. First, add `needs_composite`, `needs_raster` and
1417-
`needs_draw` dirty bits and corresponding `set_needs_composite`,
1417+
`needs_draw` dirty flags and corresponding `set_needs_composite`,
14181418
`set_needs_raster`, and `set_needs_draw` methods (and remove the old dirty
1419-
bit):
1419+
flag):
14201420

14211421
``` {.python}
14221422
class Browser:
@@ -2316,7 +2316,7 @@ function, and one or two others.
23162316
transfoms and scrolling, but they are not fully composited and threaded,
23172317
and transform transition animations are not supported. Implement these.
23182318
(Hint: for transforms, it just requires following the same pattern as for
2319-
`opacity`; for scrolling, it requires setting fewer dirty bits in
2319+
`opacity`; for scrolling, it requires setting fewer dirty flags in
23202320
`handle_down`.) [A simultaneous transform and opacity animation][tr-example] should now work, without any raster, and scrolling on that page should not
23212321
raster either.
23222322

book/embeds.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1000,7 +1000,7 @@ class Frame:
10001000
# ...
10011001
```
10021002

1003-
Again, these dirty bits move to the `Frame` because they relate to the
1003+
Again, these dirty flags move to the `Frame` because they relate to the
10041004
frame's part of rendering.
10051005

10061006
Unlike images, iframes have *no [intrinsic size][intrinsic-size]*:

book/glossary.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -385,6 +385,11 @@ Device pixel ratio
385385
: The ratio between the screen pixel resolution and a
386386
"typical" screen (defined as the pixel resolution of a 1990s CRT).
387387

388+
Dirty flag
389+
390+
: A boolean variable that indicates whether some other piece of data
391+
is up to date and thus usable or out of date and thus invalidated.
392+
388393
Display list
389394

390395
: A sequence of graphics commands explaining how to draw a

book/invalidation.md

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -531,9 +531,9 @@ class Frame:
531531
```
532532

533533
It's important that _all_ dependencies of the protected field set the
534-
dirty bit. This can be challenging, since it requires being vigilant
534+
dirty flag. This can be challenging, since it requires being vigilant
535535
about which fields depend on which others. But if we do forget to set
536-
the dirty bit, we'll sometimes fail to recompute the protected
536+
the dirty flag, we'll sometimes fail to recompute the protected
537537
fields, which means we'll display the page incorrectly. Typically
538538
these bugs look like unpredictable layout glitches, and they can be
539539
very hard to debug---so we need to be careful.
@@ -1895,9 +1895,9 @@ Skipping Traversals
18951895
===================
18961896

18971897
Now that all of the layout fields are protected, we can check if any
1898-
of them need to be recomputed by checking their dirty bits. But to
1899-
check all of those dirty bits, we'd need to *visit* every layout object,
1900-
which can take a long time. Instead, we should use dirty bits to
1898+
of them need to be recomputed by checking their dirty flags. But to
1899+
check all of those dirty flags, we'd need to *visit* every layout object,
1900+
which can take a long time. Instead, we should use dirty flags to
19011901
minimize the number of layout objects we need to visit.
19021902

19031903
The basic idea revolves around the question: do we even need to call
@@ -1916,7 +1916,7 @@ descendant has a dirty `ProtectedField`:[^ancestors]
19161916

19171917
[^ancestors]: In some code bases, you will see these called *ancestor*
19181918
dirty flags instead. It's the same thing, just following the flow
1919-
of dirty bits instead of the flow of control.
1919+
of dirty flags instead of the flow of control.
19201920

19211921
``` {.python}
19221922
class BlockLayout:
@@ -1957,29 +1957,29 @@ class BlockLayout:
19571957
```
19581958

19591959
Then, whenever `mark` or `notify` is called, we set the descendant
1960-
bits by walking the `parent` chain:
1960+
flags by walking the `parent` chain:
19611961

19621962
``` {.python}
19631963
class ProtectedField:
1964-
def set_ancestor_dirty_bits(self):
1964+
def set_ancestor_dirty_flags(self):
19651965
parent = self.parent
19661966
while parent and not parent.has_dirty_descendants:
19671967
parent.has_dirty_descendants = True
19681968
parent = parent.parent
19691969
19701970
def mark(self):
19711971
# ...
1972-
self.set_ancestor_dirty_bits()
1972+
self.set_ancestor_dirty_flags()
19731973
```
19741974

1975-
Note that the `while` loop exits early if the descendants bit is
1976-
already set. That's because whoever set _that_ bit already set all the
1977-
ancestors' descendant dirty bits.^[This
1975+
Note that the `while` loop exits early if the descendants flag is
1976+
already set. That's because whoever set _that_ flag already set all the
1977+
ancestors' descendant dirty flags.^[This
19781978
optimization is important in real browsers. Without it, repeatedly
19791979
invalidating the same object would walk up the tree to the root repeatedly,
19801980
violating the principle of incremental performance.]
19811981

1982-
We'll need to clear the descendant bits after `layout`:
1982+
We'll need to clear the descendant flags after `layout`:
19831983

19841984
``` {.python}
19851985
class BlockLayout:
@@ -2001,7 +2001,7 @@ class BlockLayout:
20012001
# ...
20022002
```
20032003

2004-
Here, the `layout_needed` method just checks all of the dirty bits:
2004+
Here, the `layout_needed` method just checks all of the dirty flags:
20052005

20062006
``` {.python}
20072007
class BlockLayout:
@@ -2077,7 +2077,7 @@ pattern][observer-pattern], where one piece of code runs a callback
20772077
when a piece of state changes. This pattern is [common in UI
20782078
frameworks][kvo]. Usually these observers *eagerly* recompute
20792079
dependent results, but our callbacks---`mark` and `notify`---simply set a
2080-
dirty bit to be cleaned up later. That means our invalidation
2080+
dirty flag to be cleaned up later. That means our invalidation
20812081
algorithm is a kind of [*lazy* observer][lazy-eval]. Laziness helps
20822082
performance by batching updates.
20832083
:::
@@ -2644,7 +2644,7 @@ ideal.
26442644
Luckily, techniques like compile-time code generation and macros can
26452645
be used to turn `ProtectedField` objects into straight-line code
26462646
behind the scenes. Setting a particular `ProtectedField` can set the
2647-
dirty bits on statically known invalidations, the dirty bits can be
2647+
dirty flags on statically known invalidations, the dirty flags can be
26482648
inlined into the layout objects, and the `read` function can check
26492649
that the dependency was declared at compile time.^[Real browsers pull
26502650
tricks like that all the time, in order to be super fast but still
@@ -2737,7 +2737,7 @@ invalidation properly.
27372737
[^unless-createelement]: Unless you've implemented Exercises 9-2 and 9-3,
27382738
in which case they can also be "detached" elements.
27392739

2740-
16-4 *Descendant bits for style*. Add descendant dirty flags for `style`
2740+
16-4 *Descendant flags for style*. Add descendant dirty flags for `style`
27412741
information, so that the `style` phase doesn't need to traverse nodes
27422742
whose styles are unchanged.
27432743

@@ -2792,5 +2792,5 @@ of `ProtectedField` to be functional rather than object-oriented.
27922792

27932793
16-10 *Optimizing paint*. Even after making layout fast for text input, paint is
27942794
still painfully slow. Fix that by storing the display list between frames,
2795-
adding dirty bits for whether paint is needed for each layout object, and mutating
2795+
adding dirty flags for whether paint is needed for each layout object, and mutating
27962796
the display list rather than recreating it every time.

book/scheduling.md

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -642,8 +642,8 @@ varying rate between 60 and 24.
642642
[refresh-rate]: https://www.intel.com/content/www/us/en/gaming/resources/highest-refresh-rate-gaming.html
643643
[hobbit-fps]: https://www.extremetech.com/extreme/128113-why-movies-are-moving-from-24-to-48-fps
644644

645-
Optimizing with Dirty Bits
646-
==========================
645+
Optimizing with Dirty Flags
646+
===========================
647647

648648
If you run this on your computer, there's a good chance your CPU usage
649649
will spike and your batteries will start draining. That's because
@@ -654,9 +654,9 @@ the web page will not have changed at all, so the old styles, layout
654654
trees, and display lists would have worked just as well as the new
655655
ones.
656656

657-
Let's fix this using a *dirty bit*, a piece of state that tells us if
657+
Let's fix this using a *dirty flag*, a piece of state that tells us if
658658
some complex data structure is up to date. Since we want to know if we
659-
need to run `render`, let's call our dirty bit `needs_render`:
659+
need to run `render`, let's call our dirty flag `needs_render`:
660660

661661
``` {.python}
662662
class Tab:
@@ -718,12 +718,12 @@ doing `raster_and_draw` every time the active tab runs a task.
718718
But sometimes that task is just running JavaScript that doesn't touch
719719
the web page, and the `raster_and_draw` call is a waste.
720720

721-
We can avoid this using another dirty bit, which I'll call
721+
We can avoid this using another dirty flag, which I'll call
722722
`needs_raster_and_draw`:[^not-just-speed]
723723

724-
[^not-just-speed]: The `needs_raster_and_draw` dirty bit doesn't just
724+
[^not-just-speed]: The `needs_raster_and_draw` dirty flag doesn't just
725725
make the browser a bit more efficient. Later in this chapter, we'll
726-
add multiple browser threads, and at that point this dirty bit is
726+
add multiple browser threads, and at that point this dirty flag is
727727
necessary to avoid erratic behavior when animating. Try removing it
728728
later and see for yourself!
729729

@@ -777,7 +777,7 @@ class Chrome:
777777
return False
778778
```
779779

780-
And the `Tab` should also set this bit after running `render`:
780+
And the `Tab` should also set this flag after running `render`:
781781

782782
``` {.python dropline=set_needs_raster_and_draw}
783783
class Tab:
@@ -942,7 +942,7 @@ later, they might end up delayed by many, many frames.
942942

943943
Luckily, rendering is special in that it never makes sense to have two
944944
rendering tasks in a row, since the page wouldn't have changed in
945-
between. To avoid having two rendering tasks we'll add a dirty bit
945+
between. To avoid having two rendering tasks we'll add a dirty flag
946946
called `needs_animation_frame` to the `Browser` that indicates
947947
whether a rendering task actually needs to be scheduled:
948948

@@ -979,7 +979,7 @@ class Browser:
979979
```
980980

981981
Note that `set_needs_animation_frame` will only actually set the dirty
982-
bit if called from the active tab. This guarantees that inactive tabs
982+
flag if called from the active tab. This guarantees that inactive tabs
983983
can't interfere with active tabs. Besides preventing scripts from
984984
scheduling too many animation frames, this system also makes sure that
985985
if our browser consistently runs slower than 30 frames per second, we

src/lab16.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ def set_dependencies(self, dependencies):
8484
dependency.invalidations.add(self)
8585
self.frozen_dependencies = True
8686

87-
def set_ancestor_dirty_bits(self):
87+
def set_ancestor_dirty_flags(self):
8888
parent = self.parent
8989
while parent and not parent.has_dirty_descendants:
9090
parent.has_dirty_descendants = True
@@ -93,12 +93,12 @@ def set_ancestor_dirty_bits(self):
9393
def mark(self):
9494
if self.dirty: return
9595
self.dirty = True
96-
self.set_ancestor_dirty_bits()
96+
self.set_ancestor_dirty_flags()
9797

9898
def notify(self):
9999
for field in self.invalidations:
100100
field.mark()
101-
self.set_ancestor_dirty_bits()
101+
self.set_ancestor_dirty_flags()
102102

103103
def set(self, value):
104104
# if self.value != None:

0 commit comments

Comments
 (0)