Re: Populating nested AAs; "This wouldn't be so verbose in Ada 2020"

2019-12-07 Thread mipri via Digitalmars-d-learn

On Sunday, 8 December 2019 at 06:42:22 UTC, Paul Backus wrote:

You can use the `require` function [1] for this:

with (userHistory.require(host).require(user)) {
if (isOk) ++ok; // renamed to avoid shadowing
else ++evil;
}

Many "methods" for built-in AAs are located in the `object` 
module. It makes them a bit tricky to find in the 
documentation, if you don't already know they're there.


https://dlang.org/phobos/object.html#.require


Thanks! I wasn't aware of the 'object' doc. Looks like the
language documentation does mention require() in "Inserting if
not present", but combining it with 'with' is a neat trick.



Re: Populating nested AAs; "This wouldn't be so verbose in Ada 2020"

2019-12-07 Thread Paul Backus via Digitalmars-d-learn

On Sunday, 8 December 2019 at 04:17:45 UTC, mipri wrote:

Hello,

I've got this code:

  struct UserStats {
int ok, evil;
  }

  // module-level variable
  UserStats[string][string] userHistory;

and this code that populates it:

  // loop over DB query

  if (host !in userHistory)
  userHistory[host] = typeof(userHistory[host]).init;

  if (user !in userHistory[host])
  userHistory[host][user] = 
typeof(userHistory[host][user]).init;


  if (ok) ++userHistory[host][user].ok;
  else ++userHistory[host][user].evil;


You can use the `require` function [1] for this:

with (userHistory.require(host).require(user)) {
if (isOk) ++ok; // renamed to avoid shadowing
else ++evil;
}

Many "methods" for built-in AAs are located in the `object` 
module. It makes them a bit tricky to find in the documentation, 
if you don't already know they're there.


https://dlang.org/phobos/object.html#.require


Populating nested AAs; "This wouldn't be so verbose in Ada 2020"

2019-12-07 Thread mipri via Digitalmars-d-learn

Hello,

I've got this code:

  struct UserStats {
int ok, evil;
  }

  // module-level variable
  UserStats[string][string] userHistory;

and this code that populates it:

  // loop over DB query

  if (host !in userHistory)
  userHistory[host] = typeof(userHistory[host]).init;

  if (user !in userHistory[host])
  userHistory[host][user] = 
typeof(userHistory[host][user]).init;


  if (ok) ++userHistory[host][user].ok;
  else ++userHistory[host][user].evil;

The joke of the thread title is that in pseudo-Ada2020, those
assignments would look like

  User_History (host) = typeof (@).init;
  User_History (host) (user) = typeof (@).init;

as @ is a shortcut for the left hand side of an assignment.
It's what Ada has instead of += and friends.

Of course, I don't propose that @ be added to D; I just want to
know if there's a good idiom for new assignments to nested AAs
like this. A nice alternative for my specific use is

  struct UserStats {
static int[Tuple!(string, string)] ok, evil;
  }

and

  // loop over DB query
  if (ok) ++UserStats.ok[tuple(host, user)];
  else ++UserStats.evil[tuple(host, user)];

But of course this would be less convenient if f.e. I wanted to
pattern my data structures after a JSON production result.



Re: Using map result type

2019-12-07 Thread mipri via Digitalmars-d-learn

On Sunday, 8 December 2019 at 01:10:21 UTC, AA wrote:

I'd like to accept the return type of map. From some previous
questions that I should accept a template?


In general this is what you want to do with any kind of range
code, because you're not working with definite types, but with
types that have certain properties. And an advantage of this is
that you can decide to do more or less efficient things at
compile time based on additional properties of the types you're
working with. Just open up phobos and look for 'static if':

https://github.com/dlang/phobos/blob/master/std/algorithm/searching.d#L3858

So if you you give minPos an array, it'll just foreach() over
the array and return a slice. In which case minPos is exactly
as efficient as the code you would've written by hand instead
of using minPos, because it expands to that same code.

And if you give minPos something else, it'll still work.


So for something like:

```
void mapAccepter(Range)(Range r)
{
import std.array : array;
import std.stdio : writeln;

auto collected = r.array;
writeln(collected);
}

void main()
{
import std.algorithm.iteration : map;

int[] nums = [1, 2, 3];
auto evenness = map!(n => n % 2 == 0)(nums);
mapAccepter(evenness);
}
```



1) Is there any way I can make `mapAccepter` not a templated
function?


Not really. Even if you try to use typeof() to get the
(internal) type that std.alogorithm.map returns, you'll run
into errors like

Error: function x253.mapAccepter(MapResult!(__lambda5, int[]) r) 
is not callable using argument types (MapResult!(__lambda1, 
int[]))


when you try to use it.


2) Is there any way if I need to make `mapAccepter` templated
to constrain Range to be a range of booleans.


Certainly. Static reflection's what this kind of generic code
is all about. See all the constraints in the std.algorithm pages
in the library documentation?  Just look at this one, randomly
picked:
https://dlang.org/phobos/std_algorithm_searching.html#.endsWith

  if (isBidirectionalRange!Range
  && (Needles.length > 1)
  && is(typeof(.endsWith!pred(doesThisEnd, 
withOneOfThese[0])) : bool)
  && is(typeof(.endsWith!pred(doesThisEnd, 
withOneOfThese[1..$])) : uint));


So for your code:

  void mapAccepter(Range)(Range r)
  if (is(ElementType!Range == bool))
  {
  import std.array : array;
  import std.stdio : writeln;

  auto collected = r.array;
  writeln(collected);
  }

Or if you do this often, maybe something like this would do:

  enum RangeOfBools(T) = is(ElementType!T == bool) && 
isInputRange!T;


  void mapAccepter(Range)(Range r) if (RangeOfBools!Range)
  {
  import std.array : array;
  import std.stdio : writeln;

  auto collected = r.array;
  writeln(collected);
  }



Using map result type

2019-12-07 Thread AA via Digitalmars-d-learn
I'd like to accept the return type of map. From some previous 
questions that I should accept a template?

So for something like:

```
void mapAccepter(Range)(Range r)
{
import std.array : array;
import std.stdio : writeln;

auto collected = r.array;
writeln(collected);
}

void main()
{
import std.algorithm.iteration : map;

int[] nums = [1, 2, 3];
auto evenness = map!(n => n % 2 == 0)(nums);
mapAccepter(evenness);
}
```

1) Is there any way I can make `mapAccepter` not a templated 
function?
2) Is there any way if I need to make `mapAccepter` templated to 
constrain Range to be a range of booleans.


Re: GC.collect inflating memory usage?

2019-12-07 Thread Rainer Schuetze via Digitalmars-d-learn


On 07/12/2019 12:20, cc wrote:
> Given the following program:
[...]
> But when both FREE and COLLECT are enabled, things seem to spiral out of
> control:
> // FREE, COLLECT
> Stats(16, 1048560, 16)
>     848 4096
> 40960832  40964096
> 81920832  81924096
> 122880832  122884096
> 163840832  163844096
> 204800832  204804096
> 245760832  245764096
> 286720832  286724096
> 327680832  327684096
> 368640832  368644096
> Elapsed: 29143 ms
> 
> I wouldn't normally call GC.collect on every frame in my application,
> but I'm curious why this is happening and if there is unnecessary bloat
> being added somehow when I do choose to call GC.free manually and
> garbage collection later occurs in a long-running program.  Ideally I'd
> like to free up as many objects and arrays as soon as they become unused
> to avoid lengthy collections reducing performance.  I know that
> std.container.array is one alternative to using D's GC-managed dynamic
> arrays, but could I run into the same issue when trying to manually
> deallocate class objects as well?
> 
> Using DMD32 D Compiler v2.089.0-dirty
> 

Seems like a bug introduced in dmd 2.086, I've created a bugzilla issue:
https://issues.dlang.org/show_bug.cgi?id=20438

I suspect there is something broken with respect to the free-lists
inside the GC when manually freeing memory :-/


Re: Profiling the memory in D

2019-12-07 Thread kerdemdemir via Digitalmars-d-learn
On Wednesday, 4 December 2019 at 22:51:45 UTC, Steven 
Schveighoffer wrote:


I localized that the leak was actually being caused by 
websockets. I want to write down my experience because I did some 
weird stuff which seems to be working but I want to learn how it 
actually make sense and works.


I had a fancy work flow which caused by that bug 
https://github.com/vibe-d/vibe.d/issues/2169 which disallowed to 
open multiple sockets from my main process.


I solved that by lunching multiple process and using one web 
socket by one process. And communicated this process and my main 
process via zmqd.


My suggestion is; don't do that. Don't be super creative with 
current Vibe websockets. I had this unidentifable leak which took 
to much time to localize.


The bug I created around one year ago is solved now so I left 
creating processes approach and put web sockets in to a list.


Next problem I had while listening 300 websocket was I got some 
crushes within
webSocket.dataAvailableForRead() function, I am not sure if it is 
a bug or my misusage some how so I haven't created a bug yet. But 
my question to vibe forum can be seen 
https://forum.rejectedsoftware.com/groups/rejectedsoftware.vibed/thread/112309/


I solved that ( I hope ) by using something like:

if ( webSocket.waitForData(0.msecs) && 
webSocket.dataAvailableForRead() )


I know it looks so wierd to wait for 0.msecs but things seems to 
be working :/ .


The last problem I had was with closing the socket because this 
sockets are getting disconnected time to time. I need to close 
and reopen. When I call
webSocket.close() directly, after my program runs about 1 day it 
was freezing in a function called epoll while calling 
webSocket.close().


I also find another weird solution to that problem :

while ( true )
{
auto future = vibe.core.concurrency.async( { 
socket.socket.close(); return true;} );

vibe.core.core.sleep(100.msecs);
if ( future.ready() )
break;
writeln( " Couldn't close the socket retring ");
}
sockets.remove(uniqStreamName);// BTW order of this removal 
matters if you remove

   //from your list before closing the ticket you are screwed.


Which seems to be working with 300 websockets around 2 days 
without any leak nor crush neither freeze.


As I pointed in the beginning I don't have any question or 
problems now but I am very open to feedback if you guys have any.


Erdemdem








Re: Thin UTF8 string wrapper

2019-12-07 Thread Joseph Rushton Wakeling via Digitalmars-d-learn
On Saturday, 7 December 2019 at 15:57:14 UTC, Jonathan M Davis 
wrote:
There may have been some tweaks to std.encoding here and there, 
but for the most part, it's pretty ancient. Looking at the 
history, it's Seb who marked some if it as being a replacement 
for std.utf, which is just plain wrong.


Ouch!  I must say it was a surprise to read, precisely because 
std.encoding seemed weird and clunky.  Good to know that it's 
misleading.


Unfortunately that adds to the list I have of weirdly misleading 
docs that seem to have crept in over the last months/years :-(


std.utf.validate does need a replacement, but doing so gets 
pretty complicated. And looking at std.encoding.isValid, I'm 
not sure that what it does is any better from simply wrapping 
std.utf.validate and returning a bool based on whether an 
exception was thrown.


Unfortunately I'm dealing with a use case where exception 
throwing (and indeed, anything that generates garbage) is 
preferred to be avoided.  That's why I was looking for a function 
that returned a bool ;-)


Depending on the string, it would actually be faster to use 
validate, because std.encoding.isValid iterates through the 
entire string regardless. The way it checks validity is also 
completely different from what std.utf does. Either way, some 
of the std.encoding internals do seem to be an alternate 
implementation of what std.utf has, but outside of std.encoding 
itself, std.utf is what Phobos uses for UTF-8, UTF-16, and 
UTF-32, not std.encoding.


Thanks -- good to know.

I did do a PR at one point to add isValidUTF to std.utf so that 
we could replace std.utf.validate, but Andrei didn't like the 
implementation, so it didn't get merged, and I haven't gotten 
around to figuring out how to implement it more cleanly.


Thanks for the attempt, at least!  While I get the reasons it was 
rejected, it feels a bit of a shame -- surely it's easier to do a 
more major under-the-hood rewrite with the public API (and tests) 
already in place ... :-\


Re: Thin UTF8 string wrapper

2019-12-07 Thread Jonathan M Davis via Digitalmars-d-learn
On Saturday, December 7, 2019 5:23:30 AM MST Joseph Rushton Wakeling via 
Digitalmars-d-learn wrote:
> On Saturday, 7 December 2019 at 03:23:00 UTC, Jonathan M Davis
>
> wrote:
> > The module to look at here is std.utf, not std.encoding.
>
> Hmmm, docs may need updating then -- several functions in
> `std.encoding` explicitly state they are replacements for
> `std.utf`.  Did you mean `std.uni`?

> It is honestly a bit confusing which of these 3 modules to use,
> especially as they each offer different (and useful) tools.  For
> example, `std.utf.validate` is less useful than
> `std.encoding.isValid`, because it throws rather than returning a
> bool and giving the user the choice of behaviour.  `std.uni`
> doesn't seem to have any equivalent for either.
>
> Thanks in any case for the as-ever characteristically detailed
> and useful advice :-)

There may have been some tweaks to std.encoding here and there, but for the
most part, it's pretty ancient. Looking at the history, it's Seb who marked
some if it as being a replacement for std.utf, which is just plain wrong.
Phobos in general uses std.utf for dealing with UTF-8, UTF-16, and UTF-32,
not std.encoding. std.encoding is an old module that's had some tweaks done
to it but which probably needs a pretty serious overhaul. The only thing
that I've ever use it for is BOM stuff.

std.utf.validate does need a replacement, but doing so gets pretty
complicated. And looking at std.encoding.isValid, I'm not sure that what it
does is any better from simply wrapping std.utf.validate and returning a
bool based on whether an exception was thrown. Depending on the string, it
would actually be faster to use validate, because std.encoding.isValid
iterates through the entire string regardless. The way it checks validity is
also completely different from what std.utf does. Either way, some of the
std.encoding internals do seem to be an alternate implementation of what
std.utf has, but outside of std.encoding itself, std.utf is what Phobos uses
for UTF-8, UTF-16, and UTF-32, not std.encoding.

I did do a PR at one point to add isValidUTF to std.utf so that we could
replace std.utf.validate, but Andrei didn't like the implementation, so it
didn't get merged, and I haven't gotten around to figuring out how to
implement it more cleanly.

- Jonathan M Davis





Re: Thin UTF8 string wrapper

2019-12-07 Thread Joseph Rushton Wakeling via Digitalmars-d-learn
On Saturday, 7 December 2019 at 03:23:00 UTC, Jonathan M Davis 
wrote:

The module to look at here is std.utf, not std.encoding.


Hmmm, docs may need updating then -- several functions in 
`std.encoding` explicitly state they are replacements for 
`std.utf`.  Did you mean `std.uni`?


It is honestly a bit confusing which of these 3 modules to use, 
especially as they each offer different (and useful) tools.  For 
example, `std.utf.validate` is less useful than 
`std.encoding.isValid`, because it throws rather than returning a 
bool and giving the user the choice of behaviour.  `std.uni` 
doesn't seem to have any equivalent for either.


Thanks in any case for the as-ever characteristically detailed 
and useful advice :-)


GC.collect inflating memory usage?

2019-12-07 Thread cc via Digitalmars-d-learn

Given the following program:

//version=FREE;
//version=COLLECT;
import std.stdio;
import std.datetime.stopwatch;
import core.memory;
	immutable int[] intZ = 
[1,2,3,4,4,6,6,8,8,65,8,23,76,2,57,264,23,4,4,6,6,8,8,65,8,23,76,2,57,264,23,4,4,6,6,8,8,65,8,23,76,2,57,264,23,4,4,6,6,8,8,65,8,23,76,2,57,264,23,4,4,6,6,8,8,65,8,23,76,2,57,264,23,4,4,6,6,8,8,65,8,23,76,2,57,264,23,4,4,6,6,8,8,65,8,23,76,2,57,264,23,4,4,6,6,8,8,65,8,23,76,2,57,264,23,4,4,6,6,8,8,65,8,23,76,2,57,264,23];

void main() {
writeln(GC.stats);
enum max = 10;
StopWatch sw;
sw.start();
foreach (i; 0 .. max) {
bool doprint = !(i % (max/10));
int[] z = intZ.dup;
if (doprint) writef("%7d  ", GC.stats.usedSize);
version(FREE) GC.free(cast(void*) z.ptr);
version(COLLECT) GC.collect();
if (doprint) writefln("%7d", GC.stats.usedSize);
}
sw.stop();
writefln("Elapsed: %d ms", sw.peek.total!"msecs");
}

When compiled with neither the FREE or COLLECT versions, I get 
results like this typically:

Stats(16, 1048560, 16)
848  848
 883104   883104
 711072   711072
 539040   539040
 367008   367008
 191696   191696
  1966419664
 887200   887200
 715168   715168
 540672   540672
Elapsed: 11 ms

When only the FREE line is enabled, I see results like this:
// FREE
Stats(16, 1048560, 16)
848   32
848   32
848   32
848   32
848   32
848   32
848   32
848   32
848   32
848   32
Elapsed: 12 ms

When only the COLLECT line is enabled, I see results like this:
// COLLECT
Stats(16, 1048560, 16)
848 4096
   4928 4096
   4928 4096
   4928 4096
   9024 8192
   4928 4096
   4928 4096
   4928 4096
   4928 4096
   4928 4096
Elapsed: 1130 ms

But when both FREE and COLLECT are enabled, things seem to spiral 
out of control:

// FREE, COLLECT
Stats(16, 1048560, 16)
848 4096
40960832  40964096
81920832  81924096
122880832  122884096
163840832  163844096
204800832  204804096
245760832  245764096
286720832  286724096
327680832  327684096
368640832  368644096
Elapsed: 29143 ms

I wouldn't normally call GC.collect on every frame in my 
application, but I'm curious why this is happening and if there 
is unnecessary bloat being added somehow when I do choose to call 
GC.free manually and garbage collection later occurs in a 
long-running program.  Ideally I'd like to free up as many 
objects and arrays as soon as they become unused to avoid lengthy 
collections reducing performance.  I know that 
std.container.array is one alternative to using D's GC-managed 
dynamic arrays, but could I run into the same issue when trying 
to manually deallocate class objects as well?


Using DMD32 D Compiler v2.089.0-dirty