uringmachine 0.11 → 0.11.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +4 -0
- data/examples/bm_http_parse.rb +108 -35
- data/ext/um/um.h +2 -1
- data/ext/um/um_stream.c +28 -0
- data/ext/um/um_stream_class.c +4 -23
- data/lib/uringmachine/version.rb +1 -1
- data/uringmachine.gemspec +1 -0
- metadata +15 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ccb8488c3f313b7a3890ae110fc5cebc7ac0062bbaa9ef362fb7ff5b02c680b9
|
4
|
+
data.tar.gz: 41f2c23a9427609c4d01a6eef319cbd40d029cf85918fd6c8d00e5b502f83ef6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9bd08ebae21a7a10407ff04102d9cbf491bfab65ebe601b6ab3a6b7790632c946873415af4f45321e959bd39e875ff386e8c85f74329743204a9c0c047ce5da0
|
7
|
+
data.tar.gz: 3cd63222c0b990ef83f2b324aa46b36bd142a7b43a1a273428a9b70a95cfe25e0a1b06a2985a7463fe51a995c78e82838e34ee20d3c332cc46278ffd738652dd
|
data/CHANGELOG.md
CHANGED
data/examples/bm_http_parse.rb
CHANGED
@@ -1,16 +1,17 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'bundler/inline'
|
3
|
+
# require 'bundler/inline'
|
4
4
|
|
5
|
-
gemfile do
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
end
|
5
|
+
# gemfile do
|
6
|
+
# source 'https://rubygems.org'
|
7
|
+
# gem 'uringmachine', path: '..'
|
8
|
+
# gem 'benchmark-ips'
|
9
|
+
# gem 'http_parser.rb'
|
10
|
+
# end
|
11
11
|
|
12
|
-
require '
|
12
|
+
require 'bundler/setup'
|
13
13
|
require 'uringmachine'
|
14
|
+
require 'benchmark/ips'
|
14
15
|
require 'http/parser'
|
15
16
|
|
16
17
|
$machine = UM.new
|
@@ -19,6 +20,8 @@ HTTP_MSG = "GET /foo/bar HTTP/1.1\r\nServer: foobar.com\r\nFoo: bar\r\n\r\n"
|
|
19
20
|
|
20
21
|
$count = 0
|
21
22
|
|
23
|
+
STDOUT.sync = true
|
24
|
+
|
22
25
|
def parse_http_parser
|
23
26
|
current_fiber = Fiber.current
|
24
27
|
$count += 1
|
@@ -45,10 +48,16 @@ def parse_http_parser
|
|
45
48
|
end
|
46
49
|
|
47
50
|
$machine.write(w.fileno, HTTP_MSG)
|
48
|
-
$machine.yield
|
51
|
+
ret = $machine.yield
|
52
|
+
ret
|
53
|
+
rescue Exception => e
|
54
|
+
p e: e
|
55
|
+
exit
|
49
56
|
ensure
|
50
|
-
|
51
|
-
|
57
|
+
r.close rescue nil
|
58
|
+
w.close rescue nil
|
59
|
+
# $machine.close(r.fileno) rescue nil
|
60
|
+
# $machine.close(w.fileno) rescue nil
|
52
61
|
end
|
53
62
|
|
54
63
|
require 'stringio'
|
@@ -100,50 +109,114 @@ def parse_headers(fd)
|
|
100
109
|
end
|
101
110
|
|
102
111
|
def parse_http_stringio
|
103
|
-
|
104
|
-
|
112
|
+
rfd, wfd = UM.pipe
|
113
|
+
queue = UM::Queue.new
|
105
114
|
|
106
115
|
$machine.spin do
|
107
|
-
headers = parse_headers(
|
108
|
-
$machine.
|
116
|
+
headers = parse_headers(rfd)
|
117
|
+
$machine.push(queue, headers)
|
109
118
|
rescue Exception => e
|
110
119
|
p e
|
111
120
|
puts e.backtrace.join("\n")
|
112
121
|
exit!
|
113
122
|
end
|
114
123
|
|
115
|
-
$machine.write(
|
116
|
-
$machine.
|
124
|
+
$machine.write(wfd, HTTP_MSG)
|
125
|
+
$machine.close(wfd)
|
126
|
+
$machine.shift(queue)
|
117
127
|
ensure
|
118
|
-
$machine.close(
|
119
|
-
$machine.close(
|
128
|
+
($machine.close(rfd) rescue nil) if rfd
|
129
|
+
($machine.close(wfd) rescue nil) if wfd
|
120
130
|
end
|
121
131
|
|
122
|
-
|
123
|
-
|
124
|
-
# exit
|
132
|
+
def stream_parse_headers(fd)
|
133
|
+
stream = UM::Stream.new($machine, fd)
|
125
134
|
|
126
|
-
|
135
|
+
headers = stream_get_request_line(stream)
|
136
|
+
return nil if !headers
|
127
137
|
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
138
|
+
while true
|
139
|
+
line = stream.get_line()
|
140
|
+
break if line.empty?
|
141
|
+
|
142
|
+
m = line.match(RE_HEADER_LINE)
|
143
|
+
raise "Invalid header" if !m
|
144
|
+
|
145
|
+
headers[m[1]] = m[2]
|
146
|
+
end
|
147
|
+
|
148
|
+
headers
|
133
149
|
end
|
134
150
|
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
151
|
+
def stream_get_request_line(stream)
|
152
|
+
line = stream.get_line()
|
153
|
+
|
154
|
+
m = line.match(RE_REQUEST_LINE)
|
155
|
+
return nil if !m
|
156
|
+
|
157
|
+
{
|
158
|
+
'method' => m[1].downcase,
|
159
|
+
'path' => m[2],
|
160
|
+
'protocol' => m[3].downcase
|
161
|
+
}
|
162
|
+
end
|
163
|
+
|
164
|
+
def parse_http_stream
|
165
|
+
rfd, wfd = UM.pipe
|
166
|
+
queue = UM::Queue.new
|
167
|
+
|
168
|
+
$machine.spin do
|
169
|
+
headers = stream_parse_headers(rfd)
|
170
|
+
$machine.push(queue, headers)
|
171
|
+
rescue Exception => e
|
172
|
+
p e
|
173
|
+
puts e.backtrace.join("\n")
|
174
|
+
exit!
|
175
|
+
end
|
176
|
+
|
177
|
+
$machine.write(wfd, HTTP_MSG)
|
178
|
+
$machine.shift(queue)
|
179
|
+
ensure
|
180
|
+
($machine.close(rfd) rescue nil) if rfd
|
181
|
+
($machine.close(wfd) rescue nil) if wfd
|
182
|
+
end
|
183
|
+
|
184
|
+
# 10000.times { parse_http_parser }
|
185
|
+
# 10000.times { parse_http_stringio }
|
186
|
+
# 10000.times { parse_http_stream }
|
187
|
+
# exit
|
188
|
+
|
189
|
+
# GC.disable
|
190
|
+
|
191
|
+
# OS = ObjectSpace
|
192
|
+
|
193
|
+
# def object_count
|
194
|
+
# counts = ObjectSpace.count_objects
|
195
|
+
# counts[:TOTAL] - counts[:FREE]
|
196
|
+
# end
|
197
|
+
|
198
|
+
# def alloc_count
|
199
|
+
# GC.start
|
200
|
+
# count0 = object_count
|
201
|
+
# yield
|
202
|
+
# count1 = object_count
|
203
|
+
# count1 - count0
|
204
|
+
# end
|
205
|
+
|
206
|
+
# X = 100
|
207
|
+
# p(
|
208
|
+
# alloc_http_parser: alloc_count { X.times { parse_http_parser } },
|
209
|
+
# alloc_stringio: alloc_count { X.times { parse_http_stringio } },
|
210
|
+
# alloc_stream: alloc_count { X.times { parse_http_stream } }
|
211
|
+
# )
|
212
|
+
# exit
|
141
213
|
|
142
214
|
Benchmark.ips do |x|
|
143
215
|
x.config(:time => 5, :warmup => 3)
|
144
216
|
|
145
217
|
x.report("http_parser") { parse_http_parser }
|
146
|
-
x.report("
|
218
|
+
x.report("stringio") { parse_http_stringio }
|
219
|
+
x.report("stream") { parse_http_stream }
|
147
220
|
|
148
221
|
x.compare!
|
149
222
|
end
|
data/ext/um/um.h
CHANGED
@@ -271,7 +271,8 @@ VALUE um_queue_unshift(struct um *machine, struct um_queue *queue, VALUE value);
|
|
271
271
|
VALUE um_queue_shift(struct um *machine, struct um_queue *queue);
|
272
272
|
|
273
273
|
int stream_read_more(struct um_stream *stream);
|
274
|
-
|
274
|
+
VALUE stream_get_line(struct um_stream *stream);
|
275
|
+
VALUE stream_get_string(struct um_stream *stream, ulong len);
|
275
276
|
VALUE resp_get_line(struct um_stream *stream, VALUE out_buffer);
|
276
277
|
VALUE resp_get_string(struct um_stream *stream, ulong len, VALUE out_buffer);
|
277
278
|
VALUE resp_decode(struct um_stream *stream, VALUE out_buffer);
|
data/ext/um/um_stream.c
CHANGED
@@ -1,5 +1,32 @@
|
|
1
1
|
#include "um.h"
|
2
2
|
|
3
|
+
VALUE stream_get_line(struct um_stream *stream) {
|
4
|
+
char *start = RSTRING_PTR(stream->buffer) + stream->pos;
|
5
|
+
while (true) {
|
6
|
+
char * lf_ptr = memchr(start, '\n', stream->len - stream->pos);
|
7
|
+
if (lf_ptr) {
|
8
|
+
ulong len = lf_ptr - start;
|
9
|
+
if (len && (start[len - 1] == '\r')) len -= 1;
|
10
|
+
|
11
|
+
VALUE str = rb_str_new(start, len);
|
12
|
+
stream->pos += lf_ptr - start + 1;
|
13
|
+
return str;
|
14
|
+
}
|
15
|
+
|
16
|
+
if (!stream_read_more(stream)) return Qnil;
|
17
|
+
}
|
18
|
+
}
|
19
|
+
|
20
|
+
VALUE stream_get_string(struct um_stream *stream, ulong len) {
|
21
|
+
while (stream->len - stream->pos < len)
|
22
|
+
if (!stream_read_more(stream)) return Qnil;
|
23
|
+
|
24
|
+
char *start = RSTRING_PTR(stream->buffer) + stream->pos;
|
25
|
+
VALUE str = rb_utf8_str_new(start, len);
|
26
|
+
stream->pos += len;
|
27
|
+
return str;
|
28
|
+
}
|
29
|
+
|
3
30
|
static inline void stream_check_truncate_buffer(struct um_stream *stream) {
|
4
31
|
if ((stream->pos == stream->len) && (stream->len >= 1 << 12)) {
|
5
32
|
rb_str_modify(stream->buffer);
|
@@ -58,6 +85,7 @@ VALUE resp_get_line(struct um_stream *stream, VALUE out_buffer) {
|
|
58
85
|
VALUE str = rb_str_new(start, len + 1);
|
59
86
|
rb_str_set_len(str, len);
|
60
87
|
RSTRING_PTR(str)[len] = 0;
|
88
|
+
RB_GC_GUARD(str);
|
61
89
|
return str;
|
62
90
|
}
|
63
91
|
|
data/ext/um/um_stream_class.c
CHANGED
@@ -37,6 +37,8 @@ static VALUE Stream_allocate(VALUE klass) {
|
|
37
37
|
VALUE Stream_initialize(VALUE self, VALUE machine, VALUE fd) {
|
38
38
|
struct um_stream *stream = RTYPEDDATA_DATA(self);
|
39
39
|
|
40
|
+
stream->self = self;
|
41
|
+
|
40
42
|
stream->machine = RTYPEDDATA_DATA(machine);
|
41
43
|
stream->fd = NUM2ULONG(fd);
|
42
44
|
stream->buffer = rb_utf8_str_new_literal("");
|
@@ -54,35 +56,14 @@ VALUE Stream_get_line(VALUE self) {
|
|
54
56
|
struct um_stream *stream = RTYPEDDATA_DATA(self);
|
55
57
|
if (unlikely(stream->eof)) return Qnil;
|
56
58
|
|
57
|
-
|
58
|
-
while (true) {
|
59
|
-
char * lf_ptr = memchr(start, '\n', stream->len - stream->pos);
|
60
|
-
if (lf_ptr) {
|
61
|
-
ulong len = lf_ptr - start;
|
62
|
-
if (len && (start[len - 1] == '\r')) len -= 1;
|
63
|
-
|
64
|
-
VALUE str = rb_str_new(start, len);
|
65
|
-
stream->pos += lf_ptr - start + 1;
|
66
|
-
return str;
|
67
|
-
}
|
68
|
-
|
69
|
-
if (!stream_read_more(stream)) return Qnil;
|
70
|
-
}
|
59
|
+
return stream_get_line(stream);
|
71
60
|
}
|
72
61
|
|
73
62
|
VALUE Stream_get_string(VALUE self, VALUE len) {
|
74
63
|
struct um_stream *stream = RTYPEDDATA_DATA(self);
|
75
64
|
if (unlikely(stream->eof)) return Qnil;
|
76
65
|
|
77
|
-
|
78
|
-
|
79
|
-
while (stream->len - stream->pos < ulen)
|
80
|
-
if (!stream_read_more(stream)) return Qnil;
|
81
|
-
|
82
|
-
char *start = RSTRING_PTR(stream->buffer) + stream->pos;
|
83
|
-
VALUE str = rb_utf8_str_new(start, ulen);
|
84
|
-
stream->pos += ulen;
|
85
|
-
return str;
|
66
|
+
return stream_get_string(stream, NUM2ULONG(len));
|
86
67
|
}
|
87
68
|
|
88
69
|
VALUE Stream_resp_get_line(VALUE self) {
|
data/lib/uringmachine/version.rb
CHANGED
data/uringmachine.gemspec
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: uringmachine
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 0.11.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sharon Rosner
|
@@ -51,6 +51,20 @@ dependencies:
|
|
51
51
|
- - '='
|
52
52
|
- !ruby/object:Gem::Version
|
53
53
|
version: 2.14.0
|
54
|
+
- !ruby/object:Gem::Dependency
|
55
|
+
name: http_parser.rb
|
56
|
+
requirement: !ruby/object:Gem::Requirement
|
57
|
+
requirements:
|
58
|
+
- - '='
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: 0.8.0
|
61
|
+
type: :development
|
62
|
+
prerelease: false
|
63
|
+
version_requirements: !ruby/object:Gem::Requirement
|
64
|
+
requirements:
|
65
|
+
- - '='
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
version: 0.8.0
|
54
68
|
email: sharon@noteflakes.com
|
55
69
|
executables: []
|
56
70
|
extensions:
|