From: Eric Wong <e@80x24.org>
To: mwrap-public@80x24.org
Subject: [PATCH 19/19] mwrap_rack: Rack app to track live allocations
Date: Mon, 16 Jul 2018 21:19:33 +0000 [thread overview]
Message-ID: <20180716211933.5835-20-e@80x24.org> (raw)
In-Reply-To: <20180716211933.5835-1-e@80x24.org>
Might as well be able to see and inspect what allocations
are alive when developing a Rack application.
Demo is available at https://80x24.org/MWRAP/each/2000 (note:
"MWRAP" is capitalized) This is also running "repobrowse",
which will eventually replace cgit on 80x24.org, but is NOT
running the main HTTPS termination at https://80x24.org/
Note: this demo machine is 32-bit, so yes, it will overflow
---
lib/mwrap_rack.rb | 105 ++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 105 insertions(+)
create mode 100644 lib/mwrap_rack.rb
diff --git a/lib/mwrap_rack.rb b/lib/mwrap_rack.rb
new file mode 100644
index 0000000..ef3872b
--- /dev/null
+++ b/lib/mwrap_rack.rb
@@ -0,0 +1,105 @@
+# Copyright (C) 2018 all contributors <mwrap@80x24.org>
+# License: GPL-2.0+ <https://www.gnu.org/licenses/gpl-2.0.txt>
+# frozen_string_literal: true
+require 'mwrap'
+require 'rack'
+require 'cgi'
+
+# Usage: mwrap rackup ...
+class MwrapRack
+ module HtmlResponse
+ def response
+ [ 200, {
+ 'Expires' => 'Fri, 01 Jan 1980 00:00:00 GMT',
+ 'Pragma' => 'no-cache',
+ 'Cache-Control' => 'no-cache, max-age=0, must-revalidate',
+ 'Content-Type' => 'text/html; charset=UTF-8',
+ }, self ]
+ end
+ end
+
+ class Each < Struct.new(:script_name, :min, :sort)
+ include HtmlResponse
+ HEADER = '<tr><th>' + %w(total allocations frees mean_life max_life
+ location).join('</th><th>') + '</th></tr>'
+ FIELDS = %w(total allocations frees mean_life max_life location)
+ def each
+ Mwrap.quiet do
+ t = -"Mwrap.each(#{min})"
+ sn = script_name
+ all = []
+ f = FIELDS.dup
+ sc = FIELDS.index(sort || 'total') || 0
+ f[sc] = -"<b>#{f[sc]}</b>"
+ f.map! do |hdr|
+ if hdr.start_with?('<b>')
+ hdr
+ else
+ -%Q(<a\nhref="#{sn}/each/#{min}?sort=#{hdr}">#{hdr}</a>)
+ end
+ end
+ Mwrap.each(min) do |loc, total, allocations, frees, age_sum, max_life|
+ mean_life = frees == 0 ? Float::INFINITY : age_sum/frees.to_f
+ all << [total,allocations,frees,mean_life,max_life,loc]
+ end
+ all.sort_by! { |cols| -cols[sc] }
+
+ yield(-"<html><head><title>#{t}</title></head>" \
+ "<body><h1>#{t}</h1>\n" \
+ "<h2>Current generation: #{GC.count}</h2>\n<table>\n" \
+ "<tr><th>#{f.join('</th><th>')}</th></tr>\n")
+ all.each do |cols|
+ loc = cols.pop
+ cols[3] = sprintf('%0.3f', cols[3]) # mean_life
+ href = -(+"#{sn}/at/#{CGI.escape(loc)}").encode!(xml: :attr)
+ yield(%Q(<tr><td>#{cols.join('</td><td>')}<td><a\nhref=#{
+ href}>#{-loc.encode(xml: :text)}</a></td></tr>\n))
+ cols.clear
+ end.clear
+ yield "</table></body></html>\n"
+ end
+ end
+ end
+
+ class EachAt < Struct.new(:loc)
+ include HtmlResponse
+ HEADER = '<tr><th>size</th><th>generation</th></tr>'
+
+ def each
+ t = loc.name.encode(xml: :text)
+ yield(-"<html><head><title>#{t}</title></head>" \
+ "<body><h1>live allocations at #{t}</h1>" \
+ "<h2>Current generation: #{GC.count}</h2>\n<table>#{HEADER}")
+ loc.each do |size, generation|
+ yield("<tr><td>#{size}</td><td>#{generation}</td></tr>\n")
+ end
+ yield "</table></body></html>\n"
+ end
+ end
+
+ def r404
+ [404,{'Content-Type'=>'text/plain'},["Not found\n"]]
+ end
+
+ def call(env)
+ case env['PATH_INFO']
+ when %r{\A/each/(\d+)\z}
+ min = $1.to_i
+ m = env['QUERY_STRING'].match(/\bsort=(\w+)/)
+ Each.new(env['SCRIPT_NAME'], min, m ? m[1] : nil).response
+ when %r{\A/at/(.*)\z}
+ loc = -CGI.unescape($1)
+ loc = Mwrap[loc] or return r404
+ EachAt.new(loc).response
+ when '/'
+ n = 2000
+ u = 'https://80x24.org/mwrap/README.html'
+ b = -('<html><head><title>Mwrap demo</title></head>' \
+ "<body><p><a href=\"each/#{n}\">allocations >#{n} bytes</a>" \
+ "<p><a href=\"#{u}\">#{u}</a></body></html>\n")
+ [ 200, {'Content-Type'=>'text/html','Content-Length'=>-b.size.to_s},[b]]
+ else
+ r404
+ end
+ end
+end
--
EW
prev parent reply other threads:[~2018-07-16 21:19 UTC|newest]
Thread overview: 20+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-07-16 21:19 [PATCH 0/19] the heavy version of mwrap Eric Wong
2018-07-16 21:19 ` [PATCH 01/19] support per-allocation headers for per-alloc tracking Eric Wong
2018-07-16 21:19 ` [PATCH 02/19] mwrap: use malloc to do our own memalign Eric Wong
2018-07-16 21:19 ` [PATCH 03/19] hold RCU read lock to insert each allocation Eric Wong
2018-07-16 21:19 ` [PATCH 04/19] realloc: do not copy if allocation failed Eric Wong
2018-07-16 21:19 ` [PATCH 05/19] internal_memalign: do not assume real_malloc succeeds Eric Wong
2018-07-16 21:19 ` [PATCH 06/19] ensure ENOMEM is preserved in errno when appropriate Eric Wong
2018-07-16 21:19 ` [PATCH 07/19] memalign: check alignment on all public functions Eric Wong
2018-07-16 21:19 ` [PATCH 08/19] reduce stack usage from file names Eric Wong
2018-07-16 21:19 ` [PATCH 09/19] resolve real_malloc earlier for C++ programs Eric Wong
2018-07-16 21:19 ` [PATCH 10/19] allow analyzing live allocations via Mwrap[location] Eric Wong
2018-07-16 21:19 ` [PATCH 11/19] alias Mwrap.clear to Mwrap.reset Eric Wong
2018-07-16 21:19 ` [PATCH 12/19] implement accessors for SourceLocation Eric Wong
2018-07-16 21:19 ` [PATCH 13/19] mwrap_aref: quiet -Wshorten-64-to-32 warning Eric Wong
2018-07-16 21:19 ` [PATCH 14/19] fixes for FreeBSD 11.1 Eric Wong
2018-07-16 21:19 ` [PATCH 15/19] use memrchr to extract address under glibc Eric Wong
2018-07-16 21:19 ` [PATCH 16/19] do not track allocations for constructor and Init_ Eric Wong
2018-07-16 21:19 ` [PATCH 17/19] disable memalign tracking by default Eric Wong
2018-07-16 21:19 ` [PATCH 18/19] support Mwrap.quiet to temporarily disable allocation tracking Eric Wong
2018-07-16 21:19 ` Eric Wong [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
List information: https://80x24.org/mwrap/
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20180716211933.5835-20-e@80x24.org \
--to=e@80x24.org \
--cc=mwrap-public@80x24.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
Code repositories for project(s) associated with this public inbox
https://80x24.org/mwrap.git/
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).