Re: iPhone vs Android

2016-09-15 Thread Chris Wright via Digitalmars-d
On Wed, 14 Sep 2016 13:37:03 +, Laeeth Isharc wrote:

> On Wednesday, 14 September 2016 at 13:28:45 UTC, finalpatch wrote:
>> On Tuesday, 13 September 2016 at 18:24:26 UTC, deadalnix wrote:
>>> No you don't, as how often the GC kicks in depend of the rate at which
>>> you produce garbage, which is going to be very low with an hybrid
>>> approach.
>>
>> This is simply not true.
>>
>> Assume in a pure GC program the GC heap can grow up to X Mb before a
>> collection cycle happens, which has to scan X Mb of memory.
>>
>> Now let's say we have a hybrid program that uses 0.5X Mb of RCed memory
>> and 0.5X Mb of GC memory so the total memory consumption is still X Mb.
>> When the GC heap reaches 0.5X Mb, it has to scan both RC and GC memory.
> 
> Could you elaborate?

You can store a pointer to a GC-owned memory block inside an RCed object, 
just like how you can store a pointer to a GC-owned memory block on the 
stack.

There are three ways to handle this:

* Keep a pointer to the GCed object inside GCed memory.
* Tell the GC to pin the object, preventing it from being collected.
* Have the GC scan RCed memory as well as GC-owned memory.


Re: iPhone vs Android

2016-09-15 Thread R via Digitalmars-d
On Monday, 12 September 2016 at 22:57:23 UTC, Andrei Alexandrescu 
wrote:
[snip] If it is, that provides more impetus for reference 
counting for D by the following logic: (a) it is likely that in 
the future more code will run on portable, battery-powered 
systems; (b) battery power does not follow a Moore trajectory, 
so at this point in history demand for battery lifetime is 
elastic.



Andrei


I'm keen on reference counting because of embedded and bare-metal 
programming so I'm super keen on D having a short reference long 
garbage standard. I guess we already do this to some extent with 
scope etc.


Battery life can last for years in some of the new embedded 
devices but most languages targeting the M0 etc are really 
archaic, I have seen a rust port somewhere... but if I'm honest I 
only really care for D so I really want LDC -> ARM M0 etc... :D


Re: iPhone vs Android

2016-09-15 Thread Kagamin via Digitalmars-d
On Tuesday, 13 September 2016 at 17:59:52 UTC, Andrei 
Alexandrescu wrote:
So do you agree you were wrong in positing 2x as the rule of 
thumb?


I didn't look into how he connects perceived application 
performance with collection frequency.


Re: iPhone vs Android

2016-09-15 Thread Kagamin via Digitalmars-d

On Wednesday, 14 September 2016 at 14:43:29 UTC, H. S. Teoh wrote:
Honestly, I've never actually run across a real-life case where 
chained exceptions matter. Most of the code (that I work with, 
anyway) involve simply throwing an exception when some problem 
occurs, and the catch block simply prints the error message and 
aborts the current operation.


See e.g. 
https://github.com/dlang/druntime/blob/master/src/core/thread.d#L783


Re: iPhone vs Android

2016-09-15 Thread Shachar Shemesh via Digitalmars-d

On 14/09/16 16:49, Laeeth Isharc wrote:


In D code that I have read where people use RC types they have different
names making it quite clear - eg RCString.but


I find the suggestion that the compiler make code generation decisions 
based on type names not one I would gladly see happen.




If you're worrying about GC presumably you have a decent size problem
anyway (and I admire the ambition of weka in this respect).


Not everything a Weka employee says on this forum is about what Weka is 
doing.



How would you end up with a GC allocated struct by mistake (presuming
you think it through first) at the size you are at? 200k lines and 30
people is a lot,  but it's also not Windows scale.   And if you did,
and it mattered,  wouldn't you pick it up quickly with GC profiling?


We didn't end up with a struct that was allocated by mistake. In fact, I 
do not consider what we're doing to be a hybrid approach. More of a "use 
GC only when the language leaves us no other choice" approach, which is 
far from being the same.


With the hybrid approach, getting there is far from difficult.

struct SomeRCNonGCDataStructure {
}

...

class SomethingUseful {
   private SomeRCNonGCDataStructure dataStructure;
}

Unless you suggest that people implement each algorithm twice, having 
structs on the heap may be hard to avoid.


Shachar


Re: iPhone vs Android

2016-09-14 Thread deadalnix via Digitalmars-d

On Wednesday, 14 September 2016 at 13:28:45 UTC, finalpatch wrote:

On Tuesday, 13 September 2016 at 18:24:26 UTC, deadalnix wrote:
No you don't, as how often the GC kicks in depend of the rate 
at which you produce garbage, which is going to be very low 
with an hybrid approach.


This is simply not true.

Assume in a pure GC program the GC heap can grow up to X Mb 
before a collection cycle happens, which has to scan X Mb of 
memory.




No it has to scan the live set. If we assume we are ready to 
accept a 2X overhead in the GC heap in that program, the 
collection cycle needs to scan X/2 Mb of memory. We are for a bad 
start here.


Now let's say we have a hybrid program that uses 0.5X Mb of 
RCed memory and 0.5X Mb of GC memory so the total memory 
consumption is still X Mb. When the GC heap reaches 0.5X Mb, it 
has to scan both RC and GC memory.




Your assumption that there are 2 heap is bogus, your 2 programs 
have different live sets (A has 500kb and B 750ko of live sets). 
In addition, why the fuck is your RC system only able to reclaim 
50% of the garbage emitted ? Even with such stupids humber, you 
end up with program A able to manage 500kb with 100% overhead, 
and program B able to manage 750ko with 33% overhead, which 
completely proves my point: the hybrid approach is far superior.


Now let's get an appropriate model of how thing work in the real 
world. Let's assume we have a program that emit 1Mb of garbage 
per second, has a live set of 1Mb and we assume we can accept a 
2X memory overhead for the GC.


With the pure GC approach, we emit 1Mb of garbage per second on 
top of our live set of 1Mb, so we need one collection cycle per 
second. This collection cycle has to scan the living set, namely 
1Mb of data.


With the hybrid approach, we still emit 1Mb of garbage per 
second, but the RC system can reclaim 90% of it. We end up with a 
rate of garbage for the GC to collect of 100ko per second. If we 
allow the same memory overhead, we end up with a collection cycle 
every 10s. The live set still has the same size, so the GC still 
has to scan 1Mb of data. Therefore, we effectively divided by 10 
the resource we needed to allocate to the GC.


It's quite obvious that the time(t) it takes for program 1 to 
produce X Mb of garbage is the same as program 2 to produce 
0.5X Mb of garbage, and after time t, both program have to scan 
X Mb of memory.  However program 2 also has to pay the cost of 
reference counting on top of that.




Rule of thumb, when someone start by "it's obvious that" you can 
be sure that 99% of the time, what follows is confirmation bias 
rather than anything cogent. I think we've established this is 
the case here.




Re: iPhone vs Android

2016-09-14 Thread deadalnix via Digitalmars-d
On Wednesday, 14 September 2016 at 07:55:24 UTC, John Colvin 
wrote:

On Tuesday, 13 September 2016 at 22:28:09 UTC, deadalnix wrote:
On Tuesday, 13 September 2016 at 22:19:54 UTC, Jonathan M 
Davis wrote:
The big problem with exceptions being allocated by the GC 
isn't really the GC but @nogc.


No the problem IS @nogc . Allocating with the GC is absolutely 
not a problem is you deallocate properly. What is a problem is 
when you leak (ie, when the ownership is transferred to the 
GC). If you don't leak, GC do not kicks in.


Can you explain a bit more here? Do you mean in practice (I.e. 
in current implementation) or in theory?


My point is that if you have lifetime information for some data 
(and it looks like this is where we want to go with things like 
DIP25 and DIP1000, but let's not get lost in the specific of 
these proposal now) you know they are going to end up being freed 
without the GC having to do a collection cycle.


Therefore, you know you'll not end up having to rely on the GC as 
long as you can track lifetime, even if you allocate with it.


Now that this is established it follows that disallowing GC 
allocation in @nogc code is needlessly restrictive and promote 
unsafe patterns (like allocating using malloc + giving the range 
to the GC, which is both slower than allocating on the GC 
directly and more error prone).


A more sensible approach is to allow GC allocation in @nogc code 
but disallow cases where GC's alloc lifetime cannot be tracked. 
Note that this isn't the case for most exceptions.


For instance, when you do
throw new Exception("tagada");

The compiler can deduce that the ownership of the exception is 
transferred to the runtime, which will transfers back to the 
catch block that gets it. Depending of what this catch block is 
doing, it may or may not be @nogc, but there is no reason that 
for throw to not be allowed in @nogc code.


However, if you have something like
throw e;

With e a reference to an Exception who's lifetime cannot be 
tracked, then it makes sense to disallow it in @nogc code.


TL;DR : The problem is not new, the problem is the rhs of 
assignment operations.


Re: iPhone vs Android

2016-09-14 Thread Jonathan M Davis via Digitalmars-d
On Wednesday, September 14, 2016 07:43:29 H. S. Teoh via Digitalmars-d wrote:
> > But the fact that the workarounds either require that you don't have
> > unique, independent exceptions or that you know that you need to
> > manually free the exception after catching it is a serious problem.
> > And that's without even taking the exception chaining into account.
>
> [...]
>
> Using a preinitialized region allocator, we no longer have such
> limitations.

And how would you deal with the fact that the catching code is generally
going to assume that it has a GC-allocated exception? It's not going to do
anything to free the exception when it's done with it, and it could keep the
exception around for an indeterminate amount of time. So, having the code
that manages the allocator later assume that the exception was freed would
be unsafe. I don't see how it's going to work in the general case to have a
an exception class which is anything other than GC allocated - not as long
as it can't be wrapped in a struct that knows how to deal with freeing its
memory when it's done. Because you either end up with an exception that gets
leaked, because the catching code doesn't know that it needs to do something
to free it, or you run the risk of it being freed prematurely when the code
that manages its memory assumes that the code that caught it didn't keep it.

Obviously, if you're talking about a smaller application that isn't sharing
code with anything, you have more control over what's going on, and you can
afford to make assumptions about what is happening with exceptions and are
thus more likely to get away with stuff that won't work in the general case.
But libraries definitely have to care, and larger applications are going to
tend to have to care, because if there's enough code, it simply isn't going
to work to assume that it all behaves in a way that differs from how
exceptions normally work. Someone else is going to come onto the project and
write perfectly normal D code that then has nasty bugs when an exception
gets thrown, because other code within that large application was doing
something with exceptions that didn't work with normal D code (like
allocating them with a different allocator that won't allow you to hold onto
the exception for an arbitrary amount of time without it being mutated out
from under you or even outright freed).

- Jonathan M Davis



Re: iPhone vs Android

2016-09-14 Thread H. S. Teoh via Digitalmars-d
On Wed, Sep 14, 2016 at 05:19:45AM -0700, Jonathan M Davis via Digitalmars-d 
wrote:
> On Tuesday, September 13, 2016 16:13:05 H. S. Teoh via Digitalmars-d wrote:
> > On Tue, Sep 13, 2016 at 03:19:54PM -0700, Jonathan M Davis via Digitalmars-d
> > wrote: [...]
> >
> > > But none of the code that's marked @nogc can throw an exception
> > > unless you're either dealing with pre-allocated exceptions (in
> > > which case, they're less informative),
> >
> > I don't see why pre-allocated exceptions would be less informative.
> > You can always modify the exception object before throwing it, after
> > all.  In fact, I've always wondered about the feasibility of a @nogc
> > exception handling system where the exception is emplaced onto a
> > fixed static buffer, so that no allocation (except at the start of
> > the program) is actually necessary. Of course, chained exceptions
> > throw(!) a monkey wrench into the works, but assuming we forego
> > chained exceptions, wouldn't this work around the problem of being
> > unable to allocate exceptions in @nogc code? (Albeit with its own
> > limitations, obviously.  But it would be better than being unable to
> > use exceptions at all in @nogc code.)
> 
> As Walter points out, it's a problem if exceptions are ever saved
> (which some code does need to do). The fact that you lose chaining as
> you pointed out is also a problem.

Honestly, I've never actually run across a real-life case where chained
exceptions matter. Most of the code (that I work with, anyway) involve
simply throwing an exception when some problem occurs, and the catch
block simply prints the error message and aborts the current operation.
I agree that chained exceptions are theoretically cool and everything,
but I haven't actually found myself needing them.


> You also have problems because the file, line, and message of the
> exception either aren't going to be specific to when that exception is
> thrown, or you have to set them all before throwing, in which case you
> have issues with if/when the exception is reused.

Clearly, if a static buffer is to be used for emplacing the exception,
you'll have to sacrifice some things.  But I'm just saying that the
limitations aren't as onerous as it may seem at first, and in fact
covers a lot of common use cases.


> And regardless of all of that, the fact that string is used for the
> message throws a wrench in things for @nogc, since that's going to
> require GC allocation unless you cast something to string, and then
> you have serious problems if you need to mutate it later, since you'll
> end up violating the compiler guarantees for immutable.

Most uses of exceptions in code that I've seen involve setting a static
string as the message. This does not require GC allocation.

Granted, it's also relatively common to make the exception message more
verbose / informative, e.g. using format() to embed specific details
about the problem besides the static message string. My own code uses
this idiom quite often. This would have to be sacrificed, or some other
workaround found, of course.


[...]
> > There's nothing about the 'throw' keyword that requires GC
> > allocation.  It's just that `throw new Exception(...)` has become a
> > standard incantation. The exception object itself can, for example,
> > be emplaced onto a static buffer as I propose above.
> 
> Yes, there are ways to work around allocating an exception with new
> right before throwing it, but that's really how things are designed to
> work, and there are serious problems with any attempt to work around
> it.  At minimum, it makes throwing exceptions to be a lot more of a
> pain then it is when using the GC [...]

I disagree. There is nothing about 'throw' that requires the use of
'new'.  A further development of the emplacement idea is to
pre-initialize a region allocator specifically for throwing exceptions,
then you can write:

throw makeException("Error occurred", ...);

where makeException is a global function that allocates the exception
using the region allocator (which is initialized at startup). The catch
block then deallocates the region and re-initializes it.  This is not
that much more painful than writing:

throw new Exception("Error occurred", ...);

This is just a quick-n-dirty example, of course. In an actual
implementation you'd templatize makeException() so that you can create
different exception types, e.g.:

throw make!UserDefinedException("...", ...);

Filename, line numbers, etc., can be easily accomodated the same way
they're currently handled in exception ctors.


> But the fact that the workarounds either require that you don't have
> unique, independent exceptions or that you know that you need to
> manually free the exception after catching it is a serious problem.
> And that's without even taking the exception chaining into account.
[...]

Using a preinitialized region allocator, we no longer have such
limitations.


T

-- 
GEEK = Gatherer of 

Re: iPhone vs Android

2016-09-14 Thread Laeeth Isharc via Digitalmars-d
On Wednesday, 14 September 2016 at 06:33:59 UTC, Shachar Shemesh 
wrote:

On 14/09/16 09:05, Walter Bright wrote:

On 9/13/2016 10:38 PM, Shachar Shemesh wrote:
But if you do want to allow it, then my original problem 
comes back.

You have to
scan the malloced memory because you are not sure where that 
memory might

contain pointers to GC managed memory.


If mallocing for types that are statically known at compile 
time, it

should be knowable if they need scanning or not.



I believe you are under the assumption that structs will not be 
GC allocated. I don't think it is a good assumption to make. 
Even if it is, however:


struct SomeStruct {
  string something;
}

Please let me know if scanning this struct for GC pointers is 
necessary or not. Also, even if this is knowable, I'm not sure 
how you are suggesting we mange it.


The only practical approach I see is that if any RC managed 
memory might contain pointers to GC managed memory, then all RC 
managed memory needs to be scanned (unless you think the 
compiler can help out with that).


Shachar


In D code that I have read where people use RC types they have 
different names making it quite clear - eg RCString.but


If you're worrying about GC presumably you have a decent size 
problem anyway (and I admire the ambition of weka in this 
respect).  So then seems to me that yes,  there is a tax in 
writing code that uses the language in a way that a minority of D 
users are using it in.   The generation after the pioneers, if 
they avoid the arrows of the prior generation, at least have a 
lot more hard work than subsequent generations.   But on the 
other hand it is a package deal, and initial costs amortise.


How would you end up with a GC allocated struct by mistake 
(presuming you think it through first) at the size you are at? 
200k lines and 30 people is a lot,  but it's also not Windows 
scale.   And if you did,  and it mattered,  wouldn't you pick it 
up quickly with GC profiling?







Re: iPhone vs Android

2016-09-14 Thread Laeeth Isharc via Digitalmars-d

On Wednesday, 14 September 2016 at 13:28:45 UTC, finalpatch wrote:

On Tuesday, 13 September 2016 at 18:24:26 UTC, deadalnix wrote:
No you don't, as how often the GC kicks in depend of the rate 
at which you produce garbage, which is going to be very low 
with an hybrid approach.


This is simply not true.

Assume in a pure GC program the GC heap can grow up to X Mb 
before a collection cycle happens, which has to scan X Mb of 
memory.


Now let's say we have a hybrid program that uses 0.5X Mb of 
RCed memory and 0.5X Mb of GC memory so the total memory 
consumption is still X Mb. When the GC heap reaches 0.5X Mb, it 
has to scan both RC and GC memory.


Could you elaborate? I thought based on both personal experience 
and the papers referred to that it's uncontroversial a GC program 
to run efficiently will need a multiple of actually used memory 
as available memory.   Thus the hybrid program should require 
less total memory than the pure GC program,  meaning at the same 
total memory consumption there is less GC pressure,  which I 
understood to be part of deadalnix  point.





Re: iPhone vs Android

2016-09-14 Thread finalpatch via Digitalmars-d

On Tuesday, 13 September 2016 at 18:24:26 UTC, deadalnix wrote:
No you don't, as how often the GC kicks in depend of the rate 
at which you produce garbage, which is going to be very low 
with an hybrid approach.


This is simply not true.

Assume in a pure GC program the GC heap can grow up to X Mb 
before a collection cycle happens, which has to scan X Mb of 
memory.


Now let's say we have a hybrid program that uses 0.5X Mb of RCed 
memory and 0.5X Mb of GC memory so the total memory consumption 
is still X Mb. When the GC heap reaches 0.5X Mb, it has to scan 
both RC and GC memory.


It's quite obvious that the time(t) it takes for program 1 to 
produce X Mb of garbage is the same as program 2 to produce 0.5X 
Mb of garbage, and after time t, both program have to scan X Mb 
of memory.  However program 2 also has to pay the cost of 
reference counting on top of that.


When you say hybrid program should trigger GC at a lower rate, 
you are actually assuming the hybrid program also has X Mb of GC 
heap, which makes total memory consumption 1.5X Mb, therefore it 
is not a fair comparison anymore.


Re: iPhone vs Android

2016-09-14 Thread Jonathan M Davis via Digitalmars-d
On Tuesday, September 13, 2016 16:13:05 H. S. Teoh via Digitalmars-d wrote:
> On Tue, Sep 13, 2016 at 03:19:54PM -0700, Jonathan M Davis via Digitalmars-d
> wrote: [...]
>
> > But none of the code that's marked @nogc can throw an exception unless
> > you're either dealing with pre-allocated exceptions (in which case,
> > they're less informative),
>
> I don't see why pre-allocated exceptions would be less informative. You
> can always modify the exception object before throwing it, after all.
> In fact, I've always wondered about the feasibility of a @nogc exception
> handling system where the exception is emplaced onto a fixed static
> buffer, so that no allocation (except at the start of the program) is
> actually necessary. Of course, chained exceptions throw(!) a monkey
> wrench into the works, but assuming we forego chained exceptions,
> wouldn't this work around the problem of being unable to allocate
> exceptions in @nogc code? (Albeit with its own limitations, obviously.
> But it would be better than being unable to use exceptions at all in
> @nogc code.)

As Walter points out, it's a problem if exceptions are ever saved (which
some code does need to do). The fact that you lose chaining as you pointed
out is also a problem. You also have problems because the file, line, and
message of the exception either aren't going to be specific to when that
exception is thrown, or you have to set them all before throwing, in which
case you have issues with if/when the exception is reused. And regardless of
all of that, the fact that string is used for the message throws a wrench in
things for @nogc, since that's going to require GC allocation unless you
cast something to string, and then you have serious problems if you need to
mutate it later, since you'll end up violating the compiler guarantees for
immutable.

>
> [...]
>
> > So, I really think that we need to find a way to make it so that
> > exceptions aren't GC allocated normally anymore - or at least have a
> > way to reasonably and easily not be GC allocated - but the problem is
> > @nogc, not the actual memory management or its cost.
>
> [...]
>
> There's nothing about the 'throw' keyword that requires GC allocation.
> It's just that `throw new Exception(...)` has become a standard
> incantation. The exception object itself can, for example, be emplaced
> onto a static buffer as I propose above.

Yes, there are ways to work around allocating an exception with new right
before throwing it, but that's really how things are designed to work, and
there are serious problems with any attempt to work around it. At minimum,
it makes throwing exceptions to be a lot more of a pain then it is when
using the GC (meaning that plenty of folks will just happily use the GC when
they wouldn't need it aside from the exception, which then renders their
code unable to be @nogc), and really, that's enough to be a serious problem.
But the fact that the workarounds either require that you don't have unique,
independent exceptions or that you know that you need to manually free the
exception after catching it is a serious problem. And that's without even
taking the exception chaining into account.

At this point, I'd say that exceptions can be used in @nogc in rare
circumstances where you're very careful about what you're doing, but in the
general case, it's really not an option. Realistically, if we want folks to
be using exceptions in @nogc in general, I think that it needs to be about
as simple as throw new Exception(message); is, and we're not even close to
that. Without that, we're likely to end up with a divide between code that
uses the GC and code that uses exceptions.

- Jonathan M Davis



Re: iPhone vs Android

2016-09-14 Thread Jacob Carlborg via Digitalmars-d

On 2016-09-13 20:40, Steven Schveighoffer wrote:


Swift doesn't support exceptions AFAIK. It supports weird error handling
that looks similar to exceptions, but is really just a standard return.

i.e. this:

do
{
   try someFunctionThatErrors(arg)
}
catch(Exception ex)
{
   // handle ex
}

really compiles like this:

var _err : Error?
someFunctionThatErrors(arg, &_err)
if(_err != nil)
{
   let ex = _err!.exception
}


Exactly and you're not supposed to catch exceptions in Objective-C. It's 
more like Errors in D.


--
/Jacob Carlborg


Re: iPhone vs Android

2016-09-14 Thread Paulo Pinto via Digitalmars-d

On Wednesday, 14 September 2016 at 07:16:04 UTC, deadalnix wrote:
On Wednesday, 14 September 2016 at 05:38:38 UTC, Shachar 
Shemesh wrote:

On 14/09/16 02:59, Walter Bright wrote:

[...]


But if you do want to allow it, then my original problem comes 
back. You have to scan the malloced memory because you are not 
sure where that memory might contain pointers to GC managed 
memory.


And the hybrid hybrid approach (i.e. - only some of the memory 
allocated by malloc is scanned) is a wasp nest of potential 
bugs and problems.


Shachar


Cool down, take a step back.

There are memory management technique that can give you good 
result in most case, but will degenerate is few others. For 
instance RC doesn't handle cycles, plays poorly with 
exceptions, and so on.


There are ways to make RC work in all these case, but it is has 
severe drawbacks. Now, if you allocate using a GC, and use RC 
on top of it, you get 99% of the garbage cleaned up as you 
expect. But it allows the RC system to just delegate to the GC 
for cases it is not good at.


That way you get very occasional collection cycles to the point 
where it is usually not a problem, and if you are smart about 
it, you can even trigger them yourself at appropriate time. If 
99% of the garbage is cleanup up by the RC mechanism, the the 
garbage accumulate at 1% the rate of what it would with a 100% 
GC system, and, consequently, you can run collection 1/100 time 
what you would with a pure GC system with the same memory 
overhead.


Now you may ask, how am I so sure that this is working great ? 
The short answer is PHP.


As extra info, it was the approach taken by Cedar at Xerox PARC 
as well.


RC for almost everything, with a local tracing GC for collecting 
cycles.


https://archive.org/details/bitsavers_xeroxparcteCedarProgrammingEnvironmentAMidtermRepo_13518000

https://archive.org/details/bitsavers_xeroxparctddingGarbageCollectionandRuntimeTypestoa_1765837


Re: iPhone vs Android

2016-09-14 Thread John Colvin via Digitalmars-d

On Tuesday, 13 September 2016 at 22:28:09 UTC, deadalnix wrote:
On Tuesday, 13 September 2016 at 22:19:54 UTC, Jonathan M Davis 
wrote:
The big problem with exceptions being allocated by the GC 
isn't really the GC but @nogc.


No the problem IS @nogc . Allocating with the GC is absolutely 
not a problem is you deallocate properly. What is a problem is 
when you leak (ie, when the ownership is transferred to the 
GC). If you don't leak, GC do not kicks in.


Can you explain a bit more here? Do you mean in practice (I.e. in 
current implementation) or in theory?


Re: iPhone vs Android

2016-09-14 Thread deadalnix via Digitalmars-d
On Wednesday, 14 September 2016 at 05:38:38 UTC, Shachar Shemesh 
wrote:

On 14/09/16 02:59, Walter Bright wrote:


Memory allocated with malloc() is unknown to the GC. This 
works fine
unless a reference to the GC memory is inserted into malloc'd 
data,
which is why there's an API to the GC to let it know about 
such things.




But if you do want to allow it, then my original problem comes 
back. You have to scan the malloced memory because you are not 
sure where that memory might contain pointers to GC managed 
memory.


And the hybrid hybrid approach (i.e. - only some of the memory 
allocated by malloc is scanned) is a wasp nest of potential 
bugs and problems.


Shachar


Cool down, take a step back.

There are memory management technique that can give you good 
result in most case, but will degenerate is few others. For 
instance RC doesn't handle cycles, plays poorly with exceptions, 
and so on.


There are ways to make RC work in all these case, but it is has 
severe drawbacks. Now, if you allocate using a GC, and use RC on 
top of it, you get 99% of the garbage cleaned up as you expect. 
But it allows the RC system to just delegate to the GC for cases 
it is not good at.


That way you get very occasional collection cycles to the point 
where it is usually not a problem, and if you are smart about it, 
you can even trigger them yourself at appropriate time. If 99% of 
the garbage is cleanup up by the RC mechanism, the the garbage 
accumulate at 1% the rate of what it would with a 100% GC system, 
and, consequently, you can run collection 1/100 time what you 
would with a pure GC system with the same memory overhead.


Now you may ask, how am I so sure that this is working great ? 
The short answer is PHP.


Re: iPhone vs Android

2016-09-14 Thread Walter Bright via Digitalmars-d

On 9/13/2016 10:38 PM, Shachar Shemesh wrote:

But if you do want to allow it, then my original problem comes back. You have to
scan the malloced memory because you are not sure where that memory might
contain pointers to GC managed memory.


If mallocing for types that are statically known at compile time, it should be 
knowable if they need scanning or not.




And the hybrid hybrid approach (i.e. - only some of the memory allocated by
malloc is scanned) is a wasp nest of potential bugs and problems.


True. Manual memory allocation is that way. Hopefully RC will be better.



Re: iPhone vs Android

2016-09-13 Thread Shachar Shemesh via Digitalmars-d

On 14/09/16 02:59, Walter Bright wrote:


Memory allocated with malloc() is unknown to the GC. This works fine
unless a reference to the GC memory is inserted into malloc'd data,
which is why there's an API to the GC to let it know about such things.



But if you do want to allow it, then my original problem comes back. You 
have to scan the malloced memory because you are not sure where that 
memory might contain pointers to GC managed memory.


And the hybrid hybrid approach (i.e. - only some of the memory allocated 
by malloc is scanned) is a wasp nest of potential bugs and problems.


Shachar


Re: iPhone vs Android

2016-09-13 Thread Walter Bright via Digitalmars-d

On 9/13/2016 6:09 PM, Andrei Alexandrescu wrote:

On 09/13/2016 05:43 PM, Walter Bright wrote:

There's currently nothing that would prevent any handler code from
saving a reference to the thrown exception. Statically allocating
them would break that.


Didn't we reach the agreement to closely investigate a reference counted
exceptions hierarchy?


Yes we did. The design of Phobos would be better and more flexible if exceptions 
didn't rely on the GC.


Re: iPhone vs Android

2016-09-13 Thread Andrei Alexandrescu via Digitalmars-d

On 09/13/2016 05:43 PM, Walter Bright wrote:

The all-or-nothing approach to using the GC is as wrong as any
programming methodology is.


That's a bit much.


There's currently nothing that would prevent any handler code from
saving a reference to the thrown exception. Statically allocating
them would break that.


Didn't we reach the agreement to closely investigate a reference counted 
exceptions hierarchy?



Andrei



Re: iPhone vs Android

2016-09-13 Thread Walter Bright via Digitalmars-d

On 9/13/2016 11:24 AM, deadalnix wrote:

No you don't, as how often the GC kicks in depend of the rate at which you
produce garbage, which is going to be very low with an hybrid approach.



Also, if you only use GC for exceptions, there isn't going to be much memory it 
needs to scan.


Re: iPhone vs Android

2016-09-13 Thread Walter Bright via Digitalmars-d

On 9/13/2016 4:59 AM, Shachar Shemesh wrote:

Here's my worries about the hybrid approach. The GC run time is proportional not
to the amount of memory you manage with the GC, but to the amount of memory that
might hold a pointer to a GC managed memory. In other words, if most of my
memory is RC managed, but some of it is GC, I pay the price of both memory
manager on most of my memory.


Memory allocated with malloc() is unknown to the GC. This works fine unless a 
reference to the GC memory is inserted into malloc'd data, which is why there's 
an API to the GC to let it know about such things.




Re: iPhone vs Android

2016-09-13 Thread Walter Bright via Digitalmars-d

On 9/13/2016 4:13 PM, H. S. Teoh via Digitalmars-d wrote:

There's nothing about the 'throw' keyword that requires GC allocation.
It's just that `throw new Exception(...)` has become a standard
incantation. The exception object itself can, for example, be emplaced
onto a static buffer as I propose above.


There's currently nothing that would prevent any handler code from saving a 
reference to the thrown exception. Statically allocating them would break that.


Re: iPhone vs Android

2016-09-13 Thread Laeeth Isharc via Digitalmars-d

On Tuesday, 13 September 2016 at 19:30:16 UTC, Marco Leise wrote:

Am Tue, 13 Sep 2016 18:16:27 +
schrieb Laeeth Isharc :

Thanks you for the clear explanation.   So if you don't have 
GC allocations within RC structures and pick one or the other,

 then the concern does not apply?


That's right. Often such structures contain collections of
things, not just plain fields. And a list or a hash map working
in a @nogc environment typically checks its contained type for
any pointers with hasIndirections!T and if so adds its storage
area to the GC scanned memory to be on the safe side.
That means every collection needs a way to exempt its contents
from GC scanning and the user needs to remember to tell it so.

A practical example of that are the EMSI containers, but other 
containers, i.e. in my own private code look similar.


https://github.com/economicmodeling/containers

  struct DynamicArray(T, Allocator = Mallocator, bool supportGC 
= shouldAddGCRange!T)a certain

  {
  ...
  }

Here, when you use a dynamic array you need to specify the type 
and allocator before you get to the point of opting out of GC 
scanning. Many will prefer concise code, go with GC scanning to 
be "better safe than sorry" or don't want to fiddle with the 
options as long as the program works. This is no complaint, I'm 
just trying to draw a picture of how people end up with more GC 
scanned memory than necessary. :)


Thanks,  Marco.

So to a certain extent it's a problem of perception and of 
cognitive load when one is coming to the language - none of the 
steps taken together is necessarily difficult,  but cumulatively 
it's a lot to take in or figure out yourself - then, as you say 
people do what's easy or manageable, and then those habits come 
to constitute ones sense of what's implied by the language and 
implementation when that's not necessarily right.


There's a great blog post to be written on getting along with and 
without the GC for fun and profit - showing how to do the things 
you discussed,comparing the amount of GC D generates with eg Java 
to make vivid and concrete just how the situation is different,  
illustrating how one can use the allocator for significant 
allocations alongside the GC for trivial ones,  illustrating how 
to pre allocate buffers,  and finally demonstrating how in 
practice to use the GC profiling instrumentation we have.


Or perhaps rather a series of blog posts.   It would be helpful 
there to get across how the situation has improved.   Because the 
topic is almost guaranteed to come up in social media discussions 
(which matter as when people Google for it that is often what 
they will find), and we live in an age where the complexity means 
people use heuristic thinking,  and you can hardly blame them 
when there is no one place to point them too (as we have for 
ranges,  slices etc).


I would write it myself if I had time and understood better not 
just garbage collection techniques,  but also how other languages 
are in practice.   But it's not something for me at this point,  
and so someone else will have to do so.   I will see when it is a 
bit quieter in a year or two if someone that works with me wants 
to do it,  but in the meantime it's a great opportunity to 
improve the messaging.


The wiki could also be a bit clearer last I looked on low-GC 
solutions.   Eg you won't easily find EMSI containers from a 
casual browse.


Walter has mentioned the value as a technology professional from 
blogging and having a personal page and I think that is right.



Laeeth


Re: iPhone vs Android

2016-09-13 Thread Lurker via Digitalmars-d
On Tuesday, 13 September 2016 at 22:19:54 UTC, Jonathan M Davis 
wrote:
So, I really think that we need to find a way to make it so 
that exceptions aren't GC allocated normally anymore - or at 
least have a way to reasonably and easily not be GC allocated - 
but the problem is @nogc, not the actual memory management or 
its cost.


- Jonathan M Davis


Introduce RefCountedException?

Also that the pattern almost always is "throw new" and *very* 
rarely it is "Exception e = new ...; throw e;". I think we might 
be able to take advantage of that (e.g. "throw new E" could be a 
special case of "new" that allocates on some sort of "Exception" 
heap that is manually managed, or recognize RefCountedException).


Re: iPhone vs Android

2016-09-13 Thread H. S. Teoh via Digitalmars-d
On Tue, Sep 13, 2016 at 03:19:54PM -0700, Jonathan M Davis via Digitalmars-d 
wrote:
[...]
> But none of the code that's marked @nogc can throw an exception unless
> you're either dealing with pre-allocated exceptions (in which case,
> they're less informative),

I don't see why pre-allocated exceptions would be less informative. You
can always modify the exception object before throwing it, after all.
In fact, I've always wondered about the feasibility of a @nogc exception
handling system where the exception is emplaced onto a fixed static
buffer, so that no allocation (except at the start of the program) is
actually necessary. Of course, chained exceptions throw(!) a monkey
wrench into the works, but assuming we forego chained exceptions,
wouldn't this work around the problem of being unable to allocate
exceptions in @nogc code? (Albeit with its own limitations, obviously.
But it would be better than being unable to use exceptions at all in
@nogc code.)


[...]
> So, I really think that we need to find a way to make it so that
> exceptions aren't GC allocated normally anymore - or at least have a
> way to reasonably and easily not be GC allocated - but the problem is
> @nogc, not the actual memory management or its cost.
[...]

There's nothing about the 'throw' keyword that requires GC allocation.
It's just that `throw new Exception(...)` has become a standard
incantation. The exception object itself can, for example, be emplaced
onto a static buffer as I propose above.


T

-- 
I think Debian's doing something wrong, `apt-get install pesticide', doesn't 
seem to remove the bugs on my system! -- Mike Dresser


Re: iPhone vs Android

2016-09-13 Thread deadalnix via Digitalmars-d
On Tuesday, 13 September 2016 at 22:19:54 UTC, Jonathan M Davis 
wrote:
The big problem with exceptions being allocated by the GC isn't 
really the GC but @nogc.


No the problem IS @nogc . Allocating with the GC is absolutely 
not a problem is you deallocate properly. What is a problem is 
when you leak (ie, when the ownership is transferred to the GC). 
If you don't leak, GC do not kicks in.




Re: iPhone vs Android

2016-09-13 Thread Jonathan M Davis via Digitalmars-d
On Tuesday, September 13, 2016 14:43:09 Walter Bright via Digitalmars-d wrote:
> Case in point, exceptions. Currently exceptions are fairly wedded to being
> GC allocated. Some people have opined that this is a major problem, and it
> is if the app is throwing a lot of exceptions. But exceptions should be
> exceptional.
>
> There is still a place for GC, even in a high performance app. The
> all-or-nothing approach to using the GC is as wrong as any programming
> methodology is.

The big problem with exceptions being allocated by the GC isn't really the
GC but @nogc. Obviously, a program that does not use the GC at all can't
allocate an exception with the GC, but in general, I would fully expect that
even a program that allows the GC but uses it minimally would have no
problem with the garbage created by exceptions precisely because they should
be rare. But none of the code that's marked @nogc can throw an exception
unless you're either dealing with pre-allocated exceptions (in which case,
they're less informative), or you are _very_ careful with how you write that
code so that you can get away with malloc-ing the exception (but that
approach won't work in the general case unless you don't care about leaking
the memory from the exception, since most code would assume that the
exception was allocated by the GC and wouldn't know how to free it). So,
@nogc code is going to have a tendency to not use exceptions just because
exceptions don't work well without the GC. And those who want to use
exceptions and are willing to have their code not be @nogc will forgo @nogc
even when the code could have been @nogc otherwise.

So, I really think that we need to find a way to make it so that exceptions
aren't GC allocated normally anymore - or at least have a way to reasonably
and easily not be GC allocated - but the problem is @nogc, not the actual
memory management or its cost.

- Jonathan M Davis



Re: iPhone vs Android

2016-09-13 Thread jmh530 via Digitalmars-d
On Tuesday, 13 September 2016 at 20:19:40 UTC, Jonathan M Davis 
wrote:


LOL. It's on my unfinished projects list, so I intend to 
complete it at some point, but unfortunately, it's been on the 
backburner for a while. Still, it's funny that you say that 
considering how many typos were in that post, since I neglected 
to reread it before sending it. :)


- Jonathan M Davis


Typos are for spellcheckers.


Re: iPhone vs Android

2016-09-13 Thread Walter Bright via Digitalmars-d

On 9/13/2016 10:44 AM, Jonathan M Davis via Digitalmars-d wrote:

Folks have posted here before about taking that approach with games and the
like that they've written. In a number cases, simply being careful about
specific pieces of code and avoiding the GC in those cases was enough to get
the required performance. In some cases, simply disabling the GC during a
critical piece of code and re-enabling it afterwards fixes the performance
problems trigged by the GC without even needing manual memory management or
RC. In others, making sure that the critical thread (e.g. the rendering
thread) was not GC-managed while letting the rest of the app us the GC
takes care of the problem.

We need reference counting to solve certain problems (e.g. cases where
deterministic destruction of stuff on the heap is required), but other stuff
(like array slices) work far better with a GC. So going either full-on RC or
full-on GC is not going to be good move for most programs. I don't think
that there's any question that we'll be best off by having both as solid
options, and best practices can develop as to when to use one or the other.


Case in point, exceptions. Currently exceptions are fairly wedded to being GC 
allocated. Some people have opined that this is a major problem, and it is if 
the app is throwing a lot of exceptions. But exceptions should be exceptional.


There is still a place for GC, even in a high performance app. The 
all-or-nothing approach to using the GC is as wrong as any programming 
methodology is.




Re: iPhone vs Android

2016-09-13 Thread Jonathan M Davis via Digitalmars-d
On Tuesday, September 13, 2016 18:50:20 jmh530 via Digitalmars-d wrote:
> On Tuesday, 13 September 2016 at 18:04:19 UTC, Jonathan M Davis
>
> wrote:
> > As I understand it, [snnip]
>
> If you ever write a book, I would pre-order it.

LOL. It's on my unfinished projects list, so I intend to complete it at some
point, but unfortunately, it's been on the backburner for a while. Still,
it's funny that you say that considering how many typos were in that post,
since I neglected to reread it before sending it. :)

- Jonathan M Davis



Re: iPhone vs Android

2016-09-13 Thread Marco Leise via Digitalmars-d
Am Tue, 13 Sep 2016 18:16:27 +
schrieb Laeeth Isharc :

> Thanks you for the clear explanation.   So if you don't have GC 
> allocations within RC structures and pick one or the other,  then 
> the concern does not apply?
 
That's right. Often such structures contain collections of
things, not just plain fields. And a list or a hash map working
in a @nogc environment typically checks its contained type for
any pointers with hasIndirections!T and if so adds its storage
area to the GC scanned memory to be on the safe side.
That means every collection needs a way to exempt its contents
from GC scanning and the user needs to remember to tell it so.

A practical example of that are the EMSI containers, but
other containers, i.e. in my own private code look similar.

https://github.com/economicmodeling/containers

  struct DynamicArray(T, Allocator = Mallocator, bool supportGC = 
shouldAddGCRange!T)
  {
  ...
  }

Here, when you use a dynamic array you need to specify the
type and allocator before you get to the point of opting out
of GC scanning. Many will prefer concise code, go with GC
scanning to be "better safe than sorry" or don't want to fiddle
with the options as long as the program works. This is no
complaint, I'm just trying to draw a picture of how people end
up with more GC scanned memory than necessary. :)

-- 
Marco



Re: iPhone vs Android

2016-09-13 Thread jmh530 via Digitalmars-d
On Tuesday, 13 September 2016 at 18:04:19 UTC, Jonathan M Davis 
wrote:


As I understand it, [snnip]


If you ever write a book, I would pre-order it.


Re: iPhone vs Android

2016-09-13 Thread Steven Schveighoffer via Digitalmars-d

On 9/13/16 2:24 PM, deadalnix wrote:

This is why ObjC exeption handling and ARC never worked well together.
This is why C++ exception are dog slow and this is why Swift is nothrow
by default.


Swift doesn't support exceptions AFAIK. It supports weird error handling 
that looks similar to exceptions, but is really just a standard return.


i.e. this:

do
{
   try someFunctionThatErrors(arg)
}
catch(Exception ex)
{
   // handle ex
}

really compiles like this:

var _err : Error?
someFunctionThatErrors(arg, &_err)
if(_err != nil)
{
   let ex = _err!.exception
}

-Steve


Re: iPhone vs Android

2016-09-13 Thread deadalnix via Digitalmars-d
On Tuesday, 13 September 2016 at 11:59:46 UTC, Shachar Shemesh 
wrote:

On 13/09/16 02:21, deadalnix wrote:


RC itself is not panacea, it doesn't work well with 
exceptions, generate

a huge amount of code bloat,


I will need explanation to those two. Assuming we have RAII, 
why doesn't RC work well with exceptions?




With RC, the runtime needs to resume every frames. That makes 
exception very slow. Plus you need to generate a bunch of 
unwinding code + LSDA infos, and it clusters like crazy when you 
have destructor that can throw.


This is why ObjC exeption handling and ARC never worked well 
together. This is why C++ exception are dog slow and this is why 
Swift is nothrow by default.



But first and foremost, it is a disaster for shared data.


Again, please elaborate.



For shared data, you need synchronized reference counting, which 
is prohibitively expensive.


Here's my worries about the hybrid approach. The GC run time is 
proportional not to the amount of memory you manage with the 
GC, but to the amount of memory that might hold a pointer to a 
GC managed memory. In other words, if most of my memory is RC 
managed, but some of it is GC, I pay the price of both memory 
manager on most of my memory.


Shachar


No you don't, as how often the GC kicks in depend of the rate at 
which you produce garbage, which is going to be very low with an 
hybrid approach.




Re: iPhone vs Android

2016-09-13 Thread Laeeth Isharc via Digitalmars-d
On Tuesday, 13 September 2016 at 18:04:19 UTC, Jonathan M Davis 
wrote:
On Tuesday, September 13, 2016 17:48:38 Laeeth Isharc via 
Digitalmars-d wrote:

On Tuesday, 13 September 2016 at 11:59:46 UTC, Shachar Shemesh

wrote:
> On 13/09/16 02:21, deadalnix wrote:
>> I stay convinced that an hybrid approach is inevitable and 
>> am

>> surprised
>> why few are going there (hello PHP, here right).
>
> Here's my worries about the hybrid approach. The GC run time 
> is proportional not to the amount of memory you manage with 
> the GC, but to the amount of memory that might hold a 
> pointer to a GC managed memory. In other words, if most of 
> my memory is RC managed, but some of it is GC, I pay the 
> price of both memory manager on most of my memory.

>
> Shachar

Hi Shachar.

I hope you're well.

Would you mind elaborating a bit on why the cost of GC managed 
memory is as high as you imply when combined with other 
approaches, at least on a 64 bit machine and presuming you 
have a degree of hygiene and don't directly use a pointer 
allowed to point to either.   Eg if you use GC for long lived 
allocations and RC for short lived ones (and the RC 
constructor makes sure the thing is not registered with the GC 
so that takes care of short lived parts of long lived 
structures),  how in practice would this be a problem  ? I am 
no GC expert,  but keen to update my mental model.


As I understand it, the problem is that the length of time that 
the GC scan takes - and therefore that the world is stopped - 
depends on how much memory it has to scan, not on how much 
memory has been allocated by the GC. In many cases, that's just 
the GC heap plus the stack, but if you're malloc-ing memory, 
and that memory can hold references to GC-allocated memory, 
then you have to tell the GC to scan that memory too in order 
to avoid having anything it references being prematurely 
collected. So, ultimately, how expensive the GC is in terms of 
performance generally depends on how much memory can hold 
referencs to GC-allocated objects and not how many such objects 
there are, meaning that avoiding allocating with the GC in a 
lot of your code doesn't necessarily save you from the 
performance cost of the GC. To avoid that cost, you'd need to 
either not have many places in malloc-ed memory which could 
refer to GC-allocated memory, or you'd need to write your code 
in a way that the it was guaranteed that the GC-allocated 
objects that were referenced in malloc-ed memory would have 
other references in memory that was scanned that lived longer 
htan the malloc-ed memory so that the malloc-ed memory wouldn't 
need to be scanned (which is quite possible in some 
circumstances but potentially risky).


Using a 64-bit system significantly reduces the risk of false
pointers, but it doesn't reduce the amount of memory that 
actually needs to be scanned. And whether using the GC for 
long-lived allocations and RC for short-lived ones would help 
would depend primarily on  how many such objects would be 
around at any one time - and of course, whether they refer to 
GC-allocated memory and would thus need to be scanned. But 
reducing the amount of memory that the GC needs to scan and 
reduce how much is GC-allocated are two separate - albeit 
related - problems.


- Jonathan M Davis


Thanks you for the clear explanation.   So if you don't have GC 
allocations within RC structures and pick one or the other,  then 
the concern does not apply?




Re: iPhone vs Android

2016-09-13 Thread Andrei Alexandrescu via Digitalmars-d

On 9/13/16 1:51 PM, deadalnix wrote:

On Tuesday, 13 September 2016 at 10:04:43 UTC, Andrei Alexandrescu wrote:

On 9/13/16 3:53 AM, Kagamin wrote:

The rule of thumb is that for efficient operation an advanced GC
consumes twice the used memory.


Do you have a citation? The number I know is 3x from Emery Berger's
(old) work. -- Andrei


I assume it is going to depend of the rate at which the application
produces garbage.


That's why Berger uses a relatively large battery of benchmark from 
multiple domains. See 
http://www-cs.canisius.edu/~hertzm/gcmalloc-oopsla-2005.pdf. -- Andrei


Re: iPhone vs Android

2016-09-13 Thread Jonathan M Davis via Digitalmars-d
On Tuesday, September 13, 2016 17:48:38 Laeeth Isharc via Digitalmars-d wrote:
> On Tuesday, 13 September 2016 at 11:59:46 UTC, Shachar Shemesh
>
> wrote:
> > On 13/09/16 02:21, deadalnix wrote:
> >> I stay convinced that an hybrid approach is inevitable and am
> >> surprised
> >> why few are going there (hello PHP, here right).
> >
> > Here's my worries about the hybrid approach. The GC run time is
> > proportional not to the amount of memory you manage with the
> > GC, but to the amount of memory that might hold a pointer to a
> > GC managed memory. In other words, if most of my memory is RC
> > managed, but some of it is GC, I pay the price of both memory
> > manager on most of my memory.
> >
> > Shachar
>
> Hi Shachar.
>
> I hope you're well.
>
> Would you mind elaborating a bit on why the cost of GC managed
> memory is as high as you imply when combined with other
> approaches, at least on a 64 bit machine and presuming you have a
> degree of hygiene and don't directly use a pointer allowed to
> point to either.   Eg if you use GC for long lived allocations
> and RC for short lived ones (and the RC constructor makes sure
> the thing is not registered with the GC so that takes care of
> short lived parts of long lived structures),  how in practice
> would this be a problem  ? I am no GC expert,  but keen to update
> my mental model.

As I understand it, the problem is that the length of time that the GC scan
takes - and therefore that the world is stopped - depends on how much memory
it has to scan, not on how much memory has been allocated by the GC. In many
cases, that's just the GC heap plus the stack, but if you're malloc-ing
memory, and that memory can hold references to GC-allocated memory, then you
have to tell the GC to scan that memory too in order to avoid having
anything it references being prematurely collected. So, ultimately, how
expensive the GC is in terms of performance generally depends on how much
memory can hold referencs to GC-allocated objects and not how many such
objects there are, meaning that avoiding allocating with the GC in a lot of
your code doesn't necessarily save you from the performance cost of the GC.
To avoid that cost, you'd need to either not have many places in malloc-ed
memory which could refer to GC-allocated memory, or you'd need to write your
code in a way that the it was guaranteed that the GC-allocated objects that
were referenced in malloc-ed memory would have other references in memory
that was scanned that lived longer htan the malloc-ed memory so that the
malloc-ed memory wouldn't need to be scanned (which is quite possible in
some circumstances but potentially risky).

Using a 64-bit system significantly reduces the risk of false pointers, but
it doesn't reduce the amount of memory that actually needs to be scanned.
And whether using the GC for long-lived allocations and RC for short-lived
ones would help would depend primarily on  how many such objects would be
around at any one time - and of course, whether they refer to GC-allocated
memory and would thus need to be scanned. But reducing the amount of memory
that the GC needs to scan and reduce how much is GC-allocated are two
separate - albeit related - problems.

- Jonathan M Davis



Re: iPhone vs Android

2016-09-13 Thread Andrei Alexandrescu via Digitalmars-d

On 9/13/16 11:58 AM, Kagamin wrote:

On Tuesday, 13 September 2016 at 10:04:43 UTC, Andrei Alexandrescu wrote:

Do you have a citation? The number I know is 3x from Emery Berger's
(old) work. -- Andrei


http://sealedabstract.com/rants/why-mobile-web-apps-are-slow/


This suggests the ratio is 4x not 2x:


What this chart says is “As long as you have about 6 times as much 
memory as you really need, you’re fine.  But woe betide you if you have 
less than 4x the required memory.”




http://www-cs.canisius.edu/~hertzm/gcmalloc-oopsla-2005.pdf
Probably these.


This is Berger's paper I was referring to. It concludes the ratio is 3x 
not 2x:



With only three times as much memory, the collector runs on average 17% 
slower than explicit memory management. However, with only twice as much 
memory, garbage collection degrades performance by nearly 70%.



So do you agree you were wrong in positing 2x as the rule of thumb?


Andrei



Re: iPhone vs Android

2016-09-13 Thread deadalnix via Digitalmars-d
On Tuesday, 13 September 2016 at 10:04:43 UTC, Andrei 
Alexandrescu wrote:

On 9/13/16 3:53 AM, Kagamin wrote:
The rule of thumb is that for efficient operation an advanced 
GC

consumes twice the used memory.


Do you have a citation? The number I know is 3x from Emery 
Berger's (old) work. -- Andrei


I assume it is going to depend of the rate at which the 
application produces garbage.




Re: iPhone vs Android

2016-09-13 Thread Laeeth Isharc via Digitalmars-d
On Tuesday, 13 September 2016 at 11:59:46 UTC, Shachar Shemesh 
wrote:

On 13/09/16 02:21, deadalnix wrote:


I stay convinced that an hybrid approach is inevitable and am 
surprised

why few are going there (hello PHP, here right).



Here's my worries about the hybrid approach. The GC run time is 
proportional not to the amount of memory you manage with the 
GC, but to the amount of memory that might hold a pointer to a 
GC managed memory. In other words, if most of my memory is RC 
managed, but some of it is GC, I pay the price of both memory 
manager on most of my memory.


Shachar


Hi Shachar.

I hope you're well.

Would you mind elaborating a bit on why the cost of GC managed 
memory is as high as you imply when combined with other 
approaches, at least on a 64 bit machine and presuming you have a 
degree of hygiene and don't directly use a pointer allowed to 
point to either.   Eg if you use GC for long lived allocations 
and RC for short lived ones (and the RC constructor makes sure 
the thing is not registered with the GC so that takes care of 
short lived parts of long lived structures),  how in practice 
would this be a problem  ? I am no GC expert,  but keen to update 
my mental model.



Laeeth



Re: iPhone vs Android

2016-09-13 Thread Jonathan M Davis via Digitalmars-d
On Tuesday, September 13, 2016 03:58:50 Walter Bright via Digitalmars-d wrote:
> On 9/12/2016 4:21 PM, deadalnix wrote:
> > I stay convinced that an hybrid approach is inevitable and am surprised
> > why few are going there (hello PHP, here is a thing you get right).
>
> Interestingly, Warp (the C preprocessor I developed in D) used a hybrid
> approach. The performance critical code was all hand-managed, while the rest
> was GC'd.

Folks have posted here before about taking that approach with games and the
like that they've written. In a number cases, simply being careful about
specific pieces of code and avoiding the GC in those cases was enough to get
the required performance. In some cases, simply disabling the GC during a
critical piece of code and re-enabling it afterwards fixes the performance
problems trigged by the GC without even needing manual memory management or
RC. In others, making sure that the critical thread (e.g. the rendering
thread) was not GC-managed while letting the rest of the app us the GC
takes care of the problem.

We need reference counting to solve certain problems (e.g. cases where
deterministic destruction of stuff on the heap is required), but other stuff
(like array slices) work far better with a GC. So going either full-on RC or
full-on GC is not going to be good move for most programs. I don't think
that there's any question that we'll be best off by having both as solid
options, and best practices can develop as to when to use one or the other.

- Jonathan M Davis



Re: iPhone vs Android

2016-09-13 Thread Kagamin via Digitalmars-d
On Tuesday, 13 September 2016 at 10:04:43 UTC, Andrei 
Alexandrescu wrote:
Do you have a citation? The number I know is 3x from Emery 
Berger's (old) work. -- Andrei


http://sealedabstract.com/rants/why-mobile-web-apps-are-slow/
http://www-cs.canisius.edu/~hertzm/gcmalloc-oopsla-2005.pdf
Probably these.


Re: iPhone vs Android

2016-09-13 Thread Kagamin via Digitalmars-d
On Tuesday, 13 September 2016 at 10:04:43 UTC, Andrei 
Alexandrescu wrote:
Do you have a citation? The number I know is 3x from Emery 
Berger's (old) work. -- Andrei


IIRC there was a thread about GC here where somebody posted a 
bunch of links to resources and benchmarks.


Re: iPhone vs Android

2016-09-13 Thread Shachar Shemesh via Digitalmars-d

On 13/09/16 02:21, deadalnix wrote:


RC itself is not panacea, it doesn't work well with exceptions, generate
a huge amount of code bloat,


I will need explanation to those two. Assuming we have RAII, why doesn't 
RC work well with exceptions?


Also, please note that explicit memory management also means we support 
the equivalent of unique_ptr, which is what most memory allocations 
actually are.



But first and foremost, it is a disaster for shared data.


Again, please elaborate.



I stay convinced that an hybrid approach is inevitable and am surprised
why few are going there (hello PHP, here is a thing you get right).



Here's my worries about the hybrid approach. The GC run time is 
proportional not to the amount of memory you manage with the GC, but to 
the amount of memory that might hold a pointer to a GC managed memory. 
In other words, if most of my memory is RC managed, but some of it is 
GC, I pay the price of both memory manager on most of my memory.


Shachar


Re: iPhone vs Android

2016-09-13 Thread Stefan Koch via Digitalmars-d
On Tuesday, 13 September 2016 at 10:58:50 UTC, Walter Bright 
wrote:


Interestingly, Warp (the C preprocessor I developed in D) used 
a hybrid approach. The performance critical code was all 
hand-managed, while the rest was GC'd.


Manual Memory management is key for performance oriented code.




Re: iPhone vs Android

2016-09-13 Thread Walter Bright via Digitalmars-d

On 9/12/2016 4:21 PM, deadalnix wrote:

I stay convinced that an hybrid approach is inevitable and am surprised why few
are going there (hello PHP, here is a thing you get right).


Interestingly, Warp (the C preprocessor I developed in D) used a hybrid 
approach. The performance critical code was all hand-managed, while the rest was 
GC'd.




Re: iPhone vs Android

2016-09-13 Thread Andrei Alexandrescu via Digitalmars-d

On 9/13/16 3:53 AM, Kagamin wrote:

The rule of thumb is that for efficient operation an advanced GC
consumes twice the used memory.


Do you have a citation? The number I know is 3x from Emery Berger's 
(old) work. -- Andrei




Re: iPhone vs Android

2016-09-13 Thread angel via Digitalmars-d
I think the conclusions about iOS vs. Android OS-level memory 
collection are not applicable to D GC discussion.
An OS collects all the memory pages allocated for a process upon 
exit - no heap scan, no RC. It more resembles a one huge free() 
call.
The discussion is mainly about eager vs. less-eager 
not-currently-running process killing strategy.

D's GC lies in a different plane ...


Re: iPhone vs Android

2016-09-13 Thread Paulo Pinto via Digitalmars-d
On Monday, 12 September 2016 at 22:57:23 UTC, Andrei Alexandrescu 
wrote:
An interesting article written for laypeople: 
http://www.theverge.com/2016/9/12/12886058/iphone-7-specs-competition


One quote that may be of relevance to us: "As to the iPhone’s 
memory, this is more of a philosophical distinction between 
Apple and Google. The former is neurotic about killing 
background processes and dumping background apps from memory in 
iOS, whereas the latter is more liberal with app management in 
Android (though Google is gradually moving toward the Apple way 
of doing things). The upshot is that an iPhone can feel super 
smooth and responsive with half the RAM of an Android device. 
RAM consumes power, so having less of it is another factor 
contributing to the iPhone’s efficiency lead."


This may be interpreted as follows: the iPhone uses native apps 
with reference counting whereas the Android uses a virtual 
machine with tracing garbage collection. It follows that the 
latter needs more memory for the same performance, and is more 
jerky in behavior than the former. Wondering to what extent 
this is true. If it is, that provides more impetus for 
reference counting for D by the following logic: (a) it is 
likely that in the future more code will run on portable, 
battery-powered systems; (b) battery power does not follow a 
Moore trajectory, so at this point in history demand for 
battery lifetime is elastic.



Andrei


Just some update on your information, the Android story is much 
more complicated than having  VM.


They had a VM up to version 5.0, afterwards Java bytecode 
(actually Dex) is compiled to native code at installation time, 
then there is just the language runtime, just like D.


Now with Android 7, due to the big compilation times, specially 
when large applications need to be updated, they have an hybrid 
design. An interpreter written in Assembly that makes use of a 
JIT for hot code, then the JIT makes use of PGO and when the 
device is plugged and charging, the hot code will be AOT compiled 
to native code and never JITed or interpreted again until a new 
update takes place.


Likewise the GC algorithm in Dalvik is pretty lame, even some 
J2ME JVMs do better than it.


However that was changed in ART, updated in Android 6.0 and 
changed again in Android 7.0.


So it is not easy just to say Android works like X, because X 
depends on the Android version and OEM build, as some of them do 
also change the AOSP runtime and compilers behaviors.


Also for additional comparison, the Windows Phone also has a mix 
of RC (WinRT now renamed as UWP) and GC (.NET Native / Chackra 
JavaScript VM), yet the devices perform much better than similar 
Android devices.


Also Microsoft does a full AOT build to native code on the WP 
Store, instead of using the consumer devices for AOT compilation 
like Google does.


So it is not that easy to generalize the OS behaviors like the 
article does.





Re: iPhone vs Android

2016-09-13 Thread Kagamin via Digitalmars-d
On Monday, 12 September 2016 at 22:57:23 UTC, Andrei Alexandrescu 
wrote:
It follows that the latter needs more memory for the same 
performance, and is more jerky in behavior than the former. 
Wondering to what extent this is true.


The rule of thumb is that for efficient operation an advanced GC 
consumes twice the used memory. Also without card marking D GC 
scans entire heap every collection, which adds to energy 
consumption. I'm leaning towards arena allocator.


Re: iPhone vs Android

2016-09-12 Thread deadalnix via Digitalmars-d

On Tuesday, 13 September 2016 at 01:04:06 UTC, Joakim wrote:

https://www.engadget.com/2016/08/19/smartphone-batteries-with-twice-the-life-may-arrive-in-2017/
https://www.engadget.com/2016/04/22/accidental-discovery-batteries-last-years-longer/



The battery industry is king to drum up various techs in very 
misleading ways. What you want is higher power density, and this 
is specifically the metric that hasn't been improving that much.




Re: iPhone vs Android

2016-09-12 Thread Joakim via Digitalmars-d
On Monday, 12 September 2016 at 22:57:23 UTC, Andrei Alexandrescu 
wrote:
(a) it is likely that in the future more code will run on 
portable, battery-powered systems;


Completely agree, it's why I've been working on the Android port.

(b) battery power does not follow a Moore trajectory, so at 
this point in history demand for battery lifetime is elastic.


Not Moore, but you never know what is around the bend:

https://www.engadget.com/2016/08/19/smartphone-batteries-with-twice-the-life-may-arrive-in-2017/
https://www.engadget.com/2016/04/22/accidental-discovery-batteries-last-years-longer/

But yes, Moore's law is hitting fundamental limits and batteries 
will never match that growth curve, so efficiency will be at a 
premium in the coming years.


Re: iPhone vs Android

2016-09-12 Thread Rikki Cattermole via Digitalmars-d

On Monday, 12 September 2016 at 23:21:12 UTC, deadalnix wrote:
RC itself is not panacea, it doesn't work well with exceptions, 
generate a huge amount of code bloat, hurt throughput, which 
you don't care in UI thread, but do care in the backend, and so 
on. But first and foremost, it is a disaster for shared data.


I stay convinced that an hybrid approach is inevitable and am 
surprised why few are going there (hello PHP, here is a thing 
you get right).


I quite agree with the hybrid approach.
My rule of thumb is if it is short lived its "managed" but if it 
can last a long time use the GC.


Ok so my managed memory concept auto deallocates as any ref 
counting solution should do. So for short lived memory, this is 
perfect since it isn't being moved around much and you can afford 
it.
But for long lived references such as a window you really want 
the default to be that you specifically tell it to deallocate at 
a set point in time you know it should.


For reference, SPEW's UI creation manager[0] and screenshot 
feature[1].


[0] 
https://github.com/Devisualization/spew/blob/master/src/base/cf/spew/instance.d#L72
[1]  
https://github.com/Devisualization/spew/blob/master/src/base/cf/spew/ui/window/features/screenshot.d#L26


Re: iPhone vs Android

2016-09-12 Thread deadalnix via Digitalmars-d
On Monday, 12 September 2016 at 22:57:23 UTC, Andrei Alexandrescu 
wrote:
This may be interpreted as follows: the iPhone uses native apps 
with reference counting


I think the native part is fair, but the RC part maybe not. I 
know first hand that they have a fair amount of problem on the 
side.


whereas the Android uses a virtual machine with tracing garbage 
collection.


Dalvik's GC is truly horrible and Java is addicted to memory 
allocations, which makes it worse. A match made in hell.


It follows that the latter needs more memory for the same 
performance,

and is more jerky in behavior than the former.


Putting a stop the world GC in a UI program is the worst idea 
ever. Doing this java is giving steroïd to the worse idea ever. I 
have no idea what Google was thnking here.


Wondering to what extent this is true. If it is, that provides 
more impetus for reference counting for D by the following 
logic: (a) it is likely that in the future more code will run 
on portable, battery-powered systems; (b) battery power does 
not follow a Moore trajectory, so at this point in history 
demand for battery lifetime is elastic.




RC itself is not panacea, it doesn't work well with exceptions, 
generate a huge amount of code bloat, hurt throughput, which you 
don't care in UI thread, but do care in the backend, and so on. 
But first and foremost, it is a disaster for shared data.


I stay convinced that an hybrid approach is inevitable and am 
surprised why few are going there (hello PHP, here is a thing you 
get right).




Re: iPhone vs Android

2016-09-12 Thread Rikki Cattermole via Digitalmars-d
On Monday, 12 September 2016 at 22:57:23 UTC, Andrei Alexandrescu 
wrote:
An interesting article written for laypeople: 
http://www.theverge.com/2016/9/12/12886058/iphone-7-specs-competition


One quote that may be of relevance to us: "As to the iPhone’s 
memory, this is more of a philosophical distinction between 
Apple and Google. The former is neurotic about killing 
background processes and dumping background apps from memory in 
iOS, whereas the latter is more liberal with app management in 
Android (though Google is gradually moving toward the Apple way 
of doing things). The upshot is that an iPhone can feel super 
smooth and responsive with half the RAM of an Android device. 
RAM consumes power, so having less of it is another factor 
contributing to the iPhone’s efficiency lead."


This may be interpreted as follows: the iPhone uses native apps 
with reference counting whereas the Android uses a virtual 
machine with tracing garbage collection. It follows that the 
latter needs more memory for the same performance, and is more 
jerky in behavior than the former. Wondering to what extent 
this is true. If it is, that provides more impetus for 
reference counting for D by the following logic: (a) it is 
likely that in the future more code will run on portable, 
battery-powered systems; (b) battery power does not follow a 
Moore trajectory, so at this point in history demand for 
battery lifetime is elastic.



Andrei


I would interpret it quite differently to this.
On iOS applications that are not currently in the foreground or 
are a service get killed unconditionally.
On Android applications keep running even when they are no longer 
foreground but instead get 'paused'. Here is a handy little graph 
of the different events an Android app can be in[0]. Note the 
difference between onPause and onStop.


[0] 
https://developer.android.com/reference/android/app/Activity.html#ActivityLifecycle