raindrops 0.3.0 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- data/GIT-VERSION-GEN +1 -1
- data/GNUmakefile +1 -1
- data/README +13 -5
- data/Rakefile +1 -1
- data/TODO +0 -1
- data/ext/raindrops/extconf.rb +26 -0
- data/ext/raindrops/linux_inet_diag.c +1 -1
- data/ext/raindrops/raindrops.c +40 -13
- data/ext/raindrops/raindrops_atomic.h +23 -0
- data/lib/raindrops.rb +2 -2
- data/test/test_raindrops.rb +6 -0
- data/test/test_raindrops_gc.rb +4 -1
- metadata +6 -6
data/GIT-VERSION-GEN
CHANGED
data/GNUmakefile
CHANGED
@@ -53,7 +53,7 @@ NEWS: GIT-VERSION-FILE
|
|
53
53
|
latest: NEWS
|
54
54
|
@awk 'BEGIN{RS="=== ";ORS=""}NR==2{sub(/\n$$/,"");print RS""$$0 }' $<
|
55
55
|
|
56
|
-
SINCE = 0.2.
|
56
|
+
SINCE = 0.2.0
|
57
57
|
ChangeLog: LOG_VERSION = \
|
58
58
|
$(shell git rev-parse -q "$(GIT_VERSION)" >/dev/null 2>&1 && \
|
59
59
|
echo $(GIT_VERSION) || git describe)
|
data/README
CHANGED
@@ -3,8 +3,7 @@
|
|
3
3
|
Raindrops is a real time stats package to show statistics for Rack HTTP
|
4
4
|
servers. It is designed for preforking servers such as Rainbows! and
|
5
5
|
Unicorn, but should support any Rack HTTP server under Ruby 1.9, 1.8 and
|
6
|
-
possibly Rubinius (untested) on platforms supporting POSIX shared memory
|
7
|
-
and compiled with GCC (for atomic builtins).
|
6
|
+
possibly Rubinius (untested) on platforms supporting POSIX shared memory.
|
8
7
|
|
9
8
|
Raindrops includes a Struct-like Raindrops::Struct class that may be used
|
10
9
|
standalone to create atomic counters shared across any number of forked
|
@@ -35,9 +34,12 @@ processes under SMP.
|
|
35
34
|
|
36
35
|
== Install
|
37
36
|
|
38
|
-
|
39
|
-
atomic builtins
|
40
|
-
|
37
|
+
We recommend GCC 4+ (or compatible) to support the
|
38
|
+
{atomic builtins}[http://gcc.gnu.org/onlinedocs/gcc/Atomic-Builtins.html]
|
39
|
+
(__sync_{add,sub}_and_fetch()). For non-GCC 4+ users, we also support
|
40
|
+
compilation with the
|
41
|
+
{libatomic_ops}[http://www.hpl.hp.com/research/linux/atomic_ops/]
|
42
|
+
package starting with Raindrops 0.4.0.
|
41
43
|
|
42
44
|
If you're using a packaged Ruby distribution, make sure you have a C
|
43
45
|
compiler and the matching Ruby development libraries and headers.
|
@@ -115,6 +117,12 @@ git itself. See the Documentation/SubmittingPatches document
|
|
115
117
|
distributed with git on on patch submission guidelines to follow. Just
|
116
118
|
don't email the git mailing list or maintainer with raindrops patches.
|
117
119
|
|
120
|
+
raindrops is currently dual-licensed under the LGPLv2.1 and LGPLv3. To
|
121
|
+
allow for a transition to future versions of the LGPL, contributors are
|
122
|
+
required to sign-off changes allowing allowing the project leader to
|
123
|
+
relicense raindrops under newer versions of the LGPL (which should be
|
124
|
+
similar in spirit to the existing LGPL).
|
125
|
+
|
118
126
|
== Contact
|
119
127
|
|
120
128
|
All feedback (bug reports, user/development discussion, patches, pull
|
data/Rakefile
CHANGED
@@ -25,7 +25,7 @@ end
|
|
25
25
|
|
26
26
|
cgit_url = "http://git.bogomips.org/cgit/raindrops.git"
|
27
27
|
git_url = ENV['GIT_URL'] || 'git://git.bogomips.org/raindrops.git'
|
28
|
-
web_url = "http://
|
28
|
+
web_url = "http://raindrops.bogomips.org/"
|
29
29
|
|
30
30
|
desc 'prints news as an Atom feed'
|
31
31
|
task :news_atom do
|
data/TODO
CHANGED
data/ext/raindrops/extconf.rb
CHANGED
@@ -7,5 +7,31 @@ have_func('munmap', 'sys/mman.h') or abort 'munmap() not found'
|
|
7
7
|
have_func("rb_struct_alloc_noinit")
|
8
8
|
have_func('rb_thread_blocking_region')
|
9
9
|
|
10
|
+
checking_for "GCC 4+ atomic builtins" do
|
11
|
+
src = <<SRC
|
12
|
+
int main(int argc, char * const argv[]) {
|
13
|
+
volatile unsigned long i = 0;
|
14
|
+
__sync_add_and_fetch(&i, argc);
|
15
|
+
__sync_sub_and_fetch(&i, argc);
|
16
|
+
return 0;
|
17
|
+
}
|
18
|
+
SRC
|
19
|
+
|
20
|
+
if try_run(src)
|
21
|
+
$defs.push(format("-DHAVE_GCC_ATOMIC_BUILTINS"))
|
22
|
+
true
|
23
|
+
else
|
24
|
+
false
|
25
|
+
end
|
26
|
+
end or have_header('atomic_ops.h') or abort <<-SRC
|
27
|
+
|
28
|
+
libatomic_ops is required if GCC 4+ is not used.
|
29
|
+
See http://www.hpl.hp.com/research/linux/atomic_ops/
|
30
|
+
|
31
|
+
Users of Debian-based distros may run:
|
32
|
+
|
33
|
+
apt-get install libatomic-ops-dev
|
34
|
+
SRC
|
35
|
+
|
10
36
|
dir_config('raindrops')
|
11
37
|
create_makefile('raindrops_ext')
|
@@ -144,7 +144,7 @@ static VALUE diag(void *ptr)
|
|
144
144
|
} req;
|
145
145
|
struct msghdr msg;
|
146
146
|
const char *err = NULL;
|
147
|
-
unsigned seq =
|
147
|
+
unsigned seq = ++g_seq; /* not atomic, rely on GVL for now */
|
148
148
|
int fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_INET_DIAG);
|
149
149
|
|
150
150
|
if (fd < 0)
|
data/ext/raindrops/raindrops.c
CHANGED
@@ -1,24 +1,25 @@
|
|
1
1
|
#include <ruby.h>
|
2
|
+
#include <unistd.h>
|
2
3
|
#include <sys/mman.h>
|
3
4
|
#include <assert.h>
|
4
5
|
#include <errno.h>
|
5
6
|
#include <stddef.h>
|
7
|
+
#include "raindrops_atomic.h"
|
8
|
+
|
9
|
+
#ifndef SIZET2NUM
|
10
|
+
# define SIZET2NUM(x) ULONG2NUM(x)
|
11
|
+
#endif
|
6
12
|
|
7
13
|
/*
|
8
14
|
* most modern CPUs have a cache-line size of 64 or 128.
|
9
15
|
* We choose a bigger one by default since our structure is not
|
10
16
|
* heavily used
|
11
17
|
*/
|
12
|
-
|
13
|
-
# define CACHE_LINE_SIZE 128
|
14
|
-
#endif
|
18
|
+
static size_t raindrop_size = 128;
|
15
19
|
|
16
20
|
/* each raindrop is a counter */
|
17
21
|
struct raindrop {
|
18
|
-
|
19
|
-
unsigned long counter;
|
20
|
-
unsigned char padding[CACHE_LINE_SIZE];
|
21
|
-
} as;
|
22
|
+
unsigned long counter;
|
22
23
|
} __attribute__((packed));
|
23
24
|
|
24
25
|
/* allow mmap-ed regions can store more than one raindrop */
|
@@ -33,7 +34,7 @@ static void evaporate(void *ptr)
|
|
33
34
|
struct raindrops *r = ptr;
|
34
35
|
|
35
36
|
if (r->drops) {
|
36
|
-
int rv = munmap(r->drops,
|
37
|
+
int rv = munmap(r->drops, raindrop_size * r->size);
|
37
38
|
if (rv != 0)
|
38
39
|
rb_bug("munmap failed in gc: %s", strerror(errno));
|
39
40
|
}
|
@@ -72,9 +73,10 @@ static VALUE init(VALUE self, VALUE size)
|
|
72
73
|
rb_raise(rb_eArgError, "size must be >= 1");
|
73
74
|
|
74
75
|
retry:
|
75
|
-
r->drops = mmap(NULL,
|
76
|
+
r->drops = mmap(NULL, raindrop_size * r->size,
|
76
77
|
PROT_READ|PROT_WRITE, MAP_ANON|MAP_SHARED, -1, 0);
|
77
78
|
if (r->drops == MAP_FAILED) {
|
79
|
+
r->drops = NULL;
|
78
80
|
if ((errno == EAGAIN || errno == ENOMEM) && tries-- > 0) {
|
79
81
|
rb_gc();
|
80
82
|
goto retry;
|
@@ -92,7 +94,7 @@ static VALUE init_copy(VALUE dest, VALUE source)
|
|
92
94
|
struct raindrops *src = get(source);
|
93
95
|
|
94
96
|
init(dest, LONG2NUM(src->size));
|
95
|
-
memcpy(dst->drops, src->drops,
|
97
|
+
memcpy(dst->drops, src->drops, raindrop_size * src->size);
|
96
98
|
|
97
99
|
return dest;
|
98
100
|
}
|
@@ -100,9 +102,9 @@ static VALUE init_copy(VALUE dest, VALUE source)
|
|
100
102
|
static unsigned long *addr_of(VALUE self, VALUE index)
|
101
103
|
{
|
102
104
|
struct raindrops *r = get(self);
|
103
|
-
unsigned long off = FIX2ULONG(index) *
|
105
|
+
unsigned long off = FIX2ULONG(index) * raindrop_size;
|
104
106
|
|
105
|
-
if (off >=
|
107
|
+
if (off >= raindrop_size * r->size)
|
106
108
|
rb_raise(rb_eArgError, "offset overrun");
|
107
109
|
|
108
110
|
return (unsigned long *)((unsigned long)r->drops + off);
|
@@ -143,7 +145,7 @@ static VALUE to_ary(VALUE self)
|
|
143
145
|
|
144
146
|
for (i = 0; i < r->size; i++) {
|
145
147
|
rb_ary_push(rv, ULONG2NUM(*((unsigned long *)base)));
|
146
|
-
base +=
|
148
|
+
base += raindrop_size;
|
147
149
|
}
|
148
150
|
|
149
151
|
return rv;
|
@@ -172,9 +174,34 @@ static VALUE aref(VALUE self, VALUE index)
|
|
172
174
|
void Init_raindrops_linux_inet_diag(void);
|
173
175
|
#endif
|
174
176
|
|
177
|
+
#ifndef _SC_NPROCESSORS_ONLN
|
178
|
+
# ifdef _SC_NPROC_ONLN
|
179
|
+
# define _SC_NPROCESSORS_ONLN _SC_NPROC_ONLN
|
180
|
+
# elif defined _SC_CRAY_NCPU
|
181
|
+
# define _SC_NPROCESSORS_ONLN _SC_CRAY_NCPU
|
182
|
+
# endif
|
183
|
+
#endif
|
184
|
+
|
175
185
|
void Init_raindrops_ext(void)
|
176
186
|
{
|
177
187
|
VALUE cRaindrops = rb_define_class("Raindrops", rb_cObject);
|
188
|
+
long tmp = 2;
|
189
|
+
|
190
|
+
#ifdef _SC_NPROCESSORS_ONLN
|
191
|
+
tmp = sysconf(_SC_NPROCESSORS_ONLN);
|
192
|
+
#endif
|
193
|
+
/* no point in padding on single CPU machines */
|
194
|
+
if (tmp == 1)
|
195
|
+
raindrop_size = sizeof(unsigned long);
|
196
|
+
#ifdef _SC_LEVEL1_DCACHE_LINESIZE
|
197
|
+
if (tmp != 1) {
|
198
|
+
tmp = sysconf(_SC_LEVEL1_DCACHE_LINESIZE);
|
199
|
+
if (tmp > 0)
|
200
|
+
raindrop_size = (size_t)tmp;
|
201
|
+
}
|
202
|
+
#endif
|
203
|
+
rb_define_const(cRaindrops, "SIZE", SIZET2NUM(raindrop_size));
|
204
|
+
|
178
205
|
rb_define_alloc_func(cRaindrops, alloc);
|
179
206
|
|
180
207
|
rb_define_method(cRaindrops, "initialize", init, 1);
|
@@ -0,0 +1,23 @@
|
|
1
|
+
/*
|
2
|
+
* use wrappers around libatomic-ops for folks that don't have GCC
|
3
|
+
* or a new enough version of GCC
|
4
|
+
*/
|
5
|
+
#ifndef HAVE_GCC_ATOMIC_BUILTINS
|
6
|
+
#include <atomic_ops.h>
|
7
|
+
|
8
|
+
static inline unsigned long
|
9
|
+
__sync_add_and_fetch(unsigned long *dst, unsigned long incr)
|
10
|
+
{
|
11
|
+
AO_t tmp = AO_fetch_and_add((AO_t *)dst, (AO_t)incr);
|
12
|
+
|
13
|
+
return (unsigned long)tmp + incr;
|
14
|
+
}
|
15
|
+
|
16
|
+
static inline unsigned long
|
17
|
+
__sync_sub_and_fetch(unsigned long *dst, unsigned long incr)
|
18
|
+
{
|
19
|
+
AO_t tmp = AO_fetch_and_add((AO_t *)dst, (AO_t)(-(long)incr));
|
20
|
+
|
21
|
+
return (unsigned long)tmp - incr;
|
22
|
+
}
|
23
|
+
#endif /* HAVE_GCC_ATOMIC_BUILTINS */
|
data/lib/raindrops.rb
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
# -*- encoding: binary -*-
|
2
2
|
class Raindrops
|
3
3
|
|
4
|
-
# Raindrops is currently at version 0.
|
5
|
-
VERSION = '0.
|
4
|
+
# Raindrops is currently at version 0.4.0
|
5
|
+
VERSION = '0.4.0'
|
6
6
|
|
7
7
|
# Used to represent the number of +active+ and +queued+ sockets for
|
8
8
|
# a single listen socket across all threads and processes on a
|
data/test/test_raindrops.rb
CHANGED
@@ -4,6 +4,12 @@ require 'raindrops'
|
|
4
4
|
|
5
5
|
class TestRaindrops < Test::Unit::TestCase
|
6
6
|
|
7
|
+
def test_raindrop_size
|
8
|
+
assert_kind_of Integer, Raindrops::SIZE
|
9
|
+
assert Raindrops::SIZE > 0
|
10
|
+
puts "Raindrops::SIZE = #{Raindrops::SIZE}"
|
11
|
+
end
|
12
|
+
|
7
13
|
def test_size
|
8
14
|
rd = Raindrops.new(4)
|
9
15
|
assert_equal 4, rd.size
|
data/test/test_raindrops_gc.rb
CHANGED
@@ -4,9 +4,12 @@ require 'raindrops'
|
|
4
4
|
|
5
5
|
class TestRaindropsGc < Test::Unit::TestCase
|
6
6
|
|
7
|
+
# we may need to create more garbage as GC may be less aggressive
|
8
|
+
# about expiring things. This is completely unrealistic code,
|
9
|
+
# though...
|
7
10
|
def test_gc
|
8
11
|
assert_nothing_raised do
|
9
|
-
1000000.times { Raindrops.new(24) }
|
12
|
+
1000000.times { |i| Raindrops.new(24); [] }
|
10
13
|
end
|
11
14
|
end
|
12
15
|
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: raindrops
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 15
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
|
-
-
|
8
|
+
- 4
|
9
9
|
- 0
|
10
|
-
version: 0.
|
10
|
+
version: 0.4.0
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- raindrops hackers
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2010-
|
18
|
+
date: 2010-09-21 00:00:00 +00:00
|
19
19
|
default_executable:
|
20
20
|
dependencies: []
|
21
21
|
|
@@ -23,8 +23,7 @@ description: |-
|
|
23
23
|
Raindrops is a real time stats package to show statistics for Rack HTTP
|
24
24
|
servers. It is designed for preforking servers such as Rainbows! and
|
25
25
|
Unicorn, but should support any Rack HTTP server under Ruby 1.9, 1.8 and
|
26
|
-
possibly Rubinius (untested) on platforms supporting POSIX shared memory
|
27
|
-
and compiled with GCC (for atomic builtins).
|
26
|
+
possibly Rubinius (untested) on platforms supporting POSIX shared memory.
|
28
27
|
email: raindrops@librelist.com
|
29
28
|
executables: []
|
30
29
|
|
@@ -59,6 +58,7 @@ files:
|
|
59
58
|
- ext/raindrops/extconf.rb
|
60
59
|
- ext/raindrops/linux_inet_diag.c
|
61
60
|
- ext/raindrops/raindrops.c
|
61
|
+
- ext/raindrops/raindrops_atomic.h
|
62
62
|
- lib/raindrops.rb
|
63
63
|
- lib/raindrops/linux.rb
|
64
64
|
- lib/raindrops/middleware.rb
|