blob: 3576b12a8fef9fa286dc52317f2462ea03e8e2c1 [file] [log] [blame]
Benny Prijono313b1e42006-07-04 23:48:51 +00001# $Id$
2#
3# This file is used to generate PJSIP/PJMEDIA footprint report.
4# To use this file, just run it in pjsip-apps/build directory, to
5# produce footprint.txt and footprint.htm report files.
6#
7import os
8import sys
9import string
10import time
11
12compile_flags1 = [
13 # Base
Benny Prijono17e0d742006-07-05 20:45:55 +000014 ['BASE', 'Empty application size'],
15 ['', 'Subtotal: Empty application size'],
16
17 ['HAS_PJLIB', 'Minimum PJLIB only'],
Benny Prijono313b1e42006-07-04 23:48:51 +000018
19 # Subtotal
20 ['', 'Subtotal'],
21
22 # PJLIB-UTIL
23 ['HAS_PJLIB_STUN', 'STUN client'],
24 ['HAS_PJLIB_GETOPT', 'getopt() functionality'],
25
26 # Subtotal
27 ['', 'TOTAL']
28]
29
30compile_flags = [
31 # Base
Benny Prijono17e0d742006-07-05 20:45:55 +000032 ['BASE', 'Empty application size'],
33 ['', 'Subtotal: empty application size on this platform'],
34
35 ['HAS_PJLIB', 'PJLIB (pool, data structures, hash tables, ioqueue, socket, timer heap, etc.)'],
Benny Prijonobdf202a2006-07-08 10:03:46 +000036 ['', 'Subtotal: Minimal PJLIB application size'],
Benny Prijono313b1e42006-07-04 23:48:51 +000037
38 # PJLIB-UTIL
39 ['HAS_PJLIB_STUN', 'PJLIB-UTIL STUN client'],
40 ['HAS_PJLIB_GETOPT', 'PJLIB-UTIL getopt() functionality'],
Benny Prijono17e0d742006-07-05 20:45:55 +000041 ['HAS_PJLIB_SCANNER', 'PJLIB-UTIL text scanner (needed by SIP parser)'],
42 ['HAS_PJLIB_XML', 'PJLIB-UTIL tiny XML (parsing and API) (needs text scanner)'],
Benny Prijono313b1e42006-07-04 23:48:51 +000043
44 # PJSIP
Benny Prijonobdf202a2006-07-08 10:03:46 +000045 ['HAS_PJSIP_CORE_MSG_ELEM', 'PJSIP Core - Messaging Elements and Parsing (message, headers, SIP URI, TEL URI/RFC 3966, etc.)'],
46 ['HAS_PJSIP_CORE', 'PJSIP Core - Endpoint (transport management, module management, event distribution, etc.)'],
47 ['HAS_PJSIP_CORE_MSG_UTIL', 'PJSIP Core - Stateless operations, server resolution and fail-over'],
Benny Prijono313b1e42006-07-04 23:48:51 +000048 ['HAS_PJSIP_UDP_TRANSPORT', 'PJSIP UDP transport'],
49 ['', 'Subtotal: A very minimum SIP application (parsing, UDP transport+STUN, no transaction)'],
Benny Prijono17e0d742006-07-05 20:45:55 +000050
Benny Prijono313b1e42006-07-04 23:48:51 +000051 ['HAS_PJSIP_TCP_TRANSPORT', 'PJSIP TCP transport'],
52 ['HAS_PJSIP_INFO', 'PJSIP INFO support (RFC 2976) (no special treatment, thus the zero size)'],
53 ['HAS_PJSIP_TRANSACTION', 'PJSIP transaction and stateful API'],
Benny Prijonobdf202a2006-07-08 10:03:46 +000054 ['HAS_PJSIP_AUTH_CLIENT', 'PJSIP digest authentication client'],
Benny Prijono313b1e42006-07-04 23:48:51 +000055 ['HAS_PJSIP_UA_LAYER', 'PJSIP User agent layer and base dialog and usage management (draft-ietf-sipping-dialogusage-01)'],
Benny Prijonobdf202a2006-07-08 10:03:46 +000056 ['HAS_PJMEDIA_SDP', 'PJMEDIA SDP Parsing and API (RFC 2327), needed by SDP negotiator'],
Benny Prijono313b1e42006-07-04 23:48:51 +000057 ['HAS_PJMEDIA_SDP_NEGOTIATOR','PJMEDIA SDP negotiator (RFC 3264), needed by INVITE session'],
58 ['HAS_PJSIP_INV_SESSION', 'PJSIP INVITE session API'],
59 ['HAS_PJSIP_REGC', 'PJSIP client registration API'],
60 ['', 'Subtotal: Minimal SIP application with registration (including digest authentication)'],
61
62 ['HAS_PJSIP_EVENT_FRAMEWORK','PJSIP Event/SUBSCRIBE framework, RFC 3265 (needed by call transfer, and presence)'],
63 ['HAS_PJSIP_CALL_TRANSFER', 'PJSIP Call Transfer/REFER support (RFC 3515)'],
64 ['', 'Subtotal: Minimal SIP application with call transfer'],
65
66
67 ['HAS_PJSIP_PRESENCE', 'PJSIP Presence subscription, including PIDF/X-PIDF support (RFC 3856, RFC 3863, etc) (needs XML)'],
68 ['HAS_PJSIP_MESSAGE', 'PJSIP Instant Messaging/MESSAGE support (RFC 3428) (no special treatment, thus the zero size)'],
69 ['HAS_PJSIP_IS_COMPOSING', 'PJSIP Message Composition indication (RFC 3994)'],
70
71 # Subtotal
72 ['', 'Subtotal: Complete PJSIP package (call, registration, presence, IM) +STUN +GETOPT (+PJLIB), no media'],
73
74 # PJMEDIA
75 ['HAS_PJMEDIA_SND_DEV', 'PJMEDIA sound device backend (platform specific)'],
76 ['HAS_PJMEDIA_SILENCE_DET', 'PJMEDIA Adaptive silence detector'],
77 ['HAS_PJMEDIA', 'PJMEDIA endpoint'],
78 ['HAS_PJMEDIA_PLC', 'PJMEDIA Packet Lost Concealment implementation (needed by G.711, GSM, and sound device port)'],
79 ['HAS_PJMEDIA_SND_PORT', 'PJMEDIA sound device media port'],
Benny Prijonobdf202a2006-07-08 10:03:46 +000080 ['HAS_PJMEDIA_RESAMPLE', 'PJMEDIA resampling algorithm (large filter disabled)'],
Benny Prijono313b1e42006-07-04 23:48:51 +000081 ['HAS_PJMEDIA_G711_CODEC', 'PJMEDIA G.711 codec (PCMA/PCMU, including PLC) (may have already been linked by other module)'],
82 ['HAS_PJMEDIA_CONFERENCE', 'PJMEDIA conference bridge (needs resampling and silence detector)'],
83 ['HAS_PJMEDIA_MASTER_PORT', 'PJMEDIA master port'],
84 ['HAS_PJMEDIA_RTP', 'PJMEDIA stand-alone RTP'],
85 ['HAS_PJMEDIA_RTCP', 'PJMEDIA stand-alone RTCP and media quality calculation'],
86 ['HAS_PJMEDIA_JBUF', 'PJMEDIA stand-alone adaptive jitter buffer'],
87 ['HAS_PJMEDIA_STREAM', 'PJMEDIA stream for remote media communication (needs RTP, RTCP, and jitter buffer)'],
88 ['HAS_PJMEDIA_UDP_TRANSPORT','PJMEDIA UDP media transport'],
89 ['HAS_PJMEDIA_FILE_PLAYER', 'PJMEDIA WAV file player'],
90 ['HAS_PJMEDIA_FILE_CAPTURE', 'PJMEDIA WAV file writer'],
91 ['HAS_PJMEDIA_MEM_PLAYER', 'PJMEDIA fixed buffer player'],
92 ['HAS_PJMEDIA_MEM_CAPTURE', 'PJMEDIA fixed buffer writer'],
93
94 # Subtotal
95 ['', 'Subtotal: Complete SIP and all PJMEDIA features (G.711 codec only)'],
96
97 # Codecs
98 ['HAS_PJMEDIA_GSM_CODEC', 'PJMEDIA GSM codec (including PLC)'],
99 ['HAS_PJMEDIA_SPEEX_CODEC', 'PJMEDIA Speex codec (narrowband, wideband, ultra-wideband)'],
100
101 # Total
102 ['', 'TOTAL: complete libraries (+all codecs)'],
103]
104
105# Executable size report, tuple of:
106# <all flags>, <flags added>, <text size>, <data>, <bss>, <description>
107exe_size = []
108
109#
110# Write the report to text file
111#
112def print_text_report(filename):
113 output = open(filename, 'w')
114
115 output.write('PJSIP and PJMEDIA footprint report\n')
116 output.write('Auto-generated by pjsip-apps/build/get-footprint.py\n')
117 output.write('\n')
118
119 # Write Revision info.
120 f = os.popen('svn info | grep Revision')
121 output.write(f.readline())
122
123 output.write('Date: ')
124 output.write(time.asctime())
125 output.write('\n')
126 output.write('\n')
127
128 # Write individual module size
129 output.write('Footprint (in bytes):\n')
130 output.write(' .text .data .bss Module Description\n')
131 output.write('==========================================================\n')
132
133 for i in range(1, len(exe_size)):
134 e = exe_size[i]
135 prev = exe_size[i-1]
136
137 if e[1]<>'':
138 output.write(' ')
139 output.write( string.rjust(`string.atoi(e[2]) - string.atoi(prev[2])`, 8) )
140 output.write( string.rjust(`string.atoi(e[3]) - string.atoi(prev[3])`, 8) )
141 output.write( string.rjust(`string.atoi(e[4]) - string.atoi(prev[4])`, 8) )
142 output.write(' ' + e[5] + '\n')
143 else:
144 output.write(' ------------------------\n')
145 output.write(' ')
146 output.write( string.rjust(e[2], 8) )
147 output.write( string.rjust(e[3], 8) )
148 output.write( string.rjust(e[4], 8) )
149 output.write(' ' + e[5] + '\n')
150 output.write('\n')
151
152
153 # Done
154 output.close()
155
156
157#
158# Write the report to HTML file
159#
160def print_html_report(filename):
161 output = open(filename, 'w')
162
163 # Get Revision info.
164 f = os.popen('svn info | grep Revision')
Benny Prijono17e0d742006-07-05 20:45:55 +0000165 revision = f.readline().split()[1]
Benny Prijono313b1e42006-07-04 23:48:51 +0000166
Benny Prijono17e0d742006-07-05 20:45:55 +0000167 # Get Machine, OS, and CC name
168 f = os.popen('make -f Footprint.mak print_name')
169 names = f.readline().split()
170 m = names[0]
171 o = names[1]
172 cc = names[2]
173 cc_ver = names[3]
174
Benny Prijono313b1e42006-07-04 23:48:51 +0000175 output.write('<HTML><HEAD>\n');
Benny Prijono17e0d742006-07-05 20:45:55 +0000176 output.write(' <TITLE>PJSIP and PJMEDIA footprint report for ' + o + '/' + m + ' (r' + revision + ')</TITLE>\n')
Benny Prijono313b1e42006-07-04 23:48:51 +0000177 output.write(' <LINK href="/style/style.css" type="text/css" rel="stylesheet">\n')
178 output.write('</HEAD>\n');
179 output.write('<BODY bgcolor="white">\n');
Benny Prijono17e0d742006-07-05 20:45:55 +0000180 output.write('<!--#include virtual="/header.html" -->')
Benny Prijono313b1e42006-07-04 23:48:51 +0000181
Benny Prijono17e0d742006-07-05 20:45:55 +0000182 output.write(' <H1>PJSIP and PJMEDIA footprint report (r' + revision + ')</H1>\n')
Benny Prijono313b1e42006-07-04 23:48:51 +0000183 output.write('Auto-generated by pjsip-apps/build/get-footprint.py\n')
184 output.write('<p>Date: ' + time.asctime() + '<BR>\n')
Benny Prijono17e0d742006-07-05 20:45:55 +0000185 output.write('Revision: r' + revision + '</p>\n\n')
Benny Prijono313b1e42006-07-04 23:48:51 +0000186 output.write('<HR>\n')
187 output.write('\n')
188
189 # Info
190 output.write('<H2>Build Configuration</H2>\n')
191
192 # build.mak
193 output.write('\n<H3>build.mak</H3>\n')
194 output.write('<tt>\n')
195 f = open('../../build.mak', 'r')
196 s = f.readlines()
197 for l in s:
198 output.write(l + '<BR>\n')
199 output.write('</tt>\n')
Benny Prijono17e0d742006-07-05 20:45:55 +0000200 output.write('<p>Using ' + cc + ' version ' + cc_ver +'</p>\n')
Benny Prijono313b1e42006-07-04 23:48:51 +0000201
202 # user.mak
203 output.write('\n<H3>user.mak</H3>\n')
204 output.write('<tt>\n')
205 f = open('../../user.mak', 'r')
206 s = f.readlines()
207 for l in s:
208 output.write(l + '<BR>\n')
209 output.write('</tt>\n')
210
211 # config_site.h
212 output.write('\n<H3>&lt;pj/config.site.h&gt;</H3>\n')
213 output.write('<tt>\n')
214 f = os.popen('cpp -dM ../../pjlib/include/pj/config_site.h | grep PJ')
215 s = f.readlines()
216 for l in s:
217 output.write(l + '<BR>\n')
218 output.write('</tt>\n')
219
220
221
222 # Write individual module size
223 output.write('<H2>Footprint Report</H2>\n')
224 output.write('<p>The table below shows the footprint of individual feature, in bytes.</p>')
225 output.write('<TABLE border="1" cellpadding="2" cellspacing="0">\n' +
226 '<TR bgcolor="#e8e8ff">\n' +
227 ' <TD align="center"><strong>.text</strong></TD>\n' +
228 ' <TD align="center"><strong>.data</strong></TD>\n' +
229 ' <TD align="center"><strong>.bss</strong></TD>\n' +
230 ' <TD align="center"><strong>Features/Module Description</strong></TD>\n' +
231 '</TR>\n')
232
233
234 for i in range(1, len(exe_size)):
235 e = exe_size[i]
236 prev = exe_size[i-1]
237
238 output.write('<TR>\n')
239 if e[1]<>'':
240 output.write( ' <TD align="right">' + `string.atoi(e[2]) - string.atoi(prev[2])` + '</TD>\n')
241 output.write( ' <TD align="right">' + `string.atoi(e[3]) - string.atoi(prev[3])` + '</TD>\n')
242 output.write( ' <TD align="right">' + `string.atoi(e[4]) - string.atoi(prev[4])` + '</TD>\n' )
243 output.write( ' <TD>' + e[5] + '</TD>\n')
244 else:
245 output.write('<TR bgcolor="#e8e8ff">\n')
246 output.write( ' <TD align="right">&nbsp;</TD>\n')
247 output.write( ' <TD align="right">&nbsp;</TD>\n')
248 output.write( ' <TD align="right">&nbsp;</TD>\n')
249 output.write( ' <TD><strong>' + e[5] + ': .text=' + e[2]+ ', .data=' + e[3] + ', .bss=' + e[4] + '</strong></TD>\n')
250
251 output.write('</TR>\n')
252
253 output.write('</TABLE>\n')
Benny Prijono17e0d742006-07-05 20:45:55 +0000254 output.write('<!--#include virtual="/footer.html" -->')
Benny Prijono313b1e42006-07-04 23:48:51 +0000255 output.write('</BODY>\n')
256 output.write('</HTML>\n')
257
258 # Done
259 output.close()
260
261
262
263
264#
265# Get the size of individual feature
266#
267def get_size(all_flags, flags, desc):
268 file = 'footprint.exe'
269 # Remove file
270 rc = os.system("make -f Footprint.mak FCFLAGS='" + all_flags + "' clean")
271 # Make the executable
272 cmd = "make -f Footprint.mak FCFLAGS='" + all_flags + "' all"
273 #print cmd
274 rc = os.system(cmd)
275 if rc <> 0:
276 sys.exit(1)
277
278 # Run 'size' against the executable
279 f = os.popen('size ' + file)
280 # Skip header of the 'size' output
281 f.readline()
282 # Get the sizes
283 size = f.readline()
284 f.close()
285 # Split into tokens
286 tokens = size.split()
287 # Build the size tuple and add to exe_size
288 elem = all_flags, flags, tokens[0], tokens[1], tokens[2], desc
289 exe_size.append(elem)
290 # Remove file
291 rc = os.system("make -f Footprint.mak FCFLAGS='" + all_flags + "' clean")
292
293# Main
294elem = '', '', '0', '0', '0', ''
295exe_size.append(elem)
296
297all_flags = ''
298for elem in compile_flags:
299 if elem[0] <> '':
300 flags = '-D' + elem[0]
301 all_flags += flags + ' '
302 get_size(all_flags, elem[0], elem[1])
303 else:
304 e = exe_size[len(exe_size)-1]
305 n = all_flags, '', e[2], e[3], e[4], elem[1]
306 exe_size.append(n)
307
308
309print_text_report('footprint.txt')
310print_html_report('footprint.htm')
311