@@ -2,16 +2,34 @@ mod utils;
2
2
3
3
use std:: fmt;
4
4
use wasm_bindgen:: prelude:: * ;
5
- extern crate js_sys;
6
- // extern crate web_sys;
5
+ // extern crate js_sys;
6
+ extern crate web_sys;
7
+ use web_sys:: console;
7
8
8
9
// A macro to provide `println!(..)`-style syntax for `console.log` logging.
9
10
// macro_rules! log {
10
11
// ($( $t:tt)* ) => {
11
- // web_sys:: console::log_1(&format!( $( $t )*).into());
12
+ // console::log_1(&format!( $( $t )*).into());
12
13
// };
13
14
// }
14
15
16
+ pub struct Timer < ' a > {
17
+ name : & ' a str ,
18
+ }
19
+
20
+ impl < ' a > Timer < ' a > {
21
+ pub fn new ( name : & ' a str ) -> Timer < ' a > {
22
+ console:: time_with_label ( name) ;
23
+ Timer { name }
24
+ }
25
+ }
26
+
27
+ impl < ' a > Drop for Timer < ' a > {
28
+ fn drop ( & mut self ) {
29
+ console:: time_end_with_label ( self . name ) ;
30
+ }
31
+ }
32
+
15
33
#[ wasm_bindgen]
16
34
#[ repr( u8 ) ]
17
35
#[ derive( Clone , Copy , Debug , PartialEq , Eq ) ]
@@ -42,18 +60,62 @@ impl Universe {
42
60
}
43
61
44
62
fn live_neighbor_count ( & self , row : u32 , column : u32 ) -> u8 {
63
+ // let mut count = 0;
64
+ // for delta_row in [self.height - 1, 0, 1].iter().cloned() {
65
+ // for delta_col in [self.width - 1, 0, 1].iter().cloned() {
66
+ // if delta_row == 0 && delta_col == 0 {
67
+ // continue;
68
+ // }
69
+ // let neighbor_row = (row + delta_row) % self.height;
70
+ // let neighbor_col = (column + delta_col) % self.width;
71
+ // let idx = self.get_index(neighbor_row, neighbor_col);
72
+ // count += self.cells[idx] as u8;
73
+ // }
74
+ // }
75
+ // count
76
+
45
77
let mut count = 0 ;
46
- for delta_row in [ self . height - 1 , 0 , 1 ] . iter ( ) . cloned ( ) {
47
- for delta_col in [ self . width - 1 , 0 , 1 ] . iter ( ) . cloned ( ) {
48
- if delta_row == 0 && delta_col == 0 {
49
- continue ;
50
- }
51
- let neighbor_row = ( row + delta_row) % self . height ;
52
- let neighbor_col = ( column + delta_col) % self . width ;
53
- let idx = self . get_index ( neighbor_row, neighbor_col) ;
54
- count += self . cells [ idx] as u8 ;
55
- }
56
- }
78
+
79
+ let north = if row == 0 { self . height - 1 } else { row - 1 } ;
80
+
81
+ let south = if row == self . height - 1 { 0 } else { row + 1 } ;
82
+
83
+ let west = if column == 0 {
84
+ self . width - 1
85
+ } else {
86
+ column - 1
87
+ } ;
88
+
89
+ let east = if column == self . width - 1 {
90
+ 0
91
+ } else {
92
+ column + 1
93
+ } ;
94
+
95
+ let nw = self . get_index ( north, west) ;
96
+ count += self . cells [ nw] as u8 ;
97
+
98
+ let n = self . get_index ( north, column) ;
99
+ count += self . cells [ n] as u8 ;
100
+
101
+ let ne = self . get_index ( north, east) ;
102
+ count += self . cells [ ne] as u8 ;
103
+
104
+ let w = self . get_index ( row, west) ;
105
+ count += self . cells [ w] as u8 ;
106
+
107
+ let e = self . get_index ( row, east) ;
108
+ count += self . cells [ e] as u8 ;
109
+
110
+ let sw = self . get_index ( south, west) ;
111
+ count += self . cells [ sw] as u8 ;
112
+
113
+ let s = self . get_index ( south, column) ;
114
+ count += self . cells [ s] as u8 ;
115
+
116
+ let se = self . get_index ( south, east) ;
117
+ count += self . cells [ se] as u8 ;
118
+
57
119
count
58
120
}
59
121
@@ -75,44 +137,53 @@ impl Universe {
75
137
#[ wasm_bindgen]
76
138
impl Universe {
77
139
pub fn tick ( & mut self ) {
78
- let mut next = self . cells . clone ( ) ;
79
-
80
- for row in 0 ..self . height {
81
- for col in 0 ..self . width {
82
- let idx = self . get_index ( row, col) ;
83
- let cell = self . cells [ idx] ;
84
- let live_neighbors = self . live_neighbor_count ( row, col) ;
85
-
86
- // log!(
87
- // "cell[{}, {}] is initially {:?} and has {} live neighbors",
88
- // row,
89
- // col,
90
- // cell,
91
- // live_neighbors
92
- // );
93
-
94
- let next_cell = match ( cell, live_neighbors) {
95
- // Rule 1: Any live cell with fewer than two live neighbours
96
- // dies, as if caused by underpopulation.
97
- ( Cell :: Alive , x) if x < 2 => Cell :: Dead ,
98
- // Rule 2: Any live cell with two or three live neighbours
99
- // lives on to the next generation.
100
- ( Cell :: Alive , 2 ) | ( Cell :: Alive , 3 ) => Cell :: Alive ,
101
- // Rule 3: Any live cell with more than three live
102
- // neighbours dies, as if by overpopulation.
103
- ( Cell :: Alive , x) if x > 3 => Cell :: Dead ,
104
- // Rule 4: Any dead cell with exactly three live neighbours
105
- // becomes a live cell, as if by reproduction.
106
- ( Cell :: Dead , 3 ) => Cell :: Alive ,
107
- // All other cells remain in the same state.
108
- ( otherwise, _) => otherwise,
109
- } ;
110
-
111
- // log!("it becomes {:?}", next_cell);
112
-
113
- next[ idx] = next_cell;
140
+ let _timer = Timer :: new ( "Universe::tick" ) ;
141
+ let mut next = {
142
+ let _timer = Timer :: new ( "allocate next cells" ) ; // allocate next cells: 0.046875 ms
143
+ self . cells . clone ( )
144
+ } ;
145
+
146
+ {
147
+ let _timer = Timer :: new ( "new generation" ) ; // new generation: 0.8623046875 ms
148
+ // the vast majority of time is spent actually calculating the next generation of cells.
149
+ for row in 0 ..self . height {
150
+ for col in 0 ..self . width {
151
+ let idx = self . get_index ( row, col) ;
152
+ let cell = self . cells [ idx] ;
153
+ let live_neighbors = self . live_neighbor_count ( row, col) ;
154
+
155
+ // log!(
156
+ // "cell[{}, {}] is initially {:?} and has {} live neighbors",
157
+ // row,
158
+ // col,
159
+ // cell,
160
+ // live_neighbors
161
+ // );
162
+
163
+ let next_cell = match ( cell, live_neighbors) {
164
+ // Rule 1: Any live cell with fewer than two live neighbours
165
+ // dies, as if caused by underpopulation.
166
+ ( Cell :: Alive , x) if x < 2 => Cell :: Dead ,
167
+ // Rule 2: Any live cell with two or three live neighbours
168
+ // lives on to the next generation.
169
+ ( Cell :: Alive , 2 ) | ( Cell :: Alive , 3 ) => Cell :: Alive ,
170
+ // Rule 3: Any live cell with more than three live
171
+ // neighbours dies, as if by overpopulation.
172
+ ( Cell :: Alive , x) if x > 3 => Cell :: Dead ,
173
+ // Rule 4: Any dead cell with exactly three live neighbours
174
+ // becomes a live cell, as if by reproduction.
175
+ ( Cell :: Dead , 3 ) => Cell :: Alive ,
176
+ // All other cells remain in the same state.
177
+ ( otherwise, _) => otherwise,
178
+ } ;
179
+
180
+ // log!("it becomes {:?}", next_cell);
181
+
182
+ next[ idx] = next_cell;
183
+ }
114
184
}
115
185
}
186
+ let _timer = Timer :: new ( "free old cells" ) ; // free old cells: 0.041015625 ms
116
187
self . cells = next;
117
188
}
118
189
@@ -122,8 +193,9 @@ impl Universe {
122
193
let height = 64 ;
123
194
124
195
let cells = ( 0 ..width * height)
125
- . map ( |_i| {
126
- if js_sys:: Math :: random ( ) < 0.5 {
196
+ . map ( |i| {
197
+ // if js_sys::Math::random() < 0.5 {
198
+ if i % 2 == 0 || i % 7 == 0 {
127
199
Cell :: Alive
128
200
} else {
129
201
Cell :: Dead
0 commit comments