Re: Linking against clang produced libs on OSX

2013-02-02 Thread Hagen

Hi

Thank you for your help.
I wrapped some functions of Qt.
After updating to Qt5.0.1 it suddenly worked.

The lib is c++. Its probably a bit simple. but good to know that 
there is no problem with clang and dmd interop so far.


thx




Re: get random char from array

2013-02-02 Thread bearophile

SaltySugar:


My code:


In Phobos there isn't something like random.choice() of Python. 
This code doesn't work with truly Unicode strings (better to use 
a dstring or dchar[] for that, unless you want to walk the string 
every time you want to extract a random item):



import std.stdio, std.random;

void main() {
immutable array = "abcdef";
immutable rndChar = array[uniform(0, $)];
writeln(rndChar);
}


Bye,
bearophile


Re: get random char from array

2013-02-02 Thread SaltySugar

On Saturday, 2 February 2013 at 09:59:07 UTC, bearophile wrote:

SaltySugar:


My code:


In Phobos there isn't something like random.choice() of Python. 
This code doesn't work with truly Unicode strings (better to 
use a dstring or dchar[] for that, unless you want to walk the 
string every time you want to extract a random item):



import std.stdio, std.random;

void main() {
immutable array = "abcdef";
immutable rndChar = array[uniform(0, $)];
writeln(rndChar);
}


Bye,
bearophile


Thank you!


is there a way to define a pure base class that forces pureness of derived classes?

2013-02-02 Thread dennis luehring

i've got something like an streaming/converter system
and parts of the specialised converters are stateless other statefull

is there any way to force pureness/stateless-ness through the base
class or an interface in D?


Re: Why are commands executing out of order?

2013-02-02 Thread FG

On 2013-02-02 07:49, Josh wrote:

But main's first writeln actually outputs after f.close().


Maybe because of output buffering and you need to add flush?


The program uses ~1GB of RAM overall, even though main.results is ~50MB
according to memSize.


Wrong comparison. You should have compared to the output file's size.
info.sizeof doesn't include the size of info.name.
In my test results were 30 MB but the output file was 101 MB.


Any attempts to call the GC do nothing, but I'm probably
doing it wrong though. Is it possible that I have a memory leak somewhere that
is causing this delay, or is this a DMD problem, or something else I haven't
even thought of?


It's a problem with array concatenation and memory fragmentation.
There are two ways out of this mess. First, there's the "Unix Way" - don't use 
the results array at all and print out info records immediately as they appear. 
Your program will use under 3 MB of RAM. :)


But if you really have to do some extra processing of results, then you can 
reduce the memory used like 6 times by using an Appender instead of 
concatenating arrays and by reserving a reasonable number of records, to limit 
possible initial fragmentation when the array is resized. My program used 145 MB 
whereas the output file was 101 MB. I think it's good enough. But that's 
scanning just one, non-system drive. Won't even try to scan them all.


Try it out:

import std.datetime;
import std.file;
import std.stdio;
import std.array;

struct info
{
string name;
bool isDir;
ulong size;
SysTime timeCreated;
SysTime timeLastAccessed;
SysTime timeLastModified;

this(DirEntry d)
{
this.name = d.name;
this.isDir = d.isDir;
this.size = d.size;
this.timeCreated = d.timeCreated;
this.timeLastAccessed = d.timeLastAccessed;
this.timeLastModified = d.timeLastModified;
}
}

alias Appender!(info[]) InfoAppender;

void main()
{
writeln("Scanning drives...");
info[] results;
InfoAppender app = appender(results);
app.reserve(512*1024);  //
for (char c = 'D'; c <= 'D'; c++)
{
if (exists(c ~ ":\\"))
{
app.put(info(DirEntry(c ~ ":\\")));
scan(c ~ ":\\", app);
}
}
File f = File("driveInfo.txt", "w");
foreach (i; app.data)
{
f.writeln(i);
}
f.close();
writeln(memSize(app.data));
}

void scan(string dir, ref InfoAppender app)
{
try
{
auto de = dirEntries(dir, SpanMode.shallow);
foreach (d; de)
{
app.put(info(d));
if (d.isDir())
scan(d.name, app);
}
}
catch (FileException fe){}
}

size_t memSize(T)(T[] t)
{
return t.length * T.sizeof;
}




And the preferred version to scan whole filesystem without wasting RAM:  :)


import std.datetime;
import std.file;
import std.stdio;

struct info
{
string name;
bool isDir;
ulong size;
SysTime timeCreated;
SysTime timeLastAccessed;
SysTime timeLastModified;

this(DirEntry d)
{
this.name = d.name;
this.isDir = d.isDir;
this.size = d.size;
this.timeCreated = d.timeCreated;
this.timeLastAccessed = d.timeLastAccessed;
this.timeLastModified = d.timeLastModified;
}
}

File f;

void main()
{
writeln("Scanning drives...");
f = File("driveInfo.txt", "w");
for (char c = 'D'; c <= 'D'; c++)
{
if (exists(c ~ ":\\"))
{
f.writeln(info(DirEntry(c ~ ":\\")));
scan(c ~ ":\\");
}
}
f.close();
}

void scan(string dir)
{
try
{
auto de = dirEntries(dir, SpanMode.shallow);
foreach (d; de)
{
f.writeln(info(d));
if (d.isDir())
scan(d.name);
}
}
catch (FileException fe){}
}




Re: Why are commands executing out of order?

2013-02-02 Thread Namespace
I'm was quite surprised as I had heard the first time of these 
'appender'.

Therefore I'm asking me:
Why is the 'appender' method so much more efficient?


std.process.system and friends

2013-02-02 Thread Gor Gyolchanyan

Good day,

I'm trying to write a script in D for building D projects. I want 
to set the environment variable LIB for optlink to be able to 
pick up library files from where I put them after compiling 
dependencies.


The problem is, that the std.process.setenv is only available 
under Linux and std.process.system("set LIB=target") does not do 
anything. I guess std.process.system creates a separate process 
every time, sets the local environment variable and exists, 
erasing the local environment variable.
I tried supplying multiple commands at once by specifying a 
multi-line argument to std.process.system, but it didn't work at 
all.


How can I set my local envoronment variables so that further 
calls to std.process.system can pick  it up?


Regards,
Gor Gyolchanyan.


sc.ini

2013-02-02 Thread Gor Gyolchanyan

Good day,

I remember hearing something about separating 32-bit and 64-bit 
environment configuration in sc.ini, but I don't seem to see any 
changes. I really don't get why is sc.ini so messed up and not 
working? Is it so very hard to make a configuration file? I can't 
get 64-bit version to work. My MSVC linker doesn't get called.


Regards,
Gor Gyolchanyan.


Re: Why are commands executing out of order?

2013-02-02 Thread Era Scarecrow

On Saturday, 2 February 2013 at 11:33:07 UTC, Namespace wrote:
I'm was quite surprised as I had heard the first time of these 
'appender'.

Therefore I'm asking me:
Why is the 'appender' method so much more efficient?


 Because concatenation likely will end up relocating the memory 
over and over again (possibly lots of abandoned slices too) 
whereas the appender will allocated & reuse the same buffer. On 
the other hand you might be better off (depending on the need) 
with just reserving a lot more memory (close to what you need or 
slightly larger) and then concatenation will perform much better. 
But if it need to reallocate then you've still got the same 
problem with slices where with the appender you probably won't.


 I tend to reserve string concatenation for assert messages, and 
quicker & dirty text manipulation/building like during ctfe. 
Outside of those I use alternatives first.


Re: Get TypeNames of Variadic Templates

2013-02-02 Thread Philippe Sigaud
On Fri, Feb 1, 2013 at 11:04 PM, Christian Köstlin
 wrote:
> Hi Philippe,
>
> wonderful solution. I also added
> T get(T)() {
>   return components[staticIndexOf!(T, Children)];
> }
> to the class to get the Children out by type (works as long as there is only
> one child of each type in the tuple).

Indeed, that's easier for the user this way.
In that case, you might want to either return a tuple of one or more
type (when there is more than one of a given type) or put a
restriction on Components so it's only a set of types.

Maybe with:

... if(NoDuplicates!(Children).length == Children.length)

See http://dlang.org/phobos/std_typetuple.html#.NoDuplicates


Then, when you're feeling masochistic, the next step is to allow
assignments from other Components with a permutation of children,
because Component!(int,double) is not much different from
Components!(double, int)

:)


Re: sc.ini

2013-02-02 Thread Michael

Hi,
diff versions of Visual Studio may have diff installation path.

So here mine in proper order:

VCINSTALLDIR=C:\Program Files (x86)\Microsoft Visual Studio 
11.0\VC\


LINKCMD64=%VCINSTALLDIR%\bin\x86_amd64\link.exe

WindowsSdkDir=C:\Program Files (x86)\Microsoft SDKs\Windows\v7.1A\


P.S.: I use: Win 8 Pro 64 bit, AMD Cpu, Visual Studio 2012 
Express for Desktop.


Re: std.process.system and friends

2013-02-02 Thread Rainer Schuetze



On 02.02.2013 12:41, Gor Gyolchanyan wrote:

Good day,

I'm trying to write a script in D for building D projects. I want to set
the environment variable LIB for optlink to be able to pick up library
files from where I put them after compiling dependencies.

The problem is, that the std.process.setenv is only available under
Linux and std.process.system("set LIB=target") does not do anything. I
guess std.process.system creates a separate process every time, sets the
local environment variable and exists, erasing the local environment
variable.
I tried supplying multiple commands at once by specifying a multi-line
argument to std.process.system, but it didn't work at all.

How can I set my local envoronment variables so that further calls to
std.process.system can pick  it up?


Have you tried putenv? It is only declared in core.sys.posix.stdlib, but 
the dmc-runtime-library must have it as dmd is also using it.




Associative Array, key and value as type of string or char[]

2013-02-02 Thread timewulf
Hi all,

in the moment I'm running against a wall:

I want to put some strings together into an ass. array:

For example a command with it's description like the following.

char[char[]] ch_Description = [ 'kill' : 'kills a process',
'pause' : 'pauses a process' ]

I tried with all combinations of char[char[]] over string[char[]],
char[string] to string[string] with depending quotations 'abc' to "abc".

My idea is just to print out the combinations to console. I'm not even
.sure, if it's a good idea to do so, but what makes me cry is, after all
trying, is that I can't find a solution.

The compiler messages go from "no implicit conversion" to "cast(char) of
string is deprecated" and others.

I read much about that key-values have to be immutable and so on and I
can accept the reasons, but I can't believe, there's no possible
solution for my underlaying idea.

Any ideas?

timewulf


Re: sc.ini

2013-02-02 Thread Rainer Schuetze


On 02.02.2013 14:16, Michael wrote:

Hi,
diff versions of Visual Studio may have diff installation path.

So here mine in proper order:

VCINSTALLDIR=C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\

LINKCMD64=%VCINSTALLDIR%\bin\x86_amd64\link.exe

WindowsSdkDir=C:\Program Files (x86)\Microsoft SDKs\Windows\v7.1A\


P.S.: I use: Win 8 Pro 64 bit, AMD Cpu, Visual Studio 2012 Express for
Desktop.


You can also set 64-bit specific settings in an [Environment64] section:

[Environment64]
LIB="%@P%\..\..\lib64";c:\l\vc10\lib64"
DFLAGS=%DFLAGS% -L/nologo

I hope the dmd internal magic regarding the VCINSTALLDIR and 
WindowsSdkDir settings gets moved to this sections.


Re: Associative Array, key and value as type of string or char[]

2013-02-02 Thread Namespace
It seems you are right. I get the same error. You should open a 
bug report for this.

But as long as it isn't fixed you can use an output via foreach.

import std.stdio;

void main() {
string[string] ch_Description = [
"kill" : "kills a process",
"pause" : "pauses a process"
];

// writeln(ch_Description); // does not work, but it should
foreach (string key, string value; ch_Description) {
writeln(key, ':', value);
}
}


Re: Why are commands executing out of order?

2013-02-02 Thread Josh

On Saturday, 2 February 2013 at 11:16:50 UTC, FG wrote:

On 2013-02-02 07:49, Josh wrote:

But main's first writeln actually outputs after f.close().


Maybe because of output buffering and you need to add flush?


How do I do that? I've never heard of flush before.

The program uses ~1GB of RAM overall, even though main.results 
is ~50MB

according to memSize.


Wrong comparison. You should have compared to the output file's 
size.

info.sizeof doesn't include the size of info.name.
In my test results were 30 MB but the output file was 101 MB.


Yeah, my output file was 126MB. I figured strings had a set 
amount of memory they could use, like an int can use exactly 4 
bytes.


But if you really have to do some extra processing of results, 
then you can reduce the memory used like 6 times by using an 
Appender instead of concatenating arrays and by reserving a 
reasonable number of records, to limit possible initial 
fragmentation when the array is resized. My program used 145 MB 
whereas the output file was 101 MB. I think it's good enough.


I've never come across Appenders before. Could you please explain 
them a little bit, and what each call in your modified code does?


Thanks,

Josh


Re: Why are commands executing out of order?

2013-02-02 Thread Namespace
I've never come across Appenders before. Could you please 
explain them a little bit, and what each call in your modified 
code does?


Thanks,

Josh


http://dlang.org/phobos/std_array.html#.Appender
And read Era's post.


Array concatenation vs. Appender

2013-02-02 Thread FG

On 2013-02-02 13:50, Era Scarecrow wrote:

On Saturday, 2 February 2013 at 11:33:07 UTC, Namespace wrote:

I'm was quite surprised as I had heard the first time of these 'appender'.
Therefore I'm asking me:
Why is the 'appender' method so much more efficient?


  Because concatenation likely will end up relocating the memory over and over
again (possibly lots of abandoned slices too) whereas the appender will
allocated & reuse the same buffer. On the other hand you might be better off
(depending on the need) with just reserving a lot more memory (close to what you
need or slightly larger) and then concatenation will perform much better. But if
it need to reallocate then you've still got the same problem with slices where
with the appender you probably won't.


Yeah but let us move reallocation out of the equation.
Reserving space limits the amount of RAM used and can avoid reallocations all 
together but in a little test it came out that still appender is 2.5-4 times 
faster than tab ~= str, where tab is char[] (same when it is ubyte[]). Why is that?


Let's say we have this code:

char[] tab;
string fill = "1234";
uint loops = 100_000_000;
tab.reserve(loops * fill.length);
foreach (i; 0..loops) tab ~= fill;

Using Appender changes the above loop into something like this:

size_t capacity = tab.capacity;
foreach (i; 0..loops) {
size_t flen = fill.length;
size_t len = tab.length;
if (len + flen > capacity) {
...
// use GC.extend or GC.qalloc & memcpy
// update capacity and assign tab = memory_block[0..len]
}
tab = tab.ptr[0..len+flen];
tab.ptr[len..len+flen] = fill[];
}

Why cannot tab ~= fill achieve similar performance as this code?
Am I missing something important?




Re: Why are commands executing out of order?

2013-02-02 Thread FG

On 2013-02-02 16:22, Josh wrote:

Maybe because of output buffering and you need to add flush?


How do I do that? I've never heard of flush before.


writeln("..."); stdout.flush();

C also has flush, in the form of fflush(stdout);


I've never come across Appenders before. Could you please explain them a little
bit, and what each call in your modified code does?


I'm baffled myself as to why they perform better than normal array 
concatenation. We'll see if some interesting explanation appears.

That's why I changed the topic to "Array concatenation vs. Appender".


Re: Associative Array, key and value as type of string or char[]

2013-02-02 Thread timewulf
On 02.02.2013 16:06, Namespace wrote:
> import std.stdio;
> 
> void main() {
> string[string] ch_Description = [
> "kill" : "kills a process",
> "pause" : "pauses a process"
> ];
> 
> // writeln(ch_Description); // does not work, but it should
> foreach (string key, string value; ch_Description) {
> writeln(key, ':', value);
> }
> }

Thanks for the answer.

I tried your code and very surprisingly: It works on both ways.

After searching for the differences to my code, I found my fault:

import std.stdio;

string[string] ch_Description = [
"kill" : "kills a process",
"pause" : "pauses a process"
];

void main() {

writeln(ch_Description); // does not work, but it should
foreach (string key, string value; ch_Description) {
writeln(key, ':', value);
}
}

I declared the array outside of main(), because I wanted to use them in
more than one function. The errors I got were all, because of this first
one,

"src/tstsuite.d(3): Error: non-constant expression ["kill":"kills a
process","pause":"pauses a process"]"

which shows up when compiling this simple example.

After checking this, I stripped down my program from unneeded casts and
so on and now I see the same error message as above. It just didn't come
up, because of my workarounds, which created the other failures.

Thanks for showing me the forest behind this big tree ;-)

Now I've just to look, how to declare this array in the way of public
constants.

Thanks and have nice weekend!


Re: Associative Array, key and value as type of string or char[]

2013-02-02 Thread FG

On 2013-02-02 16:06, Namespace wrote:

 string[string] ch_Description = [
 "kill" : "kills a process",
 "pause" : "pauses a process"
 ];

 writeln(ch_Description); // does not work, but it should


Doesn't work in the current version? In DMD 2.060 it works.


Re: Associative Array, key and value as type of string or char[]

2013-02-02 Thread Namespace

On Saturday, 2 February 2013 at 16:06:09 UTC, FG wrote:

On 2013-02-02 16:06, Namespace wrote:

string[string] ch_Description = [
"kill" : "kills a process",
"pause" : "pauses a process"
];

writeln(ch_Description); // does not work, but it should


Doesn't work in the current version? In DMD 2.060 it works.


I've cloned the github version two days ago and with that I get 
lots of errors.

Maybe I should open a bug report. :)


Re: Get TypeNames of Variadic Templates

2013-02-02 Thread Christian Köstlin

Yes! very good idea!
I also added something like static assert(staticIndexOf!(T, Children) != 
-1); to get a compile time error when someone wants to get something 
which is not there.


thanks

christian


On 2/2/13 14:13 , Philippe Sigaud wrote:

On Fri, Feb 1, 2013 at 11:04 PM, Christian Köstlin
  wrote:

Hi Philippe,

wonderful solution. I also added
T get(T)() {
   return components[staticIndexOf!(T, Children)];
}
to the class to get the Children out by type (works as long as there is only
one child of each type in the tuple).


Indeed, that's easier for the user this way.
In that case, you might want to either return a tuple of one or more
type (when there is more than one of a given type) or put a
restriction on Components so it's only a set of types.

Maybe with:

... if(NoDuplicates!(Children).length == Children.length)

See http://dlang.org/phobos/std_typetuple.html#.NoDuplicates


Then, when you're feeling masochistic, the next step is to allow
assignments from other Components with a permutation of children,
because Component!(int,double) is not much different from
Components!(double, int)

:)




Re: Associative Array, key and value as type of string or char[]

2013-02-02 Thread timewulf
On 02.02.2013 17:06, FG wrote:
> On 2013-02-02 16:06, Namespace wrote:
>>  string[string] ch_Description = [
>>  "kill" : "kills a process",
>>  "pause" : "pauses a process"
>>  ];
>>
>>  writeln(ch_Description); // does not work, but it should
> 
> Doesn't work in the current version? In DMD 2.060 it works.

I tried in dmd 2.061 and git-version from yesterday: Both work!


Re: Associative Array, key and value as type of string or char[]

2013-02-02 Thread Namespace

Works now.


new T[size] vs .reserve

2013-02-02 Thread Namespace
Currently something like new ubyte[4]; reserves space for _at 
least_ 4 items.

But if I want to store now something, the index isn't 0, it's 4.
Let me explain that on a brief example:

[code]
import std.stdio;

void main() {
ubyte[] arr = new ubyte[4];
arr ~= 4; // desirable: [4, 0, 0, 0];
writeln(arr); // prints: [0, 0, 0, 0, 4]

ubyte[] arr2;
arr2.reserve(4);
arr2 ~= 4; // expect: [4, 0, 0, 0];
writeln(arr2); // prints: [4] just as well
}
[/code]

So is there any reason why this behaviour is like it is?

As I looked at arr.length and arr.capacity for the first time I 
was schocked: I want only space for 4 items, but I got space for 
15.
I read in the docs that .reserve extends the space to at least 
SIZE items, but maybe more. But at that time and still yet I 
found nothing about new ubyte[SIZE]. So I ask:
wouldn't it be better, if new ubyte[4] reserves only space for 4 
items and reallocs only if I append more than 4?


Re: new T[size] vs .reserve

2013-02-02 Thread Maxim Fomin

On Saturday, 2 February 2013 at 16:36:29 UTC, Namespace wrote:
Currently something like new ubyte[4]; reserves space for _at 
least_ 4 items.

But if I want to store now something, the index isn't 0, it's 4.
Let me explain that on a brief example:

[code]
import std.stdio;

void main() {
ubyte[] arr = new ubyte[4];


You asked for array with four zeros (T.init for ubyte is 0).


arr ~= 4; // desirable: [4, 0, 0, 0];
writeln(arr); // prints: [0, 0, 0, 0, 4]


You got it. And you appended 4 to them, so you got proper result.


ubyte[] arr2;


You asked for empty array.


arr2.reserve(4);
arr2 ~= 4; // expect: [4, 0, 0, 0];
writeln(arr2); // prints: [4] just as well
}


You appended 4 to empty array and you got [4]. By the way, note 
that the output is not [4,0,0,0] it is [4] since no one has 
pushed three zeros there.



[/code]

So is there any reason why this behaviour is like it is?


I found it is consistent and complying yo spec. new ubyte[4] and 
reverse(4) do different things.


As I looked at arr.length and arr.capacity for the first time I 
was schocked: I want only space for 4 items, but I got space 
for 15.
I read in the docs that .reserve extends the space to at least 
SIZE items, but maybe more. But at that time and still yet I 
found nothing about new ubyte[SIZE]. So I ask:
wouldn't it be better, if new ubyte[4] reserves only space for 
4 items and reallocs only if I append more than 4?


Since you have two tools which do different things, you can 
select that tool which does what you wanted. What's the problem 
here?


Re: new T[size] vs .reserve

2013-02-02 Thread Namespace

No one said that this is a problem, or? (;
But why should I generate an array with size 4 if an append of me 
resize it to 5?


I'm asking because we have currently nothing (nice) for _fixed_ 
size arrays at runtime. That should be change. Therefore new 
T[size] would be a good.


Re: new T[size] vs .reserve

2013-02-02 Thread FG

On 2013-02-02 17:36, Namespace wrote:

 ubyte[] arr = new ubyte[4];
 arr ~= 4; // desirable: [4, 0, 0, 0];


Why not arr[0] = 4? What is so special about having 4 elements?


As I looked at arr.length and arr.capacity for the first time I was schocked: I
want only space for 4 items, but I got space for 15.


I think you are out of luck with built-in dynamic arrays.
It seems that even for an array of length 1 it gives a minimum of 15 bytes
storage, so you can fit 15 bytes, 7 shorts, 3 ints, 1 long.
I'm not sure why is it 15, given alignment an all...


Re: Not able to get scaled performance on increasing number of threads

2013-02-02 Thread Dmitry Olshansky

02-Feb-2013 00:39, FG пишет:

On 2013-02-01 20:33, Dmitry Olshansky wrote:

Mine reiteration on it, with a bit of help from std.parallelism.
std.parallelism uses thread pool thus it's somewhat faster then
creating threads
anew.


Interestingly, threads+barrier here wasn't much slower than tasks:
14% slower for dmd32, only 5% for gdc64
(and taskpool in dmd 13% slower than in gdc).


I'm think that taskPool should provide better operation for 'wait till 
all tasks are finished' as yielding on each task (i.e. future) looks 
less efficient.


That being said I might be missing something in std.parallelism API, I 
haven't used it all that much before.


But I love foreach(v; parallel(range) stuff :)

--
Dmitry Olshansky


Re: new T[size] vs .reserve

2013-02-02 Thread Namespace

On Saturday, 2 February 2013 at 17:48:14 UTC, FG wrote:

On 2013-02-02 17:36, Namespace wrote:

ubyte[] arr = new ubyte[4];
arr ~= 4; // desirable: [4, 0, 0, 0];


Why not arr[0] = 4? What is so special about having 4 elements?


Example:

struct Color {
public:
ubyte[4] colors;
}

ubyte[] data = new ubyte[color_data.length * 4]; // enough storage
foreach (ref const Color col; color_data) {
data ~= col.colors;
}

Currently impossible, even with self indexing absolute annoying 
and unnecessary complicated.
Sure you could do the same with .reserve but the point is that 
you does not want more storage than color_data.length * 4.
Currently I use my own struct which reserve only 
color_data.length * 4 memory and let the index at beginning to 0.
But I'm using D because it is nice and simple, so why I should 
create my own data structure, and use ugly malloc, realloc and 
free, for such needed thing if the language could and should do 
that for you?


Re: sc.ini

2013-02-02 Thread Dmitry Olshansky

02-Feb-2013 18:55, Rainer Schuetze пишет:


On 02.02.2013 14:16, Michael wrote:

Hi,
diff versions of Visual Studio may have diff installation path.

So here mine in proper order:

VCINSTALLDIR=C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\

LINKCMD64=%VCINSTALLDIR%\bin\x86_amd64\link.exe

WindowsSdkDir=C:\Program Files (x86)\Microsoft SDKs\Windows\v7.1A\


P.S.: I use: Win 8 Pro 64 bit, AMD Cpu, Visual Studio 2012 Express for
Desktop.


You can also set 64-bit specific settings in an [Environment64] section:

[Environment64]
LIB="%@P%\..\..\lib64";c:\l\vc10\lib64"
DFLAGS=%DFLAGS% -L/nologo

I hope the dmd internal magic regarding the VCINSTALLDIR and
WindowsSdkDir settings gets moved to this sections.


Mmm.. great, thanks. I've also been wondering how to make separate 
64-bit config on Windows, as before I messed up one or the other.


--
Dmitry Olshansky


Re: new T[size] vs .reserve

2013-02-02 Thread FG

On 2013-02-02 19:01, Namespace wrote:

Example:

struct Color {
public:
 ubyte[4] colors;
}

ubyte[] data = new ubyte[color_data.length * 4]; // enough storage
foreach (ref const Color col; color_data) {
 data ~= col.colors;
}


Sorry, but what is the point of data having only 4 bytes reserved
at the beginning? What is wrong with this:

ubyte[] data;
data.reserve(color_data.length * 4);
foreach (ref const Color col; color_data)
data ~= col.colors;

Are you uncomfortable, because it may allocate twice as much space
as you need (for bigger color_data)?


Re: new T[size] vs .reserve

2013-02-02 Thread Namespace
Are you uncomfortable, because it may allocate twice as much 
space

as you need (for bigger color_data)?


Yes, that's the point.
Sorry, I cannot express myself very well in English.


Re: new T[size] vs .reserve

2013-02-02 Thread FG

On 2013-02-02 19:53, Namespace wrote:

Are you uncomfortable, because it may allocate twice as much space
as you need (for bigger color_data)?


Yes, that's the point.
Sorry, I cannot express myself very well in English.


You're right. It's surprising for anyone used to dealing with std::vector,
that it actually reserves more than you specify.

Another odd thing - when pushing back to a vector its capacity grows:
1, 2, 4, 8, 16, 32 ..., but with D arrays it's like 7, 15, 31, 63...
Why 2**n - 1? What secret data is hidden after the block? ;)


Re: Array concatenation vs. Appender

2013-02-02 Thread Steven Schveighoffer

On Sat, 02 Feb 2013 10:47:39 -0500, FG  wrote:


On 2013-02-02 13:50, Era Scarecrow wrote:

On Saturday, 2 February 2013 at 11:33:07 UTC, Namespace wrote:
I'm was quite surprised as I had heard the first time of these  
'appender'.

Therefore I'm asking me:
Why is the 'appender' method so much more efficient?


  Because concatenation likely will end up relocating the memory over  
and over

again (possibly lots of abandoned slices too) whereas the appender will
allocated & reuse the same buffer. On the other hand you might be  
better off
(depending on the need) with just reserving a lot more memory (close to  
what you
need or slightly larger) and then concatenation will perform much  
better. But if
it need to reallocate then you've still got the same problem with  
slices where

with the appender you probably won't.


Yeah but let us move reallocation out of the equation.
Reserving space limits the amount of RAM used and can avoid  
reallocations all together but in a little test it came out that still  
appender is 2.5-4 times faster than tab ~= str, where tab is char[]  
(same when it is ubyte[]). Why is that?


Let's say we have this code:

 char[] tab;
 string fill = "1234";
 uint loops = 100_000_000;
 tab.reserve(loops * fill.length);
 foreach (i; 0..loops) tab ~= fill;

Using Appender changes the above loop into something like this:

 size_t capacity = tab.capacity;
 foreach (i; 0..loops) {
 size_t flen = fill.length;
 size_t len = tab.length;
 if (len + flen > capacity) {
 ...
 // use GC.extend or GC.qalloc & memcpy
 // update capacity and assign tab = memory_block[0..len]
 }
 tab = tab.ptr[0..len+flen];
 tab.ptr[len..len+flen] = fill[];
 }

Why cannot tab ~= fill achieve similar performance as this code?
Am I missing something important?


Appender is built for appending and has higher up-front costs, and higher  
memory costs.


Normal arrays can be used for appending, but also can be used for so many  
other things.


In other words, Appender cannot have the features that standard arrays  
have in order to make appending as fast as possible.


-Steve


Re: new T[size] vs .reserve

2013-02-02 Thread Steven Schveighoffer
On Sat, 02 Feb 2013 11:36:28 -0500, Namespace   
wrote:


Currently something like new ubyte[4]; reserves space for _at least_ 4  
items.

But if I want to store now something, the index isn't 0, it's 4.
Let me explain that on a brief example:

[code]
import std.stdio;

void main() {
ubyte[] arr = new ubyte[4];
arr ~= 4; // desirable: [4, 0, 0, 0];
writeln(arr); // prints: [0, 0, 0, 0, 4]

ubyte[] arr2;
arr2.reserve(4);
arr2 ~= 4; // expect: [4, 0, 0, 0];
writeln(arr2); // prints: [4] just as well
}
[/code]

So is there any reason why this behaviour is like it is?

As I looked at arr.length and arr.capacity for the first time I was  
schocked: I want only space for 4 items, but I got space for 15.
I read in the docs that .reserve extends the space to at least SIZE  
items, but maybe more. But at that time and still yet I found nothing  
about new ubyte[SIZE]. So I ask:
wouldn't it be better, if new ubyte[4] reserves only space for 4 items  
and reallocs only if I append more than 4?


Heap block sizes start at 16.  One byte overhead is used to store the  
array length, so the minimum size of ANY array allocation is 15 bytes.


Then it doubles to 32, then to 64, then to 128, 256, 512, etc. until you  
get to a page size (4096).  Then it scales linearly by pages.


I think you misunderstand what reserve and append do.  You should read  
this article to understand arrays and appending better:  
http://dlang.org/d-array-article.html


-Steve


Re: new T[size] vs .reserve

2013-02-02 Thread monarch_dodra

On Saturday, 2 February 2013 at 19:49:39 UTC, FG wrote:

On 2013-02-02 19:53, Namespace wrote:
Are you uncomfortable, because it may allocate twice as much 
space

as you need (for bigger color_data)?


Yes, that's the point.
Sorry, I cannot express myself very well in English.


You're right. It's surprising for anyone used to dealing with 
std::vector,

that it actually reserves more than you specify.


FYI: std::vector will do exactly the same thing. The actual grow 
scheme may be different, but that is purelly an implementation 
detail.


Another thing to take into account: In C++, if you request 10 
bytes of allocation space, but the underlying implementation 
actually allocates a 32 byte block, you'll know nothing of it. If 
later, you want to grow those 10 bytes to 20 bytes, you'll have 
to request a new allocation.


std::vector has actually no idea how much space actually gets 
allocated. It requests a certain amount but has no idea how much 
it really gets. At best, it can tell you how much it requested.


In D, you can exploit the last drop of allocation space actually 
allocated. It is the underlying array itself that tells you how 
much space there is left.


Another odd thing - when pushing back to a vector its capacity 
grows:
1, 2, 4, 8, 16, 32 ..., but with D arrays it's like 7, 15, 31, 
63...

Why 2**n - 1? What secret data is hidden after the block? ;)


The currently used size.

In C++, set::vector is a struct that has a "size" member, and a 
pointer to a payload. In D, the "size" data is embedded straight 
into the payload. Kind of like how std::string is implemented 
actually.


This has a two-fold advantage: The actual slice object is light 
(just a fat pointer). Also, when you have two (or more) slices 
that reference the same data, they *know* if or if not they can 
safelly append, without cloberring the data of another slice.


I suggest you read this:
http://dlang.org/d-array-article.html
It is a very interesting read, especially for those of us with 
C++ background.


One very (very) important thing to realize is that std::vector is 
a container. D slices are not containers: they are ranges. They 
iterate on an underlying array object, but they are not 
containers themselves.


The underlying object, the so called "dynamic array" is actually 
a obscure and hidden object you cannot access dirrectly.


There is some ambiguity between both terms, and they are often 
used interchangedbly, but to really understand what is going on, 
you need to imagine them as two different objects interacting.


Re: new T[size] vs .reserve

2013-02-02 Thread FG

On 2013-02-02 22:33, Steven Schveighoffer wrote:

Heap block sizes start at 16.  One byte overhead is used to store the array
length, so the minimum size of ANY array allocation is 15 bytes.


How is the length stored because I see only strange numbers in that byte.

foreach (end; 2..31) {
ubyte[] x;
foreach (i; 0..end) {
x ~= cast(ubyte)i;
}
writeln(x.length, " ", x.capacity, " ", x.ptr[end]);
}

That code outputs following length/capacity/extra_byte:

2 15 69
3 15 0
4 15 100
5 15 26
6 15 36
7 15 0
8 15 0
9 15 0
10 15 0
11 15 0
12 15 0
13 15 0
14 15 0
15 15 15
16 31 0
17 31 0
18 31 0
19 31 0
20 31 0
21 31 0
22 31 0
23 31 0
24 31 0
25 31 0
26 31 0
27 31 0
28 31 0
29 31 0
30 31 0

Last byte's value for length == 2 is quite random on each execution.
In a smaller way also for length == 6. Other values seem constant.



Re: new T[size] vs .reserve

2013-02-02 Thread Namespace
My real question was: will we ever have fixed size arrays at 
runtime?


Re: new T[size] vs .reserve

2013-02-02 Thread FG

On 2013-02-02 22:57, FG wrote:

On 2013-02-02 22:33, Steven Schveighoffer wrote:

Heap block sizes start at 16.  One byte overhead is used to store the array
length, so the minimum size of ANY array allocation is 15 bytes.


How is the length stored because I see only strange numbers in that byte.

 foreach (end; 2..31) {
 ubyte[] x;
 foreach (i; 0..end) {
 x ~= cast(ubyte)i;
 }
 writeln(x.length, " ", x.capacity, " ", x.ptr[end]);
 }



Ah, sorry. Silly me.
I have figured out that the length byte would have to be aligned to the end
of the block, so that is where I should look. The updated code:

// size_t ends = [1,2,7,15,31]; // crashes DMD
foreach (end; 2..31) {
ubyte[] x;
foreach (i; 0..end) {
x ~= cast(ubyte)i;
}
writeln(x.length, " ", x.capacity, " ", x.ptr[x.capacity]);
}
return;

shows that indeed, there's length written at the end. :)
Output:

2 15 2
3 15 3
4 15 4
5 15 5
6 15 6
7 15 7
8 15 8
9 15 9
10 15 10
11 15 11
12 15 12
13 15 13
14 15 14
15 15 15
16 31 16
17 31 17
18 31 18
19 31 19
20 31 20
21 31 21
22 31 22
23 31 23
24 31 24
25 31 25
26 31 26
27 31 27
28 31 28
29 31 29
30 31 30





Re: new T[size] vs .reserve

2013-02-02 Thread monarch_dodra

On Saturday, 2 February 2013 at 22:15:56 UTC, Namespace wrote:
My real question was: will we ever have fixed size arrays at 
runtime?


I see no reason why we couldn't, the only problem is a syntax 
one. If you beat the syntax (by wrapping it in a struct) then you 
can do it no problem:


//
T[N]* makeFixed(size_t N, T)()
{
static struct Fixed
{
T[N] a;
}
auto p = new Fixed();
return &((*p).a);
}

void main()
{
   int[4]* p4 = makeFixed!(4, int)();
}
//

And there, a dynamically allocated fixed size array. I know it's 
not pretty, but it proves the point.


Re: new T[size] vs .reserve

2013-02-02 Thread FG

On 2013-02-02 22:47, monarch_dodra wrote:

I suggest you read this:
http://dlang.org/d-array-article.html
It is a very interesting read, especially for those of us with C++ background.


Thank you for pointing me to that article.
I have read it months ago and forgotten the important parts.
Now it (slices & arrays) finally started making sense again. :)



Re: new T[size] vs .reserve

2013-02-02 Thread Namespace

On Saturday, 2 February 2013 at 22:39:58 UTC, monarch_dodra wrote:

On Saturday, 2 February 2013 at 22:15:56 UTC, Namespace wrote:
My real question was: will we ever have fixed size arrays at 
runtime?


I see no reason why we couldn't, the only problem is a syntax 
one. If you beat the syntax (by wrapping it in a struct) then 
you can do it no problem:


//
T[N]* makeFixed(size_t N, T)()
{
static struct Fixed
{
T[N] a;
}
auto p = new Fixed();
return &((*p).a);
}

void main()
{
   int[4]* p4 = makeFixed!(4, int)();
}
//

And there, a dynamically allocated fixed size array. I know 
it's not pretty, but it proves the point.


Sure and as I said: something like that I'm using currently. It 
is very ugly and because of that I asked for a built in solution, 
like new ubyte[size].

C have also runtime fixed size arrays.
But as far as I can see all your are fine with the wrapped struct 
solution.


Re: new T[size] vs .reserve

2013-02-02 Thread Namespace
But as far as I can see all your are fine with the wrapped 
struct solution.


->
But as far as I can see, all of you are happy with the current 
wrapped struct solution.


We need an 'edit' button.


Re: Array concatenation vs. Appender

2013-02-02 Thread Era Scarecrow

On Saturday, 2 February 2013 at 15:47:37 UTC, FG wrote:
Yeah but let us move reallocation out of the equation. 
Reserving space limits the amount of RAM used and can avoid 
reallocations all together but in a little test it came out 
that still appender is 2.5-4 times faster than tab ~= str, 
where tab is char[] (same when it is ubyte[]). Why is that?


 Reserving doesn't mean it has to allocate any memory at all; 
That's up to the implementation of the runtime and OS, it may 
just say 'any allocations not related to this object start after 
address xxx', then as the reserved space needs more it requests 
the larger space from the OS. The limitations of how much you can 
use memory-wise doesn't change as that's determined by the 
infrastructure. (VM and harddrive space doesn't count).



Why cannot tab ~= fill achieve similar performance as this code?
Am I missing something important?


 As for how many checks and overhead the runtime has I'm not 
sure. Try compiling the code again with full optimizations on and 
see if it makes a difference. Concatenation may perform better 
like that (as long as relocation/copying isn't done) or maybe 
not...


Re: Array concatenation vs. Appender

2013-02-02 Thread Jonathan M Davis
On Sunday, February 03, 2013 02:27:16 Era Scarecrow wrote:
> On Saturday, 2 February 2013 at 15:47:37 UTC, FG wrote:
> > Yeah but let us move reallocation out of the equation.
> > Reserving space limits the amount of RAM used and can avoid
> > reallocations all together but in a little test it came out
> > that still appender is 2.5-4 times faster than tab ~= str,
> > where tab is char[] (same when it is ubyte[]). Why is that?
> 
>   Reserving doesn't mean it has to allocate any memory at all;
> That's up to the implementation of the runtime and OS, it may
> just say 'any allocations not related to this object start after
> address xxx', then as the reserved space needs more it requests
> the larger space from the OS. The limitations of how much you can
> use memory-wise doesn't change as that's determined by the
> infrastructure. (VM and harddrive space doesn't count).

reserve should guarantee that you have at least the requested amount of memory 
already allocated, or it's broken. Its whole purpose is to guarantee that 
capacity is at least as large as the amount being reserved so that you can do 
a single allocation up front rather than having to worry about reallocations 
occuring as you append.

- Jonathan M Davis


Re: Array concatenation vs. Appender

2013-02-02 Thread Era Scarecrow
On Sunday, 3 February 2013 at 01:41:26 UTC, Jonathan M Davis 
wrote:
reserve should guarantee that you have at least the requested 
amount of memory already allocated, or it's broken. Its whole 
purpose is to guarantee that capacity is at least as large as 
the amount being reserved so that you can do a single 
allocation up front rather than having to worry about 
reallocations occurring as you append.


 Allocated, set aside, uninterrupted continuous block, etc. As 
long as the space is actually available when it's needed it's 
implemented doesn't matter. In the end it's up to the OS.


 The OS could be using Virtual Memory space by compressing data, 
then decompressing when it's requested/needed; In that case the 
data pre-allocated is empty (zeroed) it can compress instantly to 
almost nothing (Compressed swapfile driver in Linux for example). 
The most important part is making sure nothing else can claim any 
memory in the reserved block.


shell doesn't throw on error. Is that a regression?

2013-02-02 Thread timotheecour
The doc for std.process.shell says "If the process could not be 
started or exits with an error code, throws an exception."


However on OSX I'm having a different kind of behavior.
Isn't there a unittest to test this?

---
import std.process;
import std.stdio;

void main(){
shell("asfasfasdfasdf");
writeln("ok");
}
---
prints:

in dmd.2.061 - 2.059:
sh: asfasfasdfasdf: command not found
ok

in dmd.2.057:
sh: asfasfasdfasdf: command not found
std.exception.ErrnoException@std/stdio.d(418): Could not close 
pipe `asfasfasdfasdf' (Undefined error: 0)


Re: shell doesn't throw on error. Is that a regression?

2013-02-02 Thread Andrej Mitrovic
On 2/3/13, timotheecour  wrote:
> Isn't there a unittest to test this?

The only unittest is unfortunately pretty bad:

unittest
{
auto x = shell("echo wyda");
}

Please feel free to file a bug:
http://d.puremagic.com/issues/enter_bug.cgi?product=D


why does array appending add a page size instead of doubling ?

2013-02-02 Thread timotheecour
What's the rationale behind array appending adding a page size to 
capacity instead of doubling, after the size of the array reaches 
a certain size (cf what std::vector does) ? That seems like an 
example of (evil?) early optimization.



T[]a;
int n=some big value;
foreach(i;0..n)
a~=T.init;

Depending on T.sizeof or n, the code above will be linear 
complexity in n (while capacity remains below page size) or 
quadratic (while capacity increments are one page at a time).


The C++ version doesn't have this problem, as doubling is always 
the case (in most implementations at least).


std::vectora;
int n=some big value;
for(int i=0;iNote that we can't always use a.reserve(n) as in more complex 
examples, we don't know final size. And appender is more 
restrictive. Would love some explanations!


Re: shell doesn't throw on error. Is that a regression?

2013-02-02 Thread timotheecour

here goes:
http://d.puremagic.com/issues/show_bug.cgi?id=9444

please see my added comment in 9444 regarding capturing std err 
instead of displaying it.


Re: new T[size] vs .reserve

2013-02-02 Thread Mike Parker

On Sunday, 3 February 2013 at 00:34:48 UTC, Namespace wrote:


C have also runtime fixed size arrays.


They were added in C99 (variable length arrays, they're called). 
C++, on the other hand, still doesn't have them.


Re: shell doesn't throw on error. Is that a regression?

2013-02-02 Thread timotheecour

On Sunday, 3 February 2013 at 02:28:26 UTC, timotheecour wrote:

here goes:
http://d.puremagic.com/issues/show_bug.cgi?id=9444

please see my added comment in 9444 regarding capturing std err 
instead of displaying it.


actually the new std.process pull request 
(http://forum.dlang.org/thread/k5uprq$obu$1...@digitalmars.com) 
works well. I wonder when that'll get in master?


Re: Associative Array, key and value as type of string or char[]

2013-02-02 Thread Ali Çehreli

On 02/02/2013 08:00 AM, timewulf wrote:

> After searching for the differences to my code, I found my fault:

It is not your fault. :)

> Now I've just to look, how to declare this array in the way of public
> constants.

You need 'static this()':

import std.stdio;

string[string] ch_Description;

static this()
{
ch_Description = [ "kill" : "kills a process",
   "pause" : "pauses a process" ];
}

void main() {
// ...
}

You can even make the AA immutable if it never changes:

immutable string[string] ch_Description;

Ali



Re: why does array appending add a page size instead of doubling ?

2013-02-02 Thread Ali Çehreli

On 02/02/2013 08:37 PM, Ali Çehreli wrote:
> On 02/02/2013 06:22 PM, timotheecour wrote:
>  > What's the rationale behind array appending adding a page size to
>  > capacity
>
> It is not always the case. The page is added only if the next page
> conveniently free. There is no cost for that "allocation".

I have tested this for D and C++ with the following programs. They count 
the number of times the underlying buffer gets reallocated and the 
number of elements that get moved as a result of that.


Here is the C++ program:

#include 
#include 

using namespace std;

int main()
{
for (size_t maxElements = 1; maxElements <= 0x400; maxElements 
*= 2) {

vector s;
size_t totalElementsMoved = 0;
size_t totalAllocations = 0;

for (size_t i = 0; i < maxElements; ++i) {
int *oldPtr = s.empty() ? NULL : &s[0];
s.push_back(0);

if (&s[0] != oldPtr) {
totalElementsMoved += (s.size() - 1);
++totalAllocations;
}
}

cout << "Elements: " << maxElements
 << " Allocations: " << totalAllocations
 << " Moved: " << totalElementsMoved
 << '\n';
}
}

It indeed shows amortized constant growth. The total number of elements 
that get moved is always one less than the eventual size of the array 
and the number of times of the allocations is predictable:


Elements: 1 Allocations: 1 Moved: 0
Elements: 2 Allocations: 2 Moved: 1
Elements: 4 Allocations: 3 Moved: 3
Elements: 8 Allocations: 4 Moved: 7
Elements: 16 Allocations: 5 Moved: 15
Elements: 32 Allocations: 6 Moved: 31
Elements: 64 Allocations: 7 Moved: 63
Elements: 128 Allocations: 8 Moved: 127
Elements: 256 Allocations: 9 Moved: 255
Elements: 512 Allocations: 10 Moved: 511
Elements: 1024 Allocations: 11 Moved: 1023
Elements: 2048 Allocations: 12 Moved: 2047
Elements: 4096 Allocations: 13 Moved: 4095
Elements: 8192 Allocations: 14 Moved: 8191
Elements: 16384 Allocations: 15 Moved: 16383
Elements: 32768 Allocations: 16 Moved: 32767
Elements: 65536 Allocations: 17 Moved: 65535
Elements: 131072 Allocations: 18 Moved: 131071
Elements: 262144 Allocations: 19 Moved: 262143
Elements: 524288 Allocations: 20 Moved: 524287
Elements: 1048576 Allocations: 21 Moved: 1048575
Elements: 2097152 Allocations: 22 Moved: 2097151
Elements: 4194304 Allocations: 23 Moved: 4194303
Elements: 8388608 Allocations: 24 Moved: 8388607
Elements: 16777216 Allocations: 25 Moved: 16777215
Elements: 33554432 Allocations: 26 Moved: 33554431
Elements: 67108864 Allocations: 27 Moved: 67108863

Here is the D program:

import std.stdio;

void main()
{
for (auto maxElements = 1; maxElements <= 0x400_; maxElements 
*= 2) {

int[] s;
auto totalElementsMoved = 0;
auto totalAllocations = 0;

foreach (i; 0 .. maxElements) {
auto oldPtr = s.ptr;
s ~= 0;

if (s.ptr != oldPtr) {
totalElementsMoved += (s.length - 1);
++totalAllocations;
}
}

writefln("Elements: %s, Allocations: %s, Moved: %s",
 maxElements, totalAllocations, totalElementsMoved);
}
}

Its output is different in that the number of allocations is less than 
C++ but the total number of elements that get moved are more:


Elements: 1, Allocations: 1, Moved: 0
Elements: 2, Allocations: 1, Moved: 0
Elements: 4, Allocations: 2, Moved: 3
Elements: 8, Allocations: 3, Moved: 10
Elements: 16, Allocations: 4, Moved: 25
Elements: 32, Allocations: 5, Moved: 56
Elements: 64, Allocations: 6, Moved: 119
Elements: 128, Allocations: 7, Moved: 246
Elements: 256, Allocations: 8, Moved: 501
Elements: 512, Allocations: 9, Moved: 1012
Elements: 1024, Allocations: 9, Moved: 1012
Elements: 2048, Allocations: 9, Moved: 1012
Elements: 4096, Allocations: 9, Moved: 1012
Elements: 8192, Allocations: 9, Moved: 1012
Elements: 16384, Allocations: 9, Moved: 1012
Elements: 32768, Allocations: 9, Moved: 1012
Elements: 65536, Allocations: 9, Moved: 1012
Elements: 131072, Allocations: 10, Moved: 28655
Elements: 262144, Allocations: 9, Moved: 1012
Elements: 524288, Allocations: 12, Moved: 435173
Elements: 1048576, Allocations: 13, Moved: 1431520
Elements: 2097152, Allocations: 11, Moved: 1993706
Elements: 4194304, Allocations: 13, Moved: 5877728
Elements: 8388608, Allocations: 14, Moved: 14838747
Elements: 16777216, Allocations: 12, Moved: 30438373
Elements: 33554432, Allocations: 12, Moved: 59881445
Elements: 67108864, Allocations: 12, Moved: 109627365

Ali



Re: is there a way to define a pure base class that forces pureness of derived classes?

2013-02-02 Thread Ali Çehreli

On 02/02/2013 02:23 AM, dennis luehring wrote:

i've got something like an streaming/converter system
and parts of the specialised converters are stateless other statefull

is there any way to force pureness/stateless-ness through the base
class or an interface in D?


That seems to be the case:

interface I
{
int foo() const pure;
}

int g;

class C : I
{
int foo() const
{
return g;// ERROR: pure function 'deneme.C.foo' cannot access
 //mutable static data 'g'
}
}

void main()
{
auto o = new C;
o.foo();
}

Note that there is no 'pure' on C.foo; it is inherited from I.foo.

Ali


Re: why does array appending add a page size instead of doubling ?

2013-02-02 Thread Chris Cain
Okay, I've got a question for you Ali... why is it that sometimes 
as Elements increased, there were a _drop_ of allocations?


So, these in particular:

On Sunday, 3 February 2013 at 06:02:04 UTC, Ali Çehreli wrote:

Elements: 65536, Allocations: 9, Moved: 1012
Elements: 131072, Allocations: 10, Moved: 28655
[[ Elements: 262144, Allocations: 9, Moved: 1012 ]]
Elements: 524288, Allocations: 12, Moved: 435173
Elements: 1048576, Allocations: 13, Moved: 1431520
[[ Elements: 2097152, Allocations: 11, Moved: 1993706 ]]
Elements: 4194304, Allocations: 13, Moved: 5877728
Elements: 8388608, Allocations: 14, Moved: 14838747
[[ Elements: 16777216, Allocations: 12, Moved: 30438373 ]]
Elements: 33554432, Allocations: 12, Moved: 59881445
Elements: 67108864, Allocations: 12, Moved: 109627365


That's quite an oddity to me, especially looking at the code.


Re: Associative Array, key and value as type of string or char[]

2013-02-02 Thread timewulf
On 03.02.2013 06:09, Ali Çehreli wrote:

> You need 'static this()':
> 
> import std.stdio;
> 
> string[string] ch_Description;
> 
> static this()
> {
> ch_Description = [ "kill" : "kills a process",
>"pause" : "pauses a process" ];
> }
> 
> void main() {
> // ...
> }
> 
> You can even make the AA immutable if it never changes:
> 
> immutable string[string] ch_Description;
> 
> Ali
> 
Thanks, I applied both and errors are gone.

Timewulf


Re: why does array appending add a page size instead of doubling ?

2013-02-02 Thread Ali Çehreli

On 02/02/2013 10:48 PM, Chris Cain wrote:
> Okay, I've got a question for you Ali... why is it that sometimes as
> Elements increased, there were a _drop_ of allocations?
>
> So, these in particular:
>
> On Sunday, 3 February 2013 at 06:02:04 UTC, Ali Çehreli wrote:
>> Elements: 65536, Allocations: 9, Moved: 1012
>> Elements: 131072, Allocations: 10, Moved: 28655
>> [[ Elements: 262144, Allocations: 9, Moved: 1012 ]]
>> Elements: 524288, Allocations: 12, Moved: 435173
>> Elements: 1048576, Allocations: 13, Moved: 1431520
>> [[ Elements: 2097152, Allocations: 11, Moved: 1993706 ]]
>> Elements: 4194304, Allocations: 13, Moved: 5877728
>> Elements: 8388608, Allocations: 14, Moved: 14838747
>> [[ Elements: 16777216, Allocations: 12, Moved: 30438373 ]]
>> Elements: 33554432, Allocations: 12, Moved: 59881445
>> Elements: 67108864, Allocations: 12, Moved: 109627365
>
> That's quite an oddity to me, especially looking at the code.

We must be seeing the effects of how the GC works. Note that each line 
is printed for a different slice 's'. My guess is that the GC runs a 
collection right before the observed drop and the next array gets lucky.


Ali