├── empty_project
├── debug.keystore.pass.txt
├── main
│ └── main.collection
├── debug.keystore
├── input
│ └── game.input_binding
├── manifest.private.der
├── manifest.public.der
├── .gitignore
└── game.project
├── size.png
├── bob_size.png
├── bundle_size.png
├── editor_size.png
├── engine_size.png
├── size_small.png
├── legacy_engine_size.png
├── legacy_engine_size_stripped.png
├── .gitignore
├── .github
└── workflows
│ └── check_size.yaml
├── README.md
├── bob_report.csv
├── index.html
├── editor_report.csv
├── size-analyzer
├── index.html
├── README.md
├── css
│ └── style.css
├── js
│ └── csv-parser.js
└── analysis_index.json
├── css
└── dashboard.css
├── bundle_report.csv
├── engine_report.csv
├── legacy_engine_report.csv
├── check_size.py
├── releases.json
└── js
└── dashboard.js
/empty_project/debug.keystore.pass.txt:
--------------------------------------------------------------------------------
1 | android
--------------------------------------------------------------------------------
/empty_project/main/main.collection:
--------------------------------------------------------------------------------
1 | name: "main"
2 | scale_along_z: 0
3 |
--------------------------------------------------------------------------------
/size.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/defold/build-size/HEAD/size.png
--------------------------------------------------------------------------------
/bob_size.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/defold/build-size/HEAD/bob_size.png
--------------------------------------------------------------------------------
/bundle_size.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/defold/build-size/HEAD/bundle_size.png
--------------------------------------------------------------------------------
/editor_size.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/defold/build-size/HEAD/editor_size.png
--------------------------------------------------------------------------------
/engine_size.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/defold/build-size/HEAD/engine_size.png
--------------------------------------------------------------------------------
/size_small.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/defold/build-size/HEAD/size_small.png
--------------------------------------------------------------------------------
/legacy_engine_size.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/defold/build-size/HEAD/legacy_engine_size.png
--------------------------------------------------------------------------------
/empty_project/debug.keystore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/defold/build-size/HEAD/empty_project/debug.keystore
--------------------------------------------------------------------------------
/empty_project/input/game.input_binding:
--------------------------------------------------------------------------------
1 | mouse_trigger {
2 | input: MOUSE_BUTTON_1
3 | action: "touch"
4 | }
5 |
--------------------------------------------------------------------------------
/legacy_engine_size_stripped.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/defold/build-size/HEAD/legacy_engine_size_stripped.png
--------------------------------------------------------------------------------
/empty_project/manifest.private.der:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/defold/build-size/HEAD/empty_project/manifest.private.der
--------------------------------------------------------------------------------
/empty_project/manifest.public.der:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/defold/build-size/HEAD/empty_project/manifest.public.der
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | bob*.jar
2 | bundle_output
3 |
4 | # Allow our bob.jar analysis folder and its CSV files
5 | !size-analyzer/bob.jar/
6 | !size-analyzer/bob.jar/*.csv
--------------------------------------------------------------------------------
/empty_project/.gitignore:
--------------------------------------------------------------------------------
1 | /.internal
2 | /build
3 | .externalToolBuilders
4 | .DS_Store
5 | Thumbs.db
6 | .lock-wscript
7 | *.pyc
8 | .project
9 | .cproject
10 | builtins
--------------------------------------------------------------------------------
/empty_project/game.project:
--------------------------------------------------------------------------------
1 | [bootstrap]
2 | main_collection = /main/main.collectionc
3 |
4 | [script]
5 | shared_state = 1
6 |
7 | [display]
8 | width = 960
9 | height = 640
10 |
11 | [android]
12 | input_method = HiddenInputField
--------------------------------------------------------------------------------
/.github/workflows/check_size.yaml:
--------------------------------------------------------------------------------
1 | name: Check engine size
2 |
3 | on:
4 | push:
5 | schedule:
6 | - cron: 0 2 * * *
7 | jobs:
8 | check_size:
9 | runs-on: macOS-latest
10 | steps:
11 | - name: Checkout
12 | uses: actions/checkout@v3
13 |
14 | - name: Setup Python
15 | uses: actions/setup-python@v4
16 | with:
17 | python-version: '3.10'
18 |
19 | - name: Setup Java
20 | uses: actions/setup-java@v3
21 | with:
22 | java-version: '21.0.5+11.0.LTS'
23 | distribution: 'temurin'
24 |
25 | - name: Install Python dependencies
26 | run: |
27 | python -m pip install -U pip
28 | python -m pip install -U matplotlib
29 |
30 | - name: Install bloaty (for analyze_builds.py)
31 | run: |
32 | # Install bloaty using Homebrew (macOS)
33 | brew install bloaty
34 |
35 | - name: Check size
36 | run: |
37 | python check_size.py
38 |
39 | - name: Run detailed analysis
40 | run: |
41 | python analyze_builds.py
42 |
43 | - name: Check github token
44 | id: checktoken
45 | shell: bash
46 | env:
47 | SERVICES_GITHUB_TOKEN: ${{ secrets.SERVICES_GITHUB_TOKEN }}
48 | run: |
49 | if [ "${SERVICES_GITHUB_TOKEN}" == "" ]; then
50 | # echo "::set-output name=token_exists::false"
51 | echo "token_exists=false" >> $GITHUB_OUTPUT
52 | echo "token_exists::false"
53 | else
54 | # echo "::set-output name=token_exists::true"
55 | echo "token_exists=true" >> $GITHUB_OUTPUT
56 | echo "token_exists::true"
57 | fi
58 |
59 | - name: Commit changes
60 | if: ${{ steps.checktoken.outputs.token_exists == 'true' }}
61 | shell: bash
62 | env:
63 | SERVICES_GITHUB_TOKEN: ${{ secrets.SERVICES_GITHUB_TOKEN }}
64 | run: |
65 | git add -A
66 | git commit -m "Generated new size report and graph [skip ci]" bundle_size.png engine_size.png engine_report.csv bob_size.png bob_report.csv editor_size.png editor_report.csv bundle_report.csv releases.json size-analyzer/
67 | git push "https://${SERVICES_GITHUB_TOKEN}@github.com/defold/build-size.git" HEAD
68 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | [](https://github.com/defold/build-size/actions/workflows/check_size.yaml)
2 |
3 | # Defold engine and application bundle size plot
4 | This project will plot the size of the Defold engine (aka dmengine) as well as the size of a complete Defold game bundle for all supported platforms and versions.
5 |
6 | **Live Dashboard**: https://defold.com/build-size
7 | **Interactive Size Analyzer**: https://defold.com/build-size/size-analyzer/
8 |
9 | ## Bundle size
10 | The bundle size is measured as:
11 |
12 | * Android - Size of .aab file containing one CPU architecture
13 | * iOS - Size of .ipa file
14 | * macOS - Size of .app file
15 | * Windows - Size of zip archive with engine, required library files and game archive
16 | * Linux - Size of zip archive with engine, required library files and game archive
17 | * HTML5 - Size of zip archive with either .wasm or .asm.js engine, required library files and game archive
18 |
19 | 
20 |
21 |
22 | ## Engine size
23 | This is the size of a release version of the Defold engine executable/library:
24 |
25 | 
26 |
27 | ## Editor size
28 | This is the size of the release versions of the Defold editor (including bob.jar):
29 |
30 | 
31 |
32 | ## Bob size
33 | This is the size of a release version of the our command line build interface (bob.jar):
34 |
35 | 
36 |
37 |
38 | ## Deprecated graphs
39 | Graph of versions stripped of debug symbols:
40 |
41 | 
42 |
43 | History of versions:
44 |
45 | 
46 |
47 | NOTE: In both of the deprecated graphs above the measurements show the size of the .apk file for Android and for all other platforms the size of the engine itself.
48 |
49 | # Requirements
50 | If you wish to run this script locally you need to have the following things installed:
51 |
52 | * Python 3 (developed with 3.10.5)
53 | * Java 11.0.*
54 | * [matlibplot](http://matplotlib.org/) (Install with `python3 -m pip install matplotlib`)
55 |
56 | # Usage
57 | Run [check_size.py](check_size.py):
58 |
59 | python3 check_size.py
60 |
61 | It will generate these files:
62 | * [releases.json](releases.json)
63 | * [engine_report.csv](engine_report.csv)
64 | * [bundle_report.csv](bundle_report.csv)
65 | * [bob_report.csv](bob_report.csv)
66 | * [editor_report.csv](editor_report.csv)
67 | * [engine_size.png](engine_size.png)
68 | * [bundle_size.png](bundle_size.png)
69 | * [bob_size.png](bob_size.png)
70 | * [editor_size.png](editor_size.png)
71 |
72 |
73 | To include a new version of dmengine in the report you need to [add an entry in the releases list in releases.json](https://github.com/defold/build-size/blob/master/releases.json). The sha1 of the version you wish to add can be seen at [d.defold.com](d.defold.com).
74 |
75 | The project will automatically generate new graphs and report files when a file in the project is changed.
76 |
--------------------------------------------------------------------------------
/bob_report.csv:
--------------------------------------------------------------------------------
1 | VERSION,x86_64-macos
2 | 1.2.38,0
3 | 1.2.39,0
4 | 1.2.40,0
5 | 1.2.41,0
6 | 1.2.42,0
7 | 1.2.43,0
8 | 1.2.44,0
9 | 1.2.45,0
10 | 1.2.46,0
11 | 1.2.47,0
12 | 1.2.48,0
13 | 1.2.49,0
14 | 1.2.50,0
15 | 1.2.51,0
16 | 1.2.52,0
17 | 1.2.53,0
18 | 1.2.54,0
19 | 1.2.55,0
20 | 1.2.56,0
21 | 1.2.57,0
22 | 1.2.58,0
23 | 1.2.59,0
24 | 1.2.60,0
25 | 1.2.61,0
26 | 1.2.62,0
27 | 1.2.63,0
28 | 1.2.64,0
29 | 1.2.65,0
30 | 1.2.66,0
31 | 1.2.67,0
32 | 1.2.68,0
33 | 1.2.69,0
34 | 1.2.70,0
35 | 1.2.71,0
36 | 1.2.72,0
37 | 1.2.73,0
38 | 1.2.74,0
39 | 1.2.75,0
40 | 1.2.76,0
41 | 1.2.77,0
42 | 1.2.78,0
43 | 1.2.79,0
44 | 1.2.80,0
45 | 1.2.81,0
46 | 1.2.82,0
47 | 1.2.83,0
48 | 1.2.84,0
49 | 1.2.85,0
50 | 1.2.86,0
51 | 1.2.87,0
52 | 1.2.88,0
53 | 1.2.89,0
54 | 1.2.90,0
55 | 1.2.91,0
56 | 1.2.92,0
57 | 1.2.93,0
58 | 1.2.94,0
59 | 1.2.95,0
60 | 1.2.96,0
61 | 1.2.97,0
62 | 1.2.98,0
63 | 1.2.99,0
64 | 1.2.100,0
65 | 1.2.101,0
66 | 1.2.102,0
67 | 1.2.103,0
68 | 1.2.104,0
69 | 1.2.105,0
70 | 1.2.106,0
71 | 1.2.107,0
72 | 1.2.108,0
73 | 1.2.109,0
74 | 1.2.110,0
75 | 1.2.111,0
76 | 1.2.112,0
77 | 1.2.113,0
78 | 1.2.114,0
79 | 1.2.115,0
80 | 1.2.116,0
81 | 1.2.117,0
82 | 1.2.118,0
83 | 1.2.119,0
84 | 1.2.120,0
85 | 1.2.121,0
86 | 1.2.122,0
87 | 1.2.123,0
88 | 1.2.124,0
89 | 1.2.125,0
90 | 1.2.126,0
91 | 1.2.127,0
92 | 1.2.128,0
93 | 1.2.129,0
94 | 1.2.130,0
95 | 1.2.131,0
96 | 1.2.132,0
97 | 1.2.133,0
98 | 1.2.134,0
99 | 1.2.135,0
100 | 1.2.136,0
101 | 1.2.137,0
102 | 1.2.138,0
103 | 1.2.139,0
104 | 1.2.140,0
105 | 1.2.141,0
106 | 1.2.142,0
107 | 1.2.143,0
108 | 1.2.144,0
109 | 1.2.145,0
110 | 1.2.146,0
111 | 1.2.147,0
112 | 1.2.148,0
113 | 1.2.149,0
114 | 1.2.150,0
115 | 1.2.151,0
116 | 1.2.152,0
117 | 1.2.153,0
118 | 1.2.154,0
119 | 1.2.155,0
120 | 1.2.156,0
121 | 1.2.157,0
122 | 1.2.158,0
123 | 1.2.159,0
124 | 1.2.160,0
125 | 1.2.161,0
126 | 1.2.162,0
127 | 1.2.163,0
128 | 1.2.164,0
129 | 1.2.165,0
130 | 1.2.166,107064052
131 | 1.2.167,107078765
132 | 1.2.168,107086636
133 | 1.2.169,107288572
134 | 1.2.170,135803529
135 | 1.2.171,135803529
136 | 1.2.172,135597602
137 | 1.2.173,133654536
138 | 1.2.174,133654536
139 | 1.2.175,134616479
140 | 1.2.176,134652129
141 | 1.2.177,134678844
142 | 1.2.178,134678844
143 | 1.2.179,134096242
144 | 1.2.180,134096242
145 | 1.2.181,135181408
146 | 1.2.182,132069097
147 | 1.2.183,131915149
148 | 1.2.184,131933875
149 | 1.2.185,134226201
150 | 1.2.186,134257274
151 | 1.2.187,134273270
152 | 1.2.188,133923330
153 | 1.2.189,134043599
154 | 1.2.190,132934472
155 | 1.2.191,132706312
156 | 1.2.192,132750708
157 | 1.3.0,130366147
158 | 1.3.1,130514885
159 | 1.3.2,131498227
160 | 1.3.3,131498227
161 | 1.3.4,131435613
162 | 1.3.5,134420551
163 | 1.3.6,132902440
164 | 1.3.7,133802830
165 | 1.4.0,133513289
166 | 1.4.1,136543267
167 | 1.4.2,136741886
168 | 1.4.3,141953878
169 | 1.4.4,147706730
170 | 1.4.5,147133218
171 | 1.4.6,144314016
172 | 1.4.7,139058992
173 | 1.4.8,139761626
174 | 1.5.0,142383446
175 | 1.6.0,142291689
176 | 1.6.1,151056273
177 | 1.6.2,152415095
178 | 1.6.3,142057068
179 | 1.6.4,142391490
180 | 1.7.0,142750407
181 | 1.8.0,143038403
182 | 1.8.1,143132178
183 | 1.9.0,144051552
184 | 1.9.1,144870024
185 | 1.9.2,144734030
186 | 1.9.3,145048368
187 | 1.9.4,156849600
188 | 1.9.5,159571915
189 | 1.9.6,154545456
190 | 1.9.7,165631787
191 | 1.9.8,177701000
192 | 1.10.0,183379180
193 | 1.10.1,183232147
194 | 1.10.2,187512556
195 | 1.10.3,187524563
196 | 1.10.4,191077485
197 | 1.11.0,191070974
198 | 1.11.1,191344503
199 | 1.11.2,191406260
200 |
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Defold Component Size Dashboard
7 |
8 |
9 |
10 |
11 |
12 |
13 |
17 |
18 |
19 |
34 |
35 |
36 |
51 |
52 |
53 |
68 |
69 |
70 |
85 |
86 |
89 |
90 |
91 |
92 |
93 |
--------------------------------------------------------------------------------
/editor_report.csv:
--------------------------------------------------------------------------------
1 | VERSION,x86_64-macos,x86_64-win32,x86_64-linux,arm64-macos
2 | 1.2.38,0,0,0,0
3 | 1.2.39,0,0,0,0
4 | 1.2.40,0,0,0,0
5 | 1.2.41,0,0,0,0
6 | 1.2.42,0,0,0,0
7 | 1.2.43,0,0,0,0
8 | 1.2.44,0,0,0,0
9 | 1.2.45,0,0,0,0
10 | 1.2.46,0,0,0,0
11 | 1.2.47,0,0,0,0
12 | 1.2.48,0,0,0,0
13 | 1.2.49,0,0,0,0
14 | 1.2.50,0,0,0,0
15 | 1.2.51,0,0,0,0
16 | 1.2.52,0,0,0,0
17 | 1.2.53,0,0,0,0
18 | 1.2.54,0,0,0,0
19 | 1.2.55,0,0,0,0
20 | 1.2.56,0,0,0,0
21 | 1.2.57,0,0,0,0
22 | 1.2.58,0,0,0,0
23 | 1.2.59,0,0,0,0
24 | 1.2.60,0,0,0,0
25 | 1.2.61,0,0,0,0
26 | 1.2.62,0,0,0,0
27 | 1.2.63,0,0,0,0
28 | 1.2.64,0,0,0,0
29 | 1.2.65,0,0,0,0
30 | 1.2.66,0,0,0,0
31 | 1.2.67,0,0,0,0
32 | 1.2.68,0,0,0,0
33 | 1.2.69,0,0,0,0
34 | 1.2.70,0,0,0,0
35 | 1.2.71,0,0,0,0
36 | 1.2.72,0,0,0,0
37 | 1.2.73,0,0,0,0
38 | 1.2.74,0,0,0,0
39 | 1.2.75,0,0,0,0
40 | 1.2.76,0,0,0,0
41 | 1.2.77,0,0,0,0
42 | 1.2.78,0,0,0,0
43 | 1.2.79,0,0,0,0
44 | 1.2.80,0,0,0,0
45 | 1.2.81,0,0,0,0
46 | 1.2.82,0,0,0,0
47 | 1.2.83,0,0,0,0
48 | 1.2.84,0,0,0,0
49 | 1.2.85,0,0,0,0
50 | 1.2.86,0,0,0,0
51 | 1.2.87,0,0,0,0
52 | 1.2.88,0,0,0,0
53 | 1.2.89,0,0,0,0
54 | 1.2.90,0,0,0,0
55 | 1.2.91,0,0,0,0
56 | 1.2.92,0,0,0,0
57 | 1.2.93,0,0,0,0
58 | 1.2.94,0,0,0,0
59 | 1.2.95,0,0,0,0
60 | 1.2.96,0,0,0,0
61 | 1.2.97,0,0,0,0
62 | 1.2.98,0,0,0,0
63 | 1.2.99,0,0,0,0
64 | 1.2.100,0,0,0,0
65 | 1.2.101,0,0,0,0
66 | 1.2.102,0,0,0,0
67 | 1.2.103,0,0,0,0
68 | 1.2.104,0,0,0,0
69 | 1.2.105,0,0,0,0
70 | 1.2.106,0,0,0,0
71 | 1.2.107,0,0,0,0
72 | 1.2.108,0,0,0,0
73 | 1.2.109,0,0,0,0
74 | 1.2.110,0,0,0,0
75 | 1.2.111,0,0,0,0
76 | 1.2.112,0,0,0,0
77 | 1.2.113,0,0,0,0
78 | 1.2.114,0,0,0,0
79 | 1.2.115,0,0,0,0
80 | 1.2.116,0,0,0,0
81 | 1.2.117,0,0,0,0
82 | 1.2.118,0,0,0,0
83 | 1.2.119,0,0,0,0
84 | 1.2.120,0,0,0,0
85 | 1.2.121,0,0,0,0
86 | 1.2.122,0,0,0,0
87 | 1.2.123,0,0,0,0
88 | 1.2.124,0,0,0,0
89 | 1.2.125,0,0,0,0
90 | 1.2.126,0,0,0,0
91 | 1.2.127,0,0,0,0
92 | 1.2.128,0,0,0,0
93 | 1.2.129,0,0,0,0
94 | 1.2.130,0,0,0,0
95 | 1.2.131,0,0,0,0
96 | 1.2.132,0,0,0,0
97 | 1.2.133,0,0,0,0
98 | 1.2.134,0,0,0,0
99 | 1.2.135,0,0,0,0
100 | 1.2.136,0,0,0,0
101 | 1.2.137,0,0,0,0
102 | 1.2.138,0,0,0,0
103 | 1.2.139,0,0,0,0
104 | 1.2.140,0,0,0,0
105 | 1.2.141,0,0,0,0
106 | 1.2.142,0,0,0,0
107 | 1.2.143,0,0,0,0
108 | 1.2.144,0,0,0,0
109 | 1.2.145,0,0,0,0
110 | 1.2.146,0,0,0,0
111 | 1.2.147,0,0,0,0
112 | 1.2.148,0,0,0,0
113 | 1.2.149,0,0,0,0
114 | 1.2.150,0,0,0,0
115 | 1.2.151,0,0,0,0
116 | 1.2.152,0,0,0,0
117 | 1.2.153,0,0,0,0
118 | 1.2.154,0,0,0,0
119 | 1.2.155,0,0,0,0
120 | 1.2.156,0,0,0,0
121 | 1.2.157,0,0,0,0
122 | 1.2.158,0,0,0,0
123 | 1.2.159,0,0,0,0
124 | 1.2.160,0,0,0,0
125 | 1.2.161,0,0,0,0
126 | 1.2.162,0,0,0,0
127 | 1.2.163,0,0,0,0
128 | 1.2.164,0,0,0,0
129 | 1.2.165,0,0,0,0
130 | 1.2.166,0,379211064,389782411,0
131 | 1.2.167,0,379233953,389806827,0
132 | 1.2.168,0,379247672,389820694,0
133 | 1.2.169,0,380250261,390854804,0
134 | 1.2.170,0,412104755,422618946,0
135 | 1.2.171,0,401842184,411750125,0
136 | 1.2.172,0,0,0,0
137 | 1.2.173,0,0,0,0
138 | 1.2.174,0,0,0,0
139 | 1.2.175,0,0,0,0
140 | 1.2.176,0,0,0,0
141 | 1.2.177,0,0,0,0
142 | 1.2.178,0,0,0,0
143 | 1.2.179,0,0,0,0
144 | 1.2.180,0,0,0,0
145 | 1.2.181,0,0,0,0
146 | 1.2.182,0,0,0,0
147 | 1.2.183,0,0,0,0
148 | 1.2.184,0,0,0,0
149 | 1.2.185,0,0,0,0
150 | 1.2.186,0,0,0,0
151 | 1.2.187,0,0,0,0
152 | 1.2.188,0,0,0,0
153 | 1.2.189,0,0,0,0
154 | 1.2.190,0,0,0,0
155 | 1.2.191,0,0,0,0
156 | 1.2.192,0,0,0,0
157 | 1.3.0,0,316587682,338349627,0
158 | 1.3.1,0,316938412,338701661,0
159 | 1.3.2,0,317929250,339693745,0
160 | 1.3.3,0,317929250,339693745,0
161 | 1.3.4,0,318865565,339246852,0
162 | 1.3.5,0,323399058,343681626,0
163 | 1.3.6,303920706,321976637,340424381,0
164 | 1.3.7,305512193,323659539,342069010,0
165 | 1.4.0,305704738,323415393,342046616,0
166 | 1.4.1,307442628,324990713,344815491,0
167 | 1.4.2,308844936,326502655,346331519,0
168 | 1.4.3,316487202,334328425,354158743,0
169 | 1.4.4,323940699,341762218,362593296,0
170 | 1.4.5,323505007,341407857,362239249,0
171 | 1.4.6,322872935,340695080,361990391,0
172 | 1.4.7,313592701,331450127,352746060,0
173 | 1.4.8,321992664,338251921,359643789,0
174 | 1.5.0,323375881,339339291,360742127,0
175 | 1.6.0,326986435,342744545,364207283,322581235
176 | 1.6.1,329405868,345323223,366736428,324936588
177 | 1.6.2,341084631,357483783,378523379,336171010
178 | 1.6.3,284665893,314023606,327550968,279489806
179 | 1.6.4,285094101,314690233,328378010,280206542
180 | 1.7.0,286264978,316252303,330627235,281533058
181 | 1.8.0,286516272,316722528,331062379,281639814
182 | 1.8.1,286856457,317066151,331522121,282217944
183 | 1.9.0,290008330,320997519,335119054,285241511
184 | 1.9.1,289404334,319961498,333862018,284642589
185 | 1.9.2,289316408,319791807,334100465,284519056
186 | 1.9.3,289622265,319994077,334255632,284708557
187 | 1.9.4,294665171,321761411,340243289,289312132
188 | 1.9.5,295075340,324640203,340518295,289633164
189 | 1.9.6,289570634,317850371,338526561,284317044
190 | 1.9.7,293365947,321755493,342283378,287955756
191 | 1.9.8,302517379,330869938,351385189,297200704
192 | 1.10.0,311274497,337796561,358415550,305636552
193 | 1.10.1,312700687,339344070,359475837,306903177
194 | 1.10.2,316313579,342956899,363072780,310436058
195 | 1.10.3,316291760,342991970,363212413,310706411
196 | 1.10.4,320350389,347038675,367398635,314697924
197 | 1.11.0,286014686,315139633,325208355,282740444
198 | 1.11.1,273229693,301547529,311445735,269977379
199 | 1.11.2,280441321,309384771,319429553,277216011
200 |
--------------------------------------------------------------------------------
/size-analyzer/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Defold Size Analyzer
7 |
8 |
9 |
10 |
11 |
12 |
16 |
17 |
18 |
19 | Platform:
20 |
21 |
22 |
23 |
24 |
25 | From version:
26 |
27 |
28 |
29 |
30 |
31 | To version:
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 | Change threshold: 50 bytes
40 |
41 |
42 |
43 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
Select platform and versions to begin comparison
64 |
65 |
66 |
67 |
68 | File Size
69 | VM Size
70 |
71 |
72 |
73 |
74 |
Legend
75 |
76 |
77 |
78 |
Size decreased (Left Side)
79 |
80 |
81 |
82 |
Size increased (Right Side)
83 |
84 |
85 |
86 | Shows cumulative change from the selected baseline version to the compare version.
87 | Use tabs above to switch between File Size and VM Size metrics.
88 | Click any file bar to see its detailed evolution timeline across all intermediate versions.
89 |
90 |
91 |
92 |
104 |
105 |
106 |
Comparison Details
107 |
108 |
109 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
--------------------------------------------------------------------------------
/css/dashboard.css:
--------------------------------------------------------------------------------
1 | /* Dashboard-specific styles */
2 |
3 | /* Chart sections */
4 | .chart-section {
5 | margin-bottom: 3rem;
6 | padding: 1.5rem;
7 | background: #fff;
8 | border-radius: 12px;
9 | box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
10 | border: 1px solid #e1e8ed;
11 | }
12 |
13 | .chart-header {
14 | margin-bottom: 1.5rem;
15 | border-bottom: 2px solid #f8f9fa;
16 | padding-bottom: 1rem;
17 | }
18 |
19 | .chart-header h2 {
20 | margin: 0 0 0.5rem 0;
21 | color: #2c3e50;
22 | font-size: 1.8rem;
23 | font-weight: 600;
24 | line-height: 1.2;
25 | }
26 |
27 | .chart-header p {
28 | margin: 0 0 1rem 0;
29 | color: #666;
30 | font-size: 1rem;
31 | line-height: 1.4;
32 | }
33 |
34 | /* Version controls */
35 | .version-control {
36 | margin-top: 1rem;
37 | display: flex;
38 | align-items: center;
39 | gap: 0.5rem;
40 | }
41 |
42 | .version-control label {
43 | font-size: 0.9rem;
44 | color: #555;
45 | font-weight: 500;
46 | }
47 |
48 | .version-control select {
49 | padding: 0.5rem 0.75rem;
50 | border: 1px solid #ddd;
51 | border-radius: 4px;
52 | background: white;
53 | font-size: 0.9rem;
54 | color: #333;
55 | cursor: pointer;
56 | transition: border-color 0.2s ease;
57 | }
58 |
59 | .version-control select:hover {
60 | border-color: #3498db;
61 | }
62 |
63 | .version-control select:focus {
64 | outline: none;
65 | border-color: #3498db;
66 | box-shadow: 0 0 0 2px rgba(52, 152, 219, 0.2);
67 | }
68 |
69 |
70 | /* Chart containers */
71 | .chart-container {
72 | min-height: 800px;
73 | background: #fafbfc;
74 | border-radius: 8px;
75 | padding: 1rem;
76 | }
77 |
78 | .chart-container > div {
79 | width: 100% !important;
80 | height: 800px !important;
81 | }
82 |
83 | /* Footer */
84 | footer {
85 | margin-top: 3rem;
86 | padding: 2rem 0;
87 | text-align: center;
88 | border-top: 1px solid #e1e8ed;
89 | }
90 |
91 | footer a {
92 | color: #3498db;
93 | text-decoration: none;
94 | font-weight: 500;
95 | font-size: 1.1rem;
96 | padding: 0.75rem 1.5rem;
97 | border: 2px solid #3498db;
98 | border-radius: 6px;
99 | transition: all 0.2s ease;
100 | display: inline-block;
101 | }
102 |
103 | footer a:hover {
104 | background: #3498db;
105 | color: white;
106 | transform: translateY(-1px);
107 | box-shadow: 0 4px 12px rgba(52, 152, 219, 0.3);
108 | }
109 |
110 | /* Loading states */
111 | .loading {
112 | display: flex;
113 | align-items: center;
114 | justify-content: center;
115 | height: 800px;
116 | color: #666;
117 | font-size: 1.1rem;
118 | }
119 |
120 | .loading::before {
121 | content: '';
122 | width: 20px;
123 | height: 20px;
124 | border: 2px solid #ddd;
125 | border-top: 2px solid #3498db;
126 | border-radius: 50%;
127 | animation: spin 1s linear infinite;
128 | margin-right: 0.75rem;
129 | }
130 |
131 | @keyframes spin {
132 | to { transform: rotate(360deg); }
133 | }
134 |
135 | /* Error states */
136 | .error {
137 | display: flex;
138 | align-items: center;
139 | justify-content: center;
140 | height: 800px;
141 | color: #e74c3c;
142 | font-size: 1.1rem;
143 | background: #fdf2f2;
144 | border-radius: 6px;
145 | border: 1px solid #fadbd8;
146 | }
147 |
148 | /* Responsive design */
149 | @media (max-width: 768px) {
150 | .container {
151 | padding: 1rem;
152 | }
153 |
154 | .chart-section {
155 | margin-bottom: 2rem;
156 | padding: 1rem;
157 | }
158 |
159 | .chart-header {
160 | margin-bottom: 1rem;
161 | padding-bottom: 0.75rem;
162 | }
163 |
164 | .chart-header h2 {
165 | font-size: 1.4rem;
166 | margin-bottom: 0.75rem;
167 | }
168 |
169 | .chart-header p {
170 | font-size: 0.9rem;
171 | margin-bottom: 0.75rem;
172 | }
173 |
174 | .version-control {
175 | margin-top: 0.75rem;
176 | flex-direction: column;
177 | align-items: flex-start;
178 | gap: 0.5rem;
179 | }
180 |
181 | .version-control label {
182 | font-size: 0.85rem;
183 | }
184 |
185 | .version-control select {
186 | width: 100%;
187 | max-width: 250px;
188 | padding: 0.6rem 0.75rem;
189 | }
190 |
191 | .chart-container {
192 | min-height: 500px;
193 | padding: 0.5rem;
194 | margin-top: 1rem;
195 | }
196 |
197 | .chart-container > div {
198 | height: 500px !important;
199 | }
200 |
201 | header h1 {
202 | font-size: 1.8rem;
203 | }
204 |
205 | header p {
206 | font-size: 0.9rem;
207 | }
208 | }
209 |
210 | @media (max-width: 480px) {
211 | .container {
212 | padding: 0.75rem;
213 | }
214 |
215 | .chart-section {
216 | margin-bottom: 1.5rem;
217 | padding: 0.75rem;
218 | }
219 |
220 | .chart-header h2 {
221 | font-size: 1.25rem;
222 | margin-bottom: 0.5rem;
223 | }
224 |
225 | .chart-header p {
226 | font-size: 0.85rem;
227 | margin-bottom: 0.5rem;
228 | }
229 |
230 | .version-control {
231 | margin-top: 0.5rem;
232 | }
233 |
234 | .version-control label {
235 | font-size: 0.8rem;
236 | }
237 |
238 | .version-control select {
239 | max-width: 100%;
240 | font-size: 0.85rem;
241 | padding: 0.5rem 0.6rem;
242 | }
243 |
244 | .chart-container {
245 | min-height: 400px;
246 | padding: 0.25rem;
247 | }
248 |
249 | .chart-container > div {
250 | height: 400px !important;
251 | }
252 |
253 | header h1 {
254 | font-size: 1.5rem;
255 | }
256 |
257 | header p {
258 | font-size: 0.85rem;
259 | }
260 |
261 | footer a {
262 | font-size: 1rem;
263 | padding: 0.6rem 1.2rem;
264 | }
265 | }
266 |
267 | /* Platform-specific colors for consistency */
268 | .platform-arm64-ios { color: #e74c3c; }
269 | .platform-arm64-android { color: #3498db; }
270 | .platform-armv7-android { color: #9b59b6; }
271 | .platform-x86_64-macos { color: #2ecc71; }
272 | .platform-js-web { color: #f39c12; }
273 | .platform-wasm-web { color: #e67e22; }
274 | .platform-x86_64-linux { color: #34495e; }
275 | .platform-x86-win32 { color: #16a085; }
276 | .platform-x86_64-win32 { color: #27ae60; }
277 | .platform-arm64-macos { color: #8e44ad; }
278 |
279 | /* Ensure Plotly tooltips remain readable with classic styling */
280 | .plotly .hovertext {
281 | background: #FFFFDD !important;
282 | color: black !important;
283 | border: 1px solid #333 !important;
284 | }
285 |
286 | .plotly .hovertext text {
287 | fill: black !important;
288 | }
289 |
290 | /* Override any colorful tooltip backgrounds */
291 | g.hovertext {
292 | background: #FFFFDD !important;
293 | }
294 |
295 | g.hovertext rect {
296 | fill: #FFFFDD !important;
297 | stroke: #333 !important;
298 | }
299 |
300 | g.hovertext text {
301 | fill: black !important;
302 | }
--------------------------------------------------------------------------------
/bundle_report.csv:
--------------------------------------------------------------------------------
1 | VERSION,arm64-ios,arm64-android,armv7-android,x86_64-macos,js-web,wasm-web,x86_64-linux,x86-win32,x86_64-win32,arm64-macos
2 | 1.2.38,0,0,0,0,0,0,0,0,0,0
3 | 1.2.39,0,0,0,0,0,0,0,0,0,0
4 | 1.2.40,0,0,0,0,0,0,0,0,0,0
5 | 1.2.41,0,0,0,0,0,0,0,0,0,0
6 | 1.2.42,0,0,0,0,0,0,0,0,0,0
7 | 1.2.43,0,0,0,0,0,0,0,0,0,0
8 | 1.2.44,0,0,0,0,0,0,0,0,0,0
9 | 1.2.45,0,0,0,0,0,0,0,0,0,0
10 | 1.2.46,0,0,0,0,0,0,0,0,0,0
11 | 1.2.47,0,0,0,0,0,0,0,0,0,0
12 | 1.2.48,0,0,0,0,0,0,0,0,0,0
13 | 1.2.49,0,0,0,0,0,0,0,0,0,0
14 | 1.2.50,0,0,0,0,0,0,0,0,0,0
15 | 1.2.51,0,0,0,0,0,0,0,0,0,0
16 | 1.2.52,0,0,0,0,0,0,0,0,0,0
17 | 1.2.53,0,0,0,0,0,0,0,0,0,0
18 | 1.2.54,0,0,0,0,0,0,0,0,0,0
19 | 1.2.55,0,0,0,0,0,0,0,0,0,0
20 | 1.2.56,0,0,0,0,0,0,0,0,0,0
21 | 1.2.57,0,0,0,0,0,0,0,0,0,0
22 | 1.2.58,0,0,0,0,0,0,0,0,0,0
23 | 1.2.59,0,0,0,0,0,0,0,0,0,0
24 | 1.2.60,0,0,0,0,0,0,0,0,0,0
25 | 1.2.61,0,0,0,0,0,0,0,0,0,0
26 | 1.2.62,0,0,0,0,0,0,0,0,0,0
27 | 1.2.63,0,0,0,0,0,0,0,0,0,0
28 | 1.2.64,0,0,0,0,0,0,0,0,0,0
29 | 1.2.65,0,0,0,0,0,0,0,0,0,0
30 | 1.2.66,0,0,0,0,0,0,0,0,0,0
31 | 1.2.67,0,0,0,0,0,0,0,0,0,0
32 | 1.2.68,0,0,0,0,0,0,0,0,0,0
33 | 1.2.69,0,0,0,0,0,0,0,0,0,0
34 | 1.2.70,0,0,0,0,0,0,0,0,0,0
35 | 1.2.71,0,0,0,0,0,0,0,0,0,0
36 | 1.2.72,0,0,0,0,0,0,0,0,0,0
37 | 1.2.73,0,0,0,0,0,0,0,0,0,0
38 | 1.2.74,0,0,0,0,0,0,0,0,0,0
39 | 1.2.75,0,0,0,0,0,0,0,0,0,0
40 | 1.2.76,0,0,0,0,0,0,0,0,0,0
41 | 1.2.77,0,0,0,0,0,0,0,0,0,0
42 | 1.2.78,0,0,0,0,0,0,0,0,0,0
43 | 1.2.79,0,0,0,0,0,0,0,0,0,0
44 | 1.2.80,0,0,0,0,0,0,0,0,0,0
45 | 1.2.81,0,0,0,0,0,0,0,0,0,0
46 | 1.2.82,0,0,0,0,0,0,0,0,0,0
47 | 1.2.83,0,0,0,0,0,0,0,0,0,0
48 | 1.2.84,0,0,0,0,0,0,0,0,0,0
49 | 1.2.85,0,0,0,0,0,0,0,0,0,0
50 | 1.2.86,0,0,0,0,0,0,0,0,0,0
51 | 1.2.87,0,0,0,0,0,0,0,0,0,0
52 | 1.2.88,0,0,0,0,0,0,0,0,0,0
53 | 1.2.89,0,0,0,0,0,0,0,0,0,0
54 | 1.2.90,0,0,0,0,0,0,0,0,0,0
55 | 1.2.91,0,0,0,0,0,0,0,0,0,0
56 | 1.2.92,0,0,0,0,0,0,0,0,0,0
57 | 1.2.93,0,0,0,0,0,0,0,0,0,0
58 | 1.2.94,0,0,0,0,0,0,0,0,0,0
59 | 1.2.95,0,0,0,0,0,0,0,0,0,0
60 | 1.2.96,0,0,0,0,0,0,0,0,0,0
61 | 1.2.97,0,0,0,0,0,0,0,0,0,0
62 | 1.2.98,0,0,0,0,0,0,0,0,0,0
63 | 1.2.99,0,0,0,0,0,0,0,0,0,0
64 | 1.2.100,0,0,0,0,0,0,0,0,0,0
65 | 1.2.101,0,0,0,0,0,0,0,0,0,0
66 | 1.2.102,0,0,0,0,0,0,0,0,0,0
67 | 1.2.103,0,0,0,0,0,0,0,0,0,0
68 | 1.2.104,0,0,0,0,0,0,0,0,0,0
69 | 1.2.105,0,0,0,0,0,0,0,0,0,0
70 | 1.2.106,0,0,0,0,0,0,0,0,0,0
71 | 1.2.107,0,0,0,0,0,0,0,0,0,0
72 | 1.2.108,0,0,0,0,0,0,0,0,0,0
73 | 1.2.109,0,0,0,0,0,0,0,0,0,0
74 | 1.2.110,0,0,0,0,0,0,0,0,0,0
75 | 1.2.111,0,0,0,0,0,0,0,0,0,0
76 | 1.2.112,0,0,0,0,0,0,0,0,0,0
77 | 1.2.113,0,0,0,0,0,0,0,0,0,0
78 | 1.2.114,0,0,0,0,0,0,0,0,0,0
79 | 1.2.115,0,0,0,0,0,0,0,0,0,0
80 | 1.2.116,0,0,0,0,0,0,0,0,0,0
81 | 1.2.117,0,0,0,0,0,0,0,0,0,0
82 | 1.2.118,0,0,0,0,0,0,0,0,0,0
83 | 1.2.119,0,0,0,0,0,0,0,0,0,0
84 | 1.2.120,0,0,0,0,0,0,0,0,0,0
85 | 1.2.121,0,0,0,0,0,0,0,0,0,0
86 | 1.2.122,0,0,0,0,0,0,0,0,0,0
87 | 1.2.123,0,0,0,0,0,0,0,0,0,0
88 | 1.2.124,0,0,0,0,0,0,0,0,0,0
89 | 1.2.125,0,0,0,0,0,0,0,0,0,0
90 | 1.2.126,0,0,0,0,0,0,0,0,0,0
91 | 1.2.127,0,0,0,0,0,0,0,0,0,0
92 | 1.2.128,0,0,0,0,0,0,0,0,0,0
93 | 1.2.129,0,0,0,0,0,0,0,0,0,0
94 | 1.2.130,0,0,0,0,0,0,0,0,0,0
95 | 1.2.131,0,0,0,0,0,0,0,0,0,0
96 | 1.2.132,0,0,0,0,0,0,0,0,0,0
97 | 1.2.133,0,0,0,0,0,0,0,0,0,0
98 | 1.2.134,0,0,0,0,0,0,0,0,0,0
99 | 1.2.135,0,0,0,0,0,0,0,0,0,0
100 | 1.2.136,0,0,0,0,0,0,0,0,0,0
101 | 1.2.137,0,0,0,0,0,0,0,0,0,0
102 | 1.2.138,0,0,0,0,0,0,0,0,0,0
103 | 1.2.139,0,0,0,0,0,0,0,0,0,0
104 | 1.2.140,0,0,0,0,0,0,0,0,0,0
105 | 1.2.141,0,0,0,0,0,0,0,0,0,0
106 | 1.2.142,0,0,0,0,0,0,0,0,0,0
107 | 1.2.143,0,0,0,0,0,0,0,0,0,0
108 | 1.2.144,0,0,0,0,0,0,0,0,0,0
109 | 1.2.145,0,0,0,0,0,0,0,0,0,0
110 | 1.2.146,0,0,0,0,0,0,0,0,0,0
111 | 1.2.147,0,0,0,0,0,0,0,0,0,0
112 | 1.2.148,0,0,0,0,0,0,0,0,0,0
113 | 1.2.149,0,0,0,0,0,0,0,0,0,0
114 | 1.2.150,0,0,0,0,0,0,0,0,0,0
115 | 1.2.151,0,0,0,0,0,0,0,0,0,0
116 | 1.2.152,0,0,0,0,0,0,0,0,0,0
117 | 1.2.153,0,0,0,0,0,0,0,0,0,0
118 | 1.2.154,0,0,0,0,0,0,0,0,0,0
119 | 1.2.155,0,0,0,0,0,0,0,0,0,0
120 | 1.2.156,0,0,0,0,0,0,0,0,0,0
121 | 1.2.157,0,0,0,0,0,0,0,0,0,0
122 | 1.2.158,0,0,0,0,0,0,0,0,0,0
123 | 1.2.159,0,0,0,0,0,0,0,0,0,0
124 | 1.2.160,0,0,0,0,0,0,0,0,0,0
125 | 1.2.161,0,0,0,0,0,0,0,0,0,0
126 | 1.2.162,0,0,0,0,0,0,0,0,0,0
127 | 1.2.163,0,0,0,0,0,0,0,0,0,0
128 | 1.2.164,0,0,0,0,0,0,0,0,0,0
129 | 1.2.165,0,0,0,0,0,0,0,0,0,0
130 | 1.2.166,0,0,0,4903042,2135157,2135156,2279276,2278882,2640013,0
131 | 1.2.167,0,0,0,4903195,2135613,2135614,2279761,2279380,2640468,0
132 | 1.2.168,0,0,0,4903229,2136856,2136856,2280112,2279798,2640920,0
133 | 1.2.169,0,0,0,4953181,2168338,2168338,2297914,2280313,2640715,0
134 | 1.2.170,0,0,0,4867450,2487049,2487048,2267170,2394652,2779963,0
135 | 1.2.171,0,0,0,4867450,2487049,2487048,2267170,2394652,2779963,0
136 | 1.2.172,0,0,0,4855284,2488697,2488697,2218831,2395577,2781188,0
137 | 1.2.173,0,1672536,1615194,3976115,2495531,2495532,1841827,2198735,2562808,0
138 | 1.2.174,0,1672529,1615185,4000635,2495531,2495530,1841763,2198784,2562755,0
139 | 1.2.175,0,1713489,1660240,4099506,2545905,2545905,1884656,2239733,2610053,0
140 | 1.2.176,0,1713496,1660241,4099498,2548117,2548117,1885522,2240821,2612642,0
141 | 1.2.177,0,1717591,1660246,4099498,2548392,2548391,1885603,2241100,2612616,0
142 | 1.2.178,0,1717591,1660246,4099498,2548392,2548391,1885603,2241100,2612616,0
143 | 1.2.179,0,1717589,1664346,4099605,2201171,2201171,1890197,2244298,2616297,0
144 | 1.2.180,0,1705295,1660243,3952173,2219824,2219824,1849027,2228458,2595066,0
145 | 1.2.181,0,1709398,1664337,3952293,3477357,3477357,1853922,2233274,2600308,0
146 | 1.2.182,0,1680727,1635676,3902621,2227058,2227059,1824983,2203302,2562387,0
147 | 1.2.183,0,1684815,1643862,3919069,2224087,2224087,1827518,2202140,2558347,0
148 | 1.2.184,0,1688911,1643856,3902738,2225591,2225589,1828497,2202471,2559595,0
149 | 1.2.185,0,1701201,1660243,3936135,2226683,2226683,1840156,2231271,2590955,0
150 | 1.2.186,0,1701192,1664339,3936138,2228367,2228367,1841365,2232798,2592023,0
151 | 1.2.187,0,1701199,1664348,3936138,2229301,2229302,1841612,2232901,2592234,0
152 | 1.2.188,0,1693007,1652054,3903202,2211340,2211340,1832963,2222563,2579291,0
153 | 1.2.189,0,1697102,1656151,3919762,2217192,2217192,1837336,2227505,2586530,0
154 | 1.2.190,0,1697105,1660252,3936217,2222184,2222184,1839453,2232894,2588874,0
155 | 1.2.191,0,1701207,1664337,3936337,2226956,2226955,1839068,2236151,2592502,0
156 | 1.2.192,0,1705288,1664339,3936400,2229571,2229571,1840895,2239236,2594820,0
157 | 1.3.0,1311415,1701201,1664339,3936292,2226882,2226882,1839416,2251344,2611718,0
158 | 1.3.1,1325539,1709400,1668433,3936608,2232602,2232602,1843884,2256104,2616751,0
159 | 1.3.2,1325721,1709391,1668435,3936616,2232959,2232959,1844075,2256226,2617231,0
160 | 1.3.3,1325721,1709391,1668435,3936616,2232959,2232959,1844075,2256226,2617231,0
161 | 1.3.4,1308359,1688918,1643864,3903803,2209528,2209528,1820900,2227513,2583570,0
162 | 1.3.5,1310633,1717596,1680739,4003480,2215907,2215907,1872079,2234894,2622010,0
163 | 1.3.6,1310633,1725791,1688919,4003480,2226145,2226145,1886697,2274835,2662573,0
164 | 1.3.7,1305877,1733979,1693015,4053138,2237375,2237375,1889606,2279130,2670770,0
165 | 1.4.0,1295418,1725782,1684833,4020387,2223981,2223981,1881450,2257772,2643957,0
166 | 1.4.1,1298827,1729886,1688920,4036932,2231360,2231360,1886200,2263148,2649248,0
167 | 1.4.2,1306701,1738079,1697123,4053364,2241220,2241220,1894791,2271528,2661271,0
168 | 1.4.3,1309689,1746261,1713504,4069884,2247205,2247206,1898977,2276062,2666082,0
169 | 1.4.4,1314949,1750314,1721644,3578569,2260640,2260640,1905247,2295685,2689260,0
170 | 1.4.5,1313123,1733930,1701164,3578631,2256360,2256360,1885803,2275965,2667344,0
171 | 1.4.6,1317318,1738026,1709356,3595103,2268666,2268667,1890666,2281471,2672954,0
172 | 1.4.7,1320502,1746218,1721644,3595119,2271732,2271732,1892687,2283840,2675117,3208519
173 | 1.4.8,1329218,1754410,1733932,3611875,1344415,964545,1902172,2293442,2687490,3225067
174 | 1.5.0,1339199,1766698,1750316,3644874,1355133,971917,1915733,2312242,2712942,3258386
175 | 1.6.0,1317645,1746218,1729836,3628981,1351567,968334,1895454,2292419,2694193,3258861
176 | 1.6.1,1319012,1750314,1733932,3629485,1346642,962396,1897939,2297380,2699303,3259373
177 | 1.6.2,1321164,1754410,1733932,3647229,1347477,962770,1902112,2317662,2727354,3260717
178 | 1.6.3,1326119,1758506,1742124,3647353,1354332,967108,1908050,2324926,2738152,3277329
179 | 1.6.4,1344908,1778986,1758508,3697041,1374597,981042,1929574,2346697,2763469,3310945
180 | 1.7.0,1351159,1787178,1770796,3713521,1383795,986440,1937267,2356314,2775164,3327537
181 | 1.8.0,1344643,1799466,1783084,3697201,1414710,1033877,1948337,2367135,2789744,3312897
182 | 1.8.1,1346975,1803562,1787180,3697377,1418640,1037326,1952160,2370898,2795117,3313065
183 | 1.9.0,1357163,1815850,1799468,3845113,1425926,1041757,1961881,2380784,2805620,3474337
184 | 1.9.1,1361782,1819946,1803564,3852977,1429217,1043971,1964855,2382964,2808789,3490545
185 | 1.9.2,1375761,1832234,1815852,3849693,1434086,1047536,1975042,2427588,2857904,3491141
186 | 1.9.3,1377701,1832234,1815852,3849745,1435504,1048396,1976636,2428057,2858941,3491209
187 | 1.9.4,1396325,1852714,1840428,3903801,1442770,1047320,1998650,2453272,2888976,3525049
188 | 1.9.5,1395866,1856810,1840428,3908023,1444022,1048360,2000146,2454121,2890311,3525175
189 | 1.9.6,1402198,1856810,1840428,3904559,1449431,1052964,1996883,2209294,2638902,3525799
190 | 1.9.7,1389380,1865002,1852716,3888208,1459741,1060663,2153418,2226936,2656842,3407008
191 | 1.9.8,1396550,1873194,1860908,3904719,1469982,1066779,2162410,2232197,2666100,3423639
192 | 1.10.0,1406427,1885482,1873196,8071281,1474534,1070766,2171665,2244439,2686095,7167705
193 | 1.10.1,1465240,1942826,1930540,8145227,1539076,1127986,2235780,2306343,2746970,7233955
194 | 1.10.2,1475975,1955114,1946924,8174086,1546044,1135634,2251940,2317467,2762661,7250686
195 | 1.10.3,1475848,1959210,1951020,8178224,1546867,1136488,2253383,2317877,2763540,7250704
196 | 1.10.4,1470349,1958461,1944910,8190808,1547335,1140535,2270469,2332502,2775529,7250984
197 | 1.11.0,1470584,1957303,1944706,8186976,1546237,1139066,2269918,2331525,2775088,7251272
198 | 1.11.1,1476645,1966325,1957364,8203539,1551912,1144325,2277888,2340230,2784035,7267932
199 | 1.11.2,1478187,1969202,1960879,8207703,1553921,1145773,2281888,2342655,2786691,7284471
200 |
--------------------------------------------------------------------------------
/engine_report.csv:
--------------------------------------------------------------------------------
1 | VERSION,arm64-ios,arm64-android,armv7-android,x86_64-macos,js-web,wasm-web,x86_64-linux,x86-win32,x86_64-win32,arm64-macos
2 | 1.2.38,0,0,0,0,0,0,0,0,0,0
3 | 1.2.39,0,0,0,0,0,0,0,0,0,0
4 | 1.2.40,0,0,0,0,0,0,0,0,0,0
5 | 1.2.41,0,0,0,0,0,0,0,0,0,0
6 | 1.2.42,0,0,0,0,0,0,0,0,0,0
7 | 1.2.43,0,0,0,0,0,0,0,0,0,0
8 | 1.2.44,0,0,0,0,0,0,0,0,0,0
9 | 1.2.45,0,0,0,0,0,0,0,0,0,0
10 | 1.2.46,0,0,0,0,0,0,0,0,0,0
11 | 1.2.47,0,0,0,0,0,0,0,0,0,0
12 | 1.2.48,0,0,0,0,0,0,0,0,0,0
13 | 1.2.49,0,0,0,0,0,0,0,0,0,0
14 | 1.2.50,0,0,0,0,0,0,0,0,0,0
15 | 1.2.51,0,0,0,0,0,0,0,0,0,0
16 | 1.2.52,0,0,0,0,0,0,0,0,0,0
17 | 1.2.53,0,0,0,0,0,0,0,0,0,0
18 | 1.2.54,0,0,0,0,0,0,0,0,0,0
19 | 1.2.55,0,0,0,0,0,0,0,0,0,0
20 | 1.2.56,0,0,0,0,0,0,0,0,0,0
21 | 1.2.57,0,0,0,0,0,0,0,0,0,0
22 | 1.2.58,0,0,0,0,0,0,0,0,0,0
23 | 1.2.59,0,0,0,0,0,0,0,0,0,0
24 | 1.2.60,0,0,0,0,0,0,0,0,0,0
25 | 1.2.61,0,0,0,0,0,0,0,0,0,0
26 | 1.2.62,0,0,0,0,0,0,0,0,0,0
27 | 1.2.63,0,0,0,0,0,0,0,0,0,0
28 | 1.2.64,0,0,0,0,0,0,0,0,0,0
29 | 1.2.65,0,0,0,0,0,0,0,0,0,0
30 | 1.2.66,0,0,0,0,0,0,0,0,0,0
31 | 1.2.67,0,0,0,0,0,0,0,0,0,0
32 | 1.2.68,0,0,0,0,0,0,0,0,0,0
33 | 1.2.69,0,0,0,0,0,0,0,0,0,0
34 | 1.2.70,0,0,0,0,0,0,0,0,0,0
35 | 1.2.71,0,0,0,0,0,0,0,0,0,0
36 | 1.2.72,0,0,0,0,0,0,0,0,0,0
37 | 1.2.73,0,0,0,0,0,0,0,0,0,0
38 | 1.2.74,0,0,0,0,0,0,0,0,0,0
39 | 1.2.75,0,0,0,0,0,0,0,0,0,0
40 | 1.2.76,0,0,0,0,0,0,0,0,0,0
41 | 1.2.77,0,0,0,0,0,0,0,0,0,0
42 | 1.2.78,0,0,0,0,0,0,0,0,0,0
43 | 1.2.79,0,0,0,0,0,0,0,0,0,0
44 | 1.2.80,0,0,0,0,0,0,0,0,0,0
45 | 1.2.81,0,0,0,0,0,0,0,0,0,0
46 | 1.2.82,0,0,0,0,0,0,0,0,0,0
47 | 1.2.83,0,0,0,0,0,0,0,0,0,0
48 | 1.2.84,0,0,0,0,0,0,0,0,0,0
49 | 1.2.85,0,0,0,0,0,0,0,0,0,0
50 | 1.2.86,0,0,0,0,0,0,0,0,0,0
51 | 1.2.87,0,0,0,0,0,0,0,0,0,0
52 | 1.2.88,0,0,0,0,0,0,0,0,0,0
53 | 1.2.89,0,0,0,0,0,0,0,0,0,0
54 | 1.2.90,0,0,0,0,0,0,0,0,0,0
55 | 1.2.91,0,0,0,0,0,0,0,0,0,0
56 | 1.2.92,0,0,0,0,0,0,0,0,0,0
57 | 1.2.93,0,0,0,0,0,0,0,0,0,0
58 | 1.2.94,0,0,0,0,0,0,0,0,0,0
59 | 1.2.95,0,0,0,0,0,0,0,0,0,0
60 | 1.2.96,0,0,0,0,0,0,0,0,0,0
61 | 1.2.97,0,0,0,0,0,0,0,0,0,0
62 | 1.2.98,0,0,0,0,0,0,0,0,0,0
63 | 1.2.99,0,0,0,0,0,0,0,0,0,0
64 | 1.2.100,0,0,0,0,0,0,0,0,0,0
65 | 1.2.101,0,0,0,0,0,0,0,0,0,0
66 | 1.2.102,0,0,0,0,0,0,0,0,0,0
67 | 1.2.103,0,0,0,0,0,0,0,0,0,0
68 | 1.2.104,0,0,0,0,0,0,0,0,0,0
69 | 1.2.105,0,0,0,0,0,0,0,0,0,0
70 | 1.2.106,0,0,0,0,0,0,0,0,0,0
71 | 1.2.107,0,0,0,0,0,0,0,0,0,0
72 | 1.2.108,0,0,0,0,0,0,0,0,0,0
73 | 1.2.109,0,0,0,0,0,0,0,0,0,0
74 | 1.2.110,0,0,0,0,0,0,0,0,0,0
75 | 1.2.111,0,0,0,0,0,0,0,0,0,0
76 | 1.2.112,0,0,0,0,0,0,0,0,0,0
77 | 1.2.113,0,0,0,0,0,0,0,0,0,0
78 | 1.2.114,0,0,0,0,0,0,0,0,0,0
79 | 1.2.115,0,0,0,0,0,0,0,0,0,0
80 | 1.2.116,0,0,0,0,0,0,0,0,0,0
81 | 1.2.117,0,0,0,0,0,0,0,0,0,0
82 | 1.2.118,0,0,0,0,0,0,0,0,0,0
83 | 1.2.119,0,0,0,0,0,0,0,0,0,0
84 | 1.2.120,0,0,0,0,0,0,0,0,0,0
85 | 1.2.121,0,0,0,0,0,0,0,0,0,0
86 | 1.2.122,0,0,0,0,0,0,0,0,0,0
87 | 1.2.123,0,0,0,0,0,0,0,0,0,0
88 | 1.2.124,0,0,0,0,0,0,0,0,0,0
89 | 1.2.125,0,0,0,0,0,0,0,0,0,0
90 | 1.2.126,0,0,0,0,0,0,0,0,0,0
91 | 1.2.127,0,0,0,0,0,0,0,0,0,0
92 | 1.2.128,0,0,0,0,0,0,0,0,0,0
93 | 1.2.129,0,0,0,0,0,0,0,0,0,0
94 | 1.2.130,0,0,0,0,0,0,0,0,0,0
95 | 1.2.131,0,0,0,0,0,0,0,0,0,0
96 | 1.2.132,0,0,0,0,0,0,0,0,0,0
97 | 1.2.133,0,0,0,0,0,0,0,0,0,0
98 | 1.2.134,0,0,0,0,0,0,0,0,0,0
99 | 1.2.135,0,0,0,0,0,0,0,0,0,0
100 | 1.2.136,0,0,0,0,0,0,0,0,0,0
101 | 1.2.137,0,0,0,0,0,0,0,0,0,0
102 | 1.2.138,0,0,0,0,0,0,0,0,0,0
103 | 1.2.139,0,0,0,0,0,0,0,0,0,0
104 | 1.2.140,0,0,0,0,0,0,0,0,0,0
105 | 1.2.141,0,0,0,0,0,0,0,0,0,0
106 | 1.2.142,0,0,0,0,0,0,0,0,0,0
107 | 1.2.143,0,0,0,0,0,0,0,0,0,0
108 | 1.2.144,0,0,0,0,0,0,0,0,0,0
109 | 1.2.145,0,0,0,0,0,0,0,0,0,0
110 | 1.2.146,0,0,0,0,0,0,0,0,0,0
111 | 1.2.147,0,0,0,0,0,0,0,0,0,0
112 | 1.2.148,0,0,0,0,0,0,0,0,0,0
113 | 1.2.149,0,0,0,0,0,0,0,0,0,0
114 | 1.2.150,0,0,0,0,0,0,0,0,0,0
115 | 1.2.151,0,0,0,0,0,0,0,0,0,0
116 | 1.2.152,0,0,0,0,0,0,0,0,0,0
117 | 1.2.153,0,0,0,0,0,0,0,0,0,0
118 | 1.2.154,0,0,0,0,0,0,0,0,0,0
119 | 1.2.155,0,0,0,0,0,0,0,0,0,0
120 | 1.2.156,0,0,0,0,0,0,0,0,0,0
121 | 1.2.157,0,0,0,0,0,0,0,0,0,0
122 | 1.2.158,0,0,0,0,0,0,0,0,0,0
123 | 1.2.159,0,0,0,0,0,0,0,0,0,0
124 | 1.2.160,0,0,0,0,0,0,0,0,0,0
125 | 1.2.161,0,0,0,0,0,0,0,0,0,0
126 | 1.2.162,0,0,0,0,0,0,0,0,0,0
127 | 1.2.163,0,0,0,0,0,0,0,0,0,0
128 | 1.2.164,0,0,0,0,0,0,0,0,0,0
129 | 1.2.165,0,0,0,0,0,0,0,0,0,0
130 | 1.2.166,2700168,3661544,3185048,4891172,4835755,2286395,5167560,5381632,6499840,0
131 | 1.2.167,2700184,3657632,3185144,4891188,4836689,2287332,5171848,5383680,6502400,0
132 | 1.2.168,2700184,3669920,3185144,4891188,4837918,2287888,5171848,5383168,6501376,0
133 | 1.2.169,2733488,3699696,3226680,4940932,4936683,2340041,5222440,5398528,6533120,0
134 | 1.2.170,2689520,3511296,3128384,4855172,7765741,2105327,5124024,5713920,6893568,0
135 | 1.2.171,2689520,3511296,3128384,4855172,7765741,2105327,5124024,5713920,6893568,0
136 | 1.2.172,2620432,3511288,3128364,4842868,7776508,2106805,4895928,5717504,6895104,0
137 | 1.2.173,2586136,3457880,3075028,3963408,7800581,2114245,3871648,5089280,6170624,0
138 | 1.2.174,2586132,3466072,3075028,3987904,7800441,2114250,3871648,5089280,6170624,0
139 | 1.2.175,2635492,3548216,3165252,4086760,7940338,2155920,3953824,5184512,6282240,0
140 | 1.2.176,2635492,3548216,3169348,4086752,7950699,2158372,3957920,5186560,6288896,0
141 | 1.2.177,2635492,3556408,3169348,4086752,7951095,2158464,3957920,5187072,6288896,0
142 | 1.2.178,2635492,3556408,3169348,4086752,7951095,2158464,3957920,5187072,6288896,0
143 | 1.2.179,2635532,3548216,3177540,4086840,4499044,2159059,3966112,5194240,6297600,0
144 | 1.2.180,2553404,3492512,3130052,3939384,4523023,2184641,3839616,5094400,6171136,0
145 | 1.2.181,2553460,3508896,3138244,3939504,4523023,3117419,3851904,5105664,6184448,0
146 | 1.2.182,2520080,3451544,3089084,3889832,4538185,2192835,3798632,5040128,6098432,0
147 | 1.2.183,2536296,3488408,3097276,3906144,4531672,2182293,3802720,5034496,6082048,0
148 | 1.2.184,2536312,3464184,3097628,3889784,4533137,2182616,3803072,5033472,6082048,0
149 | 1.2.185,2553000,3464144,3118032,3923176,4535548,2183817,3823616,5097472,6158848,0
150 | 1.2.186,2553000,3484680,3122160,3923184,4539647,2186237,3827744,5100032,6161920,0
151 | 1.2.187,2553000,3472392,3122160,3923184,4540474,2186724,3827744,5100544,6163456,0
152 | 1.2.188,2536536,3452096,3097680,3890248,4495274,2164996,3799264,5072384,6126080,0
153 | 1.2.189,2536952,3464728,3106064,3906808,4505080,2170497,3811936,5086208,6141952,0
154 | 1.2.190,2536968,3460632,3110160,3923224,4515600,2175511,3816032,5105152,6152192,0
155 | 1.2.191,2553568,3468904,3118392,3923344,4525468,2180643,3820120,5113856,6162944,0
156 | 1.2.192,2553584,3481200,3122488,3923384,4531041,2183249,3824216,5121536,6170624,0
157 | 1.3.0,2553472,3463344,3113496,3923272,4523948,2178435,3818616,5339648,6533120,0
158 | 1.3.1,2619992,3483864,3121720,3923312,4539555,2186567,3830968,5348864,6545920,0
159 | 1.3.2,2619992,3475680,3121728,3923320,4540390,2186884,3830968,5349376,6546432,0
160 | 1.3.3,2619992,3475680,3121728,3923320,4540390,2186884,3830968,5349376,6546432,0
161 | 1.3.4,2586800,3431496,3072544,3890304,4502203,2162204,3790840,5282304,6478336,0
162 | 1.3.5,2587056,3505600,3146440,3990376,4513615,2167120,3889560,5302272,6630400,0
163 | 1.3.6,2587192,3514312,3163040,4023480,4530569,2177882,3918752,5700096,7033856,0
164 | 1.3.7,2587208,3530152,3175056,4039976,4556679,2189135,3926368,5705216,7054336,0
165 | 1.4.0,2570952,3526080,3154592,4007192,4531531,2176479,3914112,5467648,6663680,0
166 | 1.4.1,2587416,3534440,3162928,4023720,4542916,2182191,3922496,5485568,6680064,0
167 | 1.4.2,2603848,3550880,3179352,4040152,4562341,2193278,3938912,5506560,6709760,0
168 | 1.4.3,2603984,3520336,3129468,4056672,4573881,2199084,3947232,5516288,6723584,0
169 | 1.4.4,2620448,3536264,3144340,3565296,4602216,2213157,3959776,5563392,6782464,0
170 | 1.4.5,2604248,3521984,3127068,3565320,4588181,2204783,3945440,5540352,6760448,0
171 | 1.4.6,2620720,3533600,3142524,3581792,4615856,2215713,3953600,5554688,6774784,0
172 | 1.4.7,2620736,3554528,3170044,3581808,4621966,2219383,3959360,5560832,6781440,3195208
173 | 1.4.8,2637368,3579624,3195652,3598496,4663546,2238056,3981568,5588480,6820864,3211688
174 | 1.5.0,2670192,3610568,3227628,3631456,4714611,2261946,4014464,5641216,6891520,3244968
175 | 1.6.0,2637464,3579800,3196772,3615536,4738984,2251218,3986176,5606400,6861824,3245416
176 | 1.6.1,2653904,3585600,3204132,3616040,4713017,2253176,3990688,5622272,6876160,3245928
177 | 1.6.2,2653912,3592608,3209772,3632488,4714458,2253654,3998944,5708800,7001088,3245976
178 | 1.6.3,2653992,3598360,3217076,3632592,4733592,2261293,4009024,5725696,7024128,3262568
179 | 1.6.4,2687376,3644880,3281540,3682280,4810218,2300750,4055712,5785600,7108608,3296184
180 | 1.7.0,2703800,3660120,3301492,3698792,4842740,2316340,4076432,5815296,7149568,3312808
181 | 1.8.0,2720216,3693496,3334396,3680920,4959985,2332458,4105808,5848064,7191040,3296616
182 | 1.8.1,2736656,3702408,3342892,3680976,4974831,2339221,4110000,5857280,7203840,3296664
183 | 1.9.0,2769904,3732904,3371972,3828688,4999074,2351713,4135008,5880320,7234560,3457912
184 | 1.9.1,2770248,3742768,3379924,3836552,5011281,2357939,4148352,5888000,7245312,3474120
185 | 1.9.2,2852704,3762072,3403204,3833248,5033064,2371299,4169040,6092800,7476224,3474696
186 | 1.9.3,2852736,3764568,3406692,3833280,5039346,2374239,4173144,6093824,7476736,3474744
187 | 1.9.4,2886280,3814912,3455588,3887336,5020648,2399700,4219736,6159360,7556608,3508584
188 | 1.9.5,2886416,3816832,3457772,3891432,5023084,2400982,4219832,6160384,7559680,3508584
189 | 1.9.6,2886600,3819952,3460888,3887520,5036492,2408422,4236360,6171136,7565312,3508760
190 | 1.9.7,2785520,3841824,3483256,3871008,5062847,2421742,4779512,6206976,7614464,3389800
191 | 1.9.8,2802072,3858256,3498536,3887496,5098038,2437616,4796448,6228480,7645184,3406408
192 | 1.10.0,2818464,3875480,3528840,8054200,5118085,2447038,4820344,6256640,7703040,7150616
193 | 1.10.1,2884008,3942344,3597128,8127936,5210254,2515889,4898168,6348800,7793664,7216664
194 | 1.10.2,2900496,3970736,3632600,8156760,5235836,2529364,4935096,6372864,7826432,7233352
195 | 1.10.3,2900496,3972608,3634756,8160872,5238851,2530740,4935064,6373888,7828480,7233352
196 | 1.10.4,2884208,3980152,3604580,8173400,5226192,2528224,4951992,6375936,7769600,7233576
197 | 1.11.0,2884376,3980328,3604052,8169280,5220798,2525713,4947928,6372864,7768576,7233576
198 | 1.11.1,2900864,4002776,3632140,8185824,5243653,2536605,4961408,6396416,7802368,7250216
199 | 1.11.2,2917472,4009176,3639596,8189976,5249004,2539758,4973760,6404608,7811072,7266744
200 |
--------------------------------------------------------------------------------
/legacy_engine_report.csv:
--------------------------------------------------------------------------------
1 | VERSION,arm64-darwin,armv7-android,armv7-darwin,darwin,js-web,wasm-web,linux,win32,x86_64-darwin,x86_64-linux,armv7-android,arm64-android
2 | 1.2.38,0,8264241,3627640,6230456,0,0,11582686,4840448,0,0,8264015,0
3 | 1.2.39,0,8395828,3687012,6336376,0,0,11871119,4893184,0,0,8395541,0
4 | 1.2.40,0,8400795,3690676,6346424,0,0,11884882,4897792,0,0,8400751,0
5 | 1.2.41,0,8465000,2890588,5630788,4741940,0,11195843,3952128,0,0,8464966,0
6 | 1.2.42,0,8467106,2891588,5635364,4779111,0,11203845,3951616,0,0,8467410,0
7 | 1.2.43,0,8637793,3000732,5781920,4976103,0,11366192,4042240,0,0,8638017,0
8 | 1.2.44,0,8637572,2998712,5780228,4975658,0,11362816,4037632,0,0,8637927,0
9 | 1.2.45,0,8647159,2998176,5790668,4978854,0,11390842,4042240,0,0,8647210,0
10 | 1.2.46,0,8580419,3164812,6035624,5042747,0,11516745,4151296,0,0,8579926,0
11 | 1.2.47,0,8581891,3166324,6041800,5044154,0,11523823,4151296,0,0,8581596,0
12 | 1.2.48,0,8620182,3173824,6095256,5077204,0,11628180,4183552,0,0,8619978,0
13 | 1.2.49,0,8705847,3286272,6218856,5073830,0,11784794,4177408,0,0,8706017,0
14 | 1.2.50,0,8847534,3464332,6218856,5074316,0,11788910,4177408,0,0,8847775,0
15 | 1.2.51,0,8885113,3491320,6253816,5110949,0,11879990,4200448,0,0,8884235,0
16 | 1.2.52,3841456,8890685,3494840,6261312,5115637,0,12184720,4201984,6452612,0,8890381,0
17 | 1.2.53,3842288,8917579,3495612,6281520,5137497,0,12226299,4209152,6469504,0,8916816,0
18 | 1.2.54,3844568,8924202,3497760,6283140,5138083,0,12230071,4214784,6475352,0,8923985,0
19 | 1.2.55,3849224,8932722,3501912,6282488,5118105,0,12250954,4214272,6471320,11785005,8932629,0
20 | 1.2.56,3867776,8938057,3503924,6289900,5129502,0,12268525,4219392,6479032,11805794,8937821,0
21 | 1.2.57,3897756,8998738,3535308,6360972,5169628,0,12393316,4246528,6557896,11932379,8998832,0
22 | 1.2.58,3928360,9058886,3565488,6410228,5209732,0,12499062,4269568,6608756,12031327,9059206,0
23 | 1.2.59,4034432,9129205,3688080,6529668,5527032,0,12632164,4406272,6728052,12160822,9128484,0
24 | 1.2.60,4053024,9142560,3690104,6530096,5526576,0,12636699,4412928,6733108,12165813,9142434,0
25 | 1.2.61,4051060,9147694,3688236,6532644,5528104,0,12633412,4408320,6730972,12166626,9147412,0
26 | 1.2.62,4053680,9150329,3707088,6535344,5530786,0,12643742,4415488,6737980,12172756,9150136,0
27 | 1.2.63,4092028,9180199,3727760,6535404,5536078,0,12645909,4418048,6739636,12174819,9180218,0
28 | 1.2.64,4122160,9270507,3756812,6578668,5577412,0,12753141,4437504,6780140,12279783,9270068,0
29 | 1.2.65,4137856,9276824,3756124,6585284,5583056,0,12762576,4435456,6788180,12294166,9276274,0
30 | 1.2.66,4156932,9313255,3774868,6609984,5651367,0,12794119,4460544,6810244,12323909,9313322,0
31 | 1.2.67,4156480,9315969,3774432,6610916,5651899,0,12795122,4461056,6815484,12325060,9315813,0
32 | 1.2.68,4160616,9318556,3778260,6614384,5651421,0,12803250,4468736,6819244,12337050,9318389,0
33 | 1.2.69,4146736,9312675,3747756,6588832,5556383,0,12772158,4428288,6789532,12306166,9312474,0
34 | 1.2.70,4149788,9441884,3766960,6591108,5557593,0,12782657,4434432,6795908,12312345,9442058,0
35 | 1.2.71,4160448,9444279,3785552,6567752,5563290,0,12783939,4438016,6736636,12317231,9443719,0
36 | 1.2.72,4150304,9455437,3775408,6557924,5567357,0,12777577,4435456,6726852,12308361,9455715,0
37 | 1.2.73,4161808,9469804,3785880,6570684,5577915,0,12792437,4440064,6740068,12322653,9469938,0
38 | 1.2.74,4161808,9469576,3785884,6570688,5578110,0,12792523,4440576,6741396,12322741,9469640,0
39 | 1.2.75,4186156,9578605,3809408,6579260,4981475,0,12812620,4450816,6750572,12345274,9578825,0
40 | 1.2.76,4120872,9551356,3744200,6573372,4836182,0,12723664,4389376,6754676,12240828,9551638,0
41 | 1.2.77,4122632,9551040,3745864,6574968,4836372,0,12726544,4394496,6756204,12243716,9551307,0
42 | 1.2.78,4123492,9556710,3746624,6580648,4841157,0,12730616,4398592,6762084,12253844,9556645,0
43 | 1.2.79,4123564,9560673,3746712,6576552,4845826,0,12731148,4399616,6762084,12254356,9560115,0
44 | 1.2.80,4123728,9563363,3746872,6581104,4851276,0,12736204,4418560,6764988,12259524,9563547,0
45 | 1.2.81,4306816,9937734,3922872,6961724,5136790,0,13100283,4715520,7173092,13024402,9937481,0
46 | 1.2.82,4323188,9936706,3922772,4964644,15227607,0,16605019,4140032,4889732,23237567,9936361,0
47 | 1.2.83,4324808,9979804,3924256,4975052,5202393,0,16697699,4147712,4904044,23337019,9979863,0
48 | 1.2.84,4369616,10035897,3951616,4980708,5212214,0,16705681,4150272,4905996,23346226,10035388,0
49 | 1.2.85,4370316,10037544,3952260,4980704,5215095,0,16705597,4151296,4910124,23345986,10037178,0
50 | 1.2.86,4373936,10056013,3955548,4979096,5215795,0,16703440,4151296,4913836,23337284,10056312,0
51 | 1.2.87,4332136,10061048,3954512,4977416,5222295,0,16723270,4155904,4944912,23353441,10060735,0
52 | 1.2.88,4343184,10125698,3981556,4997676,5238402,0,16877552,4165120,4966264,23492800,10125489,0
53 | 1.2.89,4368064,10185665,3989476,5018688,5267245,0,17015361,4180992,4996408,23633113,10186110,0
54 | 1.2.90,4369344,10191207,3990568,5019124,5269728,0,17021160,4184576,4997524,23640327,10190560,0
55 | 1.2.91,4369476,10192646,4007076,5020372,5269955,0,17022230,4185600,5001804,23642565,10192020,0
56 | 1.2.92,4419512,10261027,4023224,5055288,5321548,0,17177572,4207104,5030108,23807084,10260779,0
57 | 1.2.93,4424412,10274248,4044068,5068268,5336737,0,17217462,4216832,5043660,23865522,10273738,0
58 | 1.2.94,4448576,10371218,4051664,5099452,5366001,0,17476304,4239872,5075668,24206229,10371026,0
59 | 1.2.95,4448576,10371215,4051664,5098828,5366006,0,17476304,4239872,5077364,24206229,10371041,0
60 | 1.2.96,4448576,10371230,4051672,5099880,5365603,0,17481550,4658176,5075996,24206223,10371020,0
61 | 1.2.97,4510716,10500039,4112428,5174380,5436716,0,17755701,4699648,5164308,24533402,10500031,0
62 | 1.2.98,4511032,10502025,4112724,5175772,5438159,0,17761616,4700672,5163844,24541721,10501600,0
63 | 1.2.99,4544112,10532027,4145784,5208664,5532180,0,17794476,4733952,5197956,24580405,10531884,0
64 | 1.2.100,4564716,10550800,4149504,5220412,5556516,0,17838351,4746752,5204832,24631698,10550346,0
65 | 1.2.101,4565888,10556431,4150608,5225628,5559629,0,17844978,4749312,5207520,24645313,10556525,0
66 | 1.2.102,4569968,10550295,4170828,5232276,5565303,0,17840169,4741120,5224756,24655149,10550272,0
67 | 1.2.103,4570044,10556063,4170868,5238296,5567155,0,17856543,4742144,5223084,24675811,10556067,0
68 | 1.2.104,4569040,10552320,4169432,5237248,5563691,0,17830010,4743168,5226140,24618246,10552194,0
69 | 1.2.105,4573120,10565873,4173112,5245032,5571977,0,17861003,4747264,5233228,24655184,10565445,0
70 | 1.2.106,4573076,10573081,4172964,5248228,5572487,0,17877036,4751872,5236948,24682698,10572848,0
71 | 1.2.107,4596800,10602255,4180028,5267740,5587197,0,17949257,4764672,5261332,24768311,10602047,0
72 | 1.2.108,4586104,10606615,4217116,5168172,5589043,0,17953597,4766720,5241968,24774857,10605946,0
73 | 1.2.109,4593516,10643796,4240648,5192728,5621526,0,18048218,4785664,5267152,24909393,10643797,0
74 | 1.2.110,4593668,10641698,4240744,5192344,5618984,0,18026881,4784640,5270856,24907237,10641895,0
75 | 1.2.111,4593656,10641304,4240772,5196648,5620874,0,18026968,4783616,5271040,24903632,10640967,0
76 | 1.2.112,4594344,10645267,4241376,5197264,5624559,0,18024993,4785664,5271744,24920076,10645001,0
77 | 1.2.113,4594348,10653588,4257764,5205460,5655014,0,18033262,4795392,5279936,24927970,10653214,0
78 | 1.2.114,4594536,10656129,4257936,5206092,5655991,0,19373644,4850176,5284744,24936543,10655417,0
79 | 1.2.115,4639340,10713063,4269040,5238044,5734014,0,19432188,5090304,5643964,24758200,10712330,0
80 | 1.2.116,4639764,10717082,4269420,5238584,5737247,0,19440944,5091328,5644564,24762280,10716746,0
81 | 1.2.117,4397832,10436689,4012464,4985404,5016012,0,18958508,4809216,5389228,24203792,10721035,0
82 | 1.2.118,4400056,10446556,4014540,4991816,5022263,0,18979516,4813312,5391788,24229184,10730716,0
83 | 1.2.119,4407468,10451192,4021220,4998004,5039179,0,19013148,4823552,5406820,24273768,10734190,0
84 | 1.2.120,4431516,10481003,4061388,5032676,5100417,0,19041372,4862464,5447872,24345856,10754899,0
85 | 1.2.121,4431696,10480499,4061536,5030548,5090477,0,19056208,4859392,5444056,24349448,10754481,0
86 | 1.2.122,4431828,10481112,4061648,5030656,5091861,0,19058300,4860416,5444232,24353784,10756223,0
87 | 1.2.123,4414964,10486302,4061636,5067396,5092579,0,19065300,4860928,5439536,24360272,10759587,0
88 | 1.2.124,4415324,10490976,4061952,5072000,5095949,0,19068528,4861952,5440104,24363304,10764889,0
89 | 1.2.125,4411860,10491277,4060260,5072492,5096742,0,19070004,4862464,5436752,24364456,10766327,0
90 | 1.2.126,4419880,10503991,4068712,5090848,5099803,0,19117476,4866048,5456224,24413928,10778423,0
91 | 1.2.127,4374464,10494029,4037964,5053432,4969919,0,19065428,4818432,5415176,24350904,10824655,0
92 | 1.2.128,4396052,10504754,4040536,5064460,4977067,0,19087296,4825600,5421416,24378184,10836056,0
93 | 1.2.129,4398216,10850193,4044760,5071856,4983368,0,19115904,4831232,5433344,24412288,11186862,0
94 | 1.2.130,4401840,10876136,4049572,5085572,5000582,0,19169428,4839424,5447528,24485440,11212621,0
95 | 1.2.131,4402040,10878544,4049772,5086084,5002172,0,19176952,4840448,5452576,24489560,11215151,0
96 | 1.2.132,4250288,10770595,3852308,4833976,5002214,0,19213216,4840448,5194284,24615064,11109362,0
97 | 1.2.133,4222880,10766669,3810240,4794576,4988784,0,19191700,4848640,5158364,24597992,11105602,0
98 | 1.2.134,4187956,10210631,3827880,4794544,5135612,0,15138400,4786176,5109648,19131024,10547381,0
99 | 1.2.135,4187960,10215667,3827884,4797008,5138227,0,15147084,4786688,5113776,19136136,10550772,0
100 | 1.2.136,4217168,13716416,3871116,4783984,5129445,0,15135676,4783616,5095584,19117640,14052664,0
101 | 1.2.137,4217364,13719736,3871292,0,5133516,0,15140916,4785664,5095784,19123520,14056092,0
102 | 1.2.138,4235380,13725998,3873052,0,5152452,0,15161028,4794368,5106496,19149872,14063179,0
103 | 1.2.139,4157072,13588745,3812324,0,4509371,0,14848700,4725248,4999968,18769144,13928279,0
104 | 1.2.140,4157072,13589280,3812324,0,4509531,0,14849036,4725248,4999968,18769192,13928615,0
105 | 1.2.141,4155152,13579954,3810604,0,4511122,2044857,14880796,4726272,5004800,18809608,13919339,0
106 | 1.2.142,4155368,13569629,3811940,0,4508009,2072237,14853048,4725248,5010888,18776440,13909316,0
107 | 1.2.143,4157916,13573817,3813152,0,4510650,2074281,14856236,4725760,5012192,18780008,13912154,0
108 | 1.2.144,4174688,13798679,3813524,0,4522266,2080727,14867268,4732928,5016920,18792704,14190754,0
109 | 1.2.145,4192936,13828119,3831752,0,4548196,2095589,15281952,4988416,5732288,19361072,14217724,0
110 | 1.2.146,4236432,13842874,3874212,0,4568598,2112308,0,5029888,5789064,19522600,14234333,0
111 | 1.2.147,4280980,13863720,3889584,0,4586079,2121248,0,5036032,5836320,19565120,14260217,0
112 | 1.2.148,4315968,13850133,3923184,0,4456904,2111782,0,5042688,5872208,19502504,14322310,0
113 | 1.2.149,2714136,13949944,2491860,0,4473530,2119371,0,5052928,4303952,4408704,14422910,0
114 | 1.2.150,2714152,13961401,2491828,0,4472686,2118739,0,5052928,4304112,4412960,14432644,0
115 | 1.2.151,2714192,13965207,2491988,0,4483955,2125447,0,5057536,4308216,4413120,14436789,0
116 | 1.2.152,2963576,13974807,2508684,0,4484085,2125524,0,5105152,4362392,4736976,14447417,0
117 | 1.2.153,2998188,0,2543268,0,4484884,2126105,0,5166592,4418196,4802664,14503494,15336225
118 | 1.2.154,2998196,0,2543276,0,4484884,2126105,0,5167104,4418204,4802664,14503442,15234145
119 | 1.2.155,2484160,0,2126644,0,4454545,2109217,0,5142528,4418220,4802664,4488935,4711873
120 | 1.2.156,2517304,0,2159980,0,4577972,2160399,0,5151232,4434700,4814952,4493928,4719570
121 | 1.2.157,2533704,0,2160008,0,4586788,2163321,0,5153792,4439512,4819176,4495473,4721146
122 | 1.2.158,2533704,0,2160008,0,4587229,2163538,0,5153792,4439512,4819176,4495731,4721442
123 | 1.2.159,2550088,0,2160008,0,4587071,2163497,0,5175296,4451800,4835944,4495880,4721556
124 | 1.2.160,2533052,0,2159368,0,4588789,2163959,0,5149696,4451768,4840040,4153781,4378796
125 | 1.2.161,2533076,0,2159392,0,4589473,2165223,0,5157376,4455896,4844168,4191436,4284660
126 | 1.2.162,2648756,0,2258708,0,4810892,2285557,0,5334528,4633400,5021096,2000178,2101232
127 | 1.2.163,2631060,0,2241060,0,4807563,2274866,0,5341696,4629368,5015624,1923140,2022404
128 | 1.2.164,2631060,0,2241060,0,4807563,2274866,0,5341696,4629368,5015624,1923140,2022404
129 | 1.2.165,2700120,0,2306292,0,4821690,2279469,0,5369856,4878836,5019624,1929653,2027408
130 | 1.2.166,2700168,0,2306448,0,4835755,2286395,0,5381632,4891172,5167560,1934481,2032164
131 | 1.2.167,2700184,0,2306460,0,4836406,2287127,0,5382144,4891188,5171848,1934445,2032042
132 | 1.2.168,2700184,0,2306460,0,4837918,2287888,0,5383168,4891188,5171848,1935121,2032654
133 | 1.2.169,2733488,0,2340612,0,4936683,2340041,0,5398528,4940932,5222440,1951089,2047758
134 | 1.2.170,2689520,0,2250124,0,7765741,2105327,0,5713920,4855172,5124024,1917094,2000034
135 | 1.2.171,2620424,0,2168528,0,7764627,2104537,0,5713920,4842860,4895960,1917584,1999970
136 | 1.2.172,2620432,0,2168532,0,7776508,2106805,0,5717504,4842868,4895928,1918382,2001135
137 | 1.2.173,2586136,0,2134168,0,7800581,2114245,0,5089280,3963408,3871648,1888174,1970273
138 | 1.2.174,2586132,0,2134184,0,7800441,2114250,0,5089280,3987904,3871648,1888305,1970653
139 | 1.2.175,2635492,0,2167180,0,7940338,2155920,0,5184512,4086760,3953824,1936409,2015817
140 | 1.2.176,2635492,0,2183572,0,7950699,2158372,0,5186560,4086752,3957920,1938829,2017040
141 | 1.2.177,2635492,0,2183572,0,7951095,2158464,0,5187072,4086752,3957920,1939007,2016975
142 | 1.2.178,2635492,0,2183572,0,7951095,2158464,0,5187072,4086752,3957920,1939007,2016975
143 | 1.2.179,2635532,0,2183688,0,4499044,2159059,0,5194240,4086840,3966112,1946796,2024053
144 | 1.2.180,2553404,0,2084712,0,4523023,2184641,0,5094400,3939384,3839616,2026223,2092974
145 | 1.2.181,2553460,0,2101088,0,20958953,3117419,0,5105664,3939504,3851904,2029827,2096437
146 | 1.2.182,2520080,0,2067780,0,4538185,2192835,0,5040128,3889832,3798632,2003631,2070426
147 | 1.2.183,2536296,0,2067620,0,4531672,2182293,0,5034496,3906144,3802720,2008956,2073433
148 | 1.2.184,2536312,0,2067484,0,4533137,2182616,0,5033472,3889784,3803072,2009458,2074156
149 | 1.2.185,2553000,0,2084184,0,4535548,2183817,0,5097472,3923176,3823616,2029228,2087818
150 | 1.2.186,2553000,0,2084188,0,4539647,2186237,0,5100032,3923184,3827744,2030585,2089356
151 | 1.2.187,2553000,0,2084196,0,4540474,2186724,0,5100544,3923184,3827744,2030768,2089775
152 | 1.2.188,2536536,0,2067692,0,4495274,2164996,0,5072384,3890248,3799264,2020282,2079668
153 | 1.2.189,2536952,0,2084520,0,4505080,2170497,0,5086208,3906808,3811936,2023388,2083257
154 |
--------------------------------------------------------------------------------
/size-analyzer/README.md:
--------------------------------------------------------------------------------
1 | # Defold Size Analyzer
2 |
3 | A comprehensive tool for analyzing and comparing Defold component sizes across versions. The analyzer supports both native engine binaries and Java tooling (bob.jar) analysis with interactive visualizations and dashboard overview.
4 |
5 | ## Overview
6 |
7 | The Defold Size Analyzer consists of three main components:
8 | 1. **Data Collection Pipeline** - Automated analysis and CSV generation
9 | 2. **Dashboard** - High-level overview with size evolution charts
10 | 3. **Size Analyzer** - Detailed comparison and analysis tools
11 |
12 | ---
13 |
14 | ## Data Collection Pipeline
15 |
16 | ### 1. Analysis Script (`analyze_builds.py`)
17 |
18 | The Python script automates the download and analysis of Defold components across versions.
19 |
20 | #### Supported Platforms:
21 | - **Native Binaries**: `arm64-android`, `armv7-android`, `arm64-ios`, `x86_64-macos`, `arm64-macos` (libdmengine_release.so)
22 | - **Java Tooling**: `bob.jar` (editor/build tools)
23 | - **Editor Applications**: `editor-win32`, `editor-x86_64-linux`, `editor-x86_64-macos`, `editor-arm64-macos` (complete editor packages)
24 |
25 | #### Data Sources:
26 | - Downloads components from Defold's archive: `http://d.defold.com/archive/{sha1}/`
27 | - Uses `releases.json` to determine available versions and SHA1 hashes
28 | - Processes versions from 1.9.0 onwards
29 |
30 | #### Analysis Methods:
31 |
32 | **Native Binary Analysis (using Bloaty)**
33 | ```bash
34 | bloaty -d compileunits --demangle=full -n 0 binary.so --csv
35 | ```
36 | - **Tool**: [Google Bloaty](https://github.com/google/bloaty) - Binary size analysis tool
37 | - **Documentation**: [Bloaty Usage Guide](https://github.com/google/bloaty/blob/main/doc/using.md)
38 | - **Output**: `compileunits,vmsize,filesize`
39 | - **vmsize**: Virtual memory size (loaded into memory)
40 | - **filesize**: File size on disk
41 | - **compileunits**: Source file/compilation unit names
42 |
43 | **JAR Analysis (using Python zipfile)**
44 | ```python
45 | with zipfile.ZipFile(jar_path, 'r') as zf:
46 | for info in zf.infolist():
47 | # Extract: filename, compressed_size, uncompressed_size
48 | ```
49 | - **Output**: `filename,compressed,uncompressed`
50 | - **compressed**: Size of entry in JAR (compressed)
51 | - **uncompressed**: Original size of entry
52 | - **filename**: Path within JAR file
53 |
54 | **Editor Analysis (Combined Approach)**
55 | ```python
56 | # Combines JAR analysis, JDK grouping, and file analysis
57 | # - JAR contents analyzed individually with compression ratios
58 | # - JDK folder grouped as single "JDK" entity
59 | # - Other files analyzed individually (compressed == uncompressed)
60 | # - Library grouping applied to reduce complexity
61 | ```
62 | - **Output**: `filename,compressed,uncompressed`
63 | - **compressed**: Compressed size (for JARs) or file size (for other files)
64 | - **uncompressed**: Uncompressed size (for JARs) or file size (for other files)
65 | - **filename**: File path or grouped library name (e.g., `com/ibm/*.*`, `JDK`)
66 |
67 | #### Generated Files:
68 | ```
69 | size-analyzer/
70 | ├── analysis_index.json # Platform and version metadata
71 | ├── arm64-android/ # Native binary analysis
72 | │ ├── 1.9.0.csv
73 | │ ├── 1.9.1.csv
74 | │ └── ...
75 | ├── bob.jar/ # Java tooling analysis
76 | │ ├── 1.9.0.csv
77 | │ ├── 1.9.1.csv
78 | │ └── ...
79 | └── editor-*/ # Editor analysis (all platforms)
80 | ├── 1.10.3.csv
81 | ├── 1.10.4.csv
82 | └── ...
83 | ```
84 |
85 | #### Running Analysis:
86 | ```bash
87 | # Full analysis (all platforms, all versions)
88 | python3 analyze_builds.py
89 |
90 | # Test mode (single platform, latest version only)
91 | python3 analyze_builds.py --test editor # Test editor analysis
92 | python3 analyze_builds.py --test bob # Test bob.jar analysis
93 | python3 analyze_builds.py --test ios # Test iOS engine analysis
94 | ```
95 |
96 | The script will:
97 | 1. Read `releases.json` for version information
98 | 2. Download and analyze each component for each version
99 | 3. Generate CSV files with size data
100 | 4. Apply library grouping for editor analysis (reduces ~76,000 entries to ~5,500)
101 | 5. Update `analysis_index.json` with available platforms/versions
102 | 6. Clean up temporary downloaded files
103 |
104 | ---
105 |
106 | ## Dashboard
107 |
108 | ### 1. Overview Charts
109 |
110 | The dashboard provides a high-level view of component size evolution across versions:
111 |
112 | **Features:**
113 | - **Bundle Size Chart**: Game bundle sizes across all supported platforms
114 | - **Engine Size Chart**: Engine binary sizes across platforms
115 | - **Editor Size Chart**: Editor application sizes (desktop platforms)
116 | - **Bob.jar Size Chart**: Build tool size evolution (macOS only)
117 |
118 | **Interactive Elements:**
119 | - **Version Dropdowns**: Select starting version for each chart
120 | - **Legend Controls**:
121 | - Click legend items to toggle platforms on/off
122 | - Alt+click legend items to isolate single platform
123 | - **Chart Navigation**: Click any data point to open detailed analysis
124 |
125 | ### 2. Cross-Navigation
126 |
127 | **Dashboard → Size Analyzer Integration:**
128 | - Click any dot on dashboard charts to open size-analyzer
129 | - Automatically selects the correct platform
130 | - Pre-fills "from" version (previous) and "to" version (clicked)
131 | - Opens in new tab for seamless workflow
132 |
133 | **Supported Platforms:**
134 | - `arm64-ios`, `arm64-android`, `armv7-android`
135 | - `x86_64-macos`, `x86_64-linux`, `x86-win32`, `x86_64-win32`, `arm64-macos`
136 | - `js-web`, `wasm-web`
137 | - `bob.jar` (special handling for build tools)
138 | - `editor-*` platforms (automatic mapping from dashboard to size-analyzer)
139 |
140 | **Files:**
141 | - `index.html` - Dashboard interface
142 | - `js/dashboard.js` - Chart rendering and interaction logic
143 | - `css/dashboard.css` - Dashboard-specific styling
144 |
145 | ---
146 |
147 | ## Size Analyzer (Detailed View)
148 |
149 | ### 1. Architecture
150 |
151 | The viewer is a client-side web application with no server dependencies:
152 |
153 | **Technologies:**
154 | - **Vanilla JavaScript** - No frameworks, pure ES6+
155 | - **Plotly.js** - Interactive chart rendering
156 | - **CSS3** - Modern responsive styling
157 | - **Fetch API** - CSV data loading
158 |
159 | **Files:**
160 | - `index.html` - Main application interface
161 | - `js/app.js` - Main application logic and state management
162 | - `js/csv-parser.js` - CSV loading and data processing
163 | - `js/plotly-histogram.js` - Chart rendering and interactions
164 | - `css/style.css` - Visual styling and responsive design
165 |
166 | ### 2. Data-Driven Design
167 |
168 | #### Dynamic Platform Detection:
169 | The viewer automatically adapts to any CSV structure by reading headers:
170 |
171 | **arm64-android format:**
172 | ```csv
173 | compileunits,vmsize,filesize
174 | src/dlib/array.cpp,2048,4096
175 | ```
176 |
177 | **bob.jar format:**
178 | ```csv
179 | filename,compressed,uncompressed
180 | lib/android.jar,10299057,13989417
181 | ```
182 |
183 | **editor format (with library grouping):**
184 | ```csv
185 | filename,compressed,uncompressed
186 | jfxwebkit.dll,31852784,83512832
187 | JDK,58083658,58083658
188 | com/ibm/*.*,11528031,27028277
189 | com/sun/*.*,8886096,21765809
190 | clojure/*.*,6990823,15500531
191 | ```
192 |
193 | #### Tab Generation:
194 | Tabs are automatically created based on available metrics:
195 | - **Native Binary**: "File Size" and "VM Size" tabs
196 | - **JAR Files**: "Compressed" and "Uncompressed" tabs
197 | - **Future Formats**: Automatically supported by reading CSV headers
198 |
199 | ### 3. Core Features
200 |
201 | #### Version Selection Logic:
202 | - **Baseline Dropdown**: All versions except the latest (prevents impossible comparisons)
203 | - **Compare Dropdown**: Only versions newer than selected baseline
204 | - **Smart Defaults**: Automatically selects (latest-1) vs (latest) on load
205 | - **Preservation**: Maintains selections when switching platforms if versions exist
206 |
207 | #### Interactive Visualization:
208 | - **Horizontal Bar Charts**: Files sorted by change magnitude
209 | - **Color Coding**: Red (increased), Green (decreased) with metric-specific colors
210 | - **Threshold Filtering**: Dynamic range based on actual data
211 | - **Timeline Modal**: Click any bar to see version-by-version evolution
212 | - **Pan Navigation**: Charts support panning but prevent zoom in/out for consistent scale
213 | - **External Titles**: Chart titles displayed outside Plotly area for better mobile experience
214 | - **Enhanced Hover Areas**: Full-row hover detection with subtle gray overlays for easier interaction
215 | - **Cursor-Following Tooltips**: Tooltips positioned near cursor with Plotly-style yellow background
216 | - **File Name Tooltips**: Hover over long file names (chart y-axis or table) to see full paths
217 |
218 | #### Data Processing Pipeline:
219 | ```javascript
220 | 1. CSV Loading → CSVParser.loadCSV()
221 | 2. Header Detection → getMetricsFromHeaders()
222 | 3. Tab Creation → createDynamicTabs()
223 | 4. Data Processing → processDataByMetric()
224 | 5. Visualization → PlotlyHistogramChart.render()
225 | ```
226 |
227 | ### 4. Advanced Features
228 |
229 | #### Debug Section Filtering (Android):
230 | - Automatically detects Android platforms
231 | - Shows checkbox to hide debug-only sections
232 | - Filters sections like `.debug_str`, `.symtab`, etc.
233 | - Includes informational modal explaining debug sections
234 |
235 | #### Platform-Specific Adaptations:
236 | - **File Path Normalization**: Handles `../src/` vs `src/` inconsistencies
237 | - **Dynamic Filename Columns**: `compileunits` vs `filename`
238 | - **Metric-Specific Colors**: Different colors for different metrics
239 | - **Timeline Data**: Adapts to platform-specific CSV formats
240 |
241 | #### Performance Optimizations:
242 | - **CSV Caching**: Prevents redundant network requests
243 | - **Lazy Loading**: Only loads data when needed
244 | - **Efficient Filtering**: Client-side processing with smart algorithms
245 | - **Responsive UI**: Smooth interactions even with large datasets
246 | - **Chart Optimization**: Fixed axis ranges prevent expensive zoom calculations
247 | - **Mobile Performance**: Reduced chart complexity and disabled zoom for better touch performance
248 |
249 | ### 5. User Interface
250 |
251 | #### Main Interface:
252 | 1. **Platform Selection**: Choose between arm64-android, bob.jar, etc.
253 | 2. **Version Selection**: Smart dropdowns with validation
254 | 3. **Metric Tabs**: Dynamic tabs based on available data
255 | 4. **Threshold Control**: Filter by change magnitude
256 | 5. **Chart Info**: Dynamic title showing comparison details above chart
257 | 6. **Chart Visualization**: Interactive horizontal bar chart with pan-only navigation
258 | 7. **Data Table**: Detailed file list with filtering options
259 |
260 | #### Timeline Modal:
261 | - **Triggered**: Click any bar in the main chart
262 | - **Content**: Line chart showing file evolution across all intermediate versions
263 | - **Data**: Cumulative view from baseline to compare version
264 | - **Interaction**: Hover for details, responsive design
265 |
266 | #### URL Parameter Support:
267 | - **Cross-navigation**: Supports platform, from, and to version parameters
268 | - **Deep linking**: `size-analyzer/?platform=arm64-android&from=1.10.3&to=1.10.4`
269 | - **Dashboard integration**: Automatically applied when navigating from dashboard
270 |
271 | #### Responsive Design:
272 | - **Desktop**: Full-featured interface with side-by-side layouts and standard chart margins
273 | - **Tablet**: Stacked layouts with touch-friendly controls and adjusted chart spacing
274 | - **Mobile**: Simplified interface with collapsible sections and mobile-optimized chart layouts
275 | - **Dynamic Layout**: Charts automatically adjust margins and title positioning based on screen width
276 | - **Touch-Friendly**: Disabled zoom gestures to prevent accidental UI disruption on mobile devices
277 |
278 | ---
279 |
280 | ## Recent Improvements
281 |
282 | ### Editor Analysis Integration (v20):
283 | - **Complete Editor Analysis**: Added support for analyzing Defold editor packages across all platforms
284 | - **Combined Analysis Approach**: JAR contents + individual files + JDK grouping in unified CSV format
285 | - **Intelligent Library Grouping**: Reduced editor analysis from ~76,000 entries to ~5,500 (92% reduction)
286 | - **Test Mode**: Added `--test` flag for quick single-platform validation during development
287 | - **Dashboard Integration**: Automatic platform name mapping from dashboard to size-analyzer URLs
288 |
289 | ### Enhanced User Experience (v20):
290 | - **Full-Row Hover Detection**: Click/hover anywhere across chart rows, not just thin bars
291 | - **Cursor-Following Tooltips**: Tooltips now position near cursor instead of fixed right-side placement
292 | - **File Name Tooltips**: Hover over truncated file names (y-axis labels and table) to see complete paths
293 | - **Smart Tooltip Styling**: Maintained Plotly-style yellow background with dynamic width adaptation
294 | - **Subtle Visual Cues**: Light gray overlay bars indicate hoverable areas without interfering with data
295 |
296 | ### Mobile & Touch Optimization (v19):
297 | - **Responsive Chart Titles**: Moved chart titles outside Plotly area to prevent mobile overlap with modebar
298 | - **Zoom Restrictions**: Disabled zoom in/out to maintain consistent scale and prevent accidental gestures
299 | - **Touch Navigation**: Enabled pan-only interaction for better mobile experience
300 | - **Dynamic Margins**: Charts automatically adjust spacing based on screen width (≤768px detection)
301 | - **Simplified Controls**: Streamlined arrow labels ("← smaller" / "bigger →") for mobile readability
302 |
303 | ### Error Handling & Stability:
304 | - **Version Parsing**: Fixed `version.split is not a function` error in timeline modal
305 | - **Type Safety**: Added string conversion safeguards for version processing
306 | - **Data Validation**: Improved handling of analysis_index.json structure changes
307 | - **Cross-Platform URL Mapping**: Automatic conversion between dashboard platform keys and size-analyzer directories
308 |
309 | ---
310 |
311 | ## Usage Examples
312 |
313 | ### Dashboard Workflow:
314 | 1. Open dashboard (`index.html`) for overview of all components
315 | 2. Use version dropdowns to focus on specific time ranges
316 | 3. Use legend controls to filter platforms:
317 | - Click to toggle platform visibility
318 | - Alt+click to show only one platform
319 | 4. Click any data point to dive into detailed analysis
320 | 5. Size analyzer opens with pre-selected comparison
321 |
322 | ### Comparing Engine Sizes:
323 | 1. Select "arm64-android" platform (or navigate from dashboard)
324 | 2. Choose baseline version (e.g., 1.10.3)
325 | 3. Choose compare version (e.g., 1.10.4)
326 | 4. Switch between "File Size" and "VM Size" tabs
327 | 5. Adjust threshold to focus on significant changes
328 | 6. Click bars to see detailed timeline evolution
329 |
330 | ### Analyzing JAR Components:
331 | 1. Select "bob.jar" platform
332 | 2. Choose version range for comparison
333 | 3. Switch between "Compressed" and "Uncompressed" tabs
334 | 4. Identify which JAR entries contribute most to size changes
335 | 5. Use timeline view to understand growth patterns
336 |
337 | ### Analyzing Editor Components:
338 | 1. Select any "editor-*" platform (win32, linux, macos)
339 | 2. Choose version range for comparison (editor analysis starts from 1.10.3)
340 | 3. Switch between "Compressed" and "Uncompressed" tabs
341 | 4. Analyze grouped libraries (com/ibm/*.*, com/sun/*.*, etc.) and individual components
342 | 5. Compare JDK overhead vs application code vs bundled libraries
343 | 6. Use hover tooltips to see full component names for grouped entries
344 |
345 | ### Debug Analysis (Android):
346 | 1. Select arm64-android platform
347 | 2. Check "Hide debug sections" to focus on runtime code
348 | 3. Click info button to understand debug section types
349 | 4. Compare with/without debug sections to understand overhead
350 |
351 | ---
352 |
353 | ## Technical Details
354 |
355 | ### CSV Format Requirements:
356 | - **First column**: Must be filename/path (any name containing "filename" or "compileunits")
357 | - **Other columns**: Numeric size metrics (any names)
358 | - **Headers**: Used to generate tab names automatically
359 | - **Encoding**: UTF-8 with proper CSV escaping
360 |
361 | ### Browser Compatibility:
362 | - **Modern browsers**: Chrome 80+, Firefox 75+, Safari 13+, Edge 80+
363 | - **Features used**: ES6 modules, Fetch API, CSS Grid, Flexbox, window.innerWidth detection
364 | - **Mobile browsers**: iOS Safari 13+, Android Chrome 80+, mobile-optimized interactions
365 | - **No IE support**: Uses modern JavaScript features and responsive design
366 |
367 | ### Performance Characteristics:
368 | - **Data loading**: ~100ms per CSV file (cached after first load)
369 | - **Processing**: <50ms for datasets up to 10,000 files
370 | - **Rendering**: <200ms for charts with 1,000+ bars
371 | - **Memory usage**: ~5MB for typical datasets
372 |
373 | ### Extensibility:
374 | The tool is designed to handle new platforms automatically:
375 | 1. Add CSV files in new platform directory
376 | 2. Update `analysis_index.json` with platform info
377 | 3. Add platform to dashboard CSV reports (bundle_report.csv, engine_report.csv, etc.)
378 | 4. Dashboard and size analyzer automatically detect and support new format
379 | 5. No code changes required for new metrics or platforms
380 |
381 | ### Cross-Navigation:
382 | **URL Parameter Flow:**
383 | ```
384 | Dashboard Click → Generate URL → Open Size Analyzer → Parse Parameters → Apply Selection
385 | ```
386 |
387 | **Data Flow:**
388 | ```
389 | CSV Reports → Dashboard Charts → User Click → URL Generation → Size Analyzer → Detailed Analysis
390 | ```
391 |
392 | **Supported URL Parameters:**
393 | - `platform`: Platform key (e.g., arm64-android, bob.jar)
394 | - `from`: Baseline version for comparison
395 | - `to`: Target version for comparison
--------------------------------------------------------------------------------
/size-analyzer/css/style.css:
--------------------------------------------------------------------------------
1 | /* Reset and base styles */
2 | * {
3 | margin: 0;
4 | padding: 0;
5 | box-sizing: border-box;
6 | }
7 |
8 | body {
9 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
10 | line-height: 1.6;
11 | color: #333;
12 | background-color: #f5f5f5;
13 | }
14 |
15 | .container {
16 | max-width: 1400px;
17 | margin: 0 auto;
18 | padding: 20px;
19 | }
20 |
21 | /* Header */
22 | header {
23 | text-align: center;
24 | margin-bottom: 30px;
25 | }
26 |
27 | header h1 {
28 | color: #2c3e50;
29 | margin-bottom: 10px;
30 | font-size: 2.5em;
31 | font-weight: 300;
32 | }
33 |
34 | header p {
35 | color: #666;
36 | font-size: 1.1em;
37 | }
38 |
39 | /* Controls */
40 | .controls {
41 | background: white;
42 | padding: 25px;
43 | border-radius: 8px;
44 | box-shadow: 0 2px 10px rgba(0,0,0,0.1);
45 | margin-bottom: 20px;
46 | display: grid;
47 | grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
48 | gap: 20px;
49 | align-items: end;
50 | position: relative;
51 | z-index: 100;
52 | }
53 |
54 | .control-group {
55 | display: flex;
56 | flex-direction: column;
57 | }
58 |
59 | .control-group label {
60 | margin-bottom: 5px;
61 | font-weight: 500;
62 | color: #555;
63 | }
64 |
65 | .control-group select,
66 | .control-group button {
67 | padding: 8px 12px;
68 | border: 2px solid #ddd;
69 | border-radius: 4px;
70 | font-size: 14px;
71 | background: white;
72 | transition: border-color 0.2s, box-shadow 0.2s;
73 | }
74 |
75 | .control-group select:focus,
76 | .control-group button:focus {
77 | outline: none;
78 | border-color: #3498db;
79 | box-shadow: 0 0 0 3px rgba(52, 152, 219, 0.1);
80 | }
81 |
82 | .control-group select:disabled {
83 | background-color: #f8f9fa;
84 | color: #6c757d;
85 | }
86 |
87 | .checkbox-group {
88 | display: flex;
89 | gap: 15px;
90 | flex-wrap: wrap;
91 | }
92 |
93 | .checkbox-label {
94 | display: flex;
95 | align-items: center;
96 | gap: 5px;
97 | cursor: pointer;
98 | font-weight: normal !important;
99 | }
100 |
101 | .checkbox-label input[type="checkbox"] {
102 | margin: 0;
103 | }
104 |
105 | button.info-button {
106 | background: none;
107 | border: none;
108 | color: #666;
109 | cursor: pointer;
110 | padding: 2px;
111 | margin-left: 6px;
112 | border-radius: 50%;
113 | width: 20px;
114 | height: 20px;
115 | display: inline-flex;
116 | align-items: center;
117 | justify-content: center;
118 | transition: all 0.2s;
119 | vertical-align: middle;
120 | }
121 |
122 | button.info-button:hover {
123 | background: #e9ecef;
124 | color: #495057;
125 | }
126 |
127 | button.info-button svg {
128 | width: 14px;
129 | height: 14px;
130 | fill: currentColor;
131 | }
132 |
133 | button {
134 | background: #3498db;
135 | color: white;
136 | border: none;
137 | cursor: pointer;
138 | font-weight: 500;
139 | transition: background-color 0.2s;
140 | }
141 |
142 | button:hover:not(:disabled) {
143 | background: #2980b9;
144 | }
145 |
146 | button:disabled {
147 | background: #bdc3c7;
148 | cursor: not-allowed;
149 | }
150 |
151 | /* Slider styles */
152 | .slider {
153 | width: 100%;
154 | height: 5px;
155 | border-radius: 5px;
156 | background: #ddd;
157 | outline: none;
158 | opacity: 0.7;
159 | transition: opacity 0.2s;
160 | -webkit-appearance: none;
161 | }
162 |
163 | .slider:hover {
164 | opacity: 1;
165 | }
166 |
167 | .slider::-webkit-slider-thumb {
168 | -webkit-appearance: none;
169 | appearance: none;
170 | width: 20px;
171 | height: 20px;
172 | border-radius: 50%;
173 | background: #3498db;
174 | cursor: pointer;
175 | }
176 |
177 | .slider::-moz-range-thumb {
178 | width: 20px;
179 | height: 20px;
180 | border-radius: 50%;
181 | background: #3498db;
182 | cursor: pointer;
183 | border: none;
184 | }
185 |
186 | /* Table filters */
187 | .table-filters {
188 | display: grid;
189 | grid-template-columns: 2fr 1fr 1fr 1fr;
190 | gap: 10px;
191 | margin-bottom: 20px;
192 | padding: 15px;
193 | background: #f8f9fa;
194 | border-radius: 4px;
195 | }
196 |
197 | .table-filters input,
198 | .table-filters select {
199 | padding: 8px 12px;
200 | border: 1px solid #ddd;
201 | border-radius: 4px;
202 | font-size: 14px;
203 | }
204 |
205 | .file-list-section h4 {
206 | margin-bottom: 15px;
207 | color: #2c3e50;
208 | }
209 |
210 | /* Status */
211 | .status {
212 | background: #e8f4fd;
213 | border: 1px solid #bee5eb;
214 | color: #0c5460;
215 | padding: 15px;
216 | border-radius: 4px;
217 | margin-bottom: 20px;
218 | text-align: center;
219 | }
220 |
221 | /* Tabs */
222 | .tabs {
223 | margin-bottom: 20px;
224 | }
225 |
226 | .tab-buttons {
227 | display: flex;
228 | background: white;
229 | border-radius: 8px;
230 | box-shadow: 0 2px 10px rgba(0,0,0,0.1);
231 | overflow: hidden;
232 | }
233 |
234 | .tab-button {
235 | flex: 1;
236 | padding: 15px 20px;
237 | background: #f8f9fa;
238 | border: none;
239 | cursor: pointer;
240 | font-size: 16px;
241 | font-weight: 500;
242 | color: #666;
243 | transition: all 0.2s;
244 | border-right: 1px solid #dee2e6;
245 | }
246 |
247 | .tab-button:last-child {
248 | border-right: none;
249 | }
250 |
251 | .tab-button:hover {
252 | background: #e9ecef;
253 | color: #495057;
254 | }
255 |
256 | .tab-button.active {
257 | background: #3498db;
258 | color: white;
259 | }
260 |
261 | .tab-button.active:hover {
262 | background: #2980b9;
263 | }
264 |
265 | .status.error {
266 | background: #f8d7da;
267 | border-color: #f5c6cb;
268 | color: #721c24;
269 | }
270 |
271 | .status.success {
272 | background: #d4edda;
273 | border-color: #c3e6cb;
274 | color: #155724;
275 | }
276 |
277 | /* Legend */
278 | .legend {
279 | background: white;
280 | padding: 20px;
281 | border-radius: 8px;
282 | box-shadow: 0 2px 10px rgba(0,0,0,0.1);
283 | margin-bottom: 20px;
284 | }
285 |
286 | .legend h3 {
287 | margin-bottom: 15px;
288 | color: #2c3e50;
289 | }
290 |
291 | .legend-items {
292 | display: flex;
293 | gap: 25px;
294 | flex-wrap: wrap;
295 | }
296 |
297 | .legend-item {
298 | display: flex;
299 | align-items: center;
300 | gap: 8px;
301 | }
302 |
303 | .legend-color {
304 | width: 20px;
305 | height: 20px;
306 | border-radius: 3px;
307 | }
308 |
309 | .legend-color.unchanged {
310 | background: #95a5a6;
311 | }
312 |
313 | .legend-color.decreased {
314 | background: #27ae60;
315 | }
316 |
317 | .legend-color.increased {
318 | background: #e74c3c;
319 | }
320 |
321 | /* Visualization */
322 | .visualization {
323 | background: white;
324 | border-radius: 8px;
325 | box-shadow: 0 2px 10px rgba(0,0,0,0.1);
326 | margin-bottom: 20px;
327 | overflow: hidden;
328 | }
329 |
330 | .chart-container {
331 | position: relative;
332 | min-height: 600px;
333 | z-index: 1;
334 | }
335 |
336 | #metric-chart {
337 | max-height: 800px;
338 | overflow-y: auto;
339 | overflow-x: auto;
340 | position: relative;
341 | z-index: 1;
342 | margin-top: -10px;
343 | padding-top: 15px;
344 | }
345 |
346 | .chart-header {
347 | display: flex;
348 | justify-content: space-between;
349 | align-items: center;
350 | padding: 20px 40px 10px;
351 | background: #f8f9fa;
352 | border-bottom: 1px solid #dee2e6;
353 | position: relative;
354 | z-index: 50;
355 | }
356 |
357 | .version-label {
358 | font-weight: 600;
359 | color: #495057;
360 | font-size: 1.1em;
361 | }
362 |
363 | .chart-controls {
364 | display: flex;
365 | gap: 8px;
366 | align-items: center;
367 | position: relative;
368 | z-index: 200;
369 | }
370 |
371 | .chart-info {
372 | color: #666;
373 | font-size: 14px;
374 | font-style: italic;
375 | }
376 |
377 |
378 | /* Interactive elements */
379 | .chart-container .node rect {
380 | transition: stroke-width 0.2s;
381 | }
382 |
383 | .chart-container .node:hover rect {
384 | stroke-width: 2px;
385 | }
386 |
387 | .chart-container .link {
388 | transition: stroke-opacity 0.2s;
389 | }
390 |
391 | .chart-container .link:hover {
392 | stroke-opacity: 1 !important;
393 | }
394 |
395 | /* Details */
396 | .details {
397 | background: white;
398 | padding: 25px;
399 | border-radius: 8px;
400 | box-shadow: 0 2px 10px rgba(0,0,0,0.1);
401 | }
402 |
403 | .details h3 {
404 | margin-bottom: 20px;
405 | color: #2c3e50;
406 | }
407 |
408 | .summary {
409 | margin-bottom: 20px;
410 | padding: 15px;
411 | background: #f8f9fa;
412 | border-radius: 4px;
413 | }
414 |
415 | .summary-item {
416 | display: flex;
417 | justify-content: space-between;
418 | margin-bottom: 8px;
419 | }
420 |
421 | .summary-item:last-child {
422 | margin-bottom: 0;
423 | }
424 |
425 | .file-list {
426 | max-height: 800px;
427 | overflow-y: auto;
428 | position: relative;
429 | z-index: 1;
430 | }
431 |
432 | .file-list-header {
433 | display: flex;
434 | justify-content: space-between;
435 | align-items: center;
436 | padding: 12px 10px;
437 | background-color: #f8f9fa;
438 | border: 1px solid #dee2e6;
439 | border-bottom: 2px solid #adb5bd;
440 | font-weight: 600;
441 | color: #495057;
442 | position: sticky;
443 | top: 0;
444 | z-index: 10;
445 | }
446 |
447 | .file-name-header {
448 | flex: 1;
449 | font-family: 'Courier New', monospace;
450 | font-size: 0.9em;
451 | }
452 |
453 | .file-sizes-header {
454 | display: flex;
455 | gap: 15px;
456 | align-items: center;
457 | font-size: 0.9em;
458 | }
459 |
460 | .size-value-header,
461 | .size-change-header {
462 | min-width: 80px;
463 | text-align: center;
464 | font-size: 0.85em;
465 | }
466 |
467 | .file-item {
468 | display: flex;
469 | justify-content: space-between;
470 | align-items: center;
471 | padding: 10px;
472 | border-bottom: 1px solid #eee;
473 | transition: background-color 0.2s;
474 | }
475 |
476 | .file-item:hover {
477 | background-color: #f8f9fa;
478 | }
479 |
480 | .file-item:last-child {
481 | border-bottom: none;
482 | }
483 |
484 | .file-name {
485 | flex: 1;
486 | font-family: 'Courier New', monospace;
487 | font-size: 0.9em;
488 | word-break: break-all;
489 | }
490 |
491 | .file-name-tooltip {
492 | cursor: help;
493 | }
494 |
495 | .file-sizes {
496 | display: flex;
497 | gap: 15px;
498 | align-items: center;
499 | font-size: 0.9em;
500 | }
501 |
502 | .size-value {
503 | min-width: 80px;
504 | text-align: right;
505 | }
506 |
507 | .size-change {
508 | min-width: 60px;
509 | text-align: right;
510 | font-weight: 500;
511 | }
512 |
513 | .size-change.positive {
514 | color: #e74c3c;
515 | }
516 |
517 | .size-change.negative {
518 | color: #27ae60;
519 | }
520 |
521 | .size-change.neutral {
522 | color: #95a5a6;
523 | }
524 |
525 | /* Sortable headers */
526 | .sortable-header {
527 | cursor: pointer;
528 | user-select: none;
529 | position: relative;
530 | transition: background-color 0.2s ease, color 0.2s ease;
531 | }
532 |
533 | .sortable-header:hover {
534 | background-color: #e9ecef;
535 | color: #495057;
536 | }
537 |
538 | .sortable-header:active {
539 | background-color: #dee2e6;
540 | }
541 |
542 | /* Sort direction indicators */
543 | .sortable-header::after {
544 | content: '';
545 | opacity: 0.3;
546 | margin-left: 0.5em;
547 | }
548 |
549 | .sortable-header:hover::after {
550 | opacity: 0.6;
551 | }
552 |
553 | /* Ensure Plotly tooltips remain readable with classic styling */
554 | .plotly .hovertext {
555 | background: #FFFFDD !important;
556 | color: black !important;
557 | border: 1px solid #333 !important;
558 | }
559 |
560 | .plotly .hovertext text {
561 | fill: black !important;
562 | }
563 |
564 | /* Override any colorful tooltip backgrounds */
565 | g.hovertext {
566 | background: #FFFFDD !important;
567 | }
568 |
569 | g.hovertext rect {
570 | fill: #FFFFDD !important;
571 | stroke: #333 !important;
572 | }
573 |
574 | g.hovertext text {
575 | fill: black !important;
576 | }
577 |
578 | /* Safari scrollbar fixes */
579 | .file-list::-webkit-scrollbar {
580 | width: 8px;
581 | }
582 |
583 | .file-list::-webkit-scrollbar-track {
584 | background: #f1f1f1;
585 | border-radius: 4px;
586 | }
587 |
588 | .file-list::-webkit-scrollbar-thumb {
589 | background: #c1c1c1;
590 | border-radius: 4px;
591 | }
592 |
593 | .file-list::-webkit-scrollbar-thumb:hover {
594 | background: #a8a8a8;
595 | }
596 |
597 | #metric-chart::-webkit-scrollbar {
598 | width: 8px;
599 | height: 8px;
600 | }
601 |
602 | #metric-chart::-webkit-scrollbar-track {
603 | background: #f1f1f1;
604 | border-radius: 4px;
605 | }
606 |
607 | #metric-chart::-webkit-scrollbar-thumb {
608 | background: #c1c1c1;
609 | border-radius: 4px;
610 | }
611 |
612 | #metric-chart::-webkit-scrollbar-thumb:hover {
613 | background: #a8a8a8;
614 | }
615 |
616 | /* Ensure scrollable areas have proper isolation */
617 | .file-list, #metric-chart {
618 | isolation: isolate;
619 | }
620 |
621 | /* Plotly modebar (chart controls) fixes - keep on right with spacing from scrollbar */
622 | .modebar {
623 | position: absolute !important;
624 | right: 20px !important;
625 | top: 10px !important;
626 | z-index: 300 !important;
627 | }
628 |
629 | .modebar-group {
630 | position: relative !important;
631 | z-index: 300 !important;
632 | }
633 |
634 | .modebar-btn {
635 | z-index: 300 !important;
636 | }
637 |
638 | /* Prevent scrollbars from covering Plotly controls */
639 | .plotly > div {
640 | position: relative;
641 | }
642 |
643 | .plotly .modebar-container {
644 | position: relative !important;
645 | z-index: 300 !important;
646 | }
647 |
648 | /* Tooltip */
649 | .tooltip {
650 | position: absolute;
651 | background: rgba(0, 0, 0, 0.9);
652 | color: white;
653 | padding: 10px;
654 | border-radius: 4px;
655 | font-size: 12px;
656 | pointer-events: none;
657 | z-index: 1000;
658 | opacity: 0;
659 | transition: opacity 0.2s;
660 | max-width: 300px;
661 | line-height: 1.4;
662 | }
663 |
664 | .tooltip.visible {
665 | opacity: 1;
666 | }
667 |
668 | /* Responsive design */
669 | @media (max-width: 768px) {
670 | .controls {
671 | grid-template-columns: 1fr;
672 | }
673 |
674 | .legend-items {
675 | flex-direction: column;
676 | gap: 10px;
677 | }
678 |
679 | .chart-header {
680 | padding: 15px 20px 10px;
681 | }
682 |
683 | .file-sizes {
684 | flex-direction: column;
685 | gap: 5px;
686 | align-items: flex-end;
687 | }
688 | }
689 |
690 | /* Loading state */
691 | .loading {
692 | text-align: center;
693 | padding: 40px;
694 | color: #666;
695 | }
696 |
697 | .loading::after {
698 | content: '';
699 | display: inline-block;
700 | width: 20px;
701 | height: 20px;
702 | border: 2px solid #ddd;
703 | border-top: 2px solid #3498db;
704 | border-radius: 50%;
705 | animation: spin 1s linear infinite;
706 | margin-left: 10px;
707 | }
708 |
709 | @keyframes spin {
710 | 0% { transform: rotate(0deg); }
711 | 100% { transform: rotate(360deg); }
712 | }
713 |
714 | /* Timeline Modal Styles */
715 | .timeline-modal-backdrop {
716 | position: fixed;
717 | top: 0;
718 | left: 0;
719 | width: 100%;
720 | height: 100%;
721 | background: rgba(0, 0, 0, 0.5);
722 | z-index: 10000;
723 | display: flex;
724 | align-items: center;
725 | justify-content: center;
726 | animation: fadeIn 0.2s ease-out;
727 | }
728 |
729 | @keyframes fadeIn {
730 | from { opacity: 0; }
731 | to { opacity: 1; }
732 | }
733 |
734 | .timeline-modal {
735 | background: white;
736 | border-radius: 12px;
737 | box-shadow: 0 10px 40px rgba(0, 0, 0, 0.2);
738 | width: 90%;
739 | max-width: 900px;
740 | max-height: 90vh;
741 | overflow: hidden;
742 | animation: slideIn 0.3s ease-out;
743 | }
744 |
745 | @keyframes slideIn {
746 | from {
747 | opacity: 0;
748 | transform: scale(0.95) translateY(-20px);
749 | }
750 | to {
751 | opacity: 1;
752 | transform: scale(1) translateY(0);
753 | }
754 | }
755 |
756 | .timeline-modal-header {
757 | padding: 25px 30px 20px;
758 | border-bottom: 1px solid #e1e5e9;
759 | background: #f8f9fa;
760 | position: relative;
761 | }
762 |
763 | .timeline-modal-header h3 {
764 | margin: 0 0 10px 0;
765 | color: #2c3e50;
766 | font-size: 1.4em;
767 | font-weight: 600;
768 | word-break: break-all;
769 | padding-right: 40px;
770 | }
771 |
772 | .timeline-modal-summary {
773 | color: #666;
774 | font-size: 14px;
775 | }
776 |
777 | .timeline-modal-close {
778 | position: absolute;
779 | top: 20px;
780 | right: 25px;
781 | background: none;
782 | border: none;
783 | font-size: 24px;
784 | color: #999;
785 | cursor: pointer;
786 | width: 30px;
787 | height: 30px;
788 | display: flex;
789 | align-items: center;
790 | justify-content: center;
791 | border-radius: 50%;
792 | transition: all 0.2s;
793 | }
794 |
795 | .timeline-modal-close:hover {
796 | background: #f0f0f0;
797 | color: #666;
798 | }
799 |
800 | .timeline-modal-body {
801 | padding: 25px 30px 30px;
802 | max-height: calc(90vh - 120px);
803 | overflow-y: auto;
804 | }
805 |
806 | .timeline-loading {
807 | display: flex;
808 | flex-direction: column;
809 | align-items: center;
810 | padding: 40px 20px;
811 | color: #666;
812 | }
813 |
814 | .loading-spinner {
815 | width: 32px;
816 | height: 32px;
817 | border: 3px solid #f0f0f0;
818 | border-top: 3px solid #3498db;
819 | border-radius: 50%;
820 | animation: spin 1s linear infinite;
821 | margin-bottom: 15px;
822 | }
823 |
824 | .timeline-loading p {
825 | margin: 0;
826 | font-size: 16px;
827 | }
828 |
829 | /* Responsive Design */
830 | @media (max-width: 768px) {
831 | .timeline-modal {
832 | width: 95%;
833 | margin: 20px;
834 | max-height: calc(100vh - 40px);
835 | }
836 |
837 | .timeline-modal-header {
838 | padding: 20px;
839 | }
840 |
841 | .timeline-modal-header h3 {
842 | font-size: 1.2em;
843 | padding-right: 35px;
844 | }
845 |
846 | .timeline-modal-close {
847 | top: 15px;
848 | right: 15px;
849 | font-size: 20px;
850 | width: 26px;
851 | height: 26px;
852 | }
853 |
854 | .timeline-modal-body {
855 | padding: 20px;
856 | }
857 | }
858 |
859 | @media (max-width: 480px) {
860 | .timeline-modal {
861 | width: 100%;
862 | height: 100%;
863 | max-height: 100vh;
864 | border-radius: 0;
865 | margin: 0;
866 | }
867 |
868 | .timeline-modal-header h3 {
869 | font-size: 1.1em;
870 | line-height: 1.3;
871 | }
872 | }
--------------------------------------------------------------------------------
/check_size.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 | import os
3 | import sys
4 | import subprocess
5 | import tempfile
6 | import urllib
7 | import urllib.request
8 | import datetime
9 | import itertools
10 | import json
11 | import shutil
12 | import csv
13 | import zipfile
14 | import matplotlib
15 | matplotlib.use('Agg')
16 |
17 | from matplotlib import pyplot
18 | from collections import OrderedDict
19 |
20 |
21 | # https://matplotlib.org/stable/api/markers_api.html
22 | markers = '.o8s+xD*pP<<>'
23 |
24 | # old list containing architectures we no longer use
25 | # also a mix of engines and archives (apk vs engine binary)
26 | legacy_engines = [
27 | {"platform": "arm64-darwin", "filename": "dmengine_release"},
28 | {"platform": "armv7-android", "filename": "dmengine_release.apk"}, # added in 1.2.153
29 | {"platform": "armv7-darwin", "filename": "dmengine_release"},
30 | {"platform": "darwin", "filename": "dmengine_release"},
31 | {"platform": "js-web", "filename": "dmengine_release.js"},
32 | {"platform": "wasm-web", "filename": "dmengine_release.wasm"}, # added in 1.2.141
33 | {"platform": "linux", "filename": "dmengine_release"},
34 | {"platform": "win32", "filename": "dmengine_release.exe"},
35 | {"platform": "x86_64-darwin", "filename": "dmengine_release"},
36 | {"platform": "x86_64-linux", "filename": "dmengine_release"},
37 | {"platform": "armv7-android", "filename": "dmengine.apk"},
38 | {"platform": "arm64-android", "filename": "dmengine.apk"},
39 | ]
40 |
41 | engines = [
42 | {"platform": "arm64-ios", "filename": "dmengine_release"},
43 | {"platform": "arm64-android", "filename": "libdmengine_release.so"},
44 | {"platform": "armv7-android", "filename": "libdmengine_release.so"},
45 | {"platform": "x86_64-macos", "filename": "dmengine_release"},
46 | {"platform": "arm64-macos", "filename": "dmengine_release"},
47 | {"platform": "js-web", "filename": "dmengine_release.js"},
48 | {"platform": "wasm-web", "filename": "dmengine_release.wasm"},
49 | {"platform": "x86_64-linux", "filename": "dmengine_release"},
50 | {"platform": "x86-win32", "filename": "dmengine_release.exe"},
51 | {"platform": "x86_64-win32", "filename": "dmengine_release.exe"},
52 | ]
53 |
54 | bundles = [
55 | {"platform": "arm64-ios", "filename": "notused"},
56 | {"platform": "arm64-android", "filename": "notused"},
57 | {"platform": "armv7-android", "filename": "notused"},
58 | {"platform": "x86_64-macos", "filename": "notused"},
59 | {"platform": "arm64-macos", "filename": "notused"},
60 | {"platform": "js-web", "filename": "notused"},
61 | {"platform": "wasm-web", "filename": "notused"},
62 | {"platform": "x86_64-linux", "filename": "notused"},
63 | {"platform": "x86-win32", "filename": "notused"},
64 | {"platform": "x86_64-win32", "filename": "notused"},
65 | ]
66 |
67 | # each platform is the same size (it's the same bundle)
68 | bob_files = [
69 | {"platform": "x86_64-macos", "filename": "bob.jar"},
70 | ]
71 |
72 | editor_files = [
73 | {"platform": "x86_64-macos", "filename": "Defold-x86_64-macos.dmg"},
74 | {"platform": "arm64-macos", "filename": "Defold-arm64-macos.dmg"},
75 | {"platform": "x86_64-win32", "filename": "Defold-x86_64-win32.zip"},
76 | {"platform": "x86_64-linux", "filename": "Defold-x86_64-linux.zip"},
77 | ]
78 | #editor2/Defold-x86_64-macos.dmg
79 |
80 | def get_host():
81 | if sys.platform == 'linux2':
82 | return 'linux'
83 | elif sys.platform == 'win32':
84 | return 'windows'
85 | elif sys.platform == 'darwin':
86 | return 'macos'
87 | raise "Unknown platform"
88 |
89 | def download_bob(sha1):
90 | bob_path = 'bob_{}.jar'.format(sha1)
91 | if not os.path.exists(bob_path):
92 | print("Downloading bob version {} to {}".format(sha1, bob_path))
93 | url = "http://d.defold.com/archive/stable/" + sha1 + "/bob/bob.jar"
94 | urllib.request.urlretrieve(url, bob_path)
95 | return bob_path
96 |
97 | def get_size_from_url(sha1, path):
98 | url = "http://d.defold.com/archive/" + sha1 + "/" + path
99 | try:
100 | d = urllib.request.urlopen(url)
101 | if d.getcode() == 200:
102 | return d.info()['Content-Length']
103 | except urllib.error.HTTPError as e:
104 | if e.code == 404:
105 | print(e.code, "Url doesn't exist:", url)
106 | return 0
107 |
108 | def get_engine_size_from_aws(sha1, platform, filename):
109 | if platform == "x86-win32":
110 | platform = "win32"
111 | path = "engine/{}/stripped/{}"
112 | print("Gettings size of {} for platform {} with sha1 {} from AWS".format(filename, platform, sha1))
113 | path = path.format(platform, filename)
114 | size = get_size_from_url(sha1, path)
115 | if size == 0:
116 | path = "engine/{}/{}"
117 | path = path.format(platform, filename)
118 | size = get_size_from_url(sha1, path)
119 | if size == 0:
120 | path = "engine/{}/{}".format(platform, filename)
121 | size = get_size_from_url(sha1, path)
122 | return size
123 |
124 | def get_bob_size_from_aws(sha1, platform, filename):
125 | print("Gettings size of {} for platform {} with sha1 {} from AWS".format(filename, platform, sha1))
126 | path = "bob/{}".format(filename)
127 | size = get_size_from_url(sha1, path)
128 | return size
129 |
130 | def get_editor_size_from_aws(sha1, platform, filename):
131 | print("Gettings size of {} for platform {} with sha1 {} from AWS".format(filename, platform, sha1))
132 | path = "editor-alpha/editor2/{}".format(filename)
133 | size = get_size_from_url(sha1, path)
134 | return size
135 |
136 | def extract_from_bob(bob_path, filename):
137 | bob_zip = zipfile.ZipFile(bob_path)
138 | bob_info = bob_zip.getinfo(filename)
139 | return bob_zip.extract(bob_info)
140 |
141 | def get_engine_size_from_bob(sha1, platform, filename):
142 | print("Gettings size of {} for platform {} with sha1 {} from Bob".format(filename, platform, sha1))
143 | try:
144 | bob_path = download_bob(sha1)
145 | engine_path = 'libexec/{}/{}'.format(platform, filename)
146 | extracted_engine = extract_from_bob(bob_path, engine_path)
147 | return os.path.getsize(extracted_engine)
148 | except Exception as e:
149 | print(e)
150 | return 0
151 |
152 | def get_engine_size(sha1, platform, filename):
153 | # Try to get the engine size from Bob
154 | size = get_engine_size_from_bob(sha1, platform, filename)
155 | if size > 0:
156 | return size
157 |
158 | # Fall back to getting the engine size from AWS
159 | size = get_engine_size_from_aws(sha1, platform, filename)
160 | return size
161 |
162 | def get_zipped_size(path):
163 | tmp = tempfile.NamedTemporaryFile("wb")
164 | z = zipfile.ZipFile(tmp, "w", zipfile.ZIP_DEFLATED)
165 | for root, dirs, files in os.walk(path):
166 | for file in files:
167 | z.write(os.path.join(root, file))
168 | print("write " + os.path.join(root, file))
169 | z.close()
170 | return os.path.getsize(tmp.name)
171 |
172 | def get_folder_size(path):
173 | size = 0
174 | for root, dirs, files in os.walk(path):
175 | for file in files:
176 | size = size + os.path.getsize(os.path.join(root, file))
177 | return size
178 |
179 | def get_bundle_size_from_bob(sha1, platform, _):
180 | print("Gettings size of bundle for platform {} with sha1 {} using Bob".format(platform, sha1))
181 | if os.path.exists("bundle_output"):
182 | shutil.rmtree("bundle_output")
183 | os.mkdir("bundle_output")
184 |
185 | try:
186 | bob_path = download_bob(sha1)
187 | bob_filename = os.path.basename(bob_path)
188 | shutil.copy(bob_path, os.path.join("empty_project", "bob.jar"))
189 | args = []
190 | args.append("java")
191 | args.append("-jar")
192 | args.append("bob.jar")
193 | args.append("--archive")
194 | if platform in ("armv7-android", "arm64-android"):
195 | args.append("--platform=armv7-android")
196 | args.append("--architectures=" + platform)
197 | args.append("--bundle-format="+"aab")
198 | elif platform in ("wasm-web", "js-web"):
199 | args.append("--platform=js-web")
200 | args.append("--architectures=" + platform)
201 | elif platform in ("x86_64-macos", "arm64-macos"):
202 | args.append("--platform=x86_64-macos")
203 | args.append("--architectures=" + platform)
204 | else:
205 | args.append("--platform=" + platform)
206 | args.append("--variant=release")
207 | args.append("--strip-executable")
208 | args.append("--bundle-output=../bundle_output")
209 | args.extend(["clean", "build", "bundle"])
210 |
211 | subprocess.call(args,cwd="empty_project")
212 |
213 | if platform in ("armv7-android", "arm64-android"):
214 | return os.path.getsize("bundle_output/unnamed/unnamed.aab")
215 | elif platform in ("arm64-ios","x86_64-ios","arm64-darwin"):
216 | return os.path.getsize("bundle_output/unnamed.ipa")
217 | elif platform in ("x86_64-macos", "x86_64-darwin", "arm64-macos"):
218 | return get_folder_size("bundle_output/unnamed.app")
219 | elif platform in ("x86_64-win32", "x86-win32"):
220 | return get_zipped_size("bundle_output")
221 | elif platform in ("x86_64-linux",):
222 | return get_zipped_size("bundle_output")
223 | elif platform in ("wasm-web", "js-web"):
224 | return get_zipped_size("bundle_output")
225 | else:
226 | raise Exception("Unknown platform {}". format(platform))
227 | except Exception as e:
228 | print(e)
229 | return 0
230 |
231 |
232 | def get_latest_version():
233 | url = "http://d.defold.com/stable/info.json"
234 | response = urllib.request.urlopen(url)
235 | if response.getcode() == 200:
236 | return json.loads(response.read())
237 | return {}
238 |
239 | def read_releases(path):
240 | with open(path, 'rb') as f:
241 | d = json.loads(f.read())
242 | return d
243 | return {}
244 |
245 | def version_to_number(version):
246 | tokens = version.split('.')
247 | ints = list(map(int, tokens))
248 | n = ints[0] * 100000 + ints[1] * 1000 + ints[2]
249 | return n
250 |
251 |
252 | def number_to_version(number):
253 | major = number // 100000
254 | number -= major * 100000
255 | middle = number // 1000
256 | number -= middle * 1000 #minor
257 | return "%d.%d.%d" % (major, middle, number)
258 |
259 |
260 | def print_report(report):
261 |
262 | """
263 | {
264 | 'version' = ['1.3.3', '1.3.4', '1.3.5'],
265 | 'arm64-ios' = {
266 | '1.3.4' = 123456,
267 | '1.3.5' = 123789,
268 | }
269 | 'x86_64-macos' = {
270 | ...
271 | }
272 | ...
273 | }
274 | """
275 | print("report:")
276 | for key, data in report.items():
277 | if key == 'version':
278 | print(" version:")
279 | for version in data:
280 | print(" ", version)
281 | continue
282 | platform = key
283 | print(" platform:", platform)
284 | for version, size in data.items():
285 | print(" ", version, ":", size)
286 |
287 | def read_report(path):
288 | #format:
289 | #VERSION,arm64-ios,arm64-android,armv7-android,x86_64-macos,js-web,wasm-web,x86_64-linux,x86-win32,x86_64-win32
290 | #1.2.38,0,0,0,0,0,0,0,0,0,0,0,0,0
291 | #1.2.39,0,0,0,0,0,0,0,0,0,0,0,0,0
292 | lines = []
293 | with open(path, 'r') as f:
294 | reader = csv.reader(f)
295 | for row in reader:
296 | lines.append(row)
297 |
298 | header = lines[0]
299 | platforms = header[1:]
300 | assert(header[0] == 'VERSION')
301 |
302 | report = OrderedDict()
303 | report['version'] = []
304 | for line in lines[1:]:
305 | version = line[0]
306 | report['version'].append(version)
307 |
308 | if len(line) != len(header):
309 | print("%s:" % path, "Mismatching number of cells in line", line)
310 | continue
311 |
312 | # loop over each platform
313 | for i, platform in enumerate(header):
314 | if i == 0:
315 | continue
316 |
317 | if not platform in report:
318 | report[platform] = OrderedDict()
319 |
320 | size = line[i]
321 | if size == '0':
322 | continue
323 | report[platform][version] = size
324 |
325 | return report
326 |
327 | def sort_versions(versions):
328 | version_numbers = list(map(lambda x: version_to_number(x), versions))
329 | return list(map(lambda x: number_to_version(x), sorted(version_numbers)))
330 |
331 | def write_report(path, report):
332 | #format:
333 | #VERSION,arm64-ios,arm64-android,armv7-android,x86_64-macos,js-web,wasm-web,x86_64-linux,x86-win32,x86_64-win32
334 | #1.2.38,0,0,0,0,0,0,0,0,0,0,0,0,0
335 | #1.2.39,0,0,0,0,0,0,0,0,0,0,0,0,0
336 |
337 | versions = sort_versions(report['version'])
338 |
339 | platforms = [x for x in report.keys() if x != 'version']
340 |
341 | lines = []
342 | lines.append(['VERSION']+platforms) # header
343 |
344 | for version in versions:
345 | row = [version]
346 | for platform in platforms:
347 | platform_data = report[platform]
348 | size = platform_data.get(version, 0) # the size (int) or n/a (0)
349 | row.append(size)
350 |
351 | lines.append(row)
352 |
353 | with open(path, 'w') as f:
354 | writer = csv.writer(f)
355 | for line in lines:
356 | writer.writerow(line)
357 |
358 | print("Wrote {}".format(path))
359 |
360 |
361 | def create_report(report_filename, releases, report_platforms, fn):
362 | print("Creating {}".format(report_filename))
363 |
364 | report = read_report(report_filename)
365 |
366 | # Remove old platforms
367 | supported_platforms = list(map(lambda x: x['platform'], report_platforms))
368 | delete_keys = []
369 | for key,_ in report.items():
370 | if key == 'version':
371 | continue
372 | if key not in supported_platforms:
373 | print("Removed old platform", key)
374 | delete_keys.append(key)
375 | for key in delete_keys:
376 | del report[key]
377 |
378 | # Add new platforms
379 | for platform in supported_platforms:
380 | if not platform in report:
381 | report[platform] = OrderedDict()
382 |
383 |
384 | # go through the releases one by one and either use existing size data
385 | # or download and get the size data
386 | for release in releases:
387 | version = release["version"]
388 | sha1 = release["sha1"]
389 |
390 | if version in report['version']:
391 | print(f" Version {version} already exists")
392 | continue # we already had the report for this version
393 |
394 | report['version'].append(version)
395 | print("Found new version {} - Getting size".format(version))
396 |
397 | for report_platform in report_platforms:
398 | platform = report_platform["platform"]
399 | filename = report_platform["filename"]
400 | print(f" Making report for {platform}...")
401 | size = fn(sha1, platform, filename)
402 | print(f" Resported size: {platform} {size}")
403 | report[platform][version] = size
404 |
405 | write_report(report_filename, report)
406 | print("Creating {} - ok".format(report_filename))
407 |
408 | def parse_version(version_str):
409 | return tuple(map(int, version_str.split('.'))) # make it into a tuple
410 |
411 | def create_graph(report_filename, out, from_version=None):
412 | print("Creating {}".format(out))
413 | with open(report_filename, 'r') as f:
414 | data = list(csv.reader(f))
415 |
416 | # only keep the versions starting with from_version and above
417 | if from_version is not None:
418 | from_version = parse_version(from_version)
419 | new_data = []
420 | for line in data:
421 | if 'VERSION' in line[0]:
422 | new_data.append(line)
423 | continue
424 | version = parse_version(line[0])
425 | #if new_version(version, from_version):
426 | if version >= from_version:
427 | new_data.append(line)
428 | data = new_data
429 |
430 | # get all versions, ignore column headers
431 | versions = [i[0] for i in data[1::]]
432 | xaxis_version = range(0, len(versions))
433 |
434 | mb = 1024 * 1024
435 |
436 | fig, ax = pyplot.subplots(figsize=(20, 10))
437 | pyplot.xticks(xaxis_version, versions, rotation=270)
438 | max_ysize = 0
439 | min_ysize = 10000 * mb
440 | assert(len(markers) >= (len(data[0])-1)) # we need unique markers for each platform
441 |
442 | for engine, marker in zip(range(1, len(data[0])), markers):
443 | # convert from string to int
444 | # find the max y size
445 | yaxis_size = []
446 | for num in list([i[engine] for i in data[1::]]):
447 | num = int(num)
448 | max_ysize = max(max_ysize, num)
449 | min_ysize = min(min_ysize, num)
450 | yaxis_size.append(num)
451 | ax.plot(xaxis_version, yaxis_size, label=data[0][engine], marker=marker)
452 |
453 | # make sure the plot fills out the area (easier to see nuances)
454 | ax.set_ylim(bottom=min_ysize)
455 | ax.set_xlim(left=0., right=xaxis_version[-1])
456 |
457 | max_mb = int( (max_ysize+mb/2) // mb )
458 | min_mb = int( (min_ysize+mb/2) // mb )
459 | step = 1
460 | if max_mb - min_mb > 200:
461 | step = 10
462 | locs = [i * mb for i in range(min_mb, max_mb+1, step)]
463 |
464 | # create horizontal lines, to make it easier to track sizes
465 | for y in range(min_mb*mb, max_mb*mb, mb*step):
466 | ax.axhline(y, alpha=0.1)
467 |
468 | pyplot.yticks(locs, map(lambda x: "%d mb" % (x // mb), locs))
469 | pyplot.ylabel('SIZE')
470 | pyplot.xlabel('VERSION')
471 | # add timestamp to top-left corner of graph
472 | pyplot.annotate(str(datetime.datetime.now()), xy=(0.02, 0.95), xycoords='axes fraction')
473 |
474 | # create legend
475 | legend = ax.legend(loc='upper left', bbox_to_anchor=(0.02, 0.94))
476 | frame = legend.get_frame()
477 | frame.set_facecolor('0.90')
478 |
479 | fig.savefig(out, format='png', bbox_extra_artists=(legend,), bbox_inches='tight', pad_inches=1)
480 | print("Creating {} - ok".format(out))
481 |
482 |
483 | def check_for_updates(latest_release, releases):
484 | # Is the release already present?
485 | for release in releases['releases']:
486 | if latest_release['version'] == release['version']:
487 | return False
488 | return True
489 |
490 |
491 | # latest_release = { "version": "1.3.3", "sha1": "287c945fab310c324493e08b191ee1b1538ef973"}
492 | latest_release = get_latest_version()
493 |
494 | releases = read_releases('releases.json')
495 |
496 | if check_for_updates(latest_release, releases):
497 | print("Found new release {}".format(latest_release))
498 | releases['releases'].append(latest_release)
499 |
500 | # update the releases on disc
501 | with open('releases_new.json', 'w') as f:
502 | json.dump(releases, f, indent=4, separators=(',', ': '))
503 | # if everything went right, move the temp file
504 | shutil.move('releases_new.json', 'releases.json')
505 |
506 |
507 | # update reports (if releases are missing from a report file)
508 | print("Creating reports")
509 | # create_report("legacy_engine_report.csv", releases['releases'], engines, get_engine_size_from_aws)
510 | create_report("engine_report.csv", releases['releases'], engines, get_engine_size)
511 | create_report("bundle_report.csv", releases['releases'], bundles, get_bundle_size_from_bob)
512 | create_report("bob_report.csv", releases['releases'], bob_files, get_bob_size_from_aws)
513 | create_report("editor_report.csv", releases['releases'], editor_files, get_editor_size_from_aws)
514 |
515 |
516 | # create graphs based on the different reports
517 | print("Creating graphs")
518 | # create_graph("legacy_engine_report.csv", out='legacy_engine_size.png')
519 | # create_graph("legacy_engine_report.csv", out='legacy_engine_size_stripped.png', from_version='1.2.155') # from 1.2.155, we have stripped versions available for all platforms
520 | create_graph("engine_report.csv", out='engine_size.png', from_version='1.2.166')
521 | create_graph("bundle_report.csv", out='bundle_size.png', from_version='1.2.166')
522 | create_graph("bob_report.csv", out='bob_size.png', from_version='1.2.166')
523 | create_graph("editor_report.csv", out='editor_size.png', from_version='1.3.6')
524 |
--------------------------------------------------------------------------------
/size-analyzer/js/csv-parser.js:
--------------------------------------------------------------------------------
1 | // CSV Parser and Data Processing Module
2 |
3 | class CSVParser {
4 | // Cache for loaded CSV data to avoid repeated requests
5 | static csvCache = new Map();
6 |
7 | static async parseCSV(text) {
8 | const lines = text.trim().split('\n');
9 | const headers = lines[0].split(',');
10 | const data = [];
11 |
12 | for (let i = 1; i < lines.length; i++) {
13 | const values = this.parseCSVLine(lines[i]);
14 | if (values.length === headers.length) {
15 | const row = {};
16 | headers.forEach((header, index) => {
17 | row[header.trim()] = values[index].trim();
18 | });
19 | data.push(row);
20 | }
21 | }
22 |
23 | return data;
24 | }
25 |
26 | static getMetricsFromHeaders(headers) {
27 | // Get metrics from CSV headers, excluding the filename column
28 | const filenameColumns = ['compileunits', 'filename', 'symbol_group_name'];
29 | return headers
30 | .map(h => h.trim())
31 | .filter(header => !filenameColumns.includes(header.toLowerCase()));
32 | }
33 |
34 | static getFilenameColumn(headers) {
35 | // Find the filename column
36 | const filenameColumns = ['compileunits', 'filename', 'symbol_group_name'];
37 | return headers
38 | .map(h => h.trim())
39 | .find(header => filenameColumns.includes(header.toLowerCase())) || headers[0];
40 | }
41 |
42 | static parseCSVLine(line) {
43 | const result = [];
44 | let current = '';
45 | let inQuotes = false;
46 |
47 | for (let i = 0; i < line.length; i++) {
48 | const char = line[i];
49 |
50 | if (char === '"') {
51 | inQuotes = !inQuotes;
52 | } else if (char === ',' && !inQuotes) {
53 | result.push(current);
54 | current = '';
55 | } else {
56 | current += char;
57 | }
58 | }
59 |
60 | result.push(current);
61 | return result;
62 | }
63 |
64 | static async loadCSV(url) {
65 | // Check cache first
66 | if (this.csvCache.has(url)) {
67 | return this.csvCache.get(url);
68 | }
69 |
70 | try {
71 | const response = await fetch(url);
72 | if (!response.ok) {
73 | throw new Error(`HTTP error! status: ${response.status}`);
74 | }
75 | const text = await response.text();
76 | const data = await this.parseCSV(text);
77 |
78 | // Cache the parsed data
79 | this.csvCache.set(url, data);
80 | return data;
81 | } catch (error) {
82 | console.error('Error loading CSV:', url, error);
83 | throw error;
84 | }
85 | }
86 |
87 | static clearCache() {
88 | this.csvCache.clear();
89 | }
90 | }
91 |
92 | class DataProcessor {
93 | static normalizeFilePath(filePath) {
94 | if (!filePath) return filePath;
95 |
96 | // Remove leading ../ and ./ prefixes
97 | let normalized = filePath.replace(/^(\.\.\/)+/, '').replace(/^\.\//, '');
98 |
99 | // Handle cases where the path might start with different variations
100 | // Also remove any leading / if present
101 | normalized = normalized.replace(/^\/+/, '');
102 |
103 | return normalized;
104 | }
105 |
106 | static parseVersion(version) {
107 | // Ensure version is a string
108 | const versionStr = typeof version === 'string' ? version : String(version);
109 | return versionStr.split('.').map(Number);
110 | }
111 |
112 | static compareVersions(v1, v2) {
113 | const a = this.parseVersion(v1);
114 | const b = this.parseVersion(v2);
115 |
116 | for (let i = 0; i < Math.max(a.length, b.length); i++) {
117 | const numA = a[i] || 0;
118 | const numB = b[i] || 0;
119 | if (numA !== numB) {
120 | return numA - numB;
121 | }
122 | }
123 | return 0;
124 | }
125 |
126 | static getVersionsInRange(allVersions, startVersion, endVersion) {
127 | return allVersions
128 | .filter(version => {
129 | return this.compareVersions(version, startVersion) >= 0 &&
130 | this.compareVersions(version, endVersion) <= 0;
131 | })
132 | .sort(this.compareVersions.bind(this));
133 | }
134 |
135 | static async getFileTimeline(fileName, platform, startVersion, endVersion, metricType) {
136 | // Get analysis index to determine available versions
137 | const analysisResponse = await fetch('analysis_index.json');
138 | const analysisIndex = await analysisResponse.json();
139 | const allVersionObjects = analysisIndex.platforms[platform].versions;
140 |
141 | // Extract just the version strings from the objects
142 | const allVersions = allVersionObjects.map(v => v.version);
143 |
144 | // Get versions in range
145 | const versionsInRange = this.getVersionsInRange(allVersions, startVersion, endVersion);
146 |
147 | const timeline = [];
148 | let filenameColumn = 'compileunits'; // default
149 |
150 | // Load data for each version
151 | for (const version of versionsInRange) {
152 | try {
153 | const csvData = await CSVParser.loadCSV(`${platform}/${version}.csv`);
154 |
155 | // Detect filename column from first version's data
156 | if (csvData.length > 0 && filenameColumn === 'compileunits') {
157 | const headers = Object.keys(csvData[0]);
158 | filenameColumn = CSVParser.getFilenameColumn(headers);
159 | }
160 |
161 | // Find the file in this version's data
162 | const normalizedFileName = DataProcessor.normalizeFilePath(fileName);
163 | const fileRow = csvData.find(row =>
164 | DataProcessor.normalizeFilePath(row[filenameColumn]) === normalizedFileName
165 | );
166 |
167 | const size = fileRow ? (parseInt(fileRow[metricType]) || 0) : 0;
168 |
169 | timeline.push({
170 | version: version,
171 | size: size,
172 | exists: !!fileRow
173 | });
174 |
175 | } catch (error) {
176 | console.warn(`Failed to load data for version ${version}:`, error);
177 | // Add zero size for missing versions
178 | timeline.push({
179 | version: version,
180 | size: 0,
181 | exists: false
182 | });
183 | }
184 | }
185 |
186 | return timeline;
187 | }
188 |
189 | static processDataByMetric(data1, data2, metricType, changeThreshold = 50, filenameColumn = 'compileunits') {
190 | // Process data for a specific metric (dynamic based on CSV headers)
191 |
192 | const data1Map = new Map();
193 | const data2Map = new Map();
194 |
195 | // Process first dataset
196 | data1.forEach((row, index) => {
197 | const compileUnit = this.normalizeFilePath(row[filenameColumn]);
198 | const metricValue = parseInt(row[metricType]) || 0;
199 |
200 | data1Map.set(compileUnit, {
201 | size: metricValue,
202 | compileUnit,
203 | originalPath: row[filenameColumn]
204 | });
205 | });
206 |
207 | // Process second dataset
208 | data2.forEach(row => {
209 | const compileUnit = this.normalizeFilePath(row[filenameColumn]);
210 | const metricValue = parseInt(row[metricType]) || 0;
211 |
212 | data2Map.set(compileUnit, {
213 | size: metricValue,
214 | compileUnit,
215 | originalPath: row[filenameColumn]
216 | });
217 | });
218 |
219 | // Detect file moves before processing comparisons
220 | const moveDetection = this.detectFileMoves(data1Map, data2Map);
221 | const { mergedData1, mergedData2 } = moveDetection;
222 |
223 | // Compare and create comparison data using merged data (after move detection)
224 | const comparisons = [];
225 | const allKeys = new Set([...mergedData1.keys(), ...mergedData2.keys()]);
226 |
227 | allKeys.forEach(compileUnit => {
228 | const item1 = mergedData1.get(compileUnit);
229 | const item2 = mergedData2.get(compileUnit);
230 |
231 | const size1 = item1 ? item1.size : 0;
232 | const size2 = item2 ? item2.size : 0;
233 | const difference = size2 - size1;
234 | const percentChange = size1 > 0 ? ((difference / size1) * 100) : (size2 > 0 ? 100 : 0);
235 |
236 | let changeType = 'unchanged';
237 | if (Math.abs(difference) > changeThreshold) {
238 | changeType = difference > 0 ? 'increased' : 'decreased';
239 | }
240 |
241 | // Add move detection info if applicable
242 | const moveInfo = item1?.moveInfo || item2?.moveInfo;
243 |
244 | comparisons.push({
245 | compileUnit,
246 | size1,
247 | size2,
248 | difference,
249 | percentChange,
250 | changeType,
251 | metricType,
252 | ...(moveInfo && {
253 | isMoved: true,
254 | moveInfo: moveInfo,
255 | displayName: moveInfo.displayName
256 | })
257 | });
258 | });
259 |
260 | // Sort by absolute difference (largest changes first)
261 | comparisons.sort((a, b) => Math.abs(b.difference) - Math.abs(a.difference));
262 |
263 |
264 | return comparisons;
265 | }
266 |
267 | static detectFileMoves(data1Map, data2Map) {
268 | // Algorithm to detect file moves by comparing basenames and sizes
269 | // Returns merged data maps where moves are consolidated as single entities
270 |
271 | const mergedData1 = new Map(data1Map);
272 | const mergedData2 = new Map(data2Map);
273 | const moveInfo = new Map();
274 |
275 | // Get files that are only in data1 (potentially moved out)
276 | const onlyInData1 = [];
277 | for (const [key, value] of data1Map) {
278 | if (!data2Map.has(key)) {
279 | onlyInData1.push({ key, value });
280 | }
281 | }
282 |
283 | // Get files that are only in data2 (potentially moved in)
284 | const onlyInData2 = [];
285 | for (const [key, value] of data2Map) {
286 | if (!data1Map.has(key)) {
287 | onlyInData2.push({ key, value });
288 | }
289 | }
290 |
291 | // Try to match files by basename and similar size
292 | const matchedMoves = [];
293 |
294 | for (const item1 of onlyInData1) {
295 | const basename1 = this.getBasename(item1.key);
296 | const size1 = item1.value.size;
297 |
298 | for (const item2 of onlyInData2) {
299 | const basename2 = this.getBasename(item2.key);
300 | const size2 = item2.value.size;
301 |
302 | // Check if basenames match and sizes are similar (within 10% tolerance)
303 | if (basename1 === basename2 && this.sizesAreSimilar(size1, size2)) {
304 | matchedMoves.push({
305 | oldKey: item1.key,
306 | newKey: item2.key,
307 | oldValue: item1.value,
308 | newValue: item2.value,
309 | basename: basename1
310 | });
311 | break; // Move to next item1 after finding a match
312 | }
313 | }
314 | }
315 |
316 | // Process matched moves
317 | for (const move of matchedMoves) {
318 | // Use the new path as the canonical key
319 | const canonicalKey = move.newKey;
320 |
321 | // Create move info
322 | const moveDetails = {
323 | oldPath: move.oldValue.originalPath,
324 | newPath: move.newValue.originalPath,
325 | displayName: `${move.basename} (moved from ${this.getDirectoryPath(move.oldKey)} to ${this.getDirectoryPath(move.newKey)})`
326 | };
327 |
328 | // Remove the individual entries
329 | mergedData1.delete(move.oldKey);
330 | mergedData2.delete(move.newKey);
331 |
332 | // Add the moved file with combined info
333 | mergedData1.set(canonicalKey, {
334 | ...move.oldValue,
335 | moveInfo: moveDetails
336 | });
337 |
338 | mergedData2.set(canonicalKey, {
339 | ...move.newValue,
340 | moveInfo: moveDetails
341 | });
342 | }
343 |
344 | return { mergedData1, mergedData2, moveInfo: matchedMoves };
345 | }
346 |
347 | static getBasename(filePath) {
348 | // Extract the basename (filename without directory path)
349 | const parts = filePath.split('/');
350 | return parts[parts.length - 1];
351 | }
352 |
353 | static getDirectoryPath(filePath) {
354 | // Extract the directory path (everything except the basename)
355 | const parts = filePath.split('/');
356 | return parts.slice(0, -1).join('/') || '/';
357 | }
358 |
359 | static sizesAreSimilar(size1, size2, tolerance = 0.1) {
360 | // Check if sizes are similar within tolerance percentage
361 | if (size1 === 0 && size2 === 0) return true;
362 | if (size1 === 0 || size2 === 0) return false;
363 |
364 | const diff = Math.abs(size1 - size2);
365 | const average = (size1 + size2) / 2;
366 | return (diff / average) <= tolerance;
367 | }
368 |
369 | static processData(data1, data2, includeVMSize = true, includeFileSize = true, changeThreshold = 50) {
370 | // Create maps for fast lookup
371 | const data1Map = new Map();
372 | const data2Map = new Map();
373 |
374 | // Process first dataset
375 | data1.forEach(row => {
376 | const compileUnit = this.normalizeFilePath(row.compileunits);
377 | const vmsize = parseInt(row.vmsize) || 0;
378 | const filesize = parseInt(row.filesize) || 0;
379 |
380 | let totalSize = 0;
381 | if (includeVMSize) totalSize += vmsize;
382 | if (includeFileSize) totalSize += filesize;
383 |
384 | data1Map.set(compileUnit, {
385 | vmsize,
386 | filesize,
387 | totalSize,
388 | compileUnit
389 | });
390 | });
391 |
392 | // Process second dataset
393 | data2.forEach(row => {
394 | const compileUnit = this.normalizeFilePath(row.compileunits);
395 | const vmsize = parseInt(row.vmsize) || 0;
396 | const filesize = parseInt(row.filesize) || 0;
397 |
398 | let totalSize = 0;
399 | if (includeVMSize) totalSize += vmsize;
400 | if (includeFileSize) totalSize += filesize;
401 |
402 | data2Map.set(compileUnit, {
403 | vmsize,
404 | filesize,
405 | totalSize,
406 | compileUnit
407 | });
408 | });
409 |
410 | // Compare and create comparison data
411 | const comparisons = [];
412 | const allKeys = new Set([...data1Map.keys(), ...data2Map.keys()]);
413 |
414 | allKeys.forEach(compileUnit => {
415 | const item1 = data1Map.get(compileUnit);
416 | const item2 = data2Map.get(compileUnit);
417 |
418 | const size1 = item1 ? item1.totalSize : 0;
419 | const size2 = item2 ? item2.totalSize : 0;
420 | const difference = size2 - size1;
421 | const percentChange = size1 > 0 ? ((difference / size1) * 100) : (size2 > 0 ? 100 : 0);
422 |
423 | let changeType = 'unchanged';
424 | if (Math.abs(difference) > changeThreshold) {
425 | changeType = difference > 0 ? 'increased' : 'decreased';
426 | }
427 |
428 | comparisons.push({
429 | compileUnit,
430 | size1,
431 | size2,
432 | difference,
433 | percentChange,
434 | changeType,
435 | vmsize1: item1 ? item1.vmsize : 0,
436 | filesize1: item1 ? item1.filesize : 0,
437 | vmsize2: item2 ? item2.vmsize : 0,
438 | filesize2: item2 ? item2.filesize : 0
439 | });
440 | });
441 |
442 | // Sort by absolute difference (largest changes first)
443 | comparisons.sort((a, b) => Math.abs(b.difference) - Math.abs(a.difference));
444 |
445 | return comparisons;
446 | }
447 |
448 | static generateSummary(comparisons) {
449 | const summary = {
450 | totalFiles: comparisons.length,
451 | unchanged: 0,
452 | increased: 0,
453 | decreased: 0,
454 | totalSizeChange: 0,
455 | largestIncrease: null,
456 | largestDecrease: null
457 | };
458 |
459 | comparisons.forEach(comp => {
460 | summary.totalSizeChange += comp.difference;
461 |
462 | switch (comp.changeType) {
463 | case 'unchanged':
464 | summary.unchanged++;
465 | break;
466 | case 'increased':
467 | summary.increased++;
468 | if (!summary.largestIncrease || comp.difference > summary.largestIncrease.difference) {
469 | summary.largestIncrease = comp;
470 | }
471 | break;
472 | case 'decreased':
473 | summary.decreased++;
474 | if (!summary.largestDecrease || comp.difference < summary.largestDecrease.difference) {
475 | summary.largestDecrease = comp;
476 | }
477 | break;
478 | }
479 | });
480 |
481 | return summary;
482 | }
483 |
484 | static formatBytes(bytes) {
485 | if (bytes === 0) return '0 B';
486 |
487 | const k = 1024;
488 | const sizes = ['B', 'KB', 'MB', 'GB'];
489 | const i = Math.floor(Math.log(Math.abs(bytes)) / Math.log(k));
490 |
491 | return (bytes / Math.pow(k, i)).toFixed(1) + ' ' + sizes[i];
492 | }
493 |
494 | static formatNumber(num) {
495 | return num.toLocaleString();
496 | }
497 |
498 | static formatPercentage(percent) {
499 | return (percent >= 0 ? '+' : '') + percent.toFixed(1) + '%';
500 | }
501 |
502 | static prepareForVisualization(comparisons, hideUnchanged = false) {
503 | let filteredComparisons = comparisons;
504 |
505 | if (hideUnchanged) {
506 | filteredComparisons = comparisons.filter(comp => comp.changeType !== 'unchanged');
507 | }
508 |
509 | // Group by change type for better visualization
510 | const groups = {
511 | unchanged: filteredComparisons.filter(comp => comp.changeType === 'unchanged'),
512 | decreased: filteredComparisons.filter(comp => comp.changeType === 'decreased'),
513 | increased: filteredComparisons.filter(comp => comp.changeType === 'increased')
514 | };
515 |
516 | return {
517 | all: filteredComparisons,
518 | groups: groups,
519 | maxSize: Math.max(...filteredComparisons.map(comp => Math.max(comp.size1, comp.size2)))
520 | };
521 | }
522 | }
--------------------------------------------------------------------------------
/size-analyzer/analysis_index.json:
--------------------------------------------------------------------------------
1 | {
2 | "platforms": {
3 | "arm64-android": {
4 | "versions": [
5 | {
6 | "version": "1.9.0",
7 | "sha1": "d6882f432beca85d460ec42497888157c356d058"
8 | },
9 | {
10 | "version": "1.9.1",
11 | "sha1": "3be87d89fd5a93a63f527351fbedb84f8a875812"
12 | },
13 | {
14 | "version": "1.9.2",
15 | "sha1": "3251ca82359cf238a1074e383281e3126547d50b"
16 | },
17 | {
18 | "version": "1.9.3",
19 | "sha1": "e4aaff11f49c941fde1dd93883cf69c6b8abebe4"
20 | },
21 | {
22 | "version": "1.9.4",
23 | "sha1": "512763fd375633fd67197225e61fe90a5929166b"
24 | },
25 | {
26 | "version": "1.9.5",
27 | "sha1": "87b6907759f7b8dff830d54b2250b8d721bde291"
28 | },
29 | {
30 | "version": "1.9.6",
31 | "sha1": "4035511f1e258a47b77798a2005c024609ed2c67"
32 | },
33 | {
34 | "version": "1.9.7",
35 | "sha1": "a1ae95286a1b2677ed3fda6785816e76df4ee8a2"
36 | },
37 | {
38 | "version": "1.9.8",
39 | "sha1": "a9247e38b24ba1c1ed5913c4049d9a4083a314a7"
40 | },
41 | {
42 | "version": "1.10.0",
43 | "sha1": "591eb496d52f4140bc2c7de547131f1b9408b9b4"
44 | },
45 | {
46 | "version": "1.10.1",
47 | "sha1": "2783cc609cd52bc5ac92ec9e35b9b854f5f07882"
48 | },
49 | {
50 | "version": "1.10.2",
51 | "sha1": "f56fcca509a9fa5350bf55f18d8c6087295a8cef"
52 | },
53 | {
54 | "version": "1.10.3",
55 | "sha1": "1c76521bb8b08c63ef619aa8a5ab563dddf7b3cf"
56 | },
57 | {
58 | "version": "1.10.4",
59 | "sha1": "1aafd0a262ff40214ed7f51302d92fa587c607ef"
60 | },
61 | {
62 | "version": "1.11.0",
63 | "sha1": "7c81792859a6da7f7401c0ac37a4cc83bb500ff6"
64 | },
65 | {
66 | "version": "1.11.1",
67 | "sha1": "1ba9e1aa422166864c3267f03f5110144b745c1e"
68 | },
69 | {
70 | "version": "1.11.2",
71 | "sha1": "a6d86c0083f00ee6c3709478ff3b33deff5e6d19"
72 | }
73 | ]
74 | },
75 | "armv7-android": {
76 | "versions": [
77 | {
78 | "version": "1.9.0",
79 | "sha1": "d6882f432beca85d460ec42497888157c356d058"
80 | },
81 | {
82 | "version": "1.9.1",
83 | "sha1": "3be87d89fd5a93a63f527351fbedb84f8a875812"
84 | },
85 | {
86 | "version": "1.9.2",
87 | "sha1": "3251ca82359cf238a1074e383281e3126547d50b"
88 | },
89 | {
90 | "version": "1.9.3",
91 | "sha1": "e4aaff11f49c941fde1dd93883cf69c6b8abebe4"
92 | },
93 | {
94 | "version": "1.9.4",
95 | "sha1": "512763fd375633fd67197225e61fe90a5929166b"
96 | },
97 | {
98 | "version": "1.9.5",
99 | "sha1": "87b6907759f7b8dff830d54b2250b8d721bde291"
100 | },
101 | {
102 | "version": "1.9.6",
103 | "sha1": "4035511f1e258a47b77798a2005c024609ed2c67"
104 | },
105 | {
106 | "version": "1.9.7",
107 | "sha1": "a1ae95286a1b2677ed3fda6785816e76df4ee8a2"
108 | },
109 | {
110 | "version": "1.9.8",
111 | "sha1": "a9247e38b24ba1c1ed5913c4049d9a4083a314a7"
112 | },
113 | {
114 | "version": "1.10.0",
115 | "sha1": "591eb496d52f4140bc2c7de547131f1b9408b9b4"
116 | },
117 | {
118 | "version": "1.10.1",
119 | "sha1": "2783cc609cd52bc5ac92ec9e35b9b854f5f07882"
120 | },
121 | {
122 | "version": "1.10.2",
123 | "sha1": "f56fcca509a9fa5350bf55f18d8c6087295a8cef"
124 | },
125 | {
126 | "version": "1.10.3",
127 | "sha1": "1c76521bb8b08c63ef619aa8a5ab563dddf7b3cf"
128 | },
129 | {
130 | "version": "1.10.4",
131 | "sha1": "1aafd0a262ff40214ed7f51302d92fa587c607ef"
132 | },
133 | {
134 | "version": "1.11.0",
135 | "sha1": "7c81792859a6da7f7401c0ac37a4cc83bb500ff6"
136 | },
137 | {
138 | "version": "1.11.1",
139 | "sha1": "1ba9e1aa422166864c3267f03f5110144b745c1e"
140 | },
141 | {
142 | "version": "1.11.2",
143 | "sha1": "a6d86c0083f00ee6c3709478ff3b33deff5e6d19"
144 | }
145 | ]
146 | },
147 | "arm64-ios": {
148 | "versions": [
149 | {
150 | "version": "1.9.0",
151 | "sha1": "d6882f432beca85d460ec42497888157c356d058"
152 | },
153 | {
154 | "version": "1.9.1",
155 | "sha1": "3be87d89fd5a93a63f527351fbedb84f8a875812"
156 | },
157 | {
158 | "version": "1.9.2",
159 | "sha1": "3251ca82359cf238a1074e383281e3126547d50b"
160 | },
161 | {
162 | "version": "1.9.3",
163 | "sha1": "e4aaff11f49c941fde1dd93883cf69c6b8abebe4"
164 | },
165 | {
166 | "version": "1.9.4",
167 | "sha1": "512763fd375633fd67197225e61fe90a5929166b"
168 | },
169 | {
170 | "version": "1.9.5",
171 | "sha1": "87b6907759f7b8dff830d54b2250b8d721bde291"
172 | },
173 | {
174 | "version": "1.9.6",
175 | "sha1": "4035511f1e258a47b77798a2005c024609ed2c67"
176 | },
177 | {
178 | "version": "1.9.7",
179 | "sha1": "a1ae95286a1b2677ed3fda6785816e76df4ee8a2"
180 | },
181 | {
182 | "version": "1.9.8",
183 | "sha1": "a9247e38b24ba1c1ed5913c4049d9a4083a314a7"
184 | },
185 | {
186 | "version": "1.10.0",
187 | "sha1": "591eb496d52f4140bc2c7de547131f1b9408b9b4"
188 | },
189 | {
190 | "version": "1.10.1",
191 | "sha1": "2783cc609cd52bc5ac92ec9e35b9b854f5f07882"
192 | },
193 | {
194 | "version": "1.10.2",
195 | "sha1": "f56fcca509a9fa5350bf55f18d8c6087295a8cef"
196 | },
197 | {
198 | "version": "1.10.3",
199 | "sha1": "1c76521bb8b08c63ef619aa8a5ab563dddf7b3cf"
200 | },
201 | {
202 | "version": "1.10.4",
203 | "sha1": "1aafd0a262ff40214ed7f51302d92fa587c607ef"
204 | },
205 | {
206 | "version": "1.11.0",
207 | "sha1": "7c81792859a6da7f7401c0ac37a4cc83bb500ff6"
208 | },
209 | {
210 | "version": "1.11.1",
211 | "sha1": "1ba9e1aa422166864c3267f03f5110144b745c1e"
212 | },
213 | {
214 | "version": "1.11.2",
215 | "sha1": "a6d86c0083f00ee6c3709478ff3b33deff5e6d19"
216 | }
217 | ]
218 | },
219 | "x86_64-macos": {
220 | "versions": [
221 | {
222 | "version": "1.9.0",
223 | "sha1": "d6882f432beca85d460ec42497888157c356d058"
224 | },
225 | {
226 | "version": "1.9.1",
227 | "sha1": "3be87d89fd5a93a63f527351fbedb84f8a875812"
228 | },
229 | {
230 | "version": "1.9.2",
231 | "sha1": "3251ca82359cf238a1074e383281e3126547d50b"
232 | },
233 | {
234 | "version": "1.9.3",
235 | "sha1": "e4aaff11f49c941fde1dd93883cf69c6b8abebe4"
236 | },
237 | {
238 | "version": "1.9.4",
239 | "sha1": "512763fd375633fd67197225e61fe90a5929166b"
240 | },
241 | {
242 | "version": "1.9.5",
243 | "sha1": "87b6907759f7b8dff830d54b2250b8d721bde291"
244 | },
245 | {
246 | "version": "1.9.6",
247 | "sha1": "4035511f1e258a47b77798a2005c024609ed2c67"
248 | },
249 | {
250 | "version": "1.9.7",
251 | "sha1": "a1ae95286a1b2677ed3fda6785816e76df4ee8a2"
252 | },
253 | {
254 | "version": "1.9.8",
255 | "sha1": "a9247e38b24ba1c1ed5913c4049d9a4083a314a7"
256 | },
257 | {
258 | "version": "1.10.0",
259 | "sha1": "591eb496d52f4140bc2c7de547131f1b9408b9b4"
260 | },
261 | {
262 | "version": "1.10.1",
263 | "sha1": "2783cc609cd52bc5ac92ec9e35b9b854f5f07882"
264 | },
265 | {
266 | "version": "1.10.2",
267 | "sha1": "f56fcca509a9fa5350bf55f18d8c6087295a8cef"
268 | },
269 | {
270 | "version": "1.10.3",
271 | "sha1": "1c76521bb8b08c63ef619aa8a5ab563dddf7b3cf"
272 | },
273 | {
274 | "version": "1.10.4",
275 | "sha1": "1aafd0a262ff40214ed7f51302d92fa587c607ef"
276 | },
277 | {
278 | "version": "1.11.0",
279 | "sha1": "7c81792859a6da7f7401c0ac37a4cc83bb500ff6"
280 | },
281 | {
282 | "version": "1.11.1",
283 | "sha1": "1ba9e1aa422166864c3267f03f5110144b745c1e"
284 | },
285 | {
286 | "version": "1.11.2",
287 | "sha1": "a6d86c0083f00ee6c3709478ff3b33deff5e6d19"
288 | }
289 | ]
290 | },
291 | "arm64-macos": {
292 | "versions": [
293 | {
294 | "version": "1.9.0",
295 | "sha1": "d6882f432beca85d460ec42497888157c356d058"
296 | },
297 | {
298 | "version": "1.9.1",
299 | "sha1": "3be87d89fd5a93a63f527351fbedb84f8a875812"
300 | },
301 | {
302 | "version": "1.9.2",
303 | "sha1": "3251ca82359cf238a1074e383281e3126547d50b"
304 | },
305 | {
306 | "version": "1.9.3",
307 | "sha1": "e4aaff11f49c941fde1dd93883cf69c6b8abebe4"
308 | },
309 | {
310 | "version": "1.9.4",
311 | "sha1": "512763fd375633fd67197225e61fe90a5929166b"
312 | },
313 | {
314 | "version": "1.9.5",
315 | "sha1": "87b6907759f7b8dff830d54b2250b8d721bde291"
316 | },
317 | {
318 | "version": "1.9.6",
319 | "sha1": "4035511f1e258a47b77798a2005c024609ed2c67"
320 | },
321 | {
322 | "version": "1.9.7",
323 | "sha1": "a1ae95286a1b2677ed3fda6785816e76df4ee8a2"
324 | },
325 | {
326 | "version": "1.9.8",
327 | "sha1": "a9247e38b24ba1c1ed5913c4049d9a4083a314a7"
328 | },
329 | {
330 | "version": "1.10.0",
331 | "sha1": "591eb496d52f4140bc2c7de547131f1b9408b9b4"
332 | },
333 | {
334 | "version": "1.10.1",
335 | "sha1": "2783cc609cd52bc5ac92ec9e35b9b854f5f07882"
336 | },
337 | {
338 | "version": "1.10.2",
339 | "sha1": "f56fcca509a9fa5350bf55f18d8c6087295a8cef"
340 | },
341 | {
342 | "version": "1.10.3",
343 | "sha1": "1c76521bb8b08c63ef619aa8a5ab563dddf7b3cf"
344 | },
345 | {
346 | "version": "1.10.4",
347 | "sha1": "1aafd0a262ff40214ed7f51302d92fa587c607ef"
348 | },
349 | {
350 | "version": "1.11.0",
351 | "sha1": "7c81792859a6da7f7401c0ac37a4cc83bb500ff6"
352 | },
353 | {
354 | "version": "1.11.1",
355 | "sha1": "1ba9e1aa422166864c3267f03f5110144b745c1e"
356 | },
357 | {
358 | "version": "1.11.2",
359 | "sha1": "a6d86c0083f00ee6c3709478ff3b33deff5e6d19"
360 | }
361 | ]
362 | },
363 | "bob.jar": {
364 | "versions": [
365 | {
366 | "version": "1.9.0",
367 | "sha1": "d6882f432beca85d460ec42497888157c356d058"
368 | },
369 | {
370 | "version": "1.9.1",
371 | "sha1": "3be87d89fd5a93a63f527351fbedb84f8a875812"
372 | },
373 | {
374 | "version": "1.9.2",
375 | "sha1": "3251ca82359cf238a1074e383281e3126547d50b"
376 | },
377 | {
378 | "version": "1.9.3",
379 | "sha1": "e4aaff11f49c941fde1dd93883cf69c6b8abebe4"
380 | },
381 | {
382 | "version": "1.9.4",
383 | "sha1": "512763fd375633fd67197225e61fe90a5929166b"
384 | },
385 | {
386 | "version": "1.9.5",
387 | "sha1": "87b6907759f7b8dff830d54b2250b8d721bde291"
388 | },
389 | {
390 | "version": "1.9.6",
391 | "sha1": "4035511f1e258a47b77798a2005c024609ed2c67"
392 | },
393 | {
394 | "version": "1.9.7",
395 | "sha1": "a1ae95286a1b2677ed3fda6785816e76df4ee8a2"
396 | },
397 | {
398 | "version": "1.9.8",
399 | "sha1": "a9247e38b24ba1c1ed5913c4049d9a4083a314a7"
400 | },
401 | {
402 | "version": "1.10.0",
403 | "sha1": "591eb496d52f4140bc2c7de547131f1b9408b9b4"
404 | },
405 | {
406 | "version": "1.10.1",
407 | "sha1": "2783cc609cd52bc5ac92ec9e35b9b854f5f07882"
408 | },
409 | {
410 | "version": "1.10.2",
411 | "sha1": "f56fcca509a9fa5350bf55f18d8c6087295a8cef"
412 | },
413 | {
414 | "version": "1.10.3",
415 | "sha1": "1c76521bb8b08c63ef619aa8a5ab563dddf7b3cf"
416 | },
417 | {
418 | "version": "1.10.4",
419 | "sha1": "1aafd0a262ff40214ed7f51302d92fa587c607ef"
420 | },
421 | {
422 | "version": "1.11.0",
423 | "sha1": "7c81792859a6da7f7401c0ac37a4cc83bb500ff6"
424 | },
425 | {
426 | "version": "1.11.1",
427 | "sha1": "1ba9e1aa422166864c3267f03f5110144b745c1e"
428 | },
429 | {
430 | "version": "1.11.2",
431 | "sha1": "a6d86c0083f00ee6c3709478ff3b33deff5e6d19"
432 | }
433 | ]
434 | },
435 | "editor-win32": {
436 | "versions": [
437 | {
438 | "version": "1.9.0",
439 | "sha1": "d6882f432beca85d460ec42497888157c356d058"
440 | },
441 | {
442 | "version": "1.9.1",
443 | "sha1": "3be87d89fd5a93a63f527351fbedb84f8a875812"
444 | },
445 | {
446 | "version": "1.9.2",
447 | "sha1": "3251ca82359cf238a1074e383281e3126547d50b"
448 | },
449 | {
450 | "version": "1.9.3",
451 | "sha1": "e4aaff11f49c941fde1dd93883cf69c6b8abebe4"
452 | },
453 | {
454 | "version": "1.9.4",
455 | "sha1": "512763fd375633fd67197225e61fe90a5929166b"
456 | },
457 | {
458 | "version": "1.9.5",
459 | "sha1": "87b6907759f7b8dff830d54b2250b8d721bde291"
460 | },
461 | {
462 | "version": "1.9.6",
463 | "sha1": "4035511f1e258a47b77798a2005c024609ed2c67"
464 | },
465 | {
466 | "version": "1.9.7",
467 | "sha1": "a1ae95286a1b2677ed3fda6785816e76df4ee8a2"
468 | },
469 | {
470 | "version": "1.9.8",
471 | "sha1": "a9247e38b24ba1c1ed5913c4049d9a4083a314a7"
472 | },
473 | {
474 | "version": "1.10.0",
475 | "sha1": "591eb496d52f4140bc2c7de547131f1b9408b9b4"
476 | },
477 | {
478 | "version": "1.10.1",
479 | "sha1": "2783cc609cd52bc5ac92ec9e35b9b854f5f07882"
480 | },
481 | {
482 | "version": "1.10.2",
483 | "sha1": "f56fcca509a9fa5350bf55f18d8c6087295a8cef"
484 | },
485 | {
486 | "version": "1.10.3",
487 | "sha1": "1c76521bb8b08c63ef619aa8a5ab563dddf7b3cf"
488 | },
489 | {
490 | "version": "1.10.4",
491 | "sha1": "1aafd0a262ff40214ed7f51302d92fa587c607ef"
492 | },
493 | {
494 | "version": "1.11.0",
495 | "sha1": "7c81792859a6da7f7401c0ac37a4cc83bb500ff6"
496 | },
497 | {
498 | "version": "1.11.1",
499 | "sha1": "1ba9e1aa422166864c3267f03f5110144b745c1e"
500 | },
501 | {
502 | "version": "1.11.2",
503 | "sha1": "a6d86c0083f00ee6c3709478ff3b33deff5e6d19"
504 | }
505 | ]
506 | },
507 | "editor-x86_64-linux": {
508 | "versions": [
509 | {
510 | "version": "1.9.0",
511 | "sha1": "d6882f432beca85d460ec42497888157c356d058"
512 | },
513 | {
514 | "version": "1.9.1",
515 | "sha1": "3be87d89fd5a93a63f527351fbedb84f8a875812"
516 | },
517 | {
518 | "version": "1.9.2",
519 | "sha1": "3251ca82359cf238a1074e383281e3126547d50b"
520 | },
521 | {
522 | "version": "1.9.3",
523 | "sha1": "e4aaff11f49c941fde1dd93883cf69c6b8abebe4"
524 | },
525 | {
526 | "version": "1.9.4",
527 | "sha1": "512763fd375633fd67197225e61fe90a5929166b"
528 | },
529 | {
530 | "version": "1.9.5",
531 | "sha1": "87b6907759f7b8dff830d54b2250b8d721bde291"
532 | },
533 | {
534 | "version": "1.9.6",
535 | "sha1": "4035511f1e258a47b77798a2005c024609ed2c67"
536 | },
537 | {
538 | "version": "1.9.7",
539 | "sha1": "a1ae95286a1b2677ed3fda6785816e76df4ee8a2"
540 | },
541 | {
542 | "version": "1.9.8",
543 | "sha1": "a9247e38b24ba1c1ed5913c4049d9a4083a314a7"
544 | },
545 | {
546 | "version": "1.10.0",
547 | "sha1": "591eb496d52f4140bc2c7de547131f1b9408b9b4"
548 | },
549 | {
550 | "version": "1.10.1",
551 | "sha1": "2783cc609cd52bc5ac92ec9e35b9b854f5f07882"
552 | },
553 | {
554 | "version": "1.10.2",
555 | "sha1": "f56fcca509a9fa5350bf55f18d8c6087295a8cef"
556 | },
557 | {
558 | "version": "1.10.3",
559 | "sha1": "1c76521bb8b08c63ef619aa8a5ab563dddf7b3cf"
560 | },
561 | {
562 | "version": "1.10.4",
563 | "sha1": "1aafd0a262ff40214ed7f51302d92fa587c607ef"
564 | },
565 | {
566 | "version": "1.11.0",
567 | "sha1": "7c81792859a6da7f7401c0ac37a4cc83bb500ff6"
568 | },
569 | {
570 | "version": "1.11.1",
571 | "sha1": "1ba9e1aa422166864c3267f03f5110144b745c1e"
572 | },
573 | {
574 | "version": "1.11.2",
575 | "sha1": "a6d86c0083f00ee6c3709478ff3b33deff5e6d19"
576 | }
577 | ]
578 | },
579 | "editor-x86_64-macos": {
580 | "versions": [
581 | {
582 | "version": "1.9.0",
583 | "sha1": "d6882f432beca85d460ec42497888157c356d058"
584 | },
585 | {
586 | "version": "1.9.1",
587 | "sha1": "3be87d89fd5a93a63f527351fbedb84f8a875812"
588 | },
589 | {
590 | "version": "1.9.2",
591 | "sha1": "3251ca82359cf238a1074e383281e3126547d50b"
592 | },
593 | {
594 | "version": "1.9.3",
595 | "sha1": "e4aaff11f49c941fde1dd93883cf69c6b8abebe4"
596 | },
597 | {
598 | "version": "1.9.4",
599 | "sha1": "512763fd375633fd67197225e61fe90a5929166b"
600 | },
601 | {
602 | "version": "1.9.5",
603 | "sha1": "87b6907759f7b8dff830d54b2250b8d721bde291"
604 | },
605 | {
606 | "version": "1.9.6",
607 | "sha1": "4035511f1e258a47b77798a2005c024609ed2c67"
608 | },
609 | {
610 | "version": "1.9.7",
611 | "sha1": "a1ae95286a1b2677ed3fda6785816e76df4ee8a2"
612 | },
613 | {
614 | "version": "1.9.8",
615 | "sha1": "a9247e38b24ba1c1ed5913c4049d9a4083a314a7"
616 | },
617 | {
618 | "version": "1.10.0",
619 | "sha1": "591eb496d52f4140bc2c7de547131f1b9408b9b4"
620 | },
621 | {
622 | "version": "1.10.1",
623 | "sha1": "2783cc609cd52bc5ac92ec9e35b9b854f5f07882"
624 | },
625 | {
626 | "version": "1.10.2",
627 | "sha1": "f56fcca509a9fa5350bf55f18d8c6087295a8cef"
628 | },
629 | {
630 | "version": "1.10.3",
631 | "sha1": "1c76521bb8b08c63ef619aa8a5ab563dddf7b3cf"
632 | },
633 | {
634 | "version": "1.10.4",
635 | "sha1": "1aafd0a262ff40214ed7f51302d92fa587c607ef"
636 | },
637 | {
638 | "version": "1.11.0",
639 | "sha1": "7c81792859a6da7f7401c0ac37a4cc83bb500ff6"
640 | },
641 | {
642 | "version": "1.11.1",
643 | "sha1": "1ba9e1aa422166864c3267f03f5110144b745c1e"
644 | },
645 | {
646 | "version": "1.11.2",
647 | "sha1": "a6d86c0083f00ee6c3709478ff3b33deff5e6d19"
648 | }
649 | ]
650 | },
651 | "editor-arm64-macos": {
652 | "versions": [
653 | {
654 | "version": "1.9.0",
655 | "sha1": "d6882f432beca85d460ec42497888157c356d058"
656 | },
657 | {
658 | "version": "1.9.1",
659 | "sha1": "3be87d89fd5a93a63f527351fbedb84f8a875812"
660 | },
661 | {
662 | "version": "1.9.2",
663 | "sha1": "3251ca82359cf238a1074e383281e3126547d50b"
664 | },
665 | {
666 | "version": "1.9.3",
667 | "sha1": "e4aaff11f49c941fde1dd93883cf69c6b8abebe4"
668 | },
669 | {
670 | "version": "1.9.4",
671 | "sha1": "512763fd375633fd67197225e61fe90a5929166b"
672 | },
673 | {
674 | "version": "1.9.5",
675 | "sha1": "87b6907759f7b8dff830d54b2250b8d721bde291"
676 | },
677 | {
678 | "version": "1.9.6",
679 | "sha1": "4035511f1e258a47b77798a2005c024609ed2c67"
680 | },
681 | {
682 | "version": "1.9.7",
683 | "sha1": "a1ae95286a1b2677ed3fda6785816e76df4ee8a2"
684 | },
685 | {
686 | "version": "1.9.8",
687 | "sha1": "a9247e38b24ba1c1ed5913c4049d9a4083a314a7"
688 | },
689 | {
690 | "version": "1.10.0",
691 | "sha1": "591eb496d52f4140bc2c7de547131f1b9408b9b4"
692 | },
693 | {
694 | "version": "1.10.1",
695 | "sha1": "2783cc609cd52bc5ac92ec9e35b9b854f5f07882"
696 | },
697 | {
698 | "version": "1.10.2",
699 | "sha1": "f56fcca509a9fa5350bf55f18d8c6087295a8cef"
700 | },
701 | {
702 | "version": "1.10.3",
703 | "sha1": "1c76521bb8b08c63ef619aa8a5ab563dddf7b3cf"
704 | },
705 | {
706 | "version": "1.10.4",
707 | "sha1": "1aafd0a262ff40214ed7f51302d92fa587c607ef"
708 | },
709 | {
710 | "version": "1.11.0",
711 | "sha1": "7c81792859a6da7f7401c0ac37a4cc83bb500ff6"
712 | },
713 | {
714 | "version": "1.11.1",
715 | "sha1": "1ba9e1aa422166864c3267f03f5110144b745c1e"
716 | },
717 | {
718 | "version": "1.11.2",
719 | "sha1": "a6d86c0083f00ee6c3709478ff3b33deff5e6d19"
720 | }
721 | ]
722 | }
723 | }
724 | }
--------------------------------------------------------------------------------
/releases.json:
--------------------------------------------------------------------------------
1 | {
2 | "releases": [
3 | {
4 | "version": "1.2.38",
5 | "sha1": "d0fdb9c5fc1ac46debbbc39e8ac572b6fa7652f7"
6 | },
7 | {
8 | "version": "1.2.39",
9 | "sha1": "4c263ff84c19de1f6304e9c2cf756bf572009d38"
10 | },
11 | {
12 | "version": "1.2.40",
13 | "sha1": "b8b46b391ee60a5762024931f92d7cf90650b0dc"
14 | },
15 | {
16 | "version": "1.2.41",
17 | "sha1": "95d50f8ef9f04617a6498f6412dac3aab960dc6e"
18 | },
19 | {
20 | "version": "1.2.42",
21 | "sha1": "b10ae21d0ef877e91fc91c89d39399d6a8a56caf"
22 | },
23 | {
24 | "version": "1.2.43",
25 | "sha1": "a10a45eba9544958b7d64d4dbe90cf8e3eabcf0e"
26 | },
27 | {
28 | "version": "1.2.44",
29 | "sha1": "30d355de2d97ef54fabaa53938a52963dec8f88c"
30 | },
31 | {
32 | "version": "1.2.45",
33 | "sha1": "4a5a22d288d6bc2806a4a79d2162124f94059b9f"
34 | },
35 | {
36 | "version": "1.2.46",
37 | "sha1": "af94d38e4bc8fa29f807025f07b25d6c2d38efe0"
38 | },
39 | {
40 | "version": "1.2.47",
41 | "sha1": "445d9ce11e76531c6a3823743617b2937aa2bc8a"
42 | },
43 | {
44 | "version": "1.2.48",
45 | "sha1": "4886ef433cd87a45ca5a447af8bc568e4409bd52"
46 | },
47 | {
48 | "version": "1.2.49",
49 | "sha1": "84a19985eb2912d17bb571d61473c5d6be66c9b1"
50 | },
51 | {
52 | "version": "1.2.50",
53 | "sha1": "44be13348c6547916506d18c763ac96665e21f65"
54 | },
55 | {
56 | "version": "1.2.51",
57 | "sha1": "9dcd71c92feb7bbc8bcb00e24c29a6f86d76e97a"
58 | },
59 | {
60 | "version": "1.2.52",
61 | "sha1": "1b7762c5433a293fb7181eb8347f776f35ea8e09"
62 | },
63 | {
64 | "version": "1.2.53",
65 | "sha1": "a1b8f3d533e7f8713fdee217badce2d1acdc71c2"
66 | },
67 | {
68 | "version": "1.2.54",
69 | "sha1": "d9baebe87893f1d220660773a3e7ae8932e6f5a9"
70 | },
71 | {
72 | "version": "1.2.55",
73 | "sha1": "ed97ba8447a25c71eeed7b690497ae5a3c42f9a7"
74 | },
75 | {
76 | "version": "1.2.56",
77 | "sha1": "c263328a62ce78fcc86941c680670e1f20e6ce98"
78 | },
79 | {
80 | "version": "1.2.57",
81 | "sha1": "2b680b3ec7af8a84401ad584d8bc47a246f82947"
82 | },
83 | {
84 | "version": "1.2.58",
85 | "sha1": "3ffc1a4f07ca69d5d47ff11e510fff4d7993e5b3"
86 | },
87 | {
88 | "version": "1.2.59",
89 | "sha1": "c85517d64288d5d9f2d3bad146dd192687a6b493"
90 | },
91 | {
92 | "version": "1.2.60",
93 | "sha1": "f0b34f3292b01184a461f928fcee5aceae741e23"
94 | },
95 | {
96 | "version": "1.2.61",
97 | "sha1": "bfa38969ef225100fb5d9a1c43414d882f17f09a"
98 | },
99 | {
100 | "version": "1.2.62",
101 | "sha1": "36f9c452d9ba2ffb14dfbd91b96b963f17ad1a01"
102 | },
103 | {
104 | "version": "1.2.63",
105 | "sha1": "7053e150cb4412f3bc7af11562e27ac292e1e408"
106 | },
107 | {
108 | "version": "1.2.64",
109 | "sha1": "1a026deefcdb40e8251606a1c20ec665e277dcd9"
110 | },
111 | {
112 | "version": "1.2.65",
113 | "sha1": "39f180d1fc4ee616bd9e29a321bd58845317a939"
114 | },
115 | {
116 | "version": "1.2.66",
117 | "sha1": "b8e108961099b9b70ff82476bed03f6d6606ef4f"
118 | },
119 | {
120 | "version": "1.2.67",
121 | "sha1": "dd97a77bb97cde6a6a83f2dd25c3884751e9511f"
122 | },
123 | {
124 | "version": "1.2.68",
125 | "sha1": "dd13311deab181d63775c04be935656fdcbdd7cf"
126 | },
127 | {
128 | "version": "1.2.69",
129 | "sha1": "18ac5ddf4e9737833068d6e9f8a9e0230f281b68"
130 | },
131 | {
132 | "version": "1.2.70",
133 | "sha1": "864eba8ab0257ac795c9593334c79f4b3cbbbbb6"
134 | },
135 | {
136 | "version": "1.2.71",
137 | "sha1": "00c6dbb2506e5b567adec6e6b591e2684914e419"
138 | },
139 | {
140 | "version": "1.2.72",
141 | "sha1": "181f1cd0d18716abc26524eb83444ec3b1c3455e"
142 | },
143 | {
144 | "version": "1.2.73",
145 | "sha1": "181bfb10b315d75960210b4b19d13379a154a518"
146 | },
147 | {
148 | "version": "1.2.74",
149 | "sha1": "5d0293aa4206f0ad6b15c6c373dd85cc24a96454"
150 | },
151 | {
152 | "version": "1.2.75",
153 | "sha1": "0929102a19fd1c3d3b655a6fd4120fcc59d96ec2"
154 | },
155 | {
156 | "version": "1.2.76",
157 | "sha1": "85b4c750f5994f7e97460c7395f365c24e2fe215"
158 | },
159 | {
160 | "version": "1.2.77",
161 | "sha1": "86c9c6e78e532440b82c8400f328730b0d72448e"
162 | },
163 | {
164 | "version": "1.2.78",
165 | "sha1": "6b5b6a73cc16d52f2e935bd03c305b6722b73772"
166 | },
167 | {
168 | "version": "1.2.79",
169 | "sha1": "683677d7d655e9c7aa3328ce9c72dd126391447d"
170 | },
171 | {
172 | "version": "1.2.80",
173 | "sha1": "c7176baed6df55d32c3286ce27c84e1fe45406c4"
174 | },
175 | {
176 | "version": "1.2.81",
177 | "sha1": "e8e0c7d8d49d99fa51b90887e8cc5d31d7fbcf6d"
178 | },
179 | {
180 | "version": "1.2.82",
181 | "sha1": "5fb9dca1a7303e505c95c53c18a29d69418cb6d3"
182 | },
183 | {
184 | "version": "1.2.83",
185 | "sha1": "1f14af3d6d66b328bdcc4b537e5f109c3f4014b9"
186 | },
187 | {
188 | "version": "1.2.84",
189 | "sha1": "5eb478decad6398828e764ed07ba582c9423bd0b"
190 | },
191 | {
192 | "version": "1.2.85",
193 | "sha1": "69b592ceb2ff974584085b6877506a6ddc14c157"
194 | },
195 | {
196 | "version": "1.2.86",
197 | "sha1": "ae263d1a84869f9f7e8d453f86f4591a76bf0564"
198 | },
199 | {
200 | "version": "1.2.87",
201 | "sha1": "ad5e4d8464435e6b8a51645b6590e6014a454c86"
202 | },
203 | {
204 | "version": "1.2.88",
205 | "sha1": "0a5b3b315212623e0f09ae240702234aa1808992"
206 | },
207 | {
208 | "version": "1.2.89",
209 | "sha1": "5ca3dd134cc960c35ecefe12f6dc81a48f212d40"
210 | },
211 | {
212 | "version": "1.2.90",
213 | "sha1": "5d25bd72acaca1a4bd97038168f8369d370b3645"
214 | },
215 | {
216 | "version": "1.2.91",
217 | "sha1": "618f38b65e8b867ea81c3ef892bb2b2b8cc959ce"
218 | },
219 | {
220 | "version": "1.2.92",
221 | "sha1": "619820e3e9df9f588981e816bf77232a05a59eaf"
222 | },
223 | {
224 | "version": "1.2.93",
225 | "sha1": "f2c010d1fcfe5c619bfcea890feb84d46ef5f47a"
226 | },
227 | {
228 | "version": "1.2.94",
229 | "sha1": "a9ec217c3e4b486c07a86c935b0cc805b6680480"
230 | },
231 | {
232 | "version": "1.2.95",
233 | "sha1": "7ca47a7f7aa0e4809e31ab2274fd1693a1fc5a7e"
234 | },
235 | {
236 | "version": "1.2.96",
237 | "sha1": "0060183cce2e29dbd09c85ece83cbb72068ee050"
238 | },
239 | {
240 | "version": "1.2.97",
241 | "sha1": "8e1d5f8a8a0e1734c9e873ec72b56bea53f25d87"
242 | },
243 | {
244 | "version": "1.2.98",
245 | "sha1": "735ff76c8b1f93b3126ff223cd234d7ceb5b886d"
246 | },
247 | {
248 | "version": "1.2.99",
249 | "sha1": "0d7f8b51658bee90cb38f3d651b3ba072394afed"
250 | },
251 | {
252 | "version": "1.2.100",
253 | "sha1": "1afccdb2cd42ca3bc7612a0496dfa6d434a8ebf9"
254 | },
255 | {
256 | "version": "1.2.101",
257 | "sha1": "1e53d81a6306962b64381195f081d442d033ead1"
258 | },
259 | {
260 | "version": "1.2.102",
261 | "sha1": "d530758af74c2800d0898c591cc7188cc4515476"
262 | },
263 | {
264 | "version": "1.2.103",
265 | "sha1": "d126b0348d27c684d020e0bd43fde0a2771746f0"
266 | },
267 | {
268 | "version": "1.2.104",
269 | "sha1": "298b7ce75a1386a26124061dbccfa822df9bc982"
270 | },
271 | {
272 | "version": "1.2.105",
273 | "sha1": "a285bcf69ac6de9d1cab399768b74968c80cd864"
274 | },
275 | {
276 | "version": "1.2.106",
277 | "sha1": "dc92d10b96eaa8c0b3e527c76fecb22186d7cd60"
278 | },
279 | {
280 | "version": "1.2.107",
281 | "sha1": "597b94fc8d88b8f24264d54a59851951d04eae5c"
282 | },
283 | {
284 | "version": "1.2.108",
285 | "sha1": "8c2083883fdf321a3fa2aa1a1a5d319a82635c10"
286 | },
287 | {
288 | "version": "1.2.109",
289 | "sha1": "d1aad61476af35638fb6201574c7cc9869733aa6"
290 | },
291 | {
292 | "version": "1.2.110",
293 | "sha1": "de8a2aeb1843f573c81ab89c07c0ffb5f1c12e58"
294 | },
295 | {
296 | "version": "1.2.111",
297 | "sha1": "7ba1ba8d65588009458c7f389307d1943d25a683"
298 | },
299 | {
300 | "version": "1.2.112",
301 | "sha1": "0dde28ca92551934cf34137e33d029cce19b2447"
302 | },
303 | {
304 | "version": "1.2.113",
305 | "sha1": "e0ad6b7ed96333a156d95855641664f4b76fd0f6"
306 | },
307 | {
308 | "version": "1.2.114",
309 | "sha1": "5de6a24af5821865121237c3f77f8a42c8a044e2"
310 | },
311 | {
312 | "version": "1.2.115",
313 | "sha1": "57fb5f1ad5df59262aa415f298f97694debc991c"
314 | },
315 | {
316 | "version": "1.2.116",
317 | "sha1": "33da4aa91761d531471f364ef1693c2acec16de7"
318 | },
319 | {
320 | "version": "1.2.117",
321 | "sha1": "4ac025d15c25a9e0dbf14140d2e5d443c2edfdc4"
322 | },
323 | {
324 | "version": "1.2.118",
325 | "sha1": "0faa10db6bb28907d67358ad5810f3962437f3fd"
326 | },
327 | {
328 | "version": "1.2.119",
329 | "sha1": "2406775912d235d2579cfe723ab4dbcea2ca77ca"
330 | },
331 | {
332 | "version": "1.2.120",
333 | "sha1": "c70ad190898e790f8284e8dab0e31c9090476be9"
334 | },
335 | {
336 | "version": "1.2.121",
337 | "sha1": "9988355914f63362a4292c4827639f0187275e70"
338 | },
339 | {
340 | "version": "1.2.122",
341 | "sha1": "fce7921da858a71876773c75920b74310ca7ac1f"
342 | },
343 | {
344 | "version": "1.2.123",
345 | "sha1": "46d8b7e63d7e0f0f4acd545c46d25ca2b227a806"
346 | },
347 | {
348 | "version": "1.2.124",
349 | "sha1": "e3f2a48e6495946eb8aede3c843471bb037976aa"
350 | },
351 | {
352 | "version": "1.2.125",
353 | "sha1": "f9995611e4d5befaa75d6b6d7becdd52823e01eb"
354 | },
355 | {
356 | "version": "1.2.126",
357 | "sha1": "32ba5eaa128e4b54113fb36eb4b9eff33d8582b3"
358 | },
359 | {
360 | "version": "1.2.127",
361 | "sha1": "c129eafe38a95a1a69eec93679790cd29ab6c0a6"
362 | },
363 | {
364 | "version": "1.2.128",
365 | "sha1": "477e0e1034b76a6f9e07fb5ead5dc10adcd2ba6d"
366 | },
367 | {
368 | "version": "1.2.129",
369 | "sha1": "30b201abdb7224683a3b3de2a02b22946dbbd427"
370 | },
371 | {
372 | "version": "1.2.130",
373 | "sha1": "3abf70ee10dfb24e43529ff2e7ffbf1905ef5c19"
374 | },
375 | {
376 | "version": "1.2.131",
377 | "sha1": "091e7e02ce492d3c4e493324b9db57d40df69e95"
378 | },
379 | {
380 | "version": "1.2.132",
381 | "sha1": "09410355c1baf7e474e46cbc2d252f67f673e1dc"
382 | },
383 | {
384 | "version": "1.2.133",
385 | "sha1": "7b2c2c019d6fa106f78e2e98cd3009a21d4095aa"
386 | },
387 | {
388 | "version": "1.2.134",
389 | "sha1": "b2ef3a19802728e76adf84d51d02e11d636791a3"
390 | },
391 | {
392 | "version": "1.2.135",
393 | "sha1": "1b90c9a905d634b766b467e3536458b9210ec812"
394 | },
395 | {
396 | "version": "1.2.136",
397 | "sha1": "883d660f9894e0d2bcc7f5895c1eaab1153e98b6"
398 | },
399 | {
400 | "version": "1.2.137",
401 | "sha1": "936eee90249fcf505f8dbe5b215db5d165221cca"
402 | },
403 | {
404 | "version": "1.2.138",
405 | "sha1": "cd250cdbbace72ce374bf44ad8302739e69f65ec"
406 | },
407 | {
408 | "version": "1.2.139",
409 | "sha1": "eedf9a7f2aa650143bb7169bf7e209cba80ef527"
410 | },
411 | {
412 | "version": "1.2.140",
413 | "sha1": "2fc8ff32c9fa3a16c8f4ce44eba8351c054b33dd"
414 | },
415 | {
416 | "version": "1.2.141",
417 | "sha1": "738e2ebc3cba56027fa00ca27706019bb772871c"
418 | },
419 | {
420 | "version": "1.2.142",
421 | "sha1": "6230c40dfa051a311aa4005c19097574e062374d"
422 | },
423 | {
424 | "version": "1.2.143",
425 | "sha1": "d13de133800e52aeda921e270d1d7340d5ac6684"
426 | },
427 | {
428 | "version": "1.2.144",
429 | "sha1": "8def4b50c9aa049670e698d7dff3dc00d77e42d5"
430 | },
431 | {
432 | "version": "1.2.145",
433 | "sha1": "9f376d88408bad9088a4187d4f874ae4767a0185"
434 | },
435 | {
436 | "version": "1.2.146",
437 | "sha1": "851fbeb469987908d2b785fa3964003acc919394"
438 | },
439 | {
440 | "version": "1.2.147",
441 | "sha1": "5f1c6286a8bb1cfd8505517c1734f6d0666bf5df"
442 | },
443 | {
444 | "version": "1.2.148",
445 | "sha1": "47c9f8e03623ca3ac511b5a55e6cfcc7e51ce340"
446 | },
447 | {
448 | "version": "1.2.149",
449 | "sha1": "34bb9603dfcb145c74fbb4f36f4146acea4c4252"
450 | },
451 | {
452 | "version": "1.2.150",
453 | "sha1": "e79cdece4f5c8498302b3b00591808e3dc5a1827"
454 | },
455 | {
456 | "version": "1.2.151",
457 | "sha1": "e05232d70b8a6d8c69fcfe968f01b876090ffa06"
458 | },
459 | {
460 | "version": "1.2.152",
461 | "sha1": "11b1e7662dd68172fca551c52cba248eea16a364"
462 | },
463 | {
464 | "version": "1.2.153",
465 | "sha1": "89a2b88bceb3b17682f301b2212764ea16761f4c"
466 | },
467 | {
468 | "version": "1.2.154",
469 | "sha1": "2a329c6cc44abfec727e985898d428d6860f658a"
470 | },
471 | {
472 | "version": "1.2.155",
473 | "sha1": "838cecd7a26c932e6be73421d98e51ba12f1d462"
474 | },
475 | {
476 | "version": "1.2.156",
477 | "sha1": "67b68f1e1ac26a3385fb511cdce520fe52387bb0"
478 | },
479 | {
480 | "version": "1.2.157",
481 | "sha1": "d7042d5368c338ed5d66b6dff9c60a20924385ac"
482 | },
483 | {
484 | "version": "1.2.158",
485 | "sha1": "3d63d0509cc828c9555afc149cccfea0f7f83c97"
486 | },
487 | {
488 | "version": "1.2.159",
489 | "sha1": "f7d0a1ba6940e42c7f7e1c208ba484c3c34a135d"
490 | },
491 | {
492 | "version": "1.2.160",
493 | "sha1": "1a8e53ae9c38a09b742d38dffc6a9f2efdbe6e97"
494 | },
495 | {
496 | "version": "1.2.161",
497 | "sha1": "45635ad26f85009c52905724e242cc92dd252146"
498 | },
499 | {
500 | "version": "1.2.162",
501 | "sha1": "e07f3bb9e8c970eceda8dce8efd5905fd67fa720"
502 | },
503 | {
504 | "version": "1.2.163",
505 | "sha1": "13261949f45c333806c8aac8bd5b08124ca2810f"
506 | },
507 | {
508 | "version": "1.2.164",
509 | "sha1": "13261949f45c333806c8aac8bd5b08124ca2810f"
510 | },
511 | {
512 | "version": "1.2.165",
513 | "sha1": "2be2687cbb670c2dbe9cf2e99577bc3338561778"
514 | },
515 | {
516 | "version": "1.2.166",
517 | "sha1": "5295afb3878441fb12f497df8831148525dcfb10"
518 | },
519 | {
520 | "version": "1.2.167",
521 | "sha1": "96f7a5e4f617d5f6f4645f30a3e6ff656689435d"
522 | },
523 | {
524 | "version": "1.2.168",
525 | "sha1": "e22f6d2f81e7c53ebcbfefe703ff22ce5da252c0"
526 | },
527 | {
528 | "version": "1.2.169",
529 | "sha1": "4ebe7a1d548eae2398717ed46f9d7d1b103d5503"
530 | },
531 | {
532 | "version": "1.2.170",
533 | "sha1": "5791ee6d96b87e50eee5acd70abaa4026fefef28"
534 | },
535 | {
536 | "version": "1.2.171",
537 | "sha1": "29b8e598b0bce19b274327c5d9711f78b3bd0c22"
538 | },
539 | {
540 | "version": "1.2.172",
541 | "sha1": "dedf1ed10d96c92df6e361f5494531c79af4c1cf"
542 | },
543 | {
544 | "version": "1.2.173",
545 | "sha1": "fe2b689302e79b7cf8c0bc7d934f23587b268c8a"
546 | },
547 | {
548 | "version": "1.2.174",
549 | "sha1": "8f3e864464062e1b35c207521dc65dfd77899cdf"
550 | },
551 | {
552 | "version": "1.2.175",
553 | "sha1": "e41438cca6cc1550d4a0131b8fc3858c2a4097f1"
554 | },
555 | {
556 | "version": "1.2.176",
557 | "sha1": "7107bc8781535e83cbb30734b32d6b32a3039cd0"
558 | },
559 | {
560 | "version": "1.2.177",
561 | "sha1": "28a2c96432d6329caa4d845967ba76ffcc2fc773"
562 | },
563 | {
564 | "version": "1.2.178",
565 | "sha1": "d1948ec5629c0f7fe037d199b043391f2929fc58"
566 | },
567 | {
568 | "version": "1.2.179",
569 | "sha1": "af6a29c2a1e2545e2d033790089c606ac9f0bb7a"
570 | },
571 | {
572 | "version": "1.2.180",
573 | "sha1": "99c844bd84d5718189de7beb23ea801ddf72778e"
574 | },
575 | {
576 | "version": "1.2.181",
577 | "sha1": "ff5b94e432eb58dabdb8e367bed9acc5e99e129b"
578 | },
579 | {
580 | "version": "1.2.182",
581 | "sha1": "1a2776dac6a868eed1a35e41acb0c71a7e17948f"
582 | },
583 | {
584 | "version": "1.2.183",
585 | "sha1": "7e7ab0f78048390f41d187fb60d1553297a67e5f"
586 | },
587 | {
588 | "version": "1.2.184",
589 | "sha1": "1f5712609c345f870b691a85d611d4825d22a718"
590 | },
591 | {
592 | "version": "1.2.185",
593 | "sha1": "0a8d3e879724132afb18d47e0040c2034be07504"
594 | },
595 | {
596 | "version": "1.2.186",
597 | "sha1": "1f748d5b0a84e8b5c58bf747e4c48d153ef77a52"
598 | },
599 | {
600 | "version": "1.2.187",
601 | "sha1": "581c6439ae93755a8a6bcf58732c39c724fa193c"
602 | },
603 | {
604 | "version": "1.2.188",
605 | "sha1": "6bfeea3b13d7b8920483ea2cba9c181a8650b84d"
606 | },
607 | {
608 | "version": "1.2.189",
609 | "sha1": "794112e7e21be5d00f1cc70bb891b80ded986c6f"
610 | },
611 | {
612 | "version": "1.2.190",
613 | "sha1": "d31d6397a72178541a5ef6e7ef2bed090d828f58"
614 | },
615 | {
616 | "version": "1.2.191",
617 | "sha1": "d393bae6a361f86cf2263ab312c9b3cea45253ab"
618 | },
619 | {
620 | "version": "1.2.192",
621 | "sha1": "84a9c89dfd5a2c3818c01e7c6777169272d9390b"
622 | },
623 | {
624 | "version": "1.3.0",
625 | "sha1": "0e77ba11ac957ee01878bbde2e6ac0c9fae6dc01"
626 | },
627 | {
628 | "version": "1.3.1",
629 | "sha1": "06bc078e490fd7d94ec01e38abac989f6cc351a5"
630 | },
631 | {
632 | "version": "1.3.2",
633 | "sha1": "287c945fab310c324493e08b191ee1b1538ef973"
634 | },
635 | {
636 | "version": "1.3.3",
637 | "sha1": "287c945fab310c324493e08b191ee1b1538ef973"
638 | },
639 | {
640 | "version": "1.3.4",
641 | "sha1": "80b1b73fd9cdbd4682c2583403fddfbaf0919107"
642 | },
643 | {
644 | "version": "1.3.5",
645 | "sha1": "28eafea5a8bfedfddc621a7cd00b39f25bd34922"
646 | },
647 | {
648 | "version": "1.3.6",
649 | "sha1": "905234d8da2e642f1075c73aaa1bfb72e49199e3"
650 | },
651 | {
652 | "version": "1.3.7",
653 | "sha1": "f0ad06a2f1fbf0e9cbddbf96162a75bc006d84bb"
654 | },
655 | {
656 | "version": "1.4.0",
657 | "sha1": "9c44c4a9b6cbc9d0cb66b7027b7c984bf364a568"
658 | },
659 | {
660 | "version": "1.4.1",
661 | "sha1": "8f96e450ddfb006a99aa134fdd373cace3760571"
662 | },
663 | {
664 | "version": "1.4.2",
665 | "sha1": "8cd3a634b13f4db51a37607bf32bf3a3b362c8e6"
666 | },
667 | {
668 | "version": "1.4.3",
669 | "sha1": "8eaab6b1281ce492163428e0e7b2e0fa247a0a93"
670 | },
671 | {
672 | "version": "1.4.4",
673 | "sha1": "f5e114aaebe25c5242db5f0066af2f5189c09f99"
674 | },
675 | {
676 | "version": "1.4.5",
677 | "sha1": "3dbbf1dbebd3a8146f6a917d101882a61f56afdc"
678 | },
679 | {
680 | "version": "1.4.6",
681 | "sha1": "cb8b34230bd42a5e0b68c12441657f06485562a6"
682 | },
683 | {
684 | "version": "1.4.7",
685 | "sha1": "7a608d3ce6ed895d484956c1e76110ed8b78422a"
686 | },
687 | {
688 | "version": "1.4.8",
689 | "sha1": "504de7800fa81847bfc2e26a21973899db9dd747"
690 | },
691 | {
692 | "version": "1.5.0",
693 | "sha1": "57b34efdf44a922acc6f21d285b207029b53927d"
694 | },
695 | {
696 | "version": "1.6.0",
697 | "sha1": "981353ef7ba544d3074cefdbfe275b541b7038aa"
698 | },
699 | {
700 | "version": "1.6.1",
701 | "sha1": "27bbea23f00cfb65707cb096fbe82ba7b78723f6"
702 | },
703 | {
704 | "version": "1.6.2",
705 | "sha1": "708bbcc6985d4cf3719829603972a39895a03a07"
706 | },
707 | {
708 | "version": "1.6.3",
709 | "sha1": "0d35fc89aabab0456ef2ee7572f0571314b97121"
710 | },
711 | {
712 | "version": "1.6.4",
713 | "sha1": "4689e4033ebfc982176b92545900302d0fcb03b3"
714 | },
715 | {
716 | "version": "1.7.0",
717 | "sha1": "bf4dc66ab5fbbafd4294d32c2797c08b630c0be5"
718 | },
719 | {
720 | "version": "1.8.0",
721 | "sha1": "ef07c036b8f7d34f4b1d7fcc355ce46a92d2dcc8"
722 | },
723 | {
724 | "version": "1.8.1",
725 | "sha1": "fd1ad4c17bfdcd890ea7176f2672c35102384419"
726 | },
727 | {
728 | "version": "1.9.0",
729 | "sha1": "d6882f432beca85d460ec42497888157c356d058"
730 | },
731 | {
732 | "version": "1.9.1",
733 | "sha1": "3be87d89fd5a93a63f527351fbedb84f8a875812"
734 | },
735 | {
736 | "version": "1.9.2",
737 | "sha1": "3251ca82359cf238a1074e383281e3126547d50b"
738 | },
739 | {
740 | "version": "1.9.3",
741 | "sha1": "e4aaff11f49c941fde1dd93883cf69c6b8abebe4"
742 | },
743 | {
744 | "version": "1.9.4",
745 | "sha1": "512763fd375633fd67197225e61fe90a5929166b"
746 | },
747 | {
748 | "version": "1.9.5",
749 | "sha1": "87b6907759f7b8dff830d54b2250b8d721bde291"
750 | },
751 | {
752 | "version": "1.9.6",
753 | "sha1": "4035511f1e258a47b77798a2005c024609ed2c67"
754 | },
755 | {
756 | "version": "1.9.7",
757 | "sha1": "a1ae95286a1b2677ed3fda6785816e76df4ee8a2"
758 | },
759 | {
760 | "version": "1.9.8",
761 | "sha1": "a9247e38b24ba1c1ed5913c4049d9a4083a314a7"
762 | },
763 | {
764 | "version": "1.10.0",
765 | "sha1": "591eb496d52f4140bc2c7de547131f1b9408b9b4"
766 | },
767 | {
768 | "version": "1.10.1",
769 | "sha1": "2783cc609cd52bc5ac92ec9e35b9b854f5f07882"
770 | },
771 | {
772 | "version": "1.10.2",
773 | "sha1": "f56fcca509a9fa5350bf55f18d8c6087295a8cef"
774 | },
775 | {
776 | "version": "1.10.3",
777 | "sha1": "1c76521bb8b08c63ef619aa8a5ab563dddf7b3cf"
778 | },
779 | {
780 | "version": "1.10.4",
781 | "sha1": "1aafd0a262ff40214ed7f51302d92fa587c607ef"
782 | },
783 | {
784 | "version": "1.11.0",
785 | "sha1": "7c81792859a6da7f7401c0ac37a4cc83bb500ff6"
786 | },
787 | {
788 | "version": "1.11.1",
789 | "sha1": "1ba9e1aa422166864c3267f03f5110144b745c1e"
790 | },
791 | {
792 | "version": "1.11.2",
793 | "sha1": "a6d86c0083f00ee6c3709478ff3b33deff5e6d19"
794 | }
795 | ]
796 | }
--------------------------------------------------------------------------------
/js/dashboard.js:
--------------------------------------------------------------------------------
1 | // Defold Component Size Dashboard
2 |
3 | class DefoldDashboard {
4 | constructor() {
5 | this.csvCache = new Map();
6 | this.charts = new Map();
7 | this.chartConfigs = new Map(); // Store chart configurations
8 | this.platformColors = {
9 | 'arm64-ios': '#e74c3c',
10 | 'arm64-android': '#3498db',
11 | 'armv7-android': '#9b59b6',
12 | 'x86_64-macos': '#2ecc71',
13 | 'js-web': '#f39c12',
14 | 'wasm-web': '#e67e22',
15 | 'x86_64-linux': '#34495e',
16 | 'x86-win32': '#16a085',
17 | 'x86_64-win32': '#27ae60',
18 | 'arm64-macos': '#8e44ad'
19 | };
20 |
21 | this.init();
22 |
23 | // Add window resize listener to handle responsive layout changes
24 | window.addEventListener('resize', () => {
25 | this.handleResize();
26 | });
27 | }
28 |
29 | async init() {
30 | try {
31 | // Load all CSV files
32 | await this.loadAllData();
33 |
34 | // Create all charts
35 | this.createBundleChart();
36 | this.createEngineChart();
37 | this.createEditorChart();
38 | this.createBobChart();
39 |
40 | // Setup version dropdowns and event listeners
41 | this.setupVersionDropdowns();
42 |
43 | console.log('Dashboard loaded successfully');
44 |
45 | } catch (error) {
46 | console.error('Error initializing dashboard:', error);
47 | this.showError('Failed to load dashboard data');
48 | }
49 | }
50 |
51 | async loadAllData() {
52 | const files = ['bundle_report.csv', 'engine_report.csv', 'editor_report.csv', 'bob_report.csv'];
53 |
54 | for (const file of files) {
55 | await this.loadCSV(file);
56 | }
57 | }
58 |
59 | async loadCSV(filename) {
60 | if (this.csvCache.has(filename)) {
61 | return this.csvCache.get(filename);
62 | }
63 |
64 | try {
65 | const response = await fetch(filename);
66 | if (!response.ok) {
67 | throw new Error(`HTTP error! status: ${response.status}`);
68 | }
69 |
70 | const text = await response.text();
71 | const data = this.parseCSV(text);
72 |
73 | // Filter out rows with all zeros
74 | const filteredData = data.filter(row => {
75 | const values = Object.values(row);
76 | return values.some(value => value !== 'VERSION' && parseFloat(value) > 0);
77 | });
78 |
79 | this.csvCache.set(filename, filteredData);
80 | return filteredData;
81 |
82 | } catch (error) {
83 | console.error(`Error loading ${filename}:`, error);
84 | throw error;
85 | }
86 | }
87 |
88 | parseCSV(text) {
89 | const lines = text.trim().split('\n');
90 | const headers = lines[0].split(',').map(h => h.trim());
91 | const data = [];
92 |
93 | for (let i = 1; i < lines.length; i++) {
94 | const values = lines[i].split(',').map(v => v.trim());
95 | if (values.length === headers.length) {
96 | const row = {};
97 | headers.forEach((header, index) => {
98 | row[header] = values[index];
99 | });
100 | data.push(row);
101 | }
102 | }
103 |
104 | return data;
105 | }
106 |
107 | compareVersions(v1, v2) {
108 | const a = v1.split('.').map(Number);
109 | const b = v2.split('.').map(Number);
110 |
111 | for (let i = 0; i < Math.max(a.length, b.length); i++) {
112 | const numA = a[i] || 0;
113 | const numB = b[i] || 0;
114 | if (numA !== numB) {
115 | return numA - numB;
116 | }
117 | }
118 | return 0;
119 | }
120 |
121 | filterDataFromVersion(data, startVersion) {
122 | return data.filter(row => {
123 | const version = row.VERSION;
124 | return this.compareVersions(version, startVersion) >= 0;
125 | });
126 | }
127 |
128 | calculateDefaultVersion(csvFile, minimumVersion) {
129 | const rawData = this.csvCache.get(csvFile);
130 | if (!rawData) return minimumVersion;
131 |
132 | // Get all versions with data (non-zero values)
133 | const versions = rawData
134 | .filter(row => {
135 | const values = Object.values(row);
136 | return values.some(value => value !== 'VERSION' && parseFloat(value) > 0);
137 | })
138 | .map(row => row.VERSION);
139 |
140 | // Sort versions
141 | versions.sort(this.compareVersions.bind(this));
142 |
143 | // Filter to only include versions >= minimum allowed
144 | const validVersions = versions.filter(version =>
145 | this.compareVersions(version, minimumVersion) >= 0
146 | );
147 |
148 | // If we have more than 20 versions, start from the 20th from the end
149 | if (validVersions.length > 20) {
150 | const startIndex = validVersions.length - 20;
151 | return validVersions[startIndex];
152 | }
153 |
154 | // If we have 20 or fewer versions, start from the minimum
155 | return minimumVersion;
156 | }
157 |
158 | formatBytes(bytes) {
159 | if (bytes === 0) return '0 B';
160 |
161 | const k = 1024;
162 | const sizes = ['B', 'KB', 'MB', 'GB'];
163 | const i = Math.floor(Math.log(Math.abs(bytes)) / Math.log(k));
164 |
165 | return (bytes / Math.pow(k, i)).toFixed(1) + ' ' + sizes[i];
166 | }
167 |
168 | createBundleChart() {
169 | const rawData = this.csvCache.get('bundle_report.csv');
170 | const platforms = ['arm64-ios', 'arm64-android', 'armv7-android', 'x86_64-macos', 'js-web', 'wasm-web', 'x86_64-linux', 'x86-win32', 'x86_64-win32', 'arm64-macos'];
171 |
172 | // Calculate default version (last 20 versions)
173 | const defaultVersion = this.calculateDefaultVersion('bundle_report.csv', '1.2.166');
174 |
175 | // Store chart config
176 | this.chartConfigs.set('bundle-chart', {
177 | csvFile: 'bundle_report.csv',
178 | platforms: platforms,
179 | title: 'Bundle Size Evolution',
180 | defaultVersion: defaultVersion,
181 | selectId: 'bundle-version-select'
182 | });
183 |
184 | const data = this.filterDataFromVersion(rawData, defaultVersion);
185 | this.createChart('bundle-chart', data, platforms, 'Bundle Size Evolution');
186 | }
187 |
188 | createEngineChart() {
189 | const rawData = this.csvCache.get('engine_report.csv');
190 | const platforms = ['arm64-ios', 'arm64-android', 'armv7-android', 'x86_64-macos', 'js-web', 'wasm-web', 'x86_64-linux', 'x86-win32', 'x86_64-win32', 'arm64-macos'];
191 |
192 | // Calculate default version (last 20 versions)
193 | const defaultVersion = this.calculateDefaultVersion('engine_report.csv', '1.2.166');
194 |
195 | // Store chart config
196 | this.chartConfigs.set('engine-chart', {
197 | csvFile: 'engine_report.csv',
198 | platforms: platforms,
199 | title: 'Engine Size Evolution',
200 | defaultVersion: defaultVersion,
201 | selectId: 'engine-version-select'
202 | });
203 |
204 | const data = this.filterDataFromVersion(rawData, defaultVersion);
205 | this.createChart('engine-chart', data, platforms, 'Engine Size Evolution');
206 | }
207 |
208 | createEditorChart() {
209 | const rawData = this.csvCache.get('editor_report.csv');
210 | const platforms = ['x86_64-macos', 'x86_64-win32', 'x86_64-linux', 'arm64-macos'];
211 |
212 | // Calculate default version (last 20 versions)
213 | const defaultVersion = this.calculateDefaultVersion('editor_report.csv', '1.3.6');
214 |
215 | // Store chart config
216 | this.chartConfigs.set('editor-chart', {
217 | csvFile: 'editor_report.csv',
218 | platforms: platforms,
219 | title: 'Editor Size Evolution',
220 | defaultVersion: defaultVersion,
221 | selectId: 'editor-version-select'
222 | });
223 |
224 | const data = this.filterDataFromVersion(rawData, defaultVersion);
225 | this.createChart('editor-chart', data, platforms, 'Editor Size Evolution');
226 | }
227 |
228 | createBobChart() {
229 | const rawData = this.csvCache.get('bob_report.csv');
230 | const platforms = ['x86_64-macos'];
231 |
232 | // Calculate default version (last 20 versions)
233 | const defaultVersion = this.calculateDefaultVersion('bob_report.csv', '1.2.166');
234 |
235 | // Store chart config
236 | this.chartConfigs.set('bob-chart', {
237 | csvFile: 'bob_report.csv',
238 | platforms: platforms,
239 | title: 'Bob.jar Size Evolution',
240 | defaultVersion: defaultVersion,
241 | selectId: 'bob-version-select'
242 | });
243 |
244 | const data = this.filterDataFromVersion(rawData, defaultVersion);
245 | this.createChart('bob-chart', data, platforms, 'Bob.jar Size Evolution', false); // No legend for Bob chart
246 | }
247 |
248 | createChart(containerId, data, platforms, title, showLegend = true) {
249 | const container = document.getElementById(containerId);
250 |
251 | if (!data || data.length === 0) {
252 | container.innerHTML = 'No data available
';
253 | return;
254 | }
255 |
256 | // Show loading state
257 | container.innerHTML = 'Loading chart...
';
258 |
259 | const traces = [];
260 | const versions = data.map(row => row.VERSION);
261 |
262 | platforms.forEach(platform => {
263 | const sizes = data.map(row => {
264 | const size = parseFloat(row[platform]) || 0;
265 | return size;
266 | });
267 |
268 | // Only include platforms that have some data
269 | const hasData = sizes.some(size => size > 0);
270 | if (!hasData) return;
271 |
272 | traces.push({
273 | x: versions,
274 | y: sizes,
275 | type: 'scatter',
276 | mode: 'lines+markers',
277 | name: this.formatPlatformName(platform),
278 | line: {
279 | color: this.platformColors[platform] || '#666',
280 | width: 2
281 | },
282 | marker: {
283 | size: 4,
284 | color: this.platformColors[platform] || '#666'
285 | },
286 | hovertemplate: `%{fullData.name} Version: %{x} Size: %{text} Bytes: %{y:,.0f} `,
287 | text: sizes.map(size => this.formatBytes(size)),
288 | hoverlabel: {
289 | bgcolor: '#FFFFDD',
290 | bordercolor: '#333',
291 | font: { color: '#000', size: 12 }
292 | }
293 | });
294 | });
295 |
296 | // Check if we're on mobile/tablet (768px or less)
297 | const isMobile = window.innerWidth <= 768;
298 |
299 | const layout = {
300 | title: {
301 | text: title,
302 | font: { size: 16, color: '#2c3e50' },
303 | y: isMobile ? 0.92 : 0.95,
304 | yanchor: 'top'
305 | },
306 | xaxis: {
307 | title: 'Version',
308 | tickangle: -45,
309 | gridcolor: '#f0f0f0'
310 | },
311 | yaxis: {
312 | title: 'Size',
313 | tickformat: '.2s',
314 | gridcolor: '#f0f0f0'
315 | },
316 | margin: {
317 | l: 80,
318 | r: 50,
319 | t: isMobile ? 100 : 60,
320 | b: showLegend ? 100 : 60
321 | },
322 | paper_bgcolor: 'white',
323 | plot_bgcolor: 'white',
324 | showlegend: showLegend,
325 | legend: showLegend ? {
326 | orientation: 'h',
327 | x: 0,
328 | y: -0.25,
329 | xanchor: 'left',
330 | bgcolor: 'rgba(255,255,255,0.8)',
331 | bordercolor: '#ddd',
332 | borderwidth: 1,
333 | font: { size: 12 }
334 | } : {},
335 | hovermode: 'closest'
336 | };
337 |
338 | const config = {
339 | displayModeBar: true,
340 | modeBarButtonsToRemove: ['select2d', 'lasso2d'],
341 | displaylogo: false,
342 | responsive: true
343 | };
344 |
345 | // Clear loading spinner before creating chart
346 | container.innerHTML = '';
347 |
348 | Plotly.newPlot(containerId, traces, layout, config);
349 | this.charts.set(containerId, { traces, layout, config, platforms });
350 |
351 | // Add click handler to open size-analyzer with selected version
352 | document.getElementById(containerId).on('plotly_click', (data) => {
353 | this.handleChartClick(data, platforms, containerId);
354 | });
355 |
356 | // Add legend click handler for Alt+click to show only selected platform
357 | if (showLegend) {
358 | document.getElementById(containerId).on('plotly_legendclick', (data) => {
359 | return this.handleLegendClick(data, containerId);
360 | });
361 |
362 | // Add legend usage info
363 | this.addLegendInfo(containerId);
364 | }
365 | }
366 |
367 | addLegendInfo(containerId) {
368 | const container = document.getElementById(containerId);
369 | const chartContainer = container.closest('.chart-section');
370 |
371 | if (chartContainer) {
372 | // Check if info already exists
373 | const existingInfo = chartContainer.querySelector('.legend-info');
374 | if (!existingInfo) {
375 | const infoDiv = document.createElement('div');
376 | infoDiv.className = 'legend-info';
377 | infoDiv.style.cssText = `
378 | font-style: italic;
379 | font-size: 9px;
380 | color: #999;
381 | text-align: right;
382 | margin-top: 2px;
383 | line-height: 1;
384 | `;
385 | infoDiv.textContent = 'Legend: click to toggle, Alt+click to isolate';
386 |
387 | // Add after the chart container
388 | const chartDiv = chartContainer.querySelector('.chart-container');
389 | if (chartDiv) {
390 | chartDiv.insertAdjacentElement('afterend', infoDiv);
391 | } else {
392 | container.insertAdjacentElement('afterend', infoDiv);
393 | }
394 | }
395 | }
396 | }
397 |
398 | handleChartClick(data, platforms, containerId) {
399 | if (data.points && data.points.length > 0) {
400 | const point = data.points[0];
401 | const clickedVersion = point.x; // Version from X-axis
402 | const platformName = point.fullData.name; // Platform name from trace
403 |
404 | // Find the actual platform key from the formatted name
405 | let platformKey = this.findPlatformKey(platformName, platforms);
406 |
407 | // Special case: if this is the Bob chart, use 'bob.jar' as platform
408 | if (containerId === 'bob-chart') {
409 | platformKey = 'bob.jar';
410 | }
411 |
412 | // Special case: if this is the Editor chart, map to editor platform names
413 | if (containerId === 'editor-chart') {
414 | const editorPlatformMap = {
415 | 'x86_64-win32': 'editor-win32',
416 | 'x86_64-linux': 'editor-x86_64-linux',
417 | 'x86_64-macos': 'editor-x86_64-macos',
418 | 'arm64-macos': 'editor-arm64-macos'
419 | };
420 | platformKey = editorPlatformMap[platformKey] || platformKey;
421 | }
422 |
423 | if (platformKey && clickedVersion) {
424 | // Get all available versions for this platform to find the previous version
425 | const allVersions = this.getAllVersionsForPlatform(platformKey, containerId);
426 | const versionIndex = allVersions.indexOf(clickedVersion);
427 |
428 | if (versionIndex > 0) {
429 | const fromVersion = allVersions[versionIndex - 1];
430 | const toVersion = clickedVersion;
431 |
432 | // Open size-analyzer with URL parameters
433 | const url = `size-analyzer/?platform=${platformKey}&from=${fromVersion}&to=${toVersion}`;
434 | window.open(url, '_blank');
435 | } else {
436 | alert('Cannot compare: This is the first version in the dataset.');
437 | }
438 | }
439 | }
440 | }
441 |
442 | handleLegendClick(data, containerId) {
443 | // Check if Alt key is pressed
444 | if (data.event && data.event.altKey) {
445 | // Alt+click: show only the clicked trace, hide all others
446 | const clickedTraceIndex = data.curveNumber;
447 | const currentChart = this.charts.get(containerId);
448 |
449 | if (currentChart) {
450 | const update = {
451 | visible: currentChart.traces.map((trace, index) =>
452 | index === clickedTraceIndex ? true : 'legendonly'
453 | )
454 | };
455 |
456 | Plotly.restyle(containerId, update);
457 | }
458 |
459 | // Return false to prevent default legend click behavior
460 | return false;
461 | }
462 |
463 | // Return true to allow default legend click behavior (normal toggle)
464 | return true;
465 | }
466 |
467 | findPlatformKey(platformName, platforms) {
468 | // Convert formatted platform name back to platform key
469 | const reverseNameMap = {
470 | 'ARM64 iOS': 'arm64-ios',
471 | 'ARM64 Android': 'arm64-android',
472 | 'ARMv7 Android': 'armv7-android',
473 | 'x86_64 macOS': 'x86_64-macos',
474 | 'JS Web': 'js-web',
475 | 'WASM Web': 'wasm-web',
476 | 'x86_64 Linux': 'x86_64-linux',
477 | 'x86 Win32': 'x86-win32',
478 | 'x86_64 Win32': 'x86_64-win32',
479 | 'ARM64 macOS': 'arm64-macos'
480 | };
481 |
482 | return reverseNameMap[platformName] || platforms.find(p =>
483 | this.formatPlatformName(p) === platformName
484 | );
485 | }
486 |
487 | getAllVersionsForPlatform(platformKey, containerId = null) {
488 | // Get all available versions from the raw CSV data
489 | let csvFile;
490 |
491 | // Special case: if this is the Bob chart or platform is bob.jar, use bob_report.csv
492 | if (containerId === 'bob-chart' || platformKey === 'bob.jar') {
493 | csvFile = 'bob_report.csv';
494 | } else {
495 | csvFile = this.getCsvFileForPlatform(platformKey);
496 | }
497 |
498 | const rawData = this.csvCache.get(csvFile);
499 |
500 | if (rawData) {
501 | return rawData.map(row => row.VERSION).filter(v => v);
502 | }
503 |
504 | return [];
505 | }
506 |
507 | getCsvFileForPlatform(platformKey) {
508 | // Map platform to CSV file based on chart context
509 | // For desktop platforms, prefer editor_report.csv, except for bob chart
510 | if (['x86_64-macos', 'x86_64-win32', 'x86_64-linux', 'arm64-macos'].includes(platformKey)) {
511 | return 'editor_report.csv';
512 | } else {
513 | // For mobile/web platforms, use bundle_report.csv (or engine_report.csv as fallback)
514 | return this.csvCache.has('bundle_report.csv') ? 'bundle_report.csv' : 'engine_report.csv';
515 | }
516 | }
517 |
518 | formatPlatformName(platform) {
519 | const names = {
520 | 'arm64-ios': 'ARM64 iOS',
521 | 'arm64-android': 'ARM64 Android',
522 | 'armv7-android': 'ARMv7 Android',
523 | 'x86_64-macos': 'x86_64 macOS',
524 | 'js-web': 'JS Web',
525 | 'wasm-web': 'WASM Web',
526 | 'x86_64-linux': 'x86_64 Linux',
527 | 'x86-win32': 'x86 Win32',
528 | 'x86_64-win32': 'x86_64 Win32',
529 | 'arm64-macos': 'ARM64 macOS'
530 | };
531 | return names[platform] || platform;
532 | }
533 |
534 | setupVersionDropdowns() {
535 | // Setup dropdowns for each chart
536 | this.chartConfigs.forEach((config, chartId) => {
537 | this.populateVersionDropdown(config.selectId, config.csvFile, config.defaultVersion);
538 |
539 | // Add event listener for version changes
540 | const select = document.getElementById(config.selectId);
541 | select.addEventListener('change', () => {
542 | this.onVersionChange(chartId, select.value);
543 | });
544 | });
545 | }
546 |
547 | populateVersionDropdown(selectId, csvFile, defaultVersion) {
548 | const select = document.getElementById(selectId);
549 | const rawData = this.csvCache.get(csvFile);
550 |
551 | if (!rawData) return;
552 |
553 | // Define minimum allowed versions for each chart type
554 | const minimumVersions = {
555 | 'bundle_report.csv': '1.2.166',
556 | 'engine_report.csv': '1.2.166',
557 | 'editor_report.csv': '1.3.6',
558 | 'bob_report.csv': '1.2.166'
559 | };
560 |
561 | const minimumVersion = minimumVersions[csvFile];
562 |
563 | // Get all versions with data (non-zero values)
564 | const versions = rawData
565 | .filter(row => {
566 | const values = Object.values(row);
567 | return values.some(value => value !== 'VERSION' && parseFloat(value) > 0);
568 | })
569 | .map(row => row.VERSION);
570 |
571 | // Sort versions
572 | versions.sort(this.compareVersions.bind(this));
573 |
574 | // Filter versions to only include those >= minimum allowed version
575 | const validVersions = versions.filter(version =>
576 | this.compareVersions(version, minimumVersion) >= 0
577 | );
578 |
579 | // Get maximum versions for selection range (last available - 3)
580 | const maxVersionIndex = Math.max(0, validVersions.length - 4);
581 | const selectableVersions = validVersions.slice(0, maxVersionIndex + 1);
582 |
583 | // Clear and populate dropdown
584 | select.innerHTML = '';
585 |
586 | selectableVersions.forEach(version => {
587 | const option = document.createElement('option');
588 | option.value = version;
589 | option.textContent = version;
590 | if (version === defaultVersion) {
591 | option.selected = true;
592 | }
593 | select.appendChild(option);
594 | });
595 | }
596 |
597 | onVersionChange(chartId, selectedVersion) {
598 | if (!selectedVersion) return;
599 |
600 | const config = this.chartConfigs.get(chartId);
601 | if (!config) return;
602 |
603 | const rawData = this.csvCache.get(config.csvFile);
604 | const filteredData = this.filterDataFromVersion(rawData, selectedVersion);
605 |
606 | // Update the chart
607 | this.updateChartWithData(chartId, filteredData, config.platforms, config.title);
608 | }
609 |
610 | updateChartWithData(chartId, data, platforms, title) {
611 | const container = document.getElementById(chartId);
612 | const chartData = this.charts.get(chartId);
613 |
614 | if (!data || !chartData) return;
615 |
616 | const traces = [];
617 | const versions = data.map(row => row.VERSION);
618 |
619 | platforms.forEach(platform => {
620 | const sizes = data.map(row => {
621 | const size = parseFloat(row[platform]) || 0;
622 | return size;
623 | });
624 |
625 | // Only include platforms that have some data
626 | const hasData = sizes.some(size => size > 0);
627 | if (!hasData) return;
628 |
629 | traces.push({
630 | x: versions,
631 | y: sizes,
632 | type: 'scatter',
633 | mode: 'lines+markers',
634 | name: this.formatPlatformName(platform),
635 | line: {
636 | color: this.platformColors[platform] || '#666',
637 | width: 2
638 | },
639 | marker: {
640 | size: 4,
641 | color: this.platformColors[platform] || '#666'
642 | },
643 | hovertemplate: `%{fullData.name} Version: %{x} Size: %{text} Bytes: %{y:,.0f} `,
644 | text: sizes.map(size => this.formatBytes(size)),
645 | hoverlabel: {
646 | bgcolor: '#FFFFDD',
647 | bordercolor: '#333',
648 | font: { color: '#000', size: 12 }
649 | }
650 | });
651 | });
652 |
653 | Plotly.react(chartId, traces, chartData.layout, chartData.config);
654 | }
655 |
656 | handleResize() {
657 | // Debounce resize events
658 | clearTimeout(this.resizeTimeout);
659 | this.resizeTimeout = setTimeout(() => {
660 | // Update all charts with responsive layout
661 | this.chartConfigs.forEach((config, chartId) => {
662 | const chartData = this.charts.get(chartId);
663 | if (chartData) {
664 | const isMobile = window.innerWidth <= 768;
665 | const updatedLayout = {
666 | ...chartData.layout,
667 | title: {
668 | ...chartData.layout.title,
669 | y: isMobile ? 0.92 : 0.95
670 | },
671 | margin: {
672 | ...chartData.layout.margin,
673 | t: isMobile ? 100 : 60
674 | }
675 | };
676 |
677 | Plotly.relayout(chartId, updatedLayout);
678 | this.charts.set(chartId, { ...chartData, layout: updatedLayout });
679 | }
680 | });
681 | }, 250); // 250ms debounce
682 | }
683 |
684 | showError(message) {
685 | const sections = document.querySelectorAll('.chart-section .chart-container');
686 | sections.forEach(section => {
687 | section.innerHTML = `${message}
`;
688 | });
689 | }
690 | }
691 |
692 | // Initialize dashboard when page loads
693 | document.addEventListener('DOMContentLoaded', () => {
694 | window.defoldDashboard = new DefoldDashboard();
695 | });
--------------------------------------------------------------------------------