msgpack 1.5.2 → 1.5.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/ChangeLog +14 -0
- data/README.md +3 -1
- data/bench/bench.rb +78 -0
- data/ext/msgpack/buffer.c +9 -36
- data/ext/msgpack/buffer.h +9 -1
- data/ext/msgpack/buffer_class.c +6 -6
- data/ext/msgpack/compat.h +0 -99
- data/ext/msgpack/extconf.rb +9 -11
- data/ext/msgpack/packer.c +0 -24
- data/ext/msgpack/packer.h +1 -7
- data/ext/msgpack/packer_class.c +1 -1
- data/ext/msgpack/unpacker.c +56 -65
- data/ext/msgpack/unpacker.h +10 -6
- data/ext/msgpack/unpacker_class.c +2 -3
- data/lib/msgpack/version.rb +1 -1
- data/msgpack.gemspec +1 -0
- data/spec/factory_spec.rb +28 -0
- data/spec/spec_helper.rb +5 -1
- data/spec/unpacker_spec.rb +12 -0
- metadata +18 -13
- data/bench/pack.rb +0 -23
- data/bench/pack_log.rb +0 -33
- data/bench/pack_log_long.rb +0 -65
- data/bench/pack_symbols.rb +0 -28
- data/bench/run.sh +0 -14
- data/bench/run_long.sh +0 -35
- data/bench/run_symbols.sh +0 -26
- data/bench/unpack.rb +0 -21
- data/bench/unpack_log.rb +0 -34
- data/bench/unpack_log_long.rb +0 -67
data/ext/msgpack/unpacker.c
CHANGED
@@ -34,6 +34,13 @@ static ID s_call;
|
|
34
34
|
static msgpack_rmem_t s_stack_rmem;
|
35
35
|
#endif
|
36
36
|
|
37
|
+
#if !defined(HAVE_RB_HASH_NEW_CAPA)
|
38
|
+
static inline VALUE rb_hash_new_capa(long capa)
|
39
|
+
{
|
40
|
+
return rb_hash_new();
|
41
|
+
}
|
42
|
+
#endif
|
43
|
+
|
37
44
|
void msgpack_unpacker_static_init()
|
38
45
|
{
|
39
46
|
#ifdef UNPACKER_STACK_RMEM
|
@@ -53,13 +60,16 @@ void msgpack_unpacker_static_destroy()
|
|
53
60
|
#define HEAD_BYTE_REQUIRED 0xc1
|
54
61
|
|
55
62
|
static inline msgpack_unpacker_stack_t* _msgpack_unpacker_new_stack(void) {
|
63
|
+
msgpack_unpacker_stack_t *stack = ZALLOC(msgpack_unpacker_stack_t);
|
64
|
+
stack->capacity = MSGPACK_UNPACKER_STACK_CAPACITY;
|
56
65
|
#ifdef UNPACKER_STACK_RMEM
|
57
|
-
|
66
|
+
stack->data = msgpack_rmem_alloc(&s_stack_rmem);
|
58
67
|
/*memset(uk->stack, 0, MSGPACK_UNPACKER_STACK_CAPACITY);*/
|
59
68
|
#else
|
60
|
-
/*uk->stack = calloc(MSGPACK_UNPACKER_STACK_CAPACITY, sizeof(
|
61
|
-
|
69
|
+
/*uk->stack = calloc(MSGPACK_UNPACKER_STACK_CAPACITY, sizeof(msgpack_unpacker_stack_entry_t));*/
|
70
|
+
stack->data = xmalloc(MSGPACK_UNPACKER_STACK_CAPACITY * sizeof(msgpack_unpacker_stack_entry_t));
|
62
71
|
#endif
|
72
|
+
return stack;
|
63
73
|
}
|
64
74
|
|
65
75
|
msgpack_unpacker_t* _msgpack_unpacker_new(void)
|
@@ -74,17 +84,17 @@ msgpack_unpacker_t* _msgpack_unpacker_new(void)
|
|
74
84
|
uk->reading_raw = Qnil;
|
75
85
|
|
76
86
|
uk->stack = _msgpack_unpacker_new_stack();
|
77
|
-
uk->stack_capacity = MSGPACK_UNPACKER_STACK_CAPACITY;
|
78
87
|
|
79
88
|
return uk;
|
80
89
|
}
|
81
90
|
|
82
91
|
static inline void _msgpack_unpacker_free_stack(msgpack_unpacker_stack_t* stack) {
|
83
92
|
#ifdef UNPACKER_STACK_RMEM
|
84
|
-
msgpack_rmem_free(&s_stack_rmem, stack);
|
93
|
+
msgpack_rmem_free(&s_stack_rmem, stack->data);
|
85
94
|
#else
|
86
|
-
xfree(stack);
|
95
|
+
xfree(stack->data);
|
87
96
|
#endif
|
97
|
+
xfree(stack);
|
88
98
|
}
|
89
99
|
|
90
100
|
void _msgpack_unpacker_destroy(msgpack_unpacker_t* uk)
|
@@ -93,18 +103,24 @@ void _msgpack_unpacker_destroy(msgpack_unpacker_t* uk)
|
|
93
103
|
msgpack_buffer_destroy(UNPACKER_BUFFER_(uk));
|
94
104
|
}
|
95
105
|
|
106
|
+
void msgpack_unpacker_mark_stack(msgpack_unpacker_stack_t* stack)
|
107
|
+
{
|
108
|
+
while (stack) {
|
109
|
+
msgpack_unpacker_stack_entry_t* s = stack->data;
|
110
|
+
msgpack_unpacker_stack_entry_t* send = stack->data + stack->depth;
|
111
|
+
for(; s < send; s++) {
|
112
|
+
rb_gc_mark(s->object);
|
113
|
+
rb_gc_mark(s->key);
|
114
|
+
}
|
115
|
+
stack = stack->parent;
|
116
|
+
}
|
117
|
+
}
|
118
|
+
|
96
119
|
void msgpack_unpacker_mark(msgpack_unpacker_t* uk)
|
97
120
|
{
|
98
121
|
rb_gc_mark(uk->last_object);
|
99
122
|
rb_gc_mark(uk->reading_raw);
|
100
|
-
|
101
|
-
msgpack_unpacker_stack_t* s = uk->stack;
|
102
|
-
msgpack_unpacker_stack_t* send = uk->stack + uk->stack_depth;
|
103
|
-
for(; s < send; s++) {
|
104
|
-
rb_gc_mark(s->object);
|
105
|
-
rb_gc_mark(s->key);
|
106
|
-
}
|
107
|
-
|
123
|
+
msgpack_unpacker_mark_stack(uk->stack);
|
108
124
|
/* See MessagePack_Buffer_wrap */
|
109
125
|
/* msgpack_buffer_mark(UNPACKER_BUFFER_(uk)); */
|
110
126
|
rb_gc_mark(uk->buffer_ref);
|
@@ -116,9 +132,8 @@ void _msgpack_unpacker_reset(msgpack_unpacker_t* uk)
|
|
116
132
|
|
117
133
|
uk->head_byte = HEAD_BYTE_REQUIRED;
|
118
134
|
|
119
|
-
/*memset(uk->stack, 0, sizeof(msgpack_unpacker_t) * uk->
|
120
|
-
uk->
|
121
|
-
|
135
|
+
/*memset(uk->stack, 0, sizeof(msgpack_unpacker_t) * uk->stack->depth);*/
|
136
|
+
uk->stack->depth = 0;
|
122
137
|
uk->last_object = Qnil;
|
123
138
|
uk->reading_raw = Qnil;
|
124
139
|
uk->reading_raw_remaining = 0;
|
@@ -170,6 +185,9 @@ static inline int object_complete_symbol(msgpack_unpacker_t* uk, VALUE object)
|
|
170
185
|
static inline int object_complete_ext(msgpack_unpacker_t* uk, int ext_type, VALUE str)
|
171
186
|
{
|
172
187
|
if (uk->optimized_symbol_ext_type && ext_type == uk->symbol_ext_type) {
|
188
|
+
if (RB_UNLIKELY(NIL_P(str))) { // empty extension is returned as Qnil
|
189
|
+
return object_complete_symbol(uk, ID2SYM(rb_intern3("", 0, rb_utf8_encoding())));
|
190
|
+
}
|
173
191
|
return object_complete_symbol(uk, rb_str_intern(str));
|
174
192
|
}
|
175
193
|
|
@@ -191,37 +209,37 @@ static inline int object_complete_ext(msgpack_unpacker_t* uk, int ext_type, VALU
|
|
191
209
|
}
|
192
210
|
|
193
211
|
/* stack funcs */
|
194
|
-
static inline
|
212
|
+
static inline msgpack_unpacker_stack_entry_t* _msgpack_unpacker_stack_entry_top(msgpack_unpacker_t* uk)
|
195
213
|
{
|
196
|
-
return &uk->stack[uk->
|
214
|
+
return &uk->stack->data[uk->stack->depth-1];
|
197
215
|
}
|
198
216
|
|
199
217
|
static inline int _msgpack_unpacker_stack_push(msgpack_unpacker_t* uk, enum stack_type_t type, size_t count, VALUE object)
|
200
218
|
{
|
201
219
|
reset_head_byte(uk);
|
202
220
|
|
203
|
-
if(uk->
|
221
|
+
if(uk->stack->capacity - uk->stack->depth <= 0) {
|
204
222
|
return PRIMITIVE_STACK_TOO_DEEP;
|
205
223
|
}
|
206
224
|
|
207
|
-
|
225
|
+
msgpack_unpacker_stack_entry_t* next = &uk->stack->data[uk->stack->depth];
|
208
226
|
next->count = count;
|
209
227
|
next->type = type;
|
210
228
|
next->object = object;
|
211
229
|
next->key = Qnil;
|
212
230
|
|
213
|
-
uk->
|
231
|
+
uk->stack->depth++;
|
214
232
|
return PRIMITIVE_CONTAINER_START;
|
215
233
|
}
|
216
234
|
|
217
235
|
static inline VALUE msgpack_unpacker_stack_pop(msgpack_unpacker_t* uk)
|
218
236
|
{
|
219
|
-
return --uk->
|
237
|
+
return --uk->stack->depth;
|
220
238
|
}
|
221
239
|
|
222
240
|
static inline bool msgpack_unpacker_stack_is_empty(msgpack_unpacker_t* uk)
|
223
241
|
{
|
224
|
-
return uk->
|
242
|
+
return uk->stack->depth == 0;
|
225
243
|
}
|
226
244
|
|
227
245
|
#ifdef USE_CASE_RANGE
|
@@ -249,8 +267,8 @@ static inline bool msgpack_unpacker_stack_is_empty(msgpack_unpacker_t* uk)
|
|
249
267
|
|
250
268
|
static inline bool is_reading_map_key(msgpack_unpacker_t* uk)
|
251
269
|
{
|
252
|
-
if(uk->
|
253
|
-
|
270
|
+
if(uk->stack->depth > 0) {
|
271
|
+
msgpack_unpacker_stack_entry_t* top = _msgpack_unpacker_stack_entry_top(uk);
|
254
272
|
if(top->type == STACK_TYPE_MAP_KEY) {
|
255
273
|
return true;
|
256
274
|
}
|
@@ -304,20 +322,14 @@ static inline int read_raw_body_begin(msgpack_unpacker_t* uk, int raw_type)
|
|
304
322
|
reset_head_byte(uk);
|
305
323
|
uk->reading_raw_remaining = 0;
|
306
324
|
|
307
|
-
msgpack_unpacker_stack_t*
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
uk->stack = _msgpack_unpacker_new_stack();
|
312
|
-
uk->stack_depth = 0;
|
313
|
-
uk->stack_capacity = MSGPACK_UNPACKER_STACK_CAPACITY;
|
325
|
+
msgpack_unpacker_stack_t* child_stack = _msgpack_unpacker_new_stack();
|
326
|
+
child_stack->parent = uk->stack;
|
327
|
+
uk->stack = child_stack;
|
314
328
|
|
315
329
|
obj = rb_funcall(proc, s_call, 1, uk->buffer.owner);
|
316
330
|
|
317
|
-
|
318
|
-
|
319
|
-
uk->stack_depth = stack_depth;
|
320
|
-
uk->stack_capacity = stack_capacity;
|
331
|
+
uk->stack = child_stack->parent;
|
332
|
+
_msgpack_unpacker_free_stack(child_stack);
|
321
333
|
|
322
334
|
return object_complete(uk, obj);
|
323
335
|
}
|
@@ -371,9 +383,6 @@ static int read_primitive(msgpack_unpacker_t* uk)
|
|
371
383
|
|
372
384
|
SWITCH_RANGE(b, 0xa0, 0xbf) // FixRaw / fixstr
|
373
385
|
int count = b & 0x1f;
|
374
|
-
if(count == 0) {
|
375
|
-
return object_complete(uk, rb_utf8_str_new_static("", 0));
|
376
|
-
}
|
377
386
|
/* read_raw_body_begin sets uk->reading_raw */
|
378
387
|
uk->reading_raw_remaining = count;
|
379
388
|
return read_raw_body_begin(uk, RAW_TYPE_STRING);
|
@@ -390,7 +399,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
|
|
390
399
|
if(count == 0) {
|
391
400
|
return object_complete(uk, rb_hash_new());
|
392
401
|
}
|
393
|
-
return _msgpack_unpacker_stack_push(uk, STACK_TYPE_MAP_KEY, count*2,
|
402
|
+
return _msgpack_unpacker_stack_push(uk, STACK_TYPE_MAP_KEY, count*2, rb_hash_new_capa(count));
|
394
403
|
|
395
404
|
SWITCH_RANGE(b, 0xc0, 0xdf) // Variable
|
396
405
|
switch(b) {
|
@@ -473,7 +482,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
|
|
473
482
|
{
|
474
483
|
READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 4);
|
475
484
|
uint32_t u32 = _msgpack_be32(cb->u32);
|
476
|
-
return object_complete(uk, ULONG2NUM(
|
485
|
+
return object_complete(uk, ULONG2NUM(u32)); // long at least 32 bits
|
477
486
|
}
|
478
487
|
|
479
488
|
case 0xcf: // unsigned int 64
|
@@ -501,7 +510,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
|
|
501
510
|
{
|
502
511
|
READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 4);
|
503
512
|
int32_t i32 = _msgpack_be32(cb->i32);
|
504
|
-
return object_complete(uk, LONG2NUM(
|
513
|
+
return object_complete(uk, LONG2NUM(i32)); // long at least 32 bits
|
505
514
|
}
|
506
515
|
|
507
516
|
case 0xd3: // signed int 64
|
@@ -556,9 +565,6 @@ static int read_primitive(msgpack_unpacker_t* uk)
|
|
556
565
|
{
|
557
566
|
READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 1);
|
558
567
|
uint8_t count = cb->u8;
|
559
|
-
if(count == 0) {
|
560
|
-
return object_complete(uk, rb_utf8_str_new_static("", 0));
|
561
|
-
}
|
562
568
|
/* read_raw_body_begin sets uk->reading_raw */
|
563
569
|
uk->reading_raw_remaining = count;
|
564
570
|
return read_raw_body_begin(uk, RAW_TYPE_STRING);
|
@@ -568,9 +574,6 @@ static int read_primitive(msgpack_unpacker_t* uk)
|
|
568
574
|
{
|
569
575
|
READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 2);
|
570
576
|
uint16_t count = _msgpack_be16(cb->u16);
|
571
|
-
if(count == 0) {
|
572
|
-
return object_complete(uk, rb_utf8_str_new_static("", 0));
|
573
|
-
}
|
574
577
|
/* read_raw_body_begin sets uk->reading_raw */
|
575
578
|
uk->reading_raw_remaining = count;
|
576
579
|
return read_raw_body_begin(uk, RAW_TYPE_STRING);
|
@@ -580,9 +583,6 @@ static int read_primitive(msgpack_unpacker_t* uk)
|
|
580
583
|
{
|
581
584
|
READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 4);
|
582
585
|
uint32_t count = _msgpack_be32(cb->u32);
|
583
|
-
if(count == 0) {
|
584
|
-
return object_complete(uk, rb_utf8_str_new_static("", 0));
|
585
|
-
}
|
586
586
|
/* read_raw_body_begin sets uk->reading_raw */
|
587
587
|
uk->reading_raw_remaining = count;
|
588
588
|
return read_raw_body_begin(uk, RAW_TYPE_STRING);
|
@@ -592,9 +592,6 @@ static int read_primitive(msgpack_unpacker_t* uk)
|
|
592
592
|
{
|
593
593
|
READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 1);
|
594
594
|
uint8_t count = cb->u8;
|
595
|
-
if(count == 0) {
|
596
|
-
return object_complete(uk, rb_str_new_static("", 0));
|
597
|
-
}
|
598
595
|
/* read_raw_body_begin sets uk->reading_raw */
|
599
596
|
uk->reading_raw_remaining = count;
|
600
597
|
return read_raw_body_begin(uk, RAW_TYPE_BINARY);
|
@@ -604,9 +601,6 @@ static int read_primitive(msgpack_unpacker_t* uk)
|
|
604
601
|
{
|
605
602
|
READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 2);
|
606
603
|
uint16_t count = _msgpack_be16(cb->u16);
|
607
|
-
if(count == 0) {
|
608
|
-
return object_complete(uk, rb_str_new_static("", 0));
|
609
|
-
}
|
610
604
|
/* read_raw_body_begin sets uk->reading_raw */
|
611
605
|
uk->reading_raw_remaining = count;
|
612
606
|
return read_raw_body_begin(uk, RAW_TYPE_BINARY);
|
@@ -616,9 +610,6 @@ static int read_primitive(msgpack_unpacker_t* uk)
|
|
616
610
|
{
|
617
611
|
READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 4);
|
618
612
|
uint32_t count = _msgpack_be32(cb->u32);
|
619
|
-
if(count == 0) {
|
620
|
-
return object_complete(uk, rb_str_new_static("", 0));
|
621
|
-
}
|
622
613
|
/* read_raw_body_begin sets uk->reading_raw */
|
623
614
|
uk->reading_raw_remaining = count;
|
624
615
|
return read_raw_body_begin(uk, RAW_TYPE_BINARY);
|
@@ -651,7 +642,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
|
|
651
642
|
if(count == 0) {
|
652
643
|
return object_complete(uk, rb_hash_new());
|
653
644
|
}
|
654
|
-
return _msgpack_unpacker_stack_push(uk, STACK_TYPE_MAP_KEY, count*2,
|
645
|
+
return _msgpack_unpacker_stack_push(uk, STACK_TYPE_MAP_KEY, count*2, rb_hash_new_capa(count));
|
655
646
|
}
|
656
647
|
|
657
648
|
case 0xdf: // map 32
|
@@ -661,7 +652,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
|
|
661
652
|
if(count == 0) {
|
662
653
|
return object_complete(uk, rb_hash_new());
|
663
654
|
}
|
664
|
-
return _msgpack_unpacker_stack_push(uk, STACK_TYPE_MAP_KEY, count*2,
|
655
|
+
return _msgpack_unpacker_stack_push(uk, STACK_TYPE_MAP_KEY, count*2, rb_hash_new_capa(count));
|
665
656
|
}
|
666
657
|
|
667
658
|
default:
|
@@ -748,7 +739,7 @@ int msgpack_unpacker_read(msgpack_unpacker_t* uk, size_t target_stack_depth)
|
|
748
739
|
|
749
740
|
container_completed:
|
750
741
|
{
|
751
|
-
|
742
|
+
msgpack_unpacker_stack_entry_t* top = _msgpack_unpacker_stack_entry_top(uk);
|
752
743
|
switch(top->type) {
|
753
744
|
case STACK_TYPE_ARRAY:
|
754
745
|
rb_ary_push(top->object, uk->last_object);
|
@@ -798,7 +789,7 @@ int msgpack_unpacker_skip(msgpack_unpacker_t* uk, size_t target_stack_depth)
|
|
798
789
|
|
799
790
|
container_completed:
|
800
791
|
{
|
801
|
-
|
792
|
+
msgpack_unpacker_stack_entry_t* top = _msgpack_unpacker_stack_entry_top(uk);
|
802
793
|
|
803
794
|
/* this section optimized out */
|
804
795
|
// TODO object_complete still creates objects which should be optimized out
|
data/ext/msgpack/unpacker.h
CHANGED
@@ -27,6 +27,7 @@
|
|
27
27
|
|
28
28
|
struct msgpack_unpacker_t;
|
29
29
|
typedef struct msgpack_unpacker_t msgpack_unpacker_t;
|
30
|
+
typedef struct msgpack_unpacker_stack_t msgpack_unpacker_stack_t;
|
30
31
|
|
31
32
|
enum stack_type_t {
|
32
33
|
STACK_TYPE_ARRAY,
|
@@ -39,19 +40,22 @@ typedef struct {
|
|
39
40
|
enum stack_type_t type;
|
40
41
|
VALUE object;
|
41
42
|
VALUE key;
|
42
|
-
}
|
43
|
+
} msgpack_unpacker_stack_entry_t;
|
44
|
+
|
45
|
+
struct msgpack_unpacker_stack_t {
|
46
|
+
size_t depth;
|
47
|
+
size_t capacity;
|
48
|
+
msgpack_unpacker_stack_entry_t *data;
|
49
|
+
msgpack_unpacker_stack_t *parent;
|
50
|
+
};
|
43
51
|
|
44
52
|
#define MSGPACK_UNPACKER_STACK_SIZE (8+4+8+8) /* assumes size_t <= 64bit, enum <= 32bit, VALUE <= 64bit */
|
45
53
|
|
46
54
|
struct msgpack_unpacker_t {
|
47
55
|
msgpack_buffer_t buffer;
|
48
|
-
|
56
|
+
msgpack_unpacker_stack_t *stack;
|
49
57
|
unsigned int head_byte;
|
50
58
|
|
51
|
-
msgpack_unpacker_stack_t* stack;
|
52
|
-
size_t stack_depth;
|
53
|
-
size_t stack_capacity;
|
54
|
-
|
55
59
|
VALUE last_object;
|
56
60
|
|
57
61
|
VALUE reading_raw;
|
@@ -209,7 +209,7 @@ static VALUE Unpacker_read_array_header(VALUE self)
|
|
209
209
|
raise_unpacker_error(r);
|
210
210
|
}
|
211
211
|
|
212
|
-
return ULONG2NUM(size);
|
212
|
+
return ULONG2NUM(size); // long at least 32 bits
|
213
213
|
}
|
214
214
|
|
215
215
|
static VALUE Unpacker_read_map_header(VALUE self)
|
@@ -222,7 +222,7 @@ static VALUE Unpacker_read_map_header(VALUE self)
|
|
222
222
|
raise_unpacker_error((int)r);
|
223
223
|
}
|
224
224
|
|
225
|
-
return ULONG2NUM(size);
|
225
|
+
return ULONG2NUM(size); // long at least 32 bits
|
226
226
|
}
|
227
227
|
|
228
228
|
|
@@ -450,4 +450,3 @@ void MessagePack_Unpacker_module_init(VALUE mMessagePack)
|
|
450
450
|
|
451
451
|
rb_define_method(cMessagePack_Unpacker, "full_unpack", Unpacker_full_unpack, 0);
|
452
452
|
}
|
453
|
-
|
data/lib/msgpack/version.rb
CHANGED
data/msgpack.gemspec
CHANGED
data/spec/factory_spec.rb
CHANGED
@@ -474,6 +474,10 @@ describe MessagePack::Factory do
|
|
474
474
|
expect(roundtrip(:symbol)).to be :symbol
|
475
475
|
end
|
476
476
|
|
477
|
+
it 'works with empty symbol' do
|
478
|
+
expect(roundtrip(:"")).to be :""
|
479
|
+
end
|
480
|
+
|
477
481
|
it 'preserves encoding for ASCII symbols' do
|
478
482
|
expect(:symbol.encoding).to be Encoding::US_ASCII
|
479
483
|
expect(roundtrip(:symbol)).to be :symbol
|
@@ -583,6 +587,30 @@ describe MessagePack::Factory do
|
|
583
587
|
GC.stress = false
|
584
588
|
end
|
585
589
|
end
|
590
|
+
|
591
|
+
it 'does not crash in recursive extensions' do
|
592
|
+
my_hash_type = Class.new(Hash)
|
593
|
+
factory = MessagePack::Factory.new
|
594
|
+
factory.register_type(7,
|
595
|
+
my_hash_type,
|
596
|
+
packer: ->(value, packer) do
|
597
|
+
packer.write(value.to_h)
|
598
|
+
end,
|
599
|
+
unpacker: ->(unpacker) { my_hash_type.new(unpacker.read) },
|
600
|
+
recursive: true,
|
601
|
+
)
|
602
|
+
|
603
|
+
payload = factory.dump(
|
604
|
+
[my_hash_type.new]
|
605
|
+
)
|
606
|
+
|
607
|
+
begin
|
608
|
+
GC.stress = true
|
609
|
+
factory.load(payload)
|
610
|
+
ensure
|
611
|
+
GC.stress = false
|
612
|
+
end
|
613
|
+
end
|
586
614
|
end
|
587
615
|
|
588
616
|
describe 'DefaultFactory' do
|
data/spec/spec_helper.rb
CHANGED
@@ -20,7 +20,11 @@ require "msgpack/bigint"
|
|
20
20
|
if GC.respond_to?(:verify_compaction_references)
|
21
21
|
# This method was added in Ruby 3.0.0. Calling it this way asks the GC to
|
22
22
|
# move objects around, helping to find object movement bugs.
|
23
|
-
|
23
|
+
begin
|
24
|
+
GC.verify_compaction_references(double_heap: true, toward: :empty)
|
25
|
+
rescue NotImplementedError
|
26
|
+
# Some platforms don't support compaction
|
27
|
+
end
|
24
28
|
end
|
25
29
|
|
26
30
|
if GC.respond_to?(:auto_compact=)
|
data/spec/unpacker_spec.rb
CHANGED
@@ -707,6 +707,18 @@ describe MessagePack::Unpacker do
|
|
707
707
|
described_class.new(:freeze => true)
|
708
708
|
end
|
709
709
|
|
710
|
+
if (-"test").equal?(-"test") # RUBY_VERSION >= "2.5"
|
711
|
+
it 'dedups strings' do
|
712
|
+
interned_str = -"test"
|
713
|
+
roundtrip = MessagePack.unpack(MessagePack.pack(interned_str), freeze: true)
|
714
|
+
expect(roundtrip).to be interned_str
|
715
|
+
|
716
|
+
interned_str = -""
|
717
|
+
roundtrip = MessagePack.unpack(MessagePack.pack(interned_str), freeze: true)
|
718
|
+
expect(roundtrip).to be interned_str
|
719
|
+
end
|
720
|
+
end
|
721
|
+
|
710
722
|
it 'can freeze objects when using .unpack' do
|
711
723
|
parsed_struct = MessagePack.unpack(buffer, freeze: true)
|
712
724
|
parsed_struct.should == struct
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: msgpack
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.5.
|
4
|
+
version: 1.5.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sadayuki Furuhashi
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2022-
|
13
|
+
date: 2022-08-22 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: bundler
|
@@ -96,6 +96,20 @@ dependencies:
|
|
96
96
|
- - ">="
|
97
97
|
- !ruby/object:Gem::Version
|
98
98
|
version: '0'
|
99
|
+
- !ruby/object:Gem::Dependency
|
100
|
+
name: benchmark-ips
|
101
|
+
requirement: !ruby/object:Gem::Requirement
|
102
|
+
requirements:
|
103
|
+
- - "~>"
|
104
|
+
- !ruby/object:Gem::Version
|
105
|
+
version: 2.10.0
|
106
|
+
type: :development
|
107
|
+
prerelease: false
|
108
|
+
version_requirements: !ruby/object:Gem::Requirement
|
109
|
+
requirements:
|
110
|
+
- - "~>"
|
111
|
+
- !ruby/object:Gem::Version
|
112
|
+
version: 2.10.0
|
99
113
|
description: MessagePack is a binary-based efficient object serialization library.
|
100
114
|
It enables to exchange structured objects between many languages like JSON. But
|
101
115
|
unlike JSON, it is very fast and small.
|
@@ -117,16 +131,7 @@ files:
|
|
117
131
|
- README.md
|
118
132
|
- Rakefile
|
119
133
|
- appveyor.yml
|
120
|
-
- bench/
|
121
|
-
- bench/pack_log.rb
|
122
|
-
- bench/pack_log_long.rb
|
123
|
-
- bench/pack_symbols.rb
|
124
|
-
- bench/run.sh
|
125
|
-
- bench/run_long.sh
|
126
|
-
- bench/run_symbols.sh
|
127
|
-
- bench/unpack.rb
|
128
|
-
- bench/unpack_log.rb
|
129
|
-
- bench/unpack_log_long.rb
|
134
|
+
- bench/bench.rb
|
130
135
|
- doclib/msgpack.rb
|
131
136
|
- doclib/msgpack/buffer.rb
|
132
137
|
- doclib/msgpack/core_ext.rb
|
@@ -231,7 +236,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
231
236
|
- !ruby/object:Gem::Version
|
232
237
|
version: '0'
|
233
238
|
requirements: []
|
234
|
-
rubygems_version: 3.
|
239
|
+
rubygems_version: 3.1.2
|
235
240
|
signing_key:
|
236
241
|
specification_version: 4
|
237
242
|
summary: MessagePack, a binary-based efficient data interchange format.
|
data/bench/pack.rb
DELETED
@@ -1,23 +0,0 @@
|
|
1
|
-
require 'viiite'
|
2
|
-
require 'msgpack'
|
3
|
-
|
4
|
-
data = { 'hello' => 'world', 'nested' => ['structure', {value: 42}] }
|
5
|
-
data_sym = { hello: 'world', nested: ['structure', {value: 42}] }
|
6
|
-
|
7
|
-
data = MessagePack.pack(:hello => 'world', :nested => ['structure', {:value => 42}])
|
8
|
-
|
9
|
-
Viiite.bench do |b|
|
10
|
-
b.range_over([10_000, 100_000, 1000_000], :runs) do |runs|
|
11
|
-
b.report(:strings) do
|
12
|
-
runs.times do
|
13
|
-
MessagePack.pack(data)
|
14
|
-
end
|
15
|
-
end
|
16
|
-
|
17
|
-
b.report(:symbols) do
|
18
|
-
runs.times do
|
19
|
-
MessagePack.pack(data_sym)
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
23
|
-
end
|
data/bench/pack_log.rb
DELETED
@@ -1,33 +0,0 @@
|
|
1
|
-
require 'viiite'
|
2
|
-
require 'msgpack'
|
3
|
-
|
4
|
-
data_plain = { 'message' => '127.0.0.1 - - [10/Oct/2000:13:55:36 -0700] "GET /apache_pb.gif HTTP/1.0" 200 2326 "http://www.example.com/start.html" "Mozilla/4.08 [en] (Win98; I ;Nav)"' }
|
5
|
-
data_structure = {
|
6
|
-
'remote_host' => '127.0.0.1',
|
7
|
-
'remote_user' => '-',
|
8
|
-
'date' => '10/Oct/2000:13:55:36 -0700',
|
9
|
-
'request' => 'GET /apache_pb.gif HTTP/1.0',
|
10
|
-
'method' => 'GET',
|
11
|
-
'path' => '/apache_pb.gif',
|
12
|
-
'protocol' => 'HTTP/1.0',
|
13
|
-
'status' => 200,
|
14
|
-
'bytes' => 2326,
|
15
|
-
'referer' => 'http://www.example.com/start.html',
|
16
|
-
'agent' => 'Mozilla/4.08 [en] (Win98; I ;Nav)',
|
17
|
-
}
|
18
|
-
|
19
|
-
Viiite.bench do |b|
|
20
|
-
b.range_over([10_000, 100_000, 1000_000], :runs) do |runs|
|
21
|
-
b.report(:plain) do
|
22
|
-
runs.times do
|
23
|
-
MessagePack.pack(data_plain)
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
b.report(:structure) do
|
28
|
-
runs.times do
|
29
|
-
MessagePack.pack(data_structure)
|
30
|
-
end
|
31
|
-
end
|
32
|
-
end
|
33
|
-
end
|
data/bench/pack_log_long.rb
DELETED
@@ -1,65 +0,0 @@
|
|
1
|
-
# viiite report --regroup bench,threads bench/pack_log_long.rb
|
2
|
-
|
3
|
-
require 'viiite'
|
4
|
-
require 'msgpack'
|
5
|
-
|
6
|
-
data_plain = { 'message' => '127.0.0.1 - - [10/Oct/2000:13:55:36 -0700] "GET /apache_pb.gif HTTP/1.0" 200 2326 "http://www.example.com/start.html" "Mozilla/4.08 [en] (Win98; I ;Nav)"' }
|
7
|
-
data_structure = {
|
8
|
-
'remote_host' => '127.0.0.1',
|
9
|
-
'remote_user' => '-',
|
10
|
-
'date' => '10/Oct/2000:13:55:36 -0700',
|
11
|
-
'request' => 'GET /apache_pb.gif HTTP/1.0',
|
12
|
-
'method' => 'GET',
|
13
|
-
'path' => '/apache_pb.gif',
|
14
|
-
'protocol' => 'HTTP/1.0',
|
15
|
-
'status' => 200,
|
16
|
-
'bytes' => 2326,
|
17
|
-
'referer' => 'http://www.example.com/start.html',
|
18
|
-
'agent' => 'Mozilla/4.08 [en] (Win98; I ;Nav)',
|
19
|
-
}
|
20
|
-
|
21
|
-
seconds = 3600 # 1 hour
|
22
|
-
|
23
|
-
Viiite.bench do |b|
|
24
|
-
b.range_over([1, 2, 4, 8, 16], :threads) do |threads|
|
25
|
-
b.report(:plain) do
|
26
|
-
ths = []
|
27
|
-
end_at = Time.now + seconds
|
28
|
-
threads.times do
|
29
|
-
t = Thread.new do
|
30
|
-
packs = 0
|
31
|
-
while Time.now < end_at
|
32
|
-
10000.times do
|
33
|
-
MessagePack.pack(data_plain)
|
34
|
-
end
|
35
|
-
packs += 10000
|
36
|
-
end
|
37
|
-
packs
|
38
|
-
end
|
39
|
-
ths.push t
|
40
|
-
end
|
41
|
-
sum = ths.reduce(0){|r,t| r + t.value }
|
42
|
-
puts "MessagePack.pack, plain, #{threads} threads: #{sum} times, #{sum / seconds} times/second."
|
43
|
-
end
|
44
|
-
|
45
|
-
b.report(:structure) do
|
46
|
-
ths = []
|
47
|
-
end_at = Time.now + seconds
|
48
|
-
threads.times do
|
49
|
-
t = Thread.new do
|
50
|
-
packs = 0
|
51
|
-
while Time.now < end_at
|
52
|
-
10000.times do
|
53
|
-
MessagePack.pack(data_structure)
|
54
|
-
end
|
55
|
-
packs += 10000
|
56
|
-
end
|
57
|
-
packs
|
58
|
-
end
|
59
|
-
ths.push t
|
60
|
-
end
|
61
|
-
sum = ths.reduce(0){|r,t| r + t.value }
|
62
|
-
puts "MessagePack.pack, structured, #{threads} threads: #{sum} times, #{sum / seconds} times/second."
|
63
|
-
end
|
64
|
-
end
|
65
|
-
end
|
data/bench/pack_symbols.rb
DELETED
@@ -1,28 +0,0 @@
|
|
1
|
-
require 'viiite'
|
2
|
-
require 'msgpack'
|
3
|
-
|
4
|
-
data = :symbol
|
5
|
-
|
6
|
-
Viiite.bench do |b|
|
7
|
-
b.variation_point :branch, `git rev-parse --abbrev-ref HEAD`
|
8
|
-
|
9
|
-
b.range_over([:symbol, :none], :reg_type) do |reg_type|
|
10
|
-
packer = MessagePack::Packer.new
|
11
|
-
packer.register_type(0x00, Symbol, :to_msgpack_ext) if reg_type == :symbol
|
12
|
-
|
13
|
-
b.range_over([100_000, 1_000_000, 10_000_000], :count) do |count|
|
14
|
-
packer.clear
|
15
|
-
b.report(:multi_run) do
|
16
|
-
count.times do
|
17
|
-
packer.pack(data)
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
packer.clear
|
22
|
-
items_data = [].fill(data, 0, count)
|
23
|
-
b.report(:large_run) do
|
24
|
-
packer.pack(items_data)
|
25
|
-
end
|
26
|
-
end
|
27
|
-
end
|
28
|
-
end
|