Re: Sending Tid in a struct

2018-09-28 Thread Chris Katko via Digitalmars-d-learn
On Wednesday, 23 November 2016 at 08:47:56 UTC, Christian Köstlin 
wrote:

On 03/03/2012 18:35, Timon Gehr wrote:

On 03/03/2012 12:09 PM, Nicolas Silva wrote:

[...]


Yes, this seems to be a bug.

Workaround:

struct Foo{
string s;
Tid id;
}

void foo(){
Foo foo;
receive((Tuple!(string,"s",Tid,"id") 
bar){foo=Foo(bar.s,bar.id);});

}

void main(){
auto id = spawn();
id.send("string",id);
...
}
I had a similar problem with this an it seems this is still a 
bug with dmd 2.072.


best regards,
christian


So this appears to still be a bug in 2.078.0-beta.1. Sigh...

So the only way to actually use concurrency in D... is to use 
this hack? Or has it been fixed since January? Is there an 
official bug report?


Re: Weird compilation error only as static library

2018-09-28 Thread Márcio Martins via Digitalmars-d-learn
On Friday, 28 September 2018 at 15:24:03 UTC, Andrea Fontana 
wrote:
On Wednesday, 26 September 2018 at 19:08:45 UTC, Márcio Martins 
wrote:

Hi!

I am getting this error when compiling my code as a static 
library.
It works fine as an executable. I have no idea what's 
happening.
Has someone seen something like this before? What could be 
different?


This is the error:
/usr/include/dmd/druntime/import/core/stdc/stdint.d(159,26): 
Error: undefined identifier cpp_ulong

/usr/include/dmd/druntime/import/core/sys/posix/sys/types.d(109,11): Error: 
undefined identifier c_long
../../../.dub/packages/libuv-1.20.3/libuv/deimos/libuv/uv.d(367,2): Error: 
mixin `deimos.libuv.uv.uv_stream_s.UV_STREAM_FIELDS!()` error instantiating

It's a small library with libuv as the only dependency. It 
works fine compiling it's own example, but fails when I 
compile it as a dub dependency.


What are you importing on top of your code?

Andrea


Basically my static library imports deimos.libuv, and my program 
imports my static library.
I think it must be some issue with deimos.libuv, but I can't 
figure out what, and it's also weird the static library 
compilation is different than the executable, other than linking. 
I think I will look for new libuv bindings or create my own.


Re: Can I create static c callable library?

2018-09-28 Thread H. S. Teoh via Digitalmars-d-learn
On Fri, Sep 28, 2018 at 02:08:25PM +, Atila Neves via Digitalmars-d-learn 
wrote:
> On Thursday, 27 September 2018 at 23:53:50 UTC, Steven Schveighoffer wrote:
[...]
> > Since C initialization functions have no order to them, it's
> > possible that some  initialization functions in the D runtime are
> > using uninitialized pieces of the C runtime
> 
> No, that can't happen. The C runtime is initialised no matter what you
> do (unless you write `_start` yourself), _then_ the global
> constructors are run. The code I wrote isn't standard C - it's just
> that gcc/clang/cl are all also C++ compilers so they chose to extend
> the already existing functionality to C.
[...]

Potentially some C libraries have not yet been initialized, though.  I
don't know if the druntime init depends on any of them -- it's doubtful,
but if it does, it may cause problems depending on which order library
ctors are called.


T

-- 
In a world without fences, who needs Windows and Gates? -- Christian Surchi


Re: Weird compilation error only as static library

2018-09-28 Thread Andrea Fontana via Digitalmars-d-learn
On Wednesday, 26 September 2018 at 19:08:45 UTC, Márcio Martins 
wrote:

Hi!

I am getting this error when compiling my code as a static 
library.

It works fine as an executable. I have no idea what's happening.
Has someone seen something like this before? What could be 
different?


This is the error:
/usr/include/dmd/druntime/import/core/stdc/stdint.d(159,26): 
Error: undefined identifier cpp_ulong

/usr/include/dmd/druntime/import/core/sys/posix/sys/types.d(109,11): Error: 
undefined identifier c_long
../../../.dub/packages/libuv-1.20.3/libuv/deimos/libuv/uv.d(367,2): Error: 
mixin `deimos.libuv.uv.uv_stream_s.UV_STREAM_FIELDS!()` error instantiating

It's a small library with libuv as the only dependency. It 
works fine compiling it's own example, but fails when I compile 
it as a dub dependency.


What are you importing on top of your code?

Andrea


Re: Can I create static c callable library?

2018-09-28 Thread Atila Neves via Digitalmars-d-learn
On Thursday, 27 September 2018 at 23:53:50 UTC, Steven 
Schveighoffer wrote:

On 9/27/18 8:16 AM, Atila Neves wrote:
On Tuesday, 25 September 2018 at 14:13:50 UTC, Jacob Carlborg 
wrote:
On Tuesday, 25 September 2018 at 12:05:21 UTC, Jonathan M 
Davis wrote:


If you use -betterC, then it's trivial, because your D 
program is restricted to extern(C) functions and features 
which don't require druntime. It can also be done without 
-betterC (and thus with druntime), but it gets to be _way_ 
more of a pain, because it requires that you manually 
initialize druntime - either by forcing whatever is using 
your "C" library to call a specific function to initialize 
druntime before using any of its normal functions or by 
having every function in the library check whether druntime 
has been initialized yet and initialize it if it hasn't been 
before it does whatever it's supposed to do.


Shouldn't it be possible to use a C initialization function, 
i.e. pragma(crt_constructor) to initialize druntime? Then it 
only needs to be initialized once and it's not required to 
check if it's initialized all the time.


--
/Jacob Carlborg


Even easier, compile this C file and add the resulting object 
file to your (now mostly) D static library:


---
extern int rt_init(void);
extern int rt_term(void);

__attribute__((__constructor__)) void dinit(void) {
     rt_init();
}
__attribute__((__destructor__)) void dterm(void) {
     rt_term();
}
---

The C runtime will initialise the D runtime for you.



I will point out that this is EXACTLY what 
pragma(crt_constructor) does.


Really? Huh. You live, you learn. I didn't even know that pragma 
existed - it's not listed here at all:


https://dlang.org/spec/pragma.html



And my comments still aren't answered -- I'm not sure whether 
this works correctly or not, as we don't test initializing 
druntime before C main runs.


It's worked for me in practice.

Since C initialization functions have no order to them, it's 
possible that some  initialization functions in the D runtime 
are using uninitialized pieces of the C runtime


No, that can't happen. The C runtime is initialised no matter 
what you do (unless you write `_start` yourself), _then_ the 
global constructors are run. The code I wrote isn't standard C - 
it's just that gcc/clang/cl are all also C++ compilers so they 
chose to extend the already existing functionality to C.






Re: Performance of GC.collect() for single block of `byte`s

2018-09-28 Thread Per Nordlöw via Digitalmars-d-learn
On Monday, 24 September 2018 at 14:31:45 UTC, Steven 
Schveighoffer wrote:

It's not scanning the blocks. But it is scanning the stack.

Each time you are increasing the space it must search for a 
given *target*. It also must *collect* any previous items at 
the end of the scan. Note that a collection is going to mark 
every single page and bitset that is contained in the item 
being collected (which gets increasingly larger).


Is this because of the potentially (many) slices referencing this 
large block?


I assume the GC doesn't scan the `byte`-array for pointer-values 
in this case, but that happens for `void`-arrays and 
class/pointer-arrays right?


Couldn't that scan be optimized by adding a bitset that indicates 
which pages need to be scanned?


Is it common for GC's to treat large objects in this way?


Re: vibe.d error

2018-09-28 Thread Sebastiaan Koppe via Digitalmars-d-learn
On Thursday, 27 September 2018 at 17:37:43 UTC, hridyansh thakur 
wrote:

[snip]


What version of dmd do you use?


Re: Performance of GC.collect() for single block of `byte`s

2018-09-28 Thread Per Nordlöw via Digitalmars-d-learn
On Monday, 24 September 2018 at 14:31:45 UTC, Steven 
Schveighoffer wrote:
ever growing task. And really, this isn't that much (at the 
end, you are still less than 1ms).


Compared to GCs like Go's this is an enormous latency for a 
single allocation of value elements.


Re: Performance of GC.collect() for single block of `byte`s

2018-09-28 Thread Per Nordlöw via Digitalmars-d-learn

On Friday, 28 September 2018 at 09:14:18 UTC, Per Nordlöw wrote:
How is it possible for the GC to be 500-1000 times slower than 
a malloc-free call for a single array containing just bytes 
with no indirections for such a simple function!!!?


I really don't understand this...


I change the code to not make use of the GC when printing:

import core.stdc.stdio: printf;

void* mallocAndFreeBytes(size_t byteCount)()
{
import core.memory : pureMalloc, pureFree;
void* ptr = pureMalloc(byteCount);
pureFree(ptr);
return ptr; // for side-effects
}

void main(string[] args)
{
import std.datetime.stopwatch : benchmark;
import core.time : Duration;

immutable benchmarkCount = 1;

// GC
static foreach (const size_t i; 0 .. 32)
{
{
enum byteCount = 2UL^^i;
const Duration[1] resultsC = 
benchmark!(mallocAndFreeBytes!(i))(benchmarkCount);

printf("%ld bytes: mallocAndFreeBytes: %ld nsecs",
   byteCount, 
cast(size_t)(cast(double)resultsC[0].total!"nsecs"/benchmarkCount));


import core.memory : GC;
auto dArray = new byte[byteCount]; // one Gig
const Duration[1] resultsD = 
benchmark!(GC.collect)(benchmarkCount);

printf("  GC.collect(): %ld nsecs after %p\n",
   
cast(size_t)(cast(double)resultsD[0].total!"nsecs"/benchmarkCount), dArray.ptr);

dArray = null;
}
}
}

I still get terrible numbers:

1 bytes: mallocAndFreeBytes: 600 nsecs  GC.collect(): 29600 nsecs 
after 0x7fbab535b000
2 bytes: mallocAndFreeBytes: 500 nsecs  GC.collect(): 28600 nsecs 
after 0x7fbab535b010
4 bytes: mallocAndFreeBytes: 400 nsecs  GC.collect(): 27700 nsecs 
after 0x7fbab535b000
8 bytes: mallocAndFreeBytes: 400 nsecs  GC.collect(): 27600 nsecs 
after 0x7fbab535b010
16 bytes: mallocAndFreeBytes: 300 nsecs  GC.collect(): 32100 
nsecs after 0x7fbab535c000
32 bytes: mallocAndFreeBytes: 400 nsecs  GC.collect(): 27100 
nsecs after 0x7fbab535b000
64 bytes: mallocAndFreeBytes: 300 nsecs  GC.collect(): 48500 
nsecs after 0x7fbab535c000
128 bytes: mallocAndFreeBytes: 400 nsecs  GC.collect(): 23300 
nsecs after 0x7fbab535b000
256 bytes: mallocAndFreeBytes: 300 nsecs  GC.collect(): 22300 
nsecs after 0x7fbab535c000
512 bytes: mallocAndFreeBytes: 400 nsecs  GC.collect(): 21800 
nsecs after 0x7fbab535b000
1024 bytes: mallocAndFreeBytes: 300 nsecs  GC.collect(): 21900 
nsecs after 0x7fbab535c000
2048 bytes: mallocAndFreeBytes: 300 nsecs  GC.collect(): 26300 
nsecs after 0x7fbab3ebe010
4096 bytes: mallocAndFreeBytes: 300 nsecs  GC.collect(): 25100 
nsecs after 0x7fbab3ebf010
8192 bytes: mallocAndFreeBytes: 300 nsecs  GC.collect(): 24500 
nsecs after 0x7fbab3ec1010
16384 bytes: mallocAndFreeBytes: 400 nsecs  GC.collect(): 24700 
nsecs after 0x7fbab3ec4010
32768 bytes: mallocAndFreeBytes: 300 nsecs  GC.collect(): 24600 
nsecs after 0x7fbab3ec9010
65536 bytes: mallocAndFreeBytes: 300 nsecs  GC.collect(): 24600 
nsecs after 0x7fbab3ed2010
131072 bytes: mallocAndFreeBytes: 300 nsecs  GC.collect(): 25000 
nsecs after 0x7fbab3ee3010
262144 bytes: mallocAndFreeBytes: 300 nsecs  GC.collect(): 25000 
nsecs after 0x7fbab3f04010
524288 bytes: mallocAndFreeBytes: 400 nsecs  GC.collect(): 25200 
nsecs after 0x7fbab3f45010
1048576 bytes: mallocAndFreeBytes: 300 nsecs  GC.collect(): 25800 
nsecs after 0x7fbab3fc6010
2097152 bytes: mallocAndFreeBytes: 300 nsecs  GC.collect(): 17200 
nsecs after 0x7fbab37be010
4194304 bytes: mallocAndFreeBytes: 500 nsecs  GC.collect(): 25700 
nsecs after 0x7fbab39bf010
8388608 bytes: mallocAndFreeBytes: 400 nsecs  GC.collect(): 65500 
nsecs after 0x7fbab2bbd010
16777216 bytes: mallocAndFreeBytes: 1100 nsecs  GC.collect(): 
47200 nsecs after 0x7fbab13bc010
33554432 bytes: mallocAndFreeBytes: 800 nsecs  GC.collect(): 
50300 nsecs after 0x7fbaae3bb010
67108864 bytes: mallocAndFreeBytes: 800 nsecs  GC.collect(): 
63800 nsecs after 0x7fbaa83ba010
134217728 bytes: mallocAndFreeBytes: 600 nsecs  GC.collect(): 
10 nsecs after 0x7fba9c3b9010
268435456 bytes: mallocAndFreeBytes: 1000 nsecs  GC.collect(): 
176100 nsecs after 0x7fba843b8010
536870912 bytes: mallocAndFreeBytes: 1000 nsecs  GC.collect(): 
415500 nsecs after 0x7fba543b7010
1073741824 bytes: mallocAndFreeBytes: 800 nsecs  GC.collect(): 
649900 nsecs after 0x7fb9f42f5010
2147483648 bytes: mallocAndFreeBytes: 1200 nsecs  GC.collect(): 
973800 nsecs after 0x7fb934112010


It seems to scale kind linearly with byteCount above 16Mb... So 
it seems like its scanning the allocated block of bytes even 
though the element type of array is a value type. Why?


If I zero the pointer just after allocation I get a GC.collect() 
taking constantly 100ns so it can't be related to the stack.


Re: Performance of GC.collect() for single block of `byte`s

2018-09-28 Thread Per Nordlöw via Digitalmars-d-learn
On Monday, 24 September 2018 at 14:31:45 UTC, Steven 
Schveighoffer wrote:
Why is the overhead so big for a single allocation of an array 
with elements containing no indirections (which the GC doesn't 
need to scan for pointers).


It's not scanning the blocks. But it is scanning the stack.


Ok, I modified the code to be

import std.stdio;

void* mallocAndFreeBytes(size_t byteCount)()
{
import core.memory : pureMalloc, pureFree;
void* ptr = pureMalloc(byteCount);
pureFree(ptr);
return ptr; // for side-effects
}

void main(string[] args)
{
import std.datetime.stopwatch : benchmark;
import core.time : Duration;

immutable benchmarkCount = 1;

// GC
static foreach (const i; 0 .. 31)
{
{
enum byteCount = 2^^i;
const Duration[1] resultsC = 
benchmark!(mallocAndFreeBytes!(i))(benchmarkCount);

writef("%s bytes: mallocAndFreeBytes: %s nsecs",
   byteCount, 
cast(double)resultsC[0].total!"nsecs"/benchmarkCount);


import core.memory : GC;
auto dArray = new byte[byteCount]; // one Gig
const Duration[1] resultsD = 
benchmark!(GC.collect)(benchmarkCount);

writefln(" GC.collect(): %s nsecs after %s",
 
cast(double)resultsD[0].total!"nsecs"/benchmarkCount, dArray.ptr);

dArray = null;
}
}
}

I still be believe these numbers are absolutely horrible

1 bytes: mallocAndFreeBytes: 400 nsecs GC.collect(): 21600 nsecs 
after 7F1ECC0B1000
2 bytes: mallocAndFreeBytes: 300 nsecs GC.collect(): 20800 nsecs 
after 7F1ECC0B1010
4 bytes: mallocAndFreeBytes: 200 nsecs GC.collect(): 20500 nsecs 
after 7F1ECC0B1000
8 bytes: mallocAndFreeBytes: 200 nsecs GC.collect(): 20300 nsecs 
after 7F1ECC0B1010
16 bytes: mallocAndFreeBytes: 200 nsecs GC.collect(): 23200 nsecs 
after 7F1ECC0B2000
32 bytes: mallocAndFreeBytes: 200 nsecs GC.collect(): 19600 nsecs 
after 7F1ECC0B1000
64 bytes: mallocAndFreeBytes: 200 nsecs GC.collect(): 17800 nsecs 
after 7F1ECC0B2000
128 bytes: mallocAndFreeBytes: 300 nsecs GC.collect(): 16600 
nsecs after 7F1ECC0B1000
256 bytes: mallocAndFreeBytes: 200 nsecs GC.collect(): 16200 
nsecs after 7F1ECC0B2000
512 bytes: mallocAndFreeBytes: 300 nsecs GC.collect(): 15900 
nsecs after 7F1ECC0B1000
1024 bytes: mallocAndFreeBytes: 200 nsecs GC.collect(): 15700 
nsecs after 7F1ECC0B2000
2048 bytes: mallocAndFreeBytes: 200 nsecs GC.collect(): 14600 
nsecs after 7F1ECC0B1010
4096 bytes: mallocAndFreeBytes: 300 nsecs GC.collect(): 14400 
nsecs after 7F1ECC0B2010
8192 bytes: mallocAndFreeBytes: 200 nsecs GC.collect(): 14200 
nsecs after 7F1ECC0B4010
16384 bytes: mallocAndFreeBytes: 200 nsecs GC.collect(): 14100 
nsecs after 7F1ECC0B7010
32768 bytes: mallocAndFreeBytes: 200 nsecs GC.collect(): 14200 
nsecs after 7F1ECC0BC010
65536 bytes: mallocAndFreeBytes: 200 nsecs GC.collect(): 14200 
nsecs after 7F1ECC0C5010
131072 bytes: mallocAndFreeBytes: 200 nsecs GC.collect(): 14200 
nsecs after 7F1ECC0D6010
262144 bytes: mallocAndFreeBytes: 200 nsecs GC.collect(): 14200 
nsecs after 7F1ECC0F7010
524288 bytes: mallocAndFreeBytes: 300 nsecs GC.collect(): 17500 
nsecs after 7F1ECAC14010
1048576 bytes: mallocAndFreeBytes: 200 nsecs GC.collect(): 18000 
nsecs after 7F1ECAC95010
2097152 bytes: mallocAndFreeBytes: 500 nsecs GC.collect(): 18700 
nsecs after 7F1ECAD96010
4194304 bytes: mallocAndFreeBytes: 300 nsecs GC.collect(): 2 
nsecs after 7F1ECA514010
8388608 bytes: mallocAndFreeBytes: 400 nsecs GC.collect(): 61000 
nsecs after 7F1EC9913010
16777216 bytes: mallocAndFreeBytes: 24900 nsecs GC.collect(): 
27100 nsecs after 7F1EC8112010
33554432 bytes: mallocAndFreeBytes: 800 nsecs GC.collect(): 36600 
nsecs after 7F1EC5111010
67108864 bytes: mallocAndFreeBytes: 600 nsecs GC.collect(): 57900 
nsecs after 7F1EBF110010
134217728 bytes: mallocAndFreeBytes: 500 nsecs GC.collect(): 
98300 nsecs after 7F1EB310F010
268435456 bytes: mallocAndFreeBytes: 700 nsecs GC.collect(): 
175700 nsecs after 7F1E9B10E010
536870912 bytes: mallocAndFreeBytes: 600 nsecs GC.collect(): 
326900 nsecs after 7F1E6B10D010
1073741824 bytes: mallocAndFreeBytes: 900 nsecs GC.collect(): 
641500 nsecs after 7F1E0B04B010


How is it possible for the GC to be 500-1000 times slower than a 
malloc-free call for a single array containing just bytes with no 
indirections for such a simple function!!!?


I really don't understand this...