Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

GC Ballast / Task Ballast question #32

Closed
hostilefork opened this issue Jan 16, 2016 · 9 comments
Closed

GC Ballast / Task Ballast question #32

hostilefork opened this issue Jan 16, 2016 · 9 comments

Comments

@hostilefork
Copy link

I changed some code that started creating a lot of series--one per function call (though most of the time this series should just be GC'd). Unfortunately, tight loops wind up making quite a few before the GC has a chance to get called. So it's easy to hit high water marks in memory that don't get released.

There are some things that can be done about it, and I expected it to be a performance hit... but I saw something strange with it seeming to GC on just about every cycle. Then I saw this code here:

https://github.com/metaeducation/ren-c/blob/8d29c1169c69dc5b9e733bfe39fa7c0f7b3220dd/src/core/m-gc.c#L1244

The GC_Ballast has always been a bit of a mystery to me, and I imagine you have looked at it . But when I put some debugging code in to print out numbers at this point I got back things like this:

PG_Mem_Usage = 14515476
TASK_BALLAST = 60
GC_Ballast increased by half -52
Recycled 0
PG_Mem_Usage = 14515476
TASK_BALLAST = 90
GC Ballast cut in half 298
Recycled 2
PG_Mem_Usage = 14515476
TASK_BALLAST = 45
GC_Ballast increased by half -11
Recycled 0
PG_Mem_Usage = 14515476
TASK_BALLAST = 66
GC_Ballast left alone 114
Recycled 1
PG_Mem_Usage = 14515476
TASK_BALLAST = 66
GC_Ballast increased by half -46
Recycled 0
PG_Mem_Usage = 14515476
TASK_BALLAST = 99
GC_Ballast left alone 147

So it has gotten to the point where it is GC'ing very frequently with a tiny TASK_BALLAST that is just sort of flipping around at small numbers, and it's recycling one or 2 series at a time.

If you've looked at this code can you give some insight into what it should be doing? Is this expected behavior that it thinks 14 MB is too much and really won't keep going without a GC every cycle?

@zsx
Copy link
Owner

zsx commented Jan 18, 2016

Yes, I added this water mark checking. I think the problem is how TASK_BALLAST
got to 60 bytes in the first place. I think it started with 3,000,000 (
https://github.com/metaeducation/ren-c/blob/8d29c1169c69dc5b9e733bfe39fa7c0f7b3220dd/src/core/b-init.c#L841
and
https://github.com/metaeducation/ren-c/blob/master/src/include/mem-pools.h#L111
).

The reason I added this was because our application uses a lot of memory
(over 1 Gigabytes), and it took forever to startup because of GC, so I
added this logic to adjust GC_Ballast as needed, and it worked well,
perhaps more testing is needed for low memory usage programs (perhaps
adding a min ballast?).

Best Regards

Shixin Zeng

On Sat, Jan 16, 2016 at 11:45 AM, Brian Dickens notifications@github.com
wrote:

I changed some code that started creating a lot of series--one per
function call *(though most of the time this series should just be GC'd).
Unfortunately, tight loops wind up making quite a few before the GC has a
chance to get called. So it's easy to hit high water marks in memory that
don't get released.

There are some things that can be done about it, and I expected it to be a
performance hit... but I saw something strange with it seeming to GC on
just about every cycle. Then I saw this code here:

https://github.com/metaeducation/ren-c/blob/8d29c1169c69dc5b9e733bfe39fa7c0f7b3220dd/src/core/m-gc.c#L1244

The GC_Ballast has always been a bit of a mystery to me, and I imagine you
have looked at it . But when I put some debugging code in to print out
numbers at this point I got back things like this:

PG_Mem_Usage = 14515476
TASK_BALLAST = 60
GC_Ballast increased by half -52
Recycled 0
PG_Mem_Usage = 14515476
TASK_BALLAST = 90
GC Ballast cut in half 298
Recycled 2
PG_Mem_Usage = 14515476
TASK_BALLAST = 45
GC_Ballast increased by half -11
Recycled 0
PG_Mem_Usage = 14515476
TASK_BALLAST = 66
GC_Ballast left alone 114
Recycled 1
PG_Mem_Usage = 14515476
TASK_BALLAST = 66
GC_Ballast increased by half -46
Recycled 0
PG_Mem_Usage = 14515476
TASK_BALLAST = 99
GC_Ballast left alone 147

So it has gotten to the point where it is GC'ing very frequently with a
tiny TASK_BALLAST that is just sort of flipping around at small numbers,
and it's recycling one or 2 series at a time.

If you've looked at this code can you give some insight into what it
should be doing? Is this expected behavior that it thinks 14 MB is too
much and really won't keep going without a GC every cycle?


Reply to this email directly or view it on GitHub
#32.

@giuliolunati
Copy link

@zsx I see you decrease TASK_BALLAST if is low relative to GC_BALLAST and increase if is high. That make sense? I'd expect viceversa... ?

@hostilefork
Copy link
Author

The part I find puzzling is that a GC is triggered by the ballast reaching 0 or negative:

https://github.com/metaeducation/ren-c/blob/a1dbe1dbf6d22b7f2844d23d0d3adca26808cb22/src/core/m-pools.c#L722

So I don't understand what the comparisons are supposed to mean in this case. What good is comparing 0 or a small negative number to anything?

I guess the thing I'd be looking for here is "the story", in the form of a comment on GC_Ballast, of what the logic is supposed to be. And because it is coming up, this question of what to do with the situation I'm creating that doesn't seem like it should be unmanageable. Basically:

 my-nothing-function: does []
 loop 10000000 [
     my-nothing-function
 ]

I'm having a situation where a REBSER is being created on each call (no memory for series data, just the REBSER node). And a REBSER is not very big, it is the sizeof(REBVAL) plus a little, and it comes out of a pool so it's pretty fast. It's not needed usually when the call is over (as in above, there's no point to it), so it should go to the GC and be cleaned up pretty soon.

But this is wreaking havoc because a loop like the above will not have any printing or other operations which would stop it from just consuming all memory with the unused REBSERs before doing a GC, and once that memory is taken it will not be given back.

But I don't think what I'm doing is that "unreasonable" in the sense that it seems the system should be kicking in the GC automatically at some point when it sees a lot of allocations. So hopefully whatever the story is with the logic could accommodate such a situation.

@zsx
Copy link
Owner

zsx commented Jan 19, 2016

I think (I didn't come up with this idea, BTW) the logic behind GC_Ballast is:

  1. GC_Ballast starts with TASK_BALLAST, which is 3,000,000
  2. GC_Ballast decreases when a new REBSER is allocated, and increase when a REBSER is released.
  3. When GC_Ballast reaches zero, GC kicks in in the hope that some memory can be recycled.
    So basically, when more than 3,000,000 bytes (if no user adjustment by changing TASK_BALLAST or running recycle/ballast) memory is allocated, GC will kick in. However, for some applications, 3,000,000 is so small that GC kicks in very often and it has not much memory to release, which wastes a lot of CPU time. So I introduced water marks for GC_Ballast.

As explained above, GC will kick in when GC_Ballast gets to zero, so GC_Ballast indicates how much more memory can be allocated before next GC kicks in. The smaller GC_Ballast is, the more often GC kicks in, so increasing GC_Ballast when it's small makes GC run less often. However, if it's too big (when last GC released a lot of memory), GC might not run often enough and result in big memory pools. Whether it's too small or too big is determined by comparing to TASK_BALLAST, which can be changed by the user. I opted it to be too small when it's smaller than half of TASK_BALLAST, and it's too big if it's bigger than 2 times of TASK_BALLAST. I think the problem @hostilefork saw can be solved by putting a limit on the minimum value TASK_BALLAST can be.

@zsx
Copy link
Owner

zsx commented Jan 19, 2016

@giuliolunati I am actually increasing GC_Ballast if it's low compared to TASK_BALLAST, and decrease it when it's high. Note this line: https://github.com/metaeducation/ren-c/blob/8d29c1169c69dc5b9e733bfe39fa7c0f7b3220dd/src/core/m-gc.c#L1262

@hostilefork
Copy link
Author

I'm not sure why I only hit this some of the time, but I'm being forced to look at it because the interpreter grinds to a crawl and can't run the tests... :-(

GC_Ballast decreases when a new REBSER is allocated, and increase when a REBSER is released.

So it does increase when a REBSER is released. The issue seems to be is that if a large amount of memory gets released, then GC Ballast becomes bigger than the task ballast. So it causes this condition to kick in...

if (GC_Ballast >= VAL_INT64(TASK_BALLAST) * 2) {
    //reduce ballast by half
    VAL_INT64(TASK_BALLAST) /= 2;
}

...BUT it doesn't kick in just once. It kicks in every time a recycle runs (which for instance in the test suite is done on each test). It only takes a few times of being divided by 2 for TASK_BALLAST to get driven down to a 0-ish point. And it never recovers.

However, for some applications, 3,000,000 is so small that GC kicks in very often and it has not much memory to release, which wastes a lot of CPU time. So I introduced water marks for GC_Ballast.

Seems that you're saying you were chewing through memory a lot--such that 3MB of allocations happens often, but you didn't want GC to run in that case? You wanted bigger numbers to trigger it (say 30MB, or whatever)...so you wanted to grow the TASK_BALLAST to a larger number, where each GC exhaustion would use that larger number. Then you wanted to have a way to back it down again if it seemed a bunch of memory had been released.

However, the mechanism is backfiring. Because if a single allocation is extremely large (as with my debug-instrumented R3 executable getting loaded in a BINARY!) then its free will be very large. And then manual calls to recycle will drive TASK_BALLAST to 0-ish, which then keeps resetting GC_Ballast to 0-ish, perpetuating the cycle.

(Note: also it may be (?) that when you added the conditions you were interpreting it as if at that point in the code, the GC_Ballast had its initialization value from the last recycle vs. the current one. Because in the non-manual-recycle case, these are comparisons against the exhausted GC_Ballast. So you're comparing against 0--which was my initial confused observation.)

I don't know if there's a good automatic heuristic to pick from here. Garbage collection is a deep topic, and what's really needed here is an incremental GC and pretty much an overhaul of it. Perhaps we could drop the heuristics in favor of just using manual control, so that in your app you could use the recycle/ballast to pick a number fitting for your situation?

@zsx
Copy link
Owner

zsx commented Jan 31, 2016

I think the easiest way to fix "resetting GC_Ballast to 0-ish" would be introducing a minimum (non-zero) TASK_BALLAST, which could probably be the one it initially started, and could be set by recycle/ballast

@hostilefork
Copy link
Author

I think the easiest way to fix "resetting GC_Ballast to 0-ish" would be introducing a minimum (non-zero) TASK_BALLAST, which could probably be the one it initially started, and could be set by recycle/ballast

I don't mind there being some bounds of minimum or maximum of "water marks". But if that's going to be added then the logic of the current water mark has to make sense...

Unless I'm reading something wrong here...I'll ask again if you can explain what this code is meant to do if--in the main relevant case of Recycle (automatic vs. manual)--a GC does not run unless GC_Ballast is <= 0:

    if (GC_Ballast <= VAL_INT32(TASK_BALLAST) / 2
        && VAL_INT64(TASK_BALLAST) < MAX_I32) {
        //increasing ballast by half
        VAL_INT64(TASK_BALLAST) /= 2;
        VAL_INT64(TASK_BALLAST) *= 3;
    } else if (GC_Ballast >= VAL_INT64(TASK_BALLAST) * 2) {
        //reduce ballast by half
        VAL_INT64(TASK_BALLAST) /= 2;
    }

    // avoid overflow
    if (
        VAL_INT64(TASK_BALLAST) < 0
        || VAL_INT64(TASK_BALLAST) >= MAX_I32
    ) {
        VAL_INT64(TASK_BALLAST) = MAX_I32;
    }

Is there something about the GC_Ballast at this point in the code that suggests to you that it carries useful information for adapting the value to which GC_Ballast will be reset? (?)

hostilefork added a commit to metaeducation/ren-c that referenced this issue Mar 4, 2016
This creates a problem described in:

zsx#32

Pending a solution, this comments it out (issue has been open since
January 16, and it's troubling to keep it patched locally...as it
brings the test suite to a crawl each time it is run.)
hostilefork added a commit to metaeducation/ren-c that referenced this issue Mar 4, 2016
This creates a problem described in:

zsx#32

Pending a solution, this comments it out (issue has been open since
January 16, and it's troubling to keep it patched locally...as it
brings the test suite to a crawl each time it is run.)
hostilefork added a commit to metaeducation/ren-c that referenced this issue Mar 4, 2016
This creates a problem described in:

zsx#32

Pending a solution, this comments it out (issue has been open since
January 16, and it's troubling to keep it patched locally...as it
brings the test suite to a crawl each time it is run.)
zsx added a commit that referenced this issue Nov 5, 2018
a simple "nl" in a text block could crash it, because it's a static
string, and not supposed to be free'd. "\n" is also supposed to be of
type wide_t*, or there'll be garbage text.

(gdb) bt
    #0  0x00007ffff72b2f73 in free () from /usr/lib/libc.so.6
    #1  0x00005555555fd956 in OS_Free (mem=0x5555556c49f8) at ../src/os/linux/host-lib.c:392
    #2  0x0000555555687413 in agg::rich_text::rt_reset (this=0x5555558f7d60) at ../src/agg/agg_truetype_text.cpp:135
    #3  0x0000555555652017 in agg::agg_graphics::agg_text (this=0x5555557ebde0, vectorial=1, p1=0x7fffffffc308, p2=0x7fffffffc310, block=0x7ffff61d6020) at ../src/agg/agg_graphics.cpp:1955
    #4  0x0000555555626103 in agg::rebdrw_text (gr=0x5555557ebde0, mode=1, p1=0x7fffffffc308, p2=0x7fffffffc310, block=0x7ffff61d6020) at ../src/os/host-draw-api-agg.cpp:413
    #5  0x0000555555623c01 in RXD_Draw (cmd=33, frm=0x7fffffffc3e0, ctx=0x7fffffffc5d0) at ../src/os/host-draw.c:571
    #6  0x000055555558b577 in Do_Commands (cmds=0x7ffff61d5fc0, context=0x7fffffffc5d0) at ../src/core/f-extension.c:585
    #7  0x000055555556b8a7 in RL_Do_Commands (blk=0x7ffff61d5fc0, flags=0, context=0x7fffffffc5d0) at ../src/core/a-lib.c:402
    #8  0x0000555555627b27 in agg::rebdrw_gob_draw (gob=0x555555940798, buf=0x7ffff5add000 '\377' <repeats 200 times>..., buf_size=..., abs_oft=..., clip_oft=..., clip_siz=...)
        at ../src/os/host-draw-api-agg.cpp:611
    #9  0x000055555562abf9 in process_gobs (ctx=0x5555559091f0, gob=0x555555940798) at ../src/os/linux/host-compositor.c:524
    #10 0x000055555562ae48 in process_gobs (ctx=0x5555559091f0, gob=0x555555940744) at ../src/os/linux/host-compositor.c:563
    #11 0x000055555562ae48 in process_gobs (ctx=0x5555559091f0, gob=0x5555559407ec) at ../src/os/linux/host-compositor.c:563
    #12 0x000055555562c037 in rebcmp_compose (ctx=0x5555559091f0, winGob=0x5555559407ec, gob=0x5555559407ec, only=0 '\000') at ../src/os/linux/host-compositor.c:691
    #13 0x000055555561affd in Draw_Window (wingob=0x5555559407ec, gob=0x5555559407ec) at ../src/os/host-view.c:225
    #14 0x000055555561b1a3 in Show_Gob (gob=0x5555559407ec) at ../src/os/host-view.c:288
    #15 0x000055555561b5ed in RXD_Graphics (cmd=5, frm=0x7fffffffd190, data=0x0) at ../src/os/host-view.c:338
    #16 0x000055555558b01a in Do_Command (value=0x7ffff6209110) at ../src/core/f-extension.c:456
    #17 0x0000555555570768 in Do_Next (block=0x7ffff61d5c00, index=9, op=0) at ../src/core/c-do.c:886
    #18 0x0000555555570e42 in Do_Blk (block=0x7ffff61d5c00, index=7) at ../src/core/c-do.c:1017
    #19 0x00005555555790f4 in Do_Function (func=0x7ffff6209070) at ../src/core/c-function.c:415
    #20 0x0000555555570768 in Do_Next (block=0x7ffff61d9a60, index=3, op=0) at ../src/core/c-do.c:886
    #21 0x0000555555570587 in Do_Next (block=0x7ffff61d9a60, index=0, op=0) at ../src/core/c-do.c:860
    #22 0x0000555555570e42 in Do_Blk (block=0x7ffff61d9a60, index=0) at ../src/core/c-do.c:1017
    #23 0x00005555555a1bc3 in N_while (ds=0x7ffff6209010) at ../src/core/n-loop.c:690
    #24 0x0000555555578bdd in Do_Native (func=0x7ffff6208fb0) at ../src/core/c-function.c:289
    #25 0x0000555555570768 in Do_Next (block=0x7ffff61d9aa0, index=5, op=0) at ../src/core/c-do.c:886
    #26 0x0000555555570e42 in Do_Blk (block=0x7ffff61d9aa0, index=2) at ../src/core/c-do.c:1017
    #27 0x00005555555790f4 in Do_Function (func=0x7ffff6208ed0) at ../src/core/c-function.c:415
    #28 0x0000555555572734 in Apply_Function (wblk=0x7ffff61d9aa0, widx=0, func=0x7ffff6208ed0, args=0x7fffffffd530) at ../src/core/c-do.c:1528
    #29 0x0000555555572883 in Apply_Func (where=0x7ffff61d9aa0, func=0x555555844da0) at ../src/core/c-do.c:1555
    #30 0x000055555559e5d2 in N_wake_up (ds=0x7ffff6208db0) at ../src/core/n-io.c:415
    #31 0x0000555555578bdd in Do_Native (func=0x7ffff6208e10) at ../src/core/c-function.c:289
    #32 0x0000555555570768 in Do_Next (block=0x7ffff7fbf1e0, index=6, op=0) at ../src/core/c-do.c:886
    #33 0x000055555556fbe8 in Do_Args (func_offset=105, path=0x0, block=0x7ffff7fbf1e0, index=3) at ../src/core/c-do.c:668
    #34 0x00005555555706ba in Do_Next (block=0x7ffff7fbf1e0, index=2, op=0) at ../src/core/c-do.c:879
    #35 0x0000555555570e42 in Do_Blk (block=0x7ffff7fbf1e0, index=2) at ../src/core/c-do.c:1017
    #36 0x000055555559b221 in N_either (ds=0x7ffff6208bd0) at ../src/core/n-control.c:596
    #37 0x0000555555578bdd in Do_Native (func=0x7ffff6208c30) at ../src/core/c-function.c:289
    #38 0x0000555555570768 in Do_Next (block=0x7ffff7fbf220, index=15, op=0) at ../src/core/c-do.c:886
    #39 0x0000555555570e42 in Do_Blk (block=0x7ffff7fbf220, index=10) at ../src/core/c-do.c:1017
    #40 0x00005555555a1bc3 in N_while (ds=0x7ffff6208bd0) at ../src/core/n-loop.c:690
    #41 0x0000555555578bdd in Do_Native (func=0x7ffff6208b70) at ../src/core/c-function.c:289
    #42 0x0000555555570768 in Do_Next (block=0x7ffff7fbf2e0, index=12, op=0) at ../src/core/c-do.c:886
    #43 0x0000555555570e42 in Do_Blk (block=0x7ffff7fbf2e0, index=9) at ../src/core/c-do.c:1017
    #44 0x00005555555790f4 in Do_Function (func=0x7ffff62089d0) at ../src/core/c-function.c:415
    #45 0x0000555555572734 in Apply_Function (wblk=0x7ffff7fbf2e0, widx=0, func=0x7ffff62089d0, args=0x7fffffffda30) at ../src/core/c-do.c:1528
    #46 0x0000555555572883 in Apply_Func (where=0x7ffff7fbf2e0, func=0x555555844140) at ../src/core/c-do.c:1555
    #47 0x000055555557979c in Awake_System (ports=0x7ffff61d5640, only=0) at ../src/core/c-port.c:183
    #48 0x0000555555579890 in Wait_Ports (ports=0x7ffff61d5640, timeout=4294967295, only=0) at ../src/core/c-port.c:217
    #49 0x000055555559e463 in N_wait (ds=0x7ffff6208890) at ../src/core/n-io.c:374
    #50 0x0000555555578bdd in Do_Native (func=0x7ffff62088f0) at ../src/core/c-function.c:289
    #51 0x0000555555570768 in Do_Next (block=0x7ffff61d9800, index=2, op=0) at ../src/core/c-do.c:886
    #52 0x0000555555570e42 in Do_Blk (block=0x7ffff61d9800, index=0) at ../src/core/c-do.c:1017
    rebol#53 0x00005555555790f4 in Do_Function (func=0x7ffff6208870) at ../src/core/c-function.c:415
    rebol#54 0x0000555555570768 in Do_Next (block=0x7ffff61d92e0, index=1, op=0) at ../src/core/c-do.c:886
    rebol#55 0x0000555555570e42 in Do_Blk (block=0x7ffff61d92e0, index=0) at ../src/core/c-do.c:1017
    rebol#56 0x000055555559b300 in N_if (ds=0x7ffff6208730) at ../src/core/n-control.c:623
    rebol#57 0x0000555555578bdd in Do_Native (func=0x7ffff6208790) at ../src/core/c-function.c:289
    rebol#58 0x0000555555570768 in Do_Next (block=0x7ffff61d9300, index=50, op=0) at ../src/core/c-do.c:886
    rebol#59 0x0000555555570e42 in Do_Blk (block=0x7ffff61d9300, index=46) at ../src/core/c-do.c:1017
    rebol#60 0x00005555555790f4 in Do_Function (func=0x7ffff62085f0) at ../src/core/c-function.c:415
    rebol#61 0x0000555555570768 in Do_Next (block=0x7ffff61d60e0, index=28, op=0) at ../src/core/c-do.c:886
    rebol#62 0x0000555555570e42 in Do_Blk (block=0x7ffff61d60e0, index=26) at ../src/core/c-do.c:1017
    rebol#63 0x000055555559b02d in N_do (ds=0x7ffff6208470) at ../src/core/n-control.c:522
    rebol#64 0x0000555555578bdd in Do_Native (func=0x7ffff62084d0) at ../src/core/c-function.c:289
    rebol#65 0x0000555555570768 in Do_Next (block=0x7ffff7fc5140, index=6, op=0) at ../src/core/c-do.c:886
    rebol#66 0x0000555555570e42 in Do_Blk (block=0x7ffff7fc5140, index=3) at ../src/core/c-do.c:1017
    rebol#67 0x000055555559b221 in N_either (ds=0x7ffff6208370) at ../src/core/n-control.c:596
    rebol#68 0x0000555555578bdd in Do_Native (func=0x7ffff62083d0) at ../src/core/c-function.c:289
    rebol#69 0x0000555555570768 in Do_Next (block=0x7ffff7fc51c0, index=20, op=0) at ../src/core/c-do.c:886
    rebol#70 0x0000555555570e42 in Do_Blk (block=0x7ffff7fc51c0, index=11) at ../src/core/c-do.c:1017
    rebol#71 0x000055555559b221 in N_either (ds=0x7ffff6208270) at ../src/core/n-control.c:596
    rebol#72 0x0000555555578bdd in Do_Native (func=0x7ffff62082d0) at ../src/core/c-function.c:289
    rebol#73 0x0000555555570768 in Do_Next (block=0x7ffff7fc5200, index=11, op=0) at ../src/core/c-do.c:886
    rebol#74 0x0000555555570e42 in Do_Blk (block=0x7ffff7fc5200, index=5) at ../src/core/c-do.c:1017
    rebol#75 0x000055555559b221 in N_either (ds=0x7ffff6208170) at ../src/core/n-control.c:596
    rebol#76 0x0000555555578bdd in Do_Native (func=0x7ffff62081d0) at ../src/core/c-function.c:289
    rebol#77 0x0000555555570768 in Do_Next (block=0x7ffff7fc5240, index=76, op=0) at ../src/core/c-do.c:886
    rebol#78 0x0000555555570e42 in Do_Blk (block=0x7ffff7fc5240, index=71) at ../src/core/c-do.c:1017
    rebol#79 0x00005555555790f4 in Do_Function (func=0x7ffff6208090) at ../src/core/c-function.c:415
    rebol#80 0x0000555555572734 in Apply_Function (wblk=0x7ffff7fc5240, widx=0, func=0x7ffff6208090, args=0x7fffffffe350) at ../src/core/c-do.c:1528
    rebol#81 0x0000555555572a40 in Do_Sys_Func (inum=34) at ../src/core/c-do.c:1588
    rebol#82 0x0000555555573f89 in Init_Mezz (reserved=0) at ../src/core/c-do.c:2320
    rebol#83 0x000055555556b558 in RL_Start (
        bin=0x5555556b63a0 <Reb_Init_Code> "x\234\325=is\334\066\226\373\231\277\002\241kK\322x\350>t\330鉣rdg\354\335\\e{j>t\261RT\223\222\070\352&{H\266e\215\343\377\276\357\302ţ[\262\235\311l\245b\221 \360\360\360\200w\342\001\375\027uV\256o\253\374\362\252Q\257_|\367\363\017\352m\266\270*\312ey\231g\265:\216~*\337E\323\361\344\311hr8;\236\314\306_Gdz\361\070\310W\353\262jԪL7\313L̓&o\226\331L\205\f\343P\275\375\341ͻɣ\261ZWeS.ʥ\252\027W\331*\v\203wYU\347e1S\343G'\217&A\221\254\240Y\263\254\203\030\240\244\331\371\346r\026\024e\221", <incomplete sequence \331>..., len=9009, script=0x0, script_len=0, flags=0)
        at ../src/core/a-lib.c:193
    rebol#84 0x00005555555fb344 in main (argc=2, argv=0x7fffffffe708) at ../src/os/host-main.c:235
    (gdb) frame 2
    #2  0x0000555555687413 in agg::rich_text::rt_reset (this=0x5555558f7d60) at ../src/agg/agg_truetype_text.cpp:135
    135					OS_Free(attr.text);
    (gdb) p attr
    $1 = {index = 10, name = 0x5555557a8af0 "/usr/share/fonts/TTF/arial.ttf", name_free = false, bold = 0, italic = 0, underline = 1, size = 18, color = {r = 128 '\200', g = 128 '\200', b = 128 '\200',
        a = 255 '\377'}, offset_x = 2, offset_y = 2, space_x = 0, space_y = 0, shadow_x = 0, shadow_y = 0, shadow_color = {r = 0 '\000', g = 0 '\000', b = 0 '\000', a = 255 '\377'}, shadow_blur = 0,
      text = 0x5555556c49f8 L"\n\x4f000000\xcf000000", text_free = true, isPara = true, para = {origin_x = 2, origin_y = 2, margin_x = 2, margin_y = 2, indent_x = 0, indent_y = 0, tabs = 40, wrap = 1,
        scroll_x = 0, scroll_y = 0, align = 19, valign = 23}, asc = 14, desc = 2, char_height = 13}
    (gdb) quit
hostilefork added a commit to metaeducation/ren-c that referenced this issue Sep 15, 2019
@hostilefork
Copy link
Author

While there's no question the GC could be improved and understood better, this code created problems...and was commented out for many years (to revert to R3-Alpha), which resolved the problems it caused. So I've deleted it in Ren-C and will close this issue:

metaeducation@a25ec58

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants