mwrap 2.0.0 → 2.0.0.4.gd1ea
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.olddoc.yml +8 -0
- data/MANIFEST +1 -0
- data/ext/mwrap/mwrap.c +21 -0
- data/lib/mwrap_rack.rb +121 -0
- data/mwrap.gemspec +3 -1
- data/test/test_mwrap.rb +11 -0
- metadata +6 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a0c1d38278467de929383b9a6415bd0364aa176c18e480c68553978536d37f2b
|
4
|
+
data.tar.gz: 96ae575c69d8dfa9204434acd5fd3cc2aebe64d6ef2ef51cf37ad6e924aa84a5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: facf03ed2e533fc8fa3faa14069101ed218e922b94cab228f5e651f89ebbd590972d44ff479374ccff9c0ed666426975fb3386df6a2eb4d2e174fb9268b8a18b
|
7
|
+
data.tar.gz: '0393004af3b3f22d6cc8581f239b838067764d48cfab0eb5d759b614edfb97a9f30c7e89bae658486f970d692951b4adb15ba08d12d326ccfd7191c60fff38e1'
|
data/.olddoc.yml
ADDED
@@ -0,0 +1,8 @@
|
|
1
|
+
---
|
2
|
+
cgit_url: https://80x24.org/mwrap.git
|
3
|
+
git_url: https://80x24.org/mwrap.git
|
4
|
+
rdoc_url: https://80x24.org/mwrap/
|
5
|
+
ml_url: https://80x24.org/mwrap-public/
|
6
|
+
public_email: mwrap-public@80x24.org
|
7
|
+
nntp_url:
|
8
|
+
- nntp://news.public-inbox.org/inbox.comp.lang.ruby.mwrap
|
data/MANIFEST
CHANGED
data/ext/mwrap/mwrap.c
CHANGED
@@ -32,6 +32,8 @@ extern size_t __attribute__((weak)) rb_gc_count(void);
|
|
32
32
|
extern VALUE __attribute__((weak)) rb_cObject;
|
33
33
|
extern VALUE __attribute__((weak)) rb_yield(VALUE);
|
34
34
|
|
35
|
+
static size_t total_bytes_inc, total_bytes_dec;
|
36
|
+
|
35
37
|
/* true for glibc/dlmalloc/ptmalloc, not sure about jemalloc */
|
36
38
|
#define ASSUMED_MALLOC_ALIGNMENT (sizeof(void *) * 2)
|
37
39
|
|
@@ -327,6 +329,8 @@ static struct src_loc *update_stats_rcu_lock(size_t size, uintptr_t caller)
|
|
327
329
|
if (caa_unlikely(!totals)) return 0;
|
328
330
|
if (locating++) goto out; /* do not recurse into another *alloc */
|
329
331
|
|
332
|
+
uatomic_add(&total_bytes_inc, size);
|
333
|
+
|
330
334
|
rcu_read_lock();
|
331
335
|
if (has_ec_p()) {
|
332
336
|
int line;
|
@@ -390,6 +394,7 @@ void free(void *p)
|
|
390
394
|
if (l) {
|
391
395
|
size_t age = generation - h->as.live.gen;
|
392
396
|
|
397
|
+
uatomic_add(&total_bytes_dec, h->size);
|
393
398
|
uatomic_set(&h->size, 0);
|
394
399
|
uatomic_add(&l->frees, 1);
|
395
400
|
uatomic_add(&l->age_total, age);
|
@@ -710,12 +715,16 @@ static VALUE mwrap_dump(int argc, VALUE * argv, VALUE mod)
|
|
710
715
|
return Qnil;
|
711
716
|
}
|
712
717
|
|
718
|
+
/* The whole operation is not remotely atomic... */
|
713
719
|
static void *totals_reset(void *ign)
|
714
720
|
{
|
715
721
|
struct cds_lfht *t;
|
716
722
|
struct cds_lfht_iter iter;
|
717
723
|
struct src_loc *l;
|
718
724
|
|
725
|
+
uatomic_set(&total_bytes_inc, 0);
|
726
|
+
uatomic_set(&total_bytes_dec, 0);
|
727
|
+
|
719
728
|
rcu_read_lock();
|
720
729
|
t = rcu_dereference(totals);
|
721
730
|
cds_lfht_for_each_entry(t, &iter, l, hnode) {
|
@@ -1033,6 +1042,16 @@ static VALUE mwrap_quiet(VALUE mod)
|
|
1033
1042
|
return rb_ensure(rb_yield, SIZET2NUM(cur), reset_locating, 0);
|
1034
1043
|
}
|
1035
1044
|
|
1045
|
+
static VALUE total_inc(VALUE mod)
|
1046
|
+
{
|
1047
|
+
return SIZET2NUM(total_bytes_inc);
|
1048
|
+
}
|
1049
|
+
|
1050
|
+
static VALUE total_dec(VALUE mod)
|
1051
|
+
{
|
1052
|
+
return SIZET2NUM(total_bytes_dec);
|
1053
|
+
}
|
1054
|
+
|
1036
1055
|
/*
|
1037
1056
|
* Document-module: Mwrap
|
1038
1057
|
*
|
@@ -1084,6 +1103,8 @@ void Init_mwrap(void)
|
|
1084
1103
|
rb_define_singleton_method(mod, "each", mwrap_each, -1);
|
1085
1104
|
rb_define_singleton_method(mod, "[]", mwrap_aref, 1);
|
1086
1105
|
rb_define_singleton_method(mod, "quiet", mwrap_quiet, 0);
|
1106
|
+
rb_define_singleton_method(mod, "total_bytes_allocated", total_inc, 0);
|
1107
|
+
rb_define_singleton_method(mod, "total_bytes_freed", total_dec, 0);
|
1087
1108
|
rb_define_method(cSrcLoc, "each", src_loc_each, 0);
|
1088
1109
|
rb_define_method(cSrcLoc, "frees", src_loc_frees, 0);
|
1089
1110
|
rb_define_method(cSrcLoc, "allocations", src_loc_allocations, 0);
|
data/lib/mwrap_rack.rb
ADDED
@@ -0,0 +1,121 @@
|
|
1
|
+
# Copyright (C) 2018 all contributors <mwrap@80x24.org>
|
2
|
+
# License: GPL-2.0+ <https://www.gnu.org/licenses/gpl-2.0.txt>
|
3
|
+
# frozen_string_literal: true
|
4
|
+
require 'mwrap'
|
5
|
+
require 'rack'
|
6
|
+
require 'cgi'
|
7
|
+
|
8
|
+
# MwrapRack is a standalone Rack application which can be
|
9
|
+
# mounted to run within your application process.
|
10
|
+
#
|
11
|
+
# Using the Rack::Builder API in config.ru, you can map it to
|
12
|
+
# the "/MWRAP/" endpoint. As with the rest of the Mwrap API,
|
13
|
+
# your Rack server needs to be spawned with the mwrap(1)
|
14
|
+
# wrapper to enable the LD_PRELOAD.
|
15
|
+
#
|
16
|
+
# require 'mwrap_rack'
|
17
|
+
# map('/MWRAP') { run(MwrapRack.new) }
|
18
|
+
# map('/') { run(your_normal_app) }
|
19
|
+
#
|
20
|
+
# A live demo is available at https://80x24.org/MWRAP/
|
21
|
+
# (warning the demo machine is 32-bit, so counters will overflow)
|
22
|
+
#
|
23
|
+
# This module is only available in mwrap 2.0.0+
|
24
|
+
class MwrapRack
|
25
|
+
module HtmlResponse # :nodoc:
|
26
|
+
def response
|
27
|
+
[ 200, {
|
28
|
+
'Expires' => 'Fri, 01 Jan 1980 00:00:00 GMT',
|
29
|
+
'Pragma' => 'no-cache',
|
30
|
+
'Cache-Control' => 'no-cache, max-age=0, must-revalidate',
|
31
|
+
'Content-Type' => 'text/html; charset=UTF-8',
|
32
|
+
}, self ]
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
class Each < Struct.new(:script_name, :min, :sort) # :nodoc:
|
37
|
+
include HtmlResponse
|
38
|
+
HEADER = '<tr><th>' + %w(total allocations frees mean_life max_life
|
39
|
+
location).join('</th><th>') + '</th></tr>'
|
40
|
+
FIELDS = %w(total allocations frees mean_life max_life location)
|
41
|
+
def each
|
42
|
+
Mwrap.quiet do
|
43
|
+
t = -"Mwrap.each(#{min})"
|
44
|
+
sn = script_name
|
45
|
+
all = []
|
46
|
+
f = FIELDS.dup
|
47
|
+
sc = FIELDS.index(sort || 'total') || 0
|
48
|
+
f[sc] = -"<b>#{f[sc]}</b>"
|
49
|
+
f.map! do |hdr|
|
50
|
+
if hdr.start_with?('<b>')
|
51
|
+
hdr
|
52
|
+
else
|
53
|
+
-%Q(<a\nhref="#{sn}/each/#{min}?sort=#{hdr}">#{hdr}</a>)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
Mwrap.each(min) do |loc, total, allocations, frees, age_sum, max_life|
|
57
|
+
mean_life = frees == 0 ? Float::INFINITY : age_sum/frees.to_f
|
58
|
+
all << [total,allocations,frees,mean_life,max_life,loc]
|
59
|
+
end
|
60
|
+
all.sort_by! { |cols| -cols[sc] }
|
61
|
+
|
62
|
+
yield(-"<html><head><title>#{t}</title></head>" \
|
63
|
+
"<body><h1>#{t}</h1>\n" \
|
64
|
+
"<h2>Current generation: #{GC.count}</h2>\n<table>\n" \
|
65
|
+
"<tr><th>#{f.join('</th><th>')}</th></tr>\n")
|
66
|
+
all.each do |cols|
|
67
|
+
loc = cols.pop
|
68
|
+
cols[3] = sprintf('%0.3f', cols[3]) # mean_life
|
69
|
+
href = -(+"#{sn}/at/#{CGI.escape(loc)}").encode!(xml: :attr)
|
70
|
+
yield(%Q(<tr><td>#{cols.join('</td><td>')}<td><a\nhref=#{
|
71
|
+
href}>#{-loc.encode(xml: :text)}</a></td></tr>\n))
|
72
|
+
cols.clear
|
73
|
+
end.clear
|
74
|
+
yield "</table></body></html>\n"
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
class EachAt < Struct.new(:loc) # :nodoc:
|
80
|
+
include HtmlResponse
|
81
|
+
HEADER = '<tr><th>size</th><th>generation</th></tr>'
|
82
|
+
|
83
|
+
def each
|
84
|
+
t = loc.name.encode(xml: :text)
|
85
|
+
yield(-"<html><head><title>#{t}</title></head>" \
|
86
|
+
"<body><h1>live allocations at #{t}</h1>" \
|
87
|
+
"<h2>Current generation: #{GC.count}</h2>\n<table>#{HEADER}")
|
88
|
+
loc.each do |size, generation|
|
89
|
+
yield("<tr><td>#{size}</td><td>#{generation}</td></tr>\n")
|
90
|
+
end
|
91
|
+
yield "</table></body></html>\n"
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
def r404 # :nodoc:
|
96
|
+
[404,{'Content-Type'=>'text/plain'},["Not found\n"]]
|
97
|
+
end
|
98
|
+
|
99
|
+
# The standard Rack application endpoint for MwrapRack
|
100
|
+
def call(env)
|
101
|
+
case env['PATH_INFO']
|
102
|
+
when %r{\A/each/(\d+)\z}
|
103
|
+
min = $1.to_i
|
104
|
+
m = env['QUERY_STRING'].match(/\bsort=(\w+)/)
|
105
|
+
Each.new(env['SCRIPT_NAME'], min, m ? m[1] : nil).response
|
106
|
+
when %r{\A/at/(.*)\z}
|
107
|
+
loc = -CGI.unescape($1)
|
108
|
+
loc = Mwrap[loc] or return r404
|
109
|
+
EachAt.new(loc).response
|
110
|
+
when '/'
|
111
|
+
n = 2000
|
112
|
+
u = 'https://80x24.org/mwrap/README.html'
|
113
|
+
b = -('<html><head><title>Mwrap demo</title></head>' \
|
114
|
+
"<body><p><a href=\"each/#{n}\">allocations >#{n} bytes</a>" \
|
115
|
+
"<p><a href=\"#{u}\">#{u}</a></body></html>\n")
|
116
|
+
[ 200, {'Content-Type'=>'text/html','Content-Length'=>-b.size.to_s},[b]]
|
117
|
+
else
|
118
|
+
r404
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
data/mwrap.gemspec
CHANGED
@@ -8,9 +8,11 @@ if git_manifest[0] && manifest != git_manifest
|
|
8
8
|
system('git add MANIFEST')
|
9
9
|
end
|
10
10
|
|
11
|
+
desc = `git describe --abbrev=4 HEAD`.strip.tr('-', '.').delete_prefix('v')
|
12
|
+
|
11
13
|
Gem::Specification.new do |s|
|
12
14
|
s.name = 'mwrap'
|
13
|
-
s.version = '2.0.0'
|
15
|
+
s.version = desc.empty? ? '2.0.0' : desc
|
14
16
|
s.homepage = 'https://80x24.org/mwrap/'
|
15
17
|
s.authors = ["Ruby hackers"]
|
16
18
|
s.summary = 'LD_PRELOAD malloc wrapper for Ruby'
|
data/test/test_mwrap.rb
CHANGED
@@ -272,4 +272,15 @@ class TestMwrap < Test::Unit::TestCase
|
|
272
272
|
res == :foo or abort 'Mwrap.quiet did not return block result'
|
273
273
|
end;
|
274
274
|
end
|
275
|
+
|
276
|
+
def test_total_bytes
|
277
|
+
assert_separately(+"#{<<~"begin;"}\n#{<<~'end;'}")
|
278
|
+
begin;
|
279
|
+
require 'mwrap'
|
280
|
+
Mwrap.total_bytes_allocated > 0 or abort 'nothing allocated'
|
281
|
+
Mwrap.total_bytes_freed > 0 or abort 'nothing freed'
|
282
|
+
Mwrap.total_bytes_allocated > Mwrap.total_bytes_freed or
|
283
|
+
abort 'freed more than allocated'
|
284
|
+
end;
|
285
|
+
end
|
275
286
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mwrap
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.0.0
|
4
|
+
version: 2.0.0.4.gd1ea
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ruby hackers
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-07-
|
11
|
+
date: 2018-07-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: test-unit
|
@@ -50,6 +50,7 @@ extra_rdoc_files: []
|
|
50
50
|
files:
|
51
51
|
- ".document"
|
52
52
|
- ".gitignore"
|
53
|
+
- ".olddoc.yml"
|
53
54
|
- COPYING
|
54
55
|
- MANIFEST
|
55
56
|
- README
|
@@ -58,6 +59,7 @@ files:
|
|
58
59
|
- ext/mwrap/extconf.rb
|
59
60
|
- ext/mwrap/jhash.h
|
60
61
|
- ext/mwrap/mwrap.c
|
62
|
+
- lib/mwrap_rack.rb
|
61
63
|
- mwrap.gemspec
|
62
64
|
- test/test_mwrap.rb
|
63
65
|
homepage: https://80x24.org/mwrap/
|
@@ -75,9 +77,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
75
77
|
version: '0'
|
76
78
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
77
79
|
requirements:
|
78
|
-
- - "
|
80
|
+
- - ">"
|
79
81
|
- !ruby/object:Gem::Version
|
80
|
-
version:
|
82
|
+
version: 1.3.1
|
81
83
|
requirements: []
|
82
84
|
rubyforge_project:
|
83
85
|
rubygems_version: 2.7.7
|