1+ <?php
2+ $ opcache = opcache_get_status (true );
3+ $ apc = array (
4+ 'cache ' => apc_cache_info ('user ' ),
5+ 'sma ' => apc_sma_info (true )
6+ );
7+
8+ function percentage ( $ a , $ b ) {
9+ return ( $ a / $ b ) * 100 ;
10+ }
11+
12+ function opcache_mem ( $ key ) {
13+ global $ opcache ;
14+
15+ if ( $ key == 'total ' )
16+ return opcache_mem ('free ' ) + opcache_mem ('used ' ) + opcache_mem ('wasted ' );
17+
18+ if ( in_array ( $ key , array ( 'used ' , 'free ' , 'wasted ' ) ) )
19+ $ key = $ key . '_memory ' ;
20+
21+ return $ opcache ['memory_usage ' ][$ key ];
22+ }
23+
24+ function opcache_stat ( $ stat ) {
25+ global $ opcache ;
26+
27+ return $ opcache ['opcache_statistics ' ][$ stat ];
28+ }
29+
30+ function apc_mem ( $ key ) {
31+ global $ apc ;
32+
33+ if ( $ key == 'total ' )
34+ return $ apc ['sma ' ]['seg_size ' ];
35+
36+ if ( $ key == 'free ' )
37+ return $ apc ['sma ' ]['avail_mem ' ];
38+
39+ if ( $ key == 'used ' )
40+ return apc_mem ('total ' ) - apc_mem ('free ' );
41+
42+ return 0 ;
43+
44+ }
45+
46+ function human_size ( $ s ) {
47+ $ size = 'B ' ;
48+ $ sizes = array ( 'KB ' , 'MB ' , 'GB ' );
49+
50+ while ( $ s > 1024 ) {
51+ $ size = array_shift ( $ sizes );
52+ $ s /= 1024 ;
53+ }
54+
55+ $ s = round ( $ s , 2 );
56+ return $ s . ' ' . $ size ;
57+ }
58+
59+ function redirect ($ url ) {
60+ header ('Status: 302 Moved Temporarily ' );
61+ header ('Location: ' . $ url );
62+ exit ();
63+ }
64+
65+ function get_selector () {
66+ return '# ' . str_replace ( '# ' , '\# ' , urldecode ($ _GET ['selector ' ]) ) . '# ' ;
67+ }
68+
69+ function sort_url ($ on ) {
70+ $ query = parse_url ($ _SERVER ['REQUEST_URI ' ], PHP_URL_QUERY );
71+ if ( empty ( $ query ) )
72+ $ query = '' ;
73+ else
74+ $ query .= '& ' ;
75+
76+ $ query = preg_replace ( '#sort=[^&]+&?# ' , '' , $ query );
77+ $ query = preg_replace ( '#order=[^&]+&?# ' , '' , $ query );
78+
79+ if ( !isset ( $ _GET ['order ' ] ) )
80+ $ _GET ['order ' ] = '' ;
81+
82+ $ query .= 'sort= ' . urlencode ($ on );
83+ $ query .= '&order= ' . ( $ _GET ['order ' ] == 'asc ' ? 'desc ' : 'asc ' );
84+
85+ return '? ' . $ query ;
86+ }
87+
88+ function sort_list (&$ list ) {
89+ if ( !isset ( $ _GET ['sort ' ] ) )
90+ return $ list ;
91+
92+ $ key = urldecode ($ _GET ['sort ' ]);
93+ $ reverse = isset ($ _GET ['order ' ]) ? ( urldecode ($ _GET ['order ' ]) == 'desc ' ) : false ;
94+ usort ($ list , function ( $ item1 , $ item2 ) use ( $ key , $ reverse ) {
95+ if ( $ reverse ) {
96+ $ tmp = $ item1 ;
97+ $ item1 = $ item2 ;
98+ $ item2 = $ tmp ;
99+ unset($ tmp );
100+ }
101+ if ( is_string ( $ item1 [$ key ] ) || is_string ( $ item2 [$ key ] ) )
102+ return strcmp ( $ item1 [$ key ], $ item2 [$ key ] );
103+
104+ return $ item1 [$ key ] - $ item2 [$ key ];
105+ });
106+
107+ return $ list ;
108+ }
109+
110+ // Opcache
111+
112+ if ( isset ( $ _GET ['action ' ] ) && $ _GET ['action ' ] == 'op_restart ' ) {
113+ opcache_reset ();
114+ redirect ('? ' );
115+ }
116+
117+ if ( isset ( $ _GET ['action ' ] ) && $ _GET ['action ' ] == 'op_delete ' ) {
118+ $ selector = get_selector ();
119+ foreach ( $ opcache ['scripts ' ] as $ key => $ value ) {
120+ if ( !preg_match ( $ selector , $ key ) ) continue ;
121+
122+ opcache_invalidate ( $ key );
123+ }
124+ redirect ('?action=op_select&selector= ' . $ _GET ['selector ' ] );
125+ }
126+
127+ // APC
128+ if ( isset ( $ _GET ['action ' ] ) && $ _GET ['action ' ] == 'apc_restart ' ) {
129+ apc_delete ( new ApcIterator ('#.*# ' ) );
130+ redirect ('? ' );
131+ }
132+
133+ if ( isset ( $ _GET ['action ' ] ) && $ _GET ['action ' ] == 'apc_delete ' ) {
134+ apc_delete ( new ApcIterator ('user ' ,get_selector ()) );
135+ redirect ( '?action=apc_select&selector= ' . $ _GET ['selector ' ] );
136+ }
137+ ?> <html>
138+ <head>
139+ <title>Cache Status</title>
140+ <meta name="viewport" content="width=device-width, height=device-height, initial-scale=1" />
141+ <style>
142+ html, body { font-family: Arial, sans-serif;}
143+ .wrap { max-width: 960px; margin: 0 auto;}
144+ .full { width: 100%; }
145+ .green { background: green; }
146+ .red { background: red; }
147+ .orange { background: orange; }
148+ .bar { height: 20px; overflow: hidden; border-radius: 4px 4px; }
149+ .bar div { height: 20px; float: left; }
150+ .bar, .bar div { background-image: repeating-linear-gradient(45deg, transparent 0, rgba( 255,255,255,0.3) 1px, rgba(255,255,255,0.3) 10px, transparent 11px, transparent 18px); background-repeat: repeat-x; }
151+ label { font-weight: bold; }
152+ table { border-spacing: 0; }
153+ table td { padding: 0.2em 1em; }
154+ table th { background: #686868; color: white; padding: 0.5em 1em 0.2em 1em; font-weight: normal; }
155+ table th a { text-decoration: none; color: white; cursor: pointer; }
156+ table tr:nth-child(2n+1) { background: #efefef; }
157+ @media screen and (max-width: 480px) {
158+ input { width: 40%; }
159+ }
160+ </style>
161+ </head>
162+
163+ <body>
164+ <div class="wrap">
165+ <div>
166+ Goto: <a href="#opcache">PHP Opcache</a> or <a href="#apcu">APCu</a>
167+ </div>
168+ <h2 id="opcache">PHP Opcache</h2>
169+ <div>
170+ <h3>Memory <?= human_size (opcache_mem ('used ' )+opcache_mem ('wasted ' ))?> of <?= human_size (opcache_mem ('total ' ))?> </h3>
171+ <div class="full bar green">
172+ <div class="orange" style="width: <?= percentage (opcache_mem ('used ' ), opcache_mem ('total ' ))?> %"></div>
173+ <div class="red" style="width: <?= percentage (opcache_mem ('wasted ' ), opcache_mem ('total ' ))?> %"></div>
174+ </div>
175+ </div>
176+ <div>
177+ <h3>Keys <?= opcache_stat ('num_cached_keys ' )?> of <?= opcache_stat ('max_cached_keys ' )?> </h3>
178+ <div class="full bar green">
179+ <div class="orange" style="width: <?= percentage (opcache_stat ('num_cached_keys ' ), opcache_stat ('max_cached_keys ' ))?> %"></div>
180+ </div>
181+ </div>
182+ <div>
183+ <h3>Cache hit <?= round (opcache_stat ('opcache_hit_rate ' ),2 )?> %</h3>
184+ <div class="full bar green">
185+ <div class="red" style="width: <?= 100 -opcache_stat ('opcache_hit_rate ' )?> %"></div>
186+ </div>
187+ </div>
188+ <div>
189+ <h3>Actions</h3>
190+ <form action="?" method="GET">
191+ <label>Cache:
192+ <button name="action" value="op_restart">Restart</button>
193+ </label>
194+ </form>
195+ <form action="?" method="GET">
196+ <label>Key(s):
197+ <input name="selector" type="text" value="" placeholder=".*" />
198+ </label>
199+ <button type="submit" name="action" value="op_select">Select</button>
200+ <button type="submit" name="action" value="op_delete">Delete</button>
201+ </form>
202+ </div>
203+ <?php if ( isset ( $ _GET ['action ' ] ) && $ _GET ['action ' ] == 'op_select ' ): ?>
204+ <div>
205+ <h3>Keys matching <?= htmlentities ('" ' .$ _GET ['selector ' ].'" ' )?> </h3>
206+ <table>
207+ <thead>
208+ <tr>
209+ <th><a href="<?= sort_url ('full_path ' )?> ">Key</a></th>
210+ <th><a href="<?= sort_url ('hits ' )?> ">Hits</a></th>
211+ <th><a href="<?= sort_url ('memory_consumption ' )?> ">Size</a></th>
212+ <th>Action</th>
213+ </tr>
214+ </thead>
215+
216+ <tfoot></tfoot>
217+
218+ <tbody>
219+ <?php foreach ( sort_list ($ opcache ['scripts ' ]) as $ item ):
220+ if ( !preg_match (get_selector (), $ item ['full_path ' ]) ) continue ;?>
221+ <tr>
222+ <td><?= $ item ['full_path ' ]?> </td>
223+ <td><?= $ item ['hits ' ]?> </td>
224+ <td><?= human_size ($ item ['memory_consumption ' ])?> </td>
225+ <td><a href="?action=op_delete&selector=<?= urlencode ('^ ' .$ item ['full_path ' ].'$ ' )?> ">Delete</a>
226+ </tr>
227+ <?php endforeach ; ?>
228+ </tbody>
229+ </table>
230+ </div>
231+ <?php endif ; ?>
232+
233+ <h2 id="apcu">APCu</h2>
234+ <div>
235+ <h3>Memory <?= human_size (apc_mem ('used ' ))?> of <?= human_size (apc_mem ('total ' ))?> </h3>
236+ <div class="full bar green">
237+ <div class="orange" style="width: <?= percentage (apc_mem ('used ' ), apc_mem ('total ' ))?> %"></div>
238+ </div>
239+ </div>
240+ <div>
241+ <h3>Actions</h3>
242+ <form action="?" method="GET">
243+ <label>Cache:
244+ <button name="action" value="apc_restart">Restart</button>
245+ </label>
246+ </form>
247+ <form action="?" method="GET">
248+ <label>Key(s):</label>
249+ <input name="selector" type="text" value="" placeholder=".*" />
250+ <button type="submit" name="action" value="apc_select">Select</button>
251+ <button type="submit" name="action" value="apc_delete">Delete</button>
252+ </form>
253+ </div>
254+ <?php if ( isset ( $ _GET ['action ' ] ) && $ _GET ['action ' ] == 'apc_select ' ): ?>
255+ <div>
256+ <h3>Keys matching <?= htmlentities ('" ' .$ _GET ['selector ' ].'" ' )?> </h3>
257+ <table>
258+ <thead>
259+ <tr>
260+ <th><a href="<?= sort_url ('key ' )?> ">Key</a></th>
261+ <th><a href="<?= sort_url ('nhits ' )?> ">Hits</a></th>
262+ <th><a href="<?= sort_url ('mem_size ' )?> ">Size</a></th>
263+ <th><a href="<?= sort_url ('ttl ' )?> ">TTL</a></th>
264+ <th>Expires</th>
265+ <th>Action</th>
266+ </tr>
267+ </thead>
268+
269+ <tfoot></tfoot>
270+
271+ <tbody>
272+ <?php foreach ( sort_list ($ apc ['cache ' ]['cache_list ' ]) as $ item ):
273+ if ( !preg_match (get_selector (), $ item ['key ' ]) ) continue ;?>
274+ <tr>
275+ <td><?= $ item ['key ' ]?> </td>
276+ <td><?= $ item ['nhits ' ]?> </td>
277+ <td><?= human_size ($ item ['mem_size ' ])?> </td>
278+ <td><?= $ item ['ttl ' ]?> </td>
279+ <td><?= date ('Y-m-d H:i ' , $ item ['mtime ' ] + $ item ['ttl ' ] )?> </td>
280+ <td><a href="?action=apc_delete&selector=<?= urlencode ('^ ' .$ item ['key ' ].'$ ' )?> ">Delete</a>
281+ </tr>
282+ <?php endforeach ; ?>
283+ </tbody>
284+ </table>
285+ </div>
286+ <?php endif ; ?>
287+ </div>
288+ </body>
289+ </html>
0 commit comments