Commit graph

1432 commits

Author SHA1 Message Date
ko1
867693fe3d * gc.c: change additional allocation policy.
Introduce new environement variable
  GC_HEAP_FREE_SLOTS_GOAL_RATIO (goal_ratio) to calculate the ratio
  of additional memory.

  Before this change, we add pages with the following formula
  (when free_slots < total_pages * RUBY_GC_HEAP_FREE_SLOTS_MIN_RATIO):
    next_pages = total_pages * RUBY_GC_HEAP_GROWTH_FACTOR

  This addition can allocate too much.

  With this change, we increase pages to satisfy the following formula:
    next_free_slots = next_total_slots * goal_ratio
  where
    next_free_slots = free_slots + adding_slots
    next_total_slots = total_slots + adding_slots.

  If you want to prepare many free slots, increase this ratio.

  If this variable is 0, then simply multiply
  RUBY_GC_HEAP_GROWTH_FACTOR.

* gc.c (get_envparam_double): enable to accept 0.


git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@54453 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2016-03-31 09:16:48 +00:00
ko1
9bb740d2ec * gc.c (gc_marks_finish): fix syntax error.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@54452 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2016-03-31 08:49:09 +00:00
ko1
49369ef173 * gc.c: simplify allocate/free detecting logic at the end of marking.
Before this change, heap_pages_min_slots are calculated at the
  beggining sweeping phase. And this value is used at the end of
  *next* marking phase.

  To simplify it, we use this value at the end of this marking phase.
  It means that we don't need to store this value as global state.

  Also heap_pages_max_slots is calculated at the begging of sweeping
  phase and used at the end of sweeping phase.
  To simplify this logic, we introduced new global value
  heap_pages_freeable_pages it means extra pages count we can free.
  gc_sweep_step() checks this value and moves empty pages to tomb_heap
  not more than this value.

  Because of this fix, heap_pages_swept_slots is no longer needed.

* gc.c (rb_objspace_t::heap_pages): restruct the objspace global
  status.

  remove the following fileds
    * swept_slots (and heap_pages_swept_slots)
    * min_free_slots (and heap_pages_min_free_slots)
    * max_free_slots (and heap_pages_max_free_slots)
  And add the following filed.
    * freeable_pages (and heap_pages_freeable_pages)

* gc.c (heap_pages_free_unused_pages): unlink tomb heap pages
  because tomb heap should have only freeable pages.

* gc.c (heap_extend_pages): add parameters for future extension.


git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@54451 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2016-03-31 08:21:35 +00:00
ko1
555f6cb089 * gc.c: add GC parameters to configure the following values:
* RUBY_GC_HEAP_FREE_SLOTS_MIN_RATIO:
    allocate additional pages when free slots is lower than
    the value (total_slots * (this ratio)).
  * RUBY_GC_HEAP_FREE_SLOTS_MAX_RATIO:
    allow to free pages when free slots is greater thatn
    the value (total_slots * (this ratio)).

  Before this change, these values are hard coded.

* gc.c (ruby_gc_params_t): ditto.

* gc.c (ruby_gc_set_params): ditto.


git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@54450 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2016-03-31 07:45:13 +00:00
svn
fb296fe6fe * remove trailing spaces.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@54449 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2016-03-31 07:02:41 +00:00
ko1
9a008c5865 * gc.c (gc_verify_heap_page): check the number of zombies.
* gc.c (gc_verify_heap_pages): check also tomb heap.


git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@54448 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2016-03-31 07:02:40 +00:00
ko1
f46b5bcfaf * gc.c (gc_page_sweep): return free slots count.
* gc.c (gc_sweep_step): use returned free slots count.

* gc.c (gc_sweep_step): change variable name `next'
  to `next_sweep_page'.


git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@54447 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2016-03-31 06:51:27 +00:00
nobu
764f39210b gc.c: fix r54115
* gc.c (gc_page_sweep): use the argument objspace.

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@54173 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2016-03-18 07:37:07 +00:00
nobu
7e81ca14fe gc.c: fix commit miss r54145
* gc.c (tick): fix missing close parenthesis.  [Fix GH-1291]

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@54170 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2016-03-18 03:25:32 +00:00
nobu
a5456a1d83 gc.c: tick for POWER arch
* gc.c (tick): Use __builtin_ppc_get_timebase for POWER arch.
  [Fix GH-1291]

This gives a little performance improvement

        user     system      total        real
Before: 20.870000   0.000000  20.870000 ( 20.893959)
After:  20.720000   0.000000  20.720000 ( 20.733970)

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@54145 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2016-03-17 08:14:53 +00:00
nobu
ed921b85dc gc.c: mark_stack_locations
* gc.c (mark_stack_locations): extract the common part from
  mark_current_machine_context and rb_gc_mark_machine_stack.

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@54116 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2016-03-15 07:02:09 +00:00
nobu
d424873980 gc.c: rb_objspace_of
* gc.c (rb_objspace_of): macro to get the objspace from a thread.

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@54115 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2016-03-15 06:42:29 +00:00
nobu
cbfe564ed2 gc.c: expand a local macro
* gc.c (mark_current_machine_context, rb_gc_mark_machine_stack):
  expand rb_gc_mark_locations local macro.

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@54114 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2016-03-15 06:42:27 +00:00
ko1
d04ee29e77 * gc.c: use 2 bits with unsigned int for rb_objspace:🎏:mode
because it always returns 0 to 2 (non-negative value).


git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@53997 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2016-03-04 10:37:35 +00:00
ko1
befcbc2cb9 * gc.c: rename "enum gc_stat" to "enum gc_mode"
because there is a same name (no related) function gc_stat().

  Also gc_stat_* are renamed to gc_mode_*,
  gc_stat_transition() to gc_mode_transition(),
  rb_objspace:🎏:stat is renamed to rb_objspace:🎏:mode.

  Change rb_objspace:🎏:mode from 2 bits to 3 bits because VC++
  returns negative enum value with 2 bits.

* gc.c (gc_mode): add a macro to access rb_objspace:🎏:mode
  with verification code (verification is enabled only on
  RGENGC_CHECK_MODE > 0).

* gc.c (gc_mode_set): same macro for setter.


git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@53996 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2016-03-04 09:53:03 +00:00
naruse
21daa56b2a * re.c: Introduce RREGEXP_PTR.
patch by dbussink.
  partially merge https://github.com/ruby/ruby/pull/497

* include/ruby/ruby.h: ditto.

* gc.c: ditto.

* ext/strscan/strscan.c: ditto.

* parse.y: ditto.

* string.c: ditto.

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@53715 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2016-02-02 04:39:44 +00:00
nobu
4378bd6628 Macro typo
* gc.c (RVALUE_PAGE_WB_UNPROTECTED): fix a typo of argument name.
  [Fix GH-1221]

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@53654 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2016-01-25 22:58:25 +00:00
nobu
439224a590 RUBY_ASSERT
* error.c (rb_assert_failure): assertion with stack dump.
* ruby_assert.h (RUBY_ASSERT): new header for the assertion.

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@53615 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2016-01-22 08:33:55 +00:00
ko1
fca0cf6e6b * gc.c: rename PAGE_* to HEAP_PAGE_* because PAGE_SIZE is used
in Mac OS X.

* test/ruby/test_gc.rb: catch up this fix.


git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@53471 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2016-01-08 22:15:40 +00:00
ko1
1f1f3112dc * gc.c: PAGE_BITMAP_PLANES (the number of bitmap) is 4, not 3.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@53470 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2016-01-08 20:46:36 +00:00
ko1
f8827cef6a * gc.c: rename constant names HEAP_* to PAGE_*.
Keys of GC::INTERNAL_CONSTANTS are also renamed.

* test/ruby/test_gc.rb: catch up this fix.


git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@53468 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2016-01-08 20:45:02 +00:00
ko1
b6261054cd * gc.c: remove heap_page::body. Instead of this field,
heap_page::start field works well.


git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@53466 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2016-01-08 10:56:27 +00:00
ko1
3ccafdb027 * gc.c: rename rb_heap_t::page_length to rb_heap_t::total_pages.
`page_length' is not clear (we may understand with length of
  a page).



git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@53464 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2016-01-08 10:34:14 +00:00
ko1
e5e37c20c9 * gc.c: remove heap_page::heap. This field is only used to recognize
whether a page is in a tomb or not. Instead of this field,
  heap_page:🎏:in_tomb (1 bit field) is added.

  Also type of heap_page::(total|free|final)_slots are changed from
  int to short. 2B is enough for them.




git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@53461 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2016-01-08 08:23:58 +00:00
normal
1142de8e2a use id_table for constant tables
valgrind 3.9.0 on x86-64 reports a minor reduction in memory usage
when loading only RubyGems and RDoc by running: ruby -rrdoc -eexit

before: HEAP SUMMARY:
    in use at exit: 2,913,448 bytes in 27,394 blocks
  total heap usage: 48,362 allocs, 20,968 frees, 9,034,621 bytes alloc

after: HEAP SUMMARY:
    in use at exit: 2,880,056 bytes in 26,712 blocks
  total heap usage: 47,791 allocs, 21,079 frees, 9,046,507 bytes alloc

* class.c (struct clone_const_arg): adjust for id_table
  (clone_const): ditto
  (clone_const_i): ditto
  (rb_mod_init_copy): ditto
  (rb_singleton_class_clone_and_attach): ditto
  (rb_include_class_new): ditto
  (include_modules_at): ditto
* constant.h (rb_free_const_table): ditto
* gc.c (free_const_entry_i): ditto
  (rb_free_const_table): ditto
  (obj_memsize_of): ditto
  (mark_const_entry_i): ditto
  (mark_const_tbl): ditto
* internal.h (struct rb_classext_struct): ditto
* object.c (rb_mod_const_set): resolve class name on assignment
* variable.c (const_update): replace with const_tbl_update
  (const_tbl_update): new function
  (fc_i): adjust for id_table
  (find_class_path): ditto
  (autoload_const_set): st_update => const_tbl_update
  (rb_const_remove): adjust for id_table
  (sv_i): ditto
  (rb_local_constants_i): ditto
  (rb_local_constants): ditto
  (rb_mod_const_at): ditto
  (rb_mod_const_set): ditto
  (rb_const_lookup): ditto

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@53376 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2015-12-29 20:19:14 +00:00
nobu
96ac47c251 gc.c: do not expose internal singleton class
* gc.c (internal_object_p): should not expose singleton classes
  without a metaclass.  based on patches by ko1 and shugo.
  [Bug #11740]
* class.c (rb_singleton_class_object_p): added.

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@53243 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2015-12-22 13:15:58 +00:00
ko1
800607aa7e revert r53228 because this patch breaks rubyspec
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@53229 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2015-12-21 10:32:33 +00:00
ko1
1bcee938d5 * gc.c (internal_object_p): should not expose singleton classes
without a metaclass.
  [Bug #11740]

* class.c (rb_singleton_class_has_metaclass_p): added.

* test/ruby/test_class.rb: add a test.




git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@53228 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2015-12-21 09:40:58 +00:00
ngoto
cef1f23e89 * gc.c: Delete excess semicolon after RUBY_ALIAS_FUNCTION().
Suppress "syntax error:  empty declaration" warnings by
  Oracle Solaris Studio 12.x on Solaris. [Bug #11821]

* hash.c: ditto, after NOINSERT_UPDATE_CALLBACK().


git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@53129 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2015-12-15 14:20:27 +00:00
hsbt
6851be0f0c * compile.c: fix typos.
[ci skip][fix GH-1140] Patch by @jutaz
* dir.c: ditto.
* gc.c: ditto.
* io.c: ditto.
* node.h: ditto.
* thread_pthread.c: ditto.
* vm_insnhelper.c: ditto.
* vsnprintf.c: ditto.

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@53103 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2015-12-14 02:51:13 +00:00
ko1
e48adae2b3 * gc.c (gc_mark_stacked_objects): fix typo.
reported by XIE Zhibang. [Bug #11763]




git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@52994 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2015-12-09 05:49:27 +00:00
ko1
2f5b8f0529 * *.c (*_memsize): do not check ptr.
NULL checking is finished Before call of memsize functions.
  See r52979.




git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@52986 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2015-12-09 00:38:32 +00:00
nobu
a8fb40db8c gc.c: NULL check at memsize
* gc.c (rb_objspace_data_type_memsize): consider NULL data uses no
  memory without calling dsize function as well as other functions.
  fix SEGV in test/objspace with RUBY_ISEQ_DUMP_DEBUG=to_binary.

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@52979 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2015-12-08 17:28:32 +00:00
nobu
bb4d72c51f make local symbols static
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@52964 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2015-12-08 15:07:41 +00:00
odaira
88376e639e * gc.c (rb_raw_obj_info): fix compile errors when USE_RGENGC
is 0.

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@52716 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2015-11-22 13:41:08 +00:00
ko1
121b6e064a * gc.c (gc_start): force to invoke GC by GC.start
even if it is GC.disable'd.

* test/ruby/test_gc.rb: add a test.




git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@52672 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2015-11-19 12:57:20 +00:00
ko1
d5d997fa11 * gc.c: trivial performance improvements.
name    modified
    vm1_gc_short_lived*                1.015
    vm1_gc_short_with_complex_long*    1.014
    vm1_gc_short_with_long*            1.000
    vm1_gc_short_with_symbol*          1.016
    vm1_gc_wb_ary*                     1.002
    vm1_gc_wb_ary_promoted*            0.996
    vm1_gc_wb_obj*                     1.045
    vm1_gc_wb_obj_promoted*            1.014
    vm3_gc                             1.021

* gc.c (gc_writebarrier_generational): reorder parameters to optimize
  register passing function call.

* gc.c (gc_writebarrier_incremental): ditto.

* gc.c (rb_gc_writebarrier): remove LIKELY().
  LIKELY() seems to move related functions not better places.




git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@52671 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2015-11-19 11:13:27 +00:00
nobu
8a3423d38b gc.c: use BUILTIN_TYPE
* gc.c (rb_raw_obj_info): BUILTIN_TYPE works fro non-special_const
  objects.

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@52660 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2015-11-18 23:33:08 +00:00
ko1
e2f0af5740 * gc.c (rb_raw_obj_info): fix trivial issues.
* support SPECIAL_CONSTs.
  * fix IMEMO/ment outputs.




git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@52635 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2015-11-18 08:08:09 +00:00
nobu
9d64a54209 internal.h: RUBY_DTRACE_HOOK
* internal.h (RUBY_DTRACE_HOOK): extract from
  RUBY_DTRACE_CREATE_HOOK for other type hooks.

* gc.c (RUBY_DTRACE_GC_HOOK): ditto.

* parse.y (RUBY_DTRACE_PARSE_HOOK): ditto.

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@52399 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2015-10-31 01:02:29 +00:00
nobu
1546ffed49 use rb_source_loc and rb_source_location
* error.c, eval.c, eval_error.c, gc.c, variable.c, vm.c,
  vm_eval.c, vm_trace.c: use rb_source_loc/rb_source_location
  instead of combination of rb_sourcefile/rb_sourcefilename and
  rb_sourceline.

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@52398 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2015-10-31 01:02:26 +00:00
ko1
a96ae767ac * gc.c (newobj_slowpath): do not need to use flags hack (commit miss).
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@52392 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2015-10-30 10:30:47 +00:00
ko1
e3e5d634f0 * gc.c (heap_get_freeobj_from_next_freepage): not so UNLIKELY.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@52390 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2015-10-30 10:09:50 +00:00
ko1
b872ad5861 * gc.c (newobj_slowpath): reduce 1 parameter to use only registers
for performance.

  On my laptop, 'N.times{x = []}' (where N = 29_000_000) is
  1.86 sec -> 1.74 sec.




git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@52389 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2015-10-30 09:33:08 +00:00
ko1
bce116617a * gc.c (gc_mark_ptr): specify NOINLINE so that gc_mark() can return
immediately when obj is not a markable object.




git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@52351 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2015-10-29 09:48:38 +00:00
nobu
7f7dcb6178 gc.c: separate event hook call from newobj_init
* gc.c (newobj_init): separate event hook call and remove the
  argument for it.

* gc.c (newobj_slowpath): call event hook after initialized the
  new object.

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@52348 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2015-10-29 08:00:01 +00:00
ko1
5869f9a3ba * gc.c (rb_imemo_new): should not pass FL_WB_PROTECTED flag.
* gc.c (rb_wb_protected_newobj_of): add more assertions.

* gc.c (rb_wb_unprotected_newobj_of): ditto.




git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@52347 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2015-10-29 07:43:48 +00:00
ko1
ffa87b4057 * gc.c: introduce rb_wb_unprotected_newobj_of() and
rb_wb_protected_newobj_of(), pass the WB_PROTECTED
  information explicitly.

* internal.h: use introduced functions by NEWOBJ_OF().
  `flag' is immediate value, so that C compilers can
  solve them at compile time.

* include/ruby/ruby.h: add a commnent about that.




git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@52346 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2015-10-29 07:26:44 +00:00
nobu
017ac002c5 gc.c: fix UNLIKELY usage
* gc.c (gc_event_hook_needed_p): UNLIKELY makes no sense for
  boolean flag value.

* gc.c (gc_event_hook, newobj_init): use in conditions instead.

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@52345 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2015-10-29 07:21:24 +00:00
ko1
a3e88485b1 * gc.c: add rb_objspace:🎏:has_hook to represent hook availability.
* gc.c: add gc_event_hook_available_p(objspace) to check that flag.

* gc.c (newobj_of): use gc_event_hook_available_p() instead of
  checking gc_event_hook_needed_p(objspace, RUBY_INTERNAL_EVENT_NEWOBJ).
  for performance.

* gc.c (newobj_init): add UNLIKELY() for FL_WB_PROTECTED flag.

* gc.c (newobj_init): change parameters order (trivial change).




git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@52344 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2015-10-29 06:17:07 +00:00