Re: Creeping Bloat in Phobos

2014-10-01 Thread Kagamin via Digitalmars-d
On Sunday, 28 September 2014 at 12:09:50 UTC, Andrei Alexandrescu 
wrote:

On 9/27/14, 4:31 PM, H. S. Teoh via Digitalmars-d wrote:
On Sat, Sep 27, 2014 at 11:00:16PM +, bearophile via 
Digitalmars-d wrote:

H. S. Teoh:

If we can get Andrei on board, I'm all for killing off 
autodecoding.


Killing auto-decoding for std.algorithm functions will break 
most of

my D2 code... perhaps we can do that in a D3 language.

[...]

Well, obviously it's not going to be done in a careless, 
drastic way!


Stuff that's missing:

* Reasonable effort to improve performance of auto-decoding;

* A study of the matter revealing either new artifacts and 
idioms, or the insufficiency of such;


* An assessment of the impact on compilability of existing code

* An assessment of the impact on correctness of existing code 
(that compiles and runs in both cases)


* An assessment of the improvement in speed of eliminating 
auto-decoding


I think there's a very strong need for this stuff, because 
claims that current alternatives to selectively avoid 
auto-decoding use the throwing of hands (and occasional chairs 
out windows) without any real investigation into how library 
artifacts may help. This approach to justifying risky moves is 
frustratingly unprincipled.


As far as I see, backward compatibility is fairly easy.
Extract autodecoding modules into `autodecoding` dub package and 
clean up phobos modules into non-decoding behavior. The phobos 
code will be simplified: it will deal with ranges as is without 
specialization, the `autodecoding` dub package will be simple: 
just wraps strings into dchar range and invokes non-decoding 
function from phobos, preserves current module interface to keep 
legacy D code working.
Run dfix on your sources, it will replace `import std.algorithm` 
with `import autodecoding.algorithm` - then the code should work.

What do you think? Worth a DIP?


Re: Creeping Bloat in Phobos

2014-09-30 Thread Dmitry Olshansky via Digitalmars-d

29-Sep-2014 16:43, Dicebot пишет:

I refuse to accept any code gen complaints based on DMD. It's
optimization facilities are generally crappy compared to gdc / ldc and
not worth caring about - it is just a reference implementation after
all. Clean and concise library code is more important.

Now if the same inlining failure happens with other two compilers - that
is something worth talking about (I don't know if it happens)


+1

--
Dmitry Olshansky


Re: Creeping Bloat in Phobos

2014-09-29 Thread Dmitry Olshansky via Digitalmars-d

29-Sep-2014 03:48, Walter Bright пишет:

On 9/28/2014 2:00 PM, Dmitry Olshansky wrote:

I've already stated my perception of the no stinking exceptions, and
no
destructors 'cause i want it fast elsewhere.

Code must be correct and fast, with correct being a precondition for any
performance tuning and speed hacks.


Sure. I'm not arguing for preferring incorrect code.



Correct usually entails exceptions and automatic cleanup. I also do
not believe
the exceptions have to be slow motto, they are costly but proportion
of such
costs was largely exaggerated.


I think it was you that suggested that instead of throwing on invalid
UTF, that the replacement character be used instead? Or maybe not, I'm
not quite sure.


Aye that was me. I'd much prefer nothrow decoding. There should be an 
option to throw on bad input though (and we have it already), for 
programs that do not expect to work with even partially broken input.




Regardless, the replacement character method is widely used and accepted
practice. There's no reason to throw.




--
Dmitry Olshansky


Re: Creeping Bloat in Phobos

2014-09-29 Thread via Digitalmars-d
On Sunday, 28 September 2014 at 21:00:46 UTC, Dmitry Olshansky 
wrote:

29-Sep-2014 00:33, Andrei Alexandrescu пишет:
The right solution here is refcounted exception plus 
policy-based
functions in conjunction with RCString. I can't believe this 
focus has
already been lost and we're back to let's remove autodecoding 
and ban

exceptions. -- Andrei


Consider what end users are going to use first, then design the 
library to fit the use cases while retaining general usefulness.


If UTF-8 decoding cannot be efficiently done as a generic adapter 
then D's approach to generic programming is a failure: dead on 
arrival.


Generic programming is not supposed to be 
special-case-everything-programming. If you cannot do generic 
programming well on strings, then don't. Provide a concrete 
single dedicated utf-8 string type instead.


I've already stated my perception of the no stinking 
exceptions, and no destructors 'cause i want it fast 
elsewhere.


Code must be correct and fast, with correct being a 
precondition for any performance tuning and speed hacks.


Correct usually entails exceptions and automatic cleanup. I 
also do not believe the exceptions have to be slow motto, 
they are costly but proportion of such costs was largely 
exaggerated.


Correctness has nothing to do with exceptions and an 
exception-specific cleanup model. It has to with having a well 
specified model of memory management, understanding the model and 
implementing code to the model with rigour.


The alternative is to have isolates only, higher level constructs 
only, GC everywhere and uniform activision-records for everything 
(no conceptual stack). Many high level languages work this way, 
even in the 60s.


When it comes to exception efficiency you have many choices:

1. no exceptions, omit frame pointer

2. no extra overhead when not throwing, standard codegen and 
linking, slow unwind


3. no extra overhead when not throwing, nonstandard codegen, 
faster unwind


4. extra overhead when not throwing, nonstandard codegen, fast 
unwind


5. small extra overhead when not throwing, no RAII/single 
landingpad, omit frame pointer possible, very fast unwind 
(C-style longjmp)


6. hidden return error value , fixed medium overhead

D has selected standard C++ (2), which means low overhead when 
not throwing and that you can use regular C backend/linker. In a 
fully GC language I think that (5) is quite acceptable and what 
you usually want when doing a web service. You just bail out to 
the root and you never really acquire resources except for 
transactions that should be terminated in the handler before 
exiting (and they will time out anyway).


But there is no best model. There are trade offs based on what 
kind application you write.


So as usual it comes back to this: what kind of applications are 
D actually targeting?


D is becoming less and less a system level language, and more a 
more a compiled scripting framework.


The more special casing, the less transparent D becomes, and the 
more of a scripting framework it becomes.


A good system level language requires transparency:

- easy to visualize memory layout

- predictable compilation of code to machine language

- no fixed memory model

- no arbitrary limits and presumptions about execution model

- allows you to get close to the max hardware performance 
potential


I have a hard time picturing D as a system level language these 
days. And the hacks that try to make it GC free are not making 
it a better system level language (I don't consider @nogc to be a 
hack). It makes D even less transparent.


Despite all the flaws of the D1 compiler, D1 was fairly 
transparent.


You really need to decide if D is supposed to be primarily a 
system level programming or if it is supposed to provide system 
level programming as an after thought on top of an application 
level programming language.


Currently it is the latter and more so for every iteration.


Re: Creeping Bloat in Phobos

2014-09-29 Thread Marco Leise via Digitalmars-d
Am Sun, 28 Sep 2014 12:38:25 -0700
schrieb Walter Bright newshou...@digitalmars.com:

 I suggest that in the future write code that is explicit about the intention 
 - 
 by character or by decoded character - by using adapters .byChar or .byDchar.

... or by user perceived character or by word or by
line. I'm always on the fence with code points. Sure they
are the code points, but what does it mean in practice?
Is it valid to start a Unicode string with just a diacritical
mark? Does it make sense to split in the middle of Korean
symbols, effectively removing parts of the glyphs and
rendering them invalid?

Bearophile, what does your code _do_ with the dchar ranges?
How is it not rendered into a caricature of its own attempts
to support non-ASCII by the above ?

-- 
Marco



Re: Creeping Bloat in Phobos

2014-09-29 Thread Marco Leise via Digitalmars-d
Am Sun, 28 Sep 2014 16:21:14 -0700
schrieb Walter Bright newshou...@digitalmars.com:

 On 9/28/2014 1:39 PM, H. S. Teoh via Digitalmars-d wrote:
  The problem with pulling such PRs is that they introduce a dichotomy
  into Phobos. Some functions autodecode, some don't, and from a user's
  POV, it's completely arbitrary and random. Which leads to bugs because
  people can't possibly remember exactly which functions autodecode and
  which don't.
 
 That's ALREADY the case, as I explained to bearophile.
 
 The solution is not to have the ranges autodecode, but to have the ALGORITHMS 
 decide to autodecode (if they need it) or not (if they don't).

Yes, that sounds like the right abstraction!

-- 
Marco



Re: Creeping Bloat in Phobos

2014-09-29 Thread Dicebot via Digitalmars-d
I refuse to accept any code gen complaints based on DMD. It's 
optimization facilities are generally crappy compared to gdc / 
ldc and not worth caring about - it is just a reference 
implementation after all. Clean and concise library code is more 
important.


Now if the same inlining failure happens with other two compilers 
- that is something worth talking about (I don't know if it 
happens)


Re: Creeping Bloat in Phobos

2014-09-29 Thread Dicebot via Digitalmars-d

On Sunday, 28 September 2014 at 23:21:15 UTC, Walter Bright wrote:

On 9/28/2014 1:39 PM, H. S. Teoh via Digitalmars-d wrote:
It can work just fine, and I wrote it. The problem is 
convincing

someone to pull it :-( as the PR was closed and reopened with
autodecoding put back in.


The problem with pulling such PRs is that they introduce a 
dichotomy
into Phobos. Some functions autodecode, some don't, and from a 
user's
POV, it's completely arbitrary and random. Which leads to bugs 
because
people can't possibly remember exactly which functions 
autodecode and

which don't.


That's ALREADY the case, as I explained to bearophile.

The solution is not to have the ranges autodecode, but to have 
the ALGORITHMS decide to autodecode (if they need it) or not 
(if they don't).


No it isn't, despite you pretending otherwise. Right now there is 
a simple rule - Phobos does auto-decoding everywhere and any 
failure to do so is considered a bug. Sometimes it is possible to 
bypass decoding for speed-up while preserving semantical 
correctness but it is always implementation detail, from the 
point of view of the API it can't be noticed (for valid unicode 
string at least).


Your proposal would have been a precedent to adding _intetional_ 
exception. It is unacceptable.


Re: Creeping Bloat in Phobos

2014-09-29 Thread Marco Leise via Digitalmars-d
Am Sun, 28 Sep 2014 16:48:53 -0700
schrieb Walter Bright newshou...@digitalmars.com:

 Regardless, the replacement character method is widely used and accepted 
 practice. There's no reason to throw.

I feel a bit uneasy about this. Could it introduce a silent
loss of information? While the replacement character method is
widely used, so is the error method. APIs typically provide
flags for this.

MultiByteToWideChar: The flag MB_ERR_INVALID_CHARS decides
 whether the API errors out or drops invalid chars.
ICU: You set up an error callback. The default replaces
 invalid characters with the Unicode substitution
 character. (We are talking about characters from
 arbitrary charsets like Amiga to Unicode.)
 Other prefab error handlers drop the invalid character or
 error out.
iconv: By default it errors out at the location where an
 incomplete or invalid sequence is detected. With the
 //IGNORE flag, it will silently drop invalid characters.

I'm not opposed to the decision, but I expected the reasoning
to me more along the line of: 
`string` is per definition correct UTF-8. Exception or
substitution character is of no concern to a correctly
written D program, because decoding errors wont happen.
Validate and treat all input as ubyte[]. (Especially when
coming from a Windows console)
or:
We may lose information in the conversion, but it's the only
practical way to reach the @nogc goal. And we are far from
having reference-counted Exceptions.
instead of:
Many people use the substitution character [in unspecified
context], so it follows that it can replace Exceptions for
Phobos' string-dchar decoding. :)

-- 
Marco



Re: Creeping Bloat in Phobos

2014-09-29 Thread monarch_dodra via Digitalmars-d

On Sunday, 28 September 2014 at 23:06:28 UTC, Walter Bright wrote:
Note that autodecode does not always happen - it doesn't happen 
for ranges of chars. It's very hard to look at piece of code 
and tell if autodecode is going to happen or not.


Arguably, this means we need to unify the behavior of strings, 
and string-like objects. Pointing to an inconsistency doesn't 
mean the design is flawed and void.


Re: Creeping Bloat in Phobos

2014-09-29 Thread monarch_dodra via Digitalmars-d

On Sunday, 28 September 2014 at 23:21:15 UTC, Walter Bright wrote:
It's very simple for an algorithm to decode if it needs to, it 
just adds in a .byDchar adapter to its input range. Done. No 
special casing needed. The lines of code written drop in half. 
And it works with both arrays of chars, arrays of dchars, and 
input ranges of either.


This just misses the *entire* familly of algorithms that operate 
on generic types, such as map. EG: the totality of 
std.algorithm. Oops.


Re: Creeping Bloat in Phobos

2014-09-29 Thread monarch_dodra via Digitalmars-d

On Sunday, 28 September 2014 at 23:48:54 UTC, Walter Bright wrote:
I think it was you that suggested that instead of throwing on 
invalid UTF, that the replacement character be used instead? Or 
maybe not, I'm not quite sure.


Regardless, the replacement character method is widely used and 
accepted practice. There's no reason to throw.


This I'm OK to stand stand behind as acceptable change (should we 
decide to go with). It will kill the auto-decode throws and uses 
the GC argument.


Re: Creeping Bloat in Phobos

2014-09-29 Thread monarch_dodra via Digitalmars-d

On Sunday, 28 September 2014 at 23:06:28 UTC, Walter Bright wrote:
It's very hard to disable the autodecode when it is not needed, 
though the new .byCodeUnit has made that much easier.


One issue with this though is that byCodeUnit is not actually 
an array. As such, by using byCodeUnit, you have just as much 
chances of improving performance, as you have of *hurting* 
performance for algorithms that are string optimized.


For example, which would be fastest:
hello world.find(' '); //(1)
hello world.byCodeUnit.find(' '); //(2)

Currently, (1) is faster :/

This is a good argument though to instead use ubyte[] or 
std.encoding.AsciiString.


What I think we (maybe) need though is std.encoding.UTF8Array, 
which explicitly means: This is a range containing UTF8 
characters. I don't want decoding. It's an array you may memchr 
or slice operate on.


Re: Creeping Bloat in Phobos

2014-09-29 Thread Marco Leise via Digitalmars-d
Am Mon, 29 Sep 2014 04:33:08 +0300
schrieb ketmar via Digitalmars-d digitalmars-d@puremagic.com:

 On Sun, 28 Sep 2014 19:44:39 +
 Uranuz via Digitalmars-d digitalmars-d@puremagic.com wrote:
 
  I speaking language which graphemes coded by 2 bytes
 UCS-4? KOI8? my locale is KOI8, and i HATE D for assuming that everyone
 one the planet using UTF-8 and happy with it. from my POV, almost all
 string decoding is broken. string i got from filesystem? good god, lest
 it not contain anything out of ASCII range! string i got from text
 file? the same. string i must write to text file or stdout? oh, 'cmon,
 what do you mean telling me п©я─п╦п╡п╣я┌?! i can't read that!

My friend, we agree here! We must convert the whole world to
UTF-8 eventually to end this madness! But for now when we
write to a terminal, we have to convert to the system locale,
because there are still people who don't use Unicode. (On
Windows consoles the wide-char writing functions are good
enough for NFC strings.)
And a path from the filesystem is actually in no specific
encoding on Unix. We only know it is byte based and uses ASCII
'/' and '\0' as delimiters. On Windows it is ushort based IIRC.
To make matters more messy, Gtk assumes Unicode, while Qt
assumes the user's locale for file names. And in reality it is
determined by the IO charset at mount time.

-- 
Marco


signature.asc
Description: PGP signature


Re: Creeping Bloat in Phobos

2014-09-29 Thread via Digitalmars-d

On Monday, 29 September 2014 at 14:25:34 UTC, monarch_dodra wrote:
This just misses the *entire* familly of algorithms that 
operate on generic types, such as map. EG: the totality of 
std.algorithm. Oops.


But if you know the common operations on strings used in many 
programs, then you want them to perform. So you need a mix of 
special cased precomputed lookup-tables and/or special cased SIMD 
instructions that will outperform a generic map() by a 
significant margin.


I am not arguing against generic apis being desirable, I am 
questioning of the feasibility of being competitive in the space 
of utf-8 strings without designing for SIMD.


Obviously, doing bitwise and 0x80808080...80 followed by a simd 
compare with will beat anything scalar based if you 
want to test for a space in a utf-8 string.


Intel has made a real effort at making UTF-8 SIMD optimizable 
with the last few generations of instruction sets.


Figuring out how to tap into that potential is a lot more 
valuable than defining an api a priori. That means writing SIMD 
code and comparing it to what you have. If SIMD blows what you 
have out of the water, then it ain't god enough.


If you can define the string APIs to fit what SIMD is good at, 
then you are onto something that could be really good. D is in a 
position where you can do that. C++ aint.


Re: Creeping Bloat in Phobos

2014-09-29 Thread Marco Leise via Digitalmars-d
Am Sun, 28 Sep 2014 11:08:13 -0700
schrieb Walter Bright newshou...@digitalmars.com:

 On 9/28/2014 5:06 AM, Uranuz wrote:
  A question: can you list some languages that represent UTF-8 narrow strings 
  as
  array of single bytes?
 
 C and C++.

Not really, C string are in C locale, not a specific
encoding. I.e. it _cannot_ deal with UTF-8 specifically.
Assuming UTF-8 would lead to funny output on consoles and the
like when passing D string to C functions. :)

-- 
Marco



Re: Creeping Bloat in Phobos

2014-09-29 Thread Martin Nowak via Digitalmars-d

On 09/28/2014 02:12 AM, Andrei Alexandrescu wrote:

Noice. Should be told, though, that reading the actual file will
dominate execution time. -- Andrei


Absolutely, and we should have different priorities right now.

It would also help to fix compiler bugs that regularly cause performance 
regressions.


https://issues.dlang.org/show_bug.cgi?id=7625
https://issues.dlang.org/buglist.cgi?keywords=performanceresolution=---



Re: Creeping Bloat in Phobos

2014-09-29 Thread via Digitalmars-d

On Monday, 29 September 2014 at 16:43:17 UTC, Martin Nowak wrote:

On 09/28/2014 02:12 AM, Andrei Alexandrescu wrote:
Noice. Should be told, though, that reading the actual file 
will

dominate execution time. -- Andrei


Absolutely, and we should have different priorities right now.


That is not obvious. Modern parsing techniques that deals with 
ambiguity are O(N^3) to O(N^4), add to this the desire for 
lexer-free parsers and you'll start to see that performance 
matters.




Re: Creeping Bloat in Phobos

2014-09-29 Thread Andrei Alexandrescu via Digitalmars-d
Martin Nowak c...@dawg.eu wrote:
 On 09/28/2014 02:12 AM, Andrei Alexandrescu wrote:
 Noice. Should be told, though, that reading the actual file will
 dominate execution time. -- Andrei
 
 Absolutely, and we should have different priorities right now.
 
 It would also help to fix compiler bugs that regularly cause performance 
 regressions.
 
 https://issues.dlang.org/show_bug.cgi?id=7625
 https://issues.dlang.org/buglist.cgi?keywords=performanceresolution=---

Totally, thank you. -- Andrei


Re: Creeping Bloat in Phobos

2014-09-28 Thread via Digitalmars-d
On Saturday, 27 September 2014 at 23:33:14 UTC, H. S. Teoh via 
Digitalmars-d wrote:
On Sat, Sep 27, 2014 at 11:00:16PM +, bearophile via 
Digitalmars-d wrote:

H. S. Teoh:

If we can get Andrei on board, I'm all for killing off 
autodecoding.


Killing auto-decoding for std.algorithm functions will break 
most of

my D2 code... perhaps we can do that in a D3 language.

[...]

Well, obviously it's not going to be done in a careless, 
drastic way!


There will be a proper migration path and deprecation cycle. We 
already
have byCodeUnit and byCodePoint, and the first step is probably 
to
migrate towards requiring usage of one or the other for 
iterating over
strings, and only once all code is using them, we will get rid 
of
autodecoding (the job now being done by byCodePoint). Then, the 
final
step would be to allow the direct use of strings in iteration 
constructs

again, but this time without autodecoding by default. Of course,
.byCodePoint will still be available for code that needs to use 
it.


The final step would almost inevitably lead to Unicode 
incorrectness, which was the reason why autodecoding was 
introduced in the first place. Just require 
byCodePoint/byCodeUnit, always. It might be a bit inconvenient, 
but that's a consequence of the fact that we're dealing with 
Unicode strings.


Re: Creeping Bloat in Phobos

2014-09-28 Thread bearophile via Digitalmars-d

H. S. Teoh:


There will be a proper migration path and deprecation cycle.


I get refusals if I propose tiny breaking changes that require 
changes in a small amount of user code.  In comparison the user 
code changes you are suggesting are very large.


Bye,
bearophile


Re: Creeping Bloat in Phobos

2014-09-28 Thread Peter Alexander via Digitalmars-d
On Sunday, 28 September 2014 at 00:13:59 UTC, Andrei Alexandrescu 
wrote:

On 9/27/14, 3:40 PM, H. S. Teoh via Digitalmars-d wrote:
If we can get Andrei on board, I'm all for killing off 
autodecoding.


That's rather vague; it's unclear what would replace it. -- 
Andrei


No autodecoding ;-)

Specifically:

1. ref T front(T[] r) always returns r[0]
2. popFront(ref T[] r) always does { ++r.ptr; --r.length; }
3. Narrow string will be hasLength, hasSlicing, 
isRandomAccessRange (i.e. they are just like any other array).


Also:

4. Disallow implicit conversions, comparisons, or any operation 
among char, wchar, dchar. This makes things like foo.find('π') 
compile time errors (or better, errors until we specialize to it 
to do foo.find(π), as it should)
5. Provide byCodePoint for narrow strings (although I suspect 
this will be rarely used).


The argument is as follows:
* First, this is a hell of a lot simpler for the implementation.
* People rarely ever search for single, non-ASCII characters in 
strings, and #4 makes it an error if they do (until we specialize 
to make it work).
* Searching, comparison, joining, and splitting functions will be 
fast and correct by default.


One possible counter argument is that this makes it easier to 
corrupt strings (since you could, e.g. insert a substring into 
the middle of a multi-byte code point). To that I say that it's 
unlikely. When inserting into a string, you're either doing it at 
the front or back (which is safe), or to some point that you've 
found by some other means (e.g. using find). I can't imagine a 
scenario where you could find a point in the middle of a string, 
that is in the middle of a code point.


Of course, I'd probably say this change isn't practical right 
now, but this is how I'd do things if I were to start over.


Re: Creeping Bloat in Phobos

2014-09-28 Thread Marco Leise via Digitalmars-d
Am Sun, 28 Sep 2014 10:04:21 +
schrieb Marc Schütz schue...@gmx.net:

 On Saturday, 27 September 2014 at 23:33:14 UTC, H. S. Teoh via 
 Digitalmars-d wrote:
  On Sat, Sep 27, 2014 at 11:00:16PM +, bearophile via 
  Digitalmars-d wrote:
  H. S. Teoh:
  
  If we can get Andrei on board, I'm all for killing off 
  autodecoding.
  
  Killing auto-decoding for std.algorithm functions will break 
  most of
  my D2 code... perhaps we can do that in a D3 language.
  [...]
 
  Well, obviously it's not going to be done in a careless, 
  drastic way!
 
  There will be a proper migration path and deprecation cycle. We 
  already
  have byCodeUnit and byCodePoint, and the first step is probably 
  to
  migrate towards requiring usage of one or the other for 
  iterating over
  strings, and only once all code is using them, we will get rid 
  of
  autodecoding (the job now being done by byCodePoint). Then, the 
  final
  step would be to allow the direct use of strings in iteration 
  constructs
  again, but this time without autodecoding by default. Of course,
  .byCodePoint will still be available for code that needs to use 
  it.
 
 The final step would almost inevitably lead to Unicode 
 incorrectness, which was the reason why autodecoding was 
 introduced in the first place. Just require 
 byCodePoint/byCodeUnit, always. It might be a bit inconvenient, 
 but that's a consequence of the fact that we're dealing with 
 Unicode strings.

And I would go so far to say that you have to make an informed
decision between code unit, code point and grapheme. They are
all useful. Graphemes being the most generally useful, hiding
away normalization and allowing cutting by user perceived
character.

-- 
Marco



Re: Creeping Bloat in Phobos

2014-09-28 Thread Dmitry Olshansky via Digitalmars-d

28-Sep-2014 00:57, Walter Bright пишет:

 From time to time, I take a break from bugs and enhancements and just
look at what some piece of code is actually doing. Sometimes, I'm
appalled. Phobos, for example, should be a lean and mean fighting machine:


http://www.nbcnews.com/id/38545625/ns/technology_and_science-science/t/king-tuts-chariots-were-formula-one-cars/#.VCceNmd0xjs


Instead, we have something more akin to:


http://untappedcities.com/2012/10/31/roulez-carrosses-carriages-of-versailles-arrive-in-arras/


More specifically, I looked at std.file.copy():

   https://github.com/D-Programming-Language/phobos/blob/master/std/file.d

Which is 3 lines of code:

   void copy(in char[] from, in char[] to) {
 immutable result = CopyFileW(from.tempCStringW(),
to.tempCStringW(), false);
 if (!result)
 throw new FileException(to.idup);
   }

Compiling this code for Windows produces the rather awful:


In all honesty - 2 RAII structs w/o inlining + setting up exception 
frame + creating and allocating an exception + idup-ing a string does 
account to about this much.





_D3std4file4copyFxAaxAaZv   comdat
 assume  CS:_D3std4file4copyFxAaxAaZv
L0: pushEBP
 mov EBP,ESP
 mov EDX,FS:__except_list
 push0h
 lea EAX,-0220h[EBP]
 pushoffset _D3std4file4copyFxAaxAaZv[0106h]
 pushEDX
 mov FS:__except_list,ESP
 sub ESP,8
 sub ESP,041Ch
 push0
 pushdword ptr 0Ch[EBP]
 pushdword ptr 8[EBP]
 callnear ptr
_D3std8internal7cstring21__T11tempCSÇàÆTuTaZÇìÆFNbNixAaZSÇ┬├3Res
 mov dword ptr -4[EBP],0
 lea EAX,-0220h[EBP]
 callnear ptr
_D3std8internal7cstring21__T11tempCStringTuTaZ11tempCStringFNbNixAaZ3Res3ptrMxFNaNbNdNiNfZPxu

 pushEAX
 lea EAX,-0430h[EBP]
 pushdword ptr 014h[EBP]
 pushdword ptr 010h[EBP]
 callnear ptr
_D3std8internal7cstring21__T11tempCSÇàÆTuTaZÇìÆFNbNixAaZSÇ┬├3Res
 mov dword ptr -4[EBP],1
 lea EAX,-0430h[EBP]
 callnear ptr
_D3std8internal7cstring21__T11tempCStringTuTaZ11tempCStringFNbNixAaZ3Res3ptrMxFNaNbNdNiNfZPxu

 pushEAX
 calldword ptr __imp__CopyFileW@12
 mov -01Ch[EBP],EAX
 mov dword ptr -4[EBP],0
 callnear ptr L83
 jmp short   L8F
L83:lea EAX,-0220h[EBP]
 callnear ptr
_D3std8internal7cstring21__T11tempCStringTuTaZ11tempCStringFNbNixAaZ3Res6__dtorMFNbNiZv

 ret
L8F:mov dword ptr -4[EBP],0h
 callnear ptr L9D
 jmp short   LA9
L9D:lea EAX,-0430h[EBP]
 callnear ptr
_D3std8internal7cstring21__T11tempCStringTuTaZ11tempCStringFNbNixAaZ3Res6__dtorMFNbNiZv

 ret
LA9:cmp dword ptr -01Ch[EBP],0
 jne LF3
 mov ECX,offset
FLAT:_D3std4file13FileException7__ClassZ
 pushECX
 callnear ptr __d_newclass
 add ESP,4
 pushdword ptr 0Ch[EBP]
 mov -018h[EBP],EAX
 pushdword ptr 8[EBP]
 callnear ptr
_D6object12__T4idupTxaZ4idupFNaNbNdNfAxaZAya
 pushEDX
 pushEAX
 calldword ptr __imp__GetLastError@0
 pushEAX
 pushdword ptr _D3std4file13FileException6__vtblZ[02Ch]
 pushdword ptr _D3std4file13FileException6__vtblZ[028h]
 push095Dh
 mov EAX,-018h[EBP]
 callnear ptr
_D3std4file13FileException6__ctorMFNfxAakAyakZC3std4file13FileException
 pushEAX
 callnear ptr __d_throwc
LF3:mov ECX,-0Ch[EBP]
 mov FS:__except_list,ECX
 mov ESP,EBP
 pop EBP
 ret 010h
 mov EAX,offset
FLAT:_D3std4file13FileException6__vtblZ[0310h]
 jmp near ptr __d_framehandler

which is TWICE as much generated code as for D1's copy(), which does the
same thing. No, it is not because D2's compiler sux. It's because it has
become encrustified with gee-gaws, jewels, decorations, and other crap.

To scrape the barnacles off, I've filed:

https://issues.dlang.org/show_bug.cgi?id=13541
https://issues.dlang.org/show_bug.cgi?id=13542
https://issues.dlang.org/show_bug.cgi?id=13543

Re: Creeping Bloat in Phobos

2014-09-28 Thread Uranuz via Digitalmars-d
On Sunday, 28 September 2014 at 00:13:59 UTC, Andrei Alexandrescu 
wrote:

On 9/27/14, 3:40 PM, H. S. Teoh via Digitalmars-d wrote:
If we can get Andrei on board, I'm all for killing off 
autodecoding.


That's rather vague; it's unclear what would replace it. -- 
Andrei


I believe that removing autodeconding will make things even 
worse. As far as understand if we will remove it from front() 
function that operates on narrow strings then it will return just 
byte of char. I believe that proceeding on narrow string by `user 
perceived chars` (graphemes) is more common use case. Operating 
on single bytes of multibyte character is uncommon task and you 
can do that via direct indexing of char[] array. I believe what 
number of bytes is in *user perceived chars* is internal 
implementation of UTF-8 encoding and it should not be considered 
in common tasks such as parsing, searching, replacing text and 
etc. If you need byte representation of string you should cast it 
into ubyte[] and work with it using the same range functions 
without autodecoding.


The main problem that I see that unexpirienced in D programmer 
can be confused where he operates by bytes or by graphemes. 
Especially it could happen when he migrates from C#, Python where 
string is not considered as array of it's bytes. Because *char* 
in D is not char it's a part of char, but not entire char. It's 
main inconsistence.


Possible solution is to include class or struct implementation of 
string and hide internal implementation of narrow string for 
those users who don't need to operate on single bytes of UTF-8 
characters. I believe it's the best way to kill all the rabbits)) 
We could provide this class String with method returning ubyte[] 
(better way) or char[] that will expose internal implementation 
for those who need it.


A question: can you list some languages that represent UTF-8 
narrow strings as array of single bytes?


Re: Creeping Bloat in Phobos

2014-09-28 Thread Andrei Alexandrescu via Digitalmars-d

On 9/27/14, 4:31 PM, H. S. Teoh via Digitalmars-d wrote:

On Sat, Sep 27, 2014 at 11:00:16PM +, bearophile via Digitalmars-d wrote:

H. S. Teoh:


If we can get Andrei on board, I'm all for killing off autodecoding.


Killing auto-decoding for std.algorithm functions will break most of
my D2 code... perhaps we can do that in a D3 language.

[...]

Well, obviously it's not going to be done in a careless, drastic way!


Stuff that's missing:

* Reasonable effort to improve performance of auto-decoding;

* A study of the matter revealing either new artifacts and idioms, or 
the insufficiency of such;


* An assessment of the impact on compilability of existing code

* An assessment of the impact on correctness of existing code (that 
compiles and runs in both cases)


* An assessment of the improvement in speed of eliminating auto-decoding

I think there's a very strong need for this stuff, because claims that 
current alternatives to selectively avoid auto-decoding use the throwing 
of hands (and occasional chairs out windows) without any real 
investigation into how library artifacts may help. This approach to 
justifying risky moves is frustratingly unprincipled.


Also I submit that diverting into this is a huge distraction at probably 
the worst moment in the history of the D programming language.


C++ and GC. C++ and GC...



Andrei



Re: Creeping Bloat in Phobos

2014-09-28 Thread Andrei Alexandrescu via Digitalmars-d

On 9/28/14, 3:04 AM, Marc Schütz schue...@gmx.net wrote:

The final step would almost inevitably lead to Unicode incorrectness,
which was the reason why autodecoding was introduced in the first place.
Just require byCodePoint/byCodeUnit, always. It might be a bit
inconvenient, but that's a consequence of the fact that we're dealing
with Unicode strings.


Also let's not forget how well it's worked for C++ to conflate arrays of 
char with Unicode strings. -- Andrei




Re: Creeping Bloat in Phobos

2014-09-28 Thread H. S. Teoh via Digitalmars-d
On Sun, Sep 28, 2014 at 12:06:16PM +, Uranuz via Digitalmars-d wrote:
 On Sunday, 28 September 2014 at 00:13:59 UTC, Andrei Alexandrescu wrote:
 On 9/27/14, 3:40 PM, H. S. Teoh via Digitalmars-d wrote:
 If we can get Andrei on board, I'm all for killing off autodecoding.
 
 That's rather vague; it's unclear what would replace it. -- Andrei
 
 I believe that removing autodeconding will make things even worse. As
 far as understand if we will remove it from front() function that
 operates on narrow strings then it will return just byte of char. I
 believe that proceeding on narrow string by `user perceived chars`
 (graphemes) is more common use case.
[...]

Unfortunately this is not what autodecoding does today. Today's
autodecoding only segments strings into code *points*, which are not the
same thing as graphemes. For example, combining diacritics are normally
not considered separate characters from the user's POV, but they *are*
separate codepoints from their base character. The only reason today's
autodecoding is even remotely considered correct from an intuitive POV
is because most Western character sets happen to use only precomposed
characters rather than combining diacritic sequences. If you were
processing, say, Korean text, the present autodecoding .front would
*not* give you what you might imagine is a single character; it would
only be halves of Korean graphemes. Which, from a user's POV, would
suffer from the same issues as dealing with individual bytes in a UTF-8
stream -- any mistake on the program's part in handling these half-units
will cause corruption of the text (not corruption in the same sense as
an improperly segmented UTF-8 byte stream, but in the sense that the
wrong glyphs will be displayed on the screen -- from the user's POV
these two are basically the same thing).

You might then be tempted to say, well let's make .front return
graphemes instead. That will solve the single intuitive character
issue, but the performance will be FAR worse than what it is today.

So basically, what we have today is neither efficient nor complete, but
a halfway solution that mostly works for Western character sets but
is incomplete for others. We're paying efficiency for only a partial
benefit. Is it worth the cost?

I think the correct solution is not for Phobos to decide for the
application at what level of abstraction a string ought to be processed.
Rather, let the user decide. If they're just dealing with opaque blocks
of text, decoding or segmenting by grapheme is completely unnecessary --
they should just operate on byte ranges as opaque data. They should use
byCodeUnit. If they need to work with Unicode codepoints, let them use
byCodePoint. If they need to work with individual user-perceived
characters (i.e., graphemes), let them use byGrapheme.

This is why I proposed the deprecation path of making it illegal to pass
raw strings to Phobos algorithms -- the caller should specify what level
of abstraction they want to work with -- byCodeUnit, byCodePoint, or
byGrapheme. The standard library's job is to empower the D programmer by
giving him the choice, not to shove a predetermined solution down his
throat.


T

-- 
Life is unfair. Ask too much from it, and it may decide you don't
deserve what you have now either.


Re: Creeping Bloat in Phobos

2014-09-28 Thread John Colvin via Digitalmars-d
On Sunday, 28 September 2014 at 14:38:57 UTC, H. S. Teoh via 
Digitalmars-d wrote:
On Sun, Sep 28, 2014 at 12:06:16PM +, Uranuz via 
Digitalmars-d wrote:
On Sunday, 28 September 2014 at 00:13:59 UTC, Andrei 
Alexandrescu wrote:

On 9/27/14, 3:40 PM, H. S. Teoh via Digitalmars-d wrote:
If we can get Andrei on board, I'm all for killing off 
autodecoding.


That's rather vague; it's unclear what would replace it. -- 
Andrei


I believe that removing autodeconding will make things even 
worse. As
far as understand if we will remove it from front() function 
that
operates on narrow strings then it will return just byte of 
char. I
believe that proceeding on narrow string by `user perceived 
chars`

(graphemes) is more common use case.

[...]

Unfortunately this is not what autodecoding does today. Today's
autodecoding only segments strings into code *points*, which 
are not the
same thing as graphemes. For example, combining diacritics are 
normally
not considered separate characters from the user's POV, but 
they *are*
separate codepoints from their base character. The only reason 
today's
autodecoding is even remotely considered correct from an 
intuitive POV
is because most Western character sets happen to use only 
precomposed
characters rather than combining diacritic sequences. If you 
were
processing, say, Korean text, the present autodecoding .front 
would
*not* give you what you might imagine is a single character; 
it would
only be halves of Korean graphemes. Which, from a user's POV, 
would
suffer from the same issues as dealing with individual bytes in 
a UTF-8
stream -- any mistake on the program's part in handling these 
half-units
will cause corruption of the text (not corruption in the same 
sense as
an improperly segmented UTF-8 byte stream, but in the sense 
that the
wrong glyphs will be displayed on the screen -- from the user's 
POV

these two are basically the same thing).

You might then be tempted to say, well let's make .front return
graphemes instead. That will solve the single intuitive 
character
issue, but the performance will be FAR worse than what it is 
today.


So basically, what we have today is neither efficient nor 
complete, but
a halfway solution that mostly works for Western character sets 
but
is incomplete for others. We're paying efficiency for only a 
partial

benefit. Is it worth the cost?

I think the correct solution is not for Phobos to decide for the
application at what level of abstraction a string ought to be 
processed.
Rather, let the user decide. If they're just dealing with 
opaque blocks
of text, decoding or segmenting by grapheme is completely 
unnecessary --
they should just operate on byte ranges as opaque data. They 
should use
byCodeUnit. If they need to work with Unicode codepoints, let 
them use

byCodePoint. If they need to work with individual user-perceived
characters (i.e., graphemes), let them use byGrapheme.

This is why I proposed the deprecation path of making it 
illegal to pass
raw strings to Phobos algorithms -- the caller should specify 
what level
of abstraction they want to work with -- byCodeUnit, 
byCodePoint, or
byGrapheme. The standard library's job is to empower the D 
programmer by
giving him the choice, not to shove a predetermined solution 
down his

throat.


T


I totally agree with all of that.

It's one of those cases where correct by default is far too slow 
(that would have to be graphemes) but fast by default is far too 
broken. Better to force an explicit choice.


There is no magic bullet for unicode in a systems language such 
as D. The programmer must be aware of it and make choices about 
how to treat it.


Re: Creeping Bloat in Phobos

2014-09-28 Thread Walter Bright via Digitalmars-d

On 9/28/2014 5:06 AM, Uranuz wrote:

A question: can you list some languages that represent UTF-8 narrow strings as
array of single bytes?


C and C++.


Re: Creeping Bloat in Phobos

2014-09-28 Thread Walter Bright via Digitalmars-d

On 9/28/2014 4:46 AM, Dmitry Olshansky wrote:

In all honesty - 2 RAII structs w/o inlining + setting up exception frame +
creating and allocating an exception + idup-ing a string does account to about
this much.


Twice as much generated code as actually necessary, and this is just for 3 lines 
of source code.




Re: Creeping Bloat in Phobos

2014-09-28 Thread Walter Bright via Digitalmars-d

On 9/28/2014 10:03 AM, John Colvin wrote:

There is no magic bullet for unicode in a systems language such as D. The
programmer must be aware of it and make choices about how to treat it.


That's really the bottom line.

The trouble with autodecode is it is done at the lowest level, meaning it is 
very hard to bypass. By moving the decision up a level (by using .byDchar or 
.byCodeUnit adapters) the caller makes the decision.


Re: Creeping Bloat in Phobos

2014-09-28 Thread Walter Bright via Digitalmars-d

On 9/28/2014 3:14 AM, bearophile wrote:

I get refusals if I propose tiny breaking changes that require changes in a
small amount of user code.  In comparison the user code changes you are
suggesting are very large.


I'm painfully aware of what a large change removing autodecoding is. That means 
it'll take a long time to do it. In the meantime, we can stop adding new code to 
Phobos that does autodecoding. We have taken the first step by adding the 
.byDchar and .byCodeUnit adapters.




Re: Creeping Bloat in Phobos

2014-09-28 Thread Walter Bright via Digitalmars-d

On 9/28/2014 5:09 AM, Andrei Alexandrescu wrote:

Stuff that's missing:

* Reasonable effort to improve performance of auto-decoding;

* A study of the matter revealing either new artifacts and idioms, or the
insufficiency of such;

* An assessment of the impact on compilability of existing code

* An assessment of the impact on correctness of existing code (that compiles and
runs in both cases)

* An assessment of the improvement in speed of eliminating auto-decoding

I think there's a very strong need for this stuff, because claims that current
alternatives to selectively avoid auto-decoding use the throwing of hands (and
occasional chairs out windows) without any real investigation into how library
artifacts may help. This approach to justifying risky moves is frustratingly
unprincipled.


I know I have to go a ways further to convince you :-) This is definitely a 
longer term issue, not a stop-the-world-we-must-fix-it-now thing.




Also I submit that diverting into this is a huge distraction at probably the
worst moment in the history of the D programming language.


I don't plan to work on this particular issue for the time being, but do want to 
stop adding more autodecoding functions like the proposed std.path.withExtension().




C++ and GC. C++ and GC...


Currently, the autodecoding functions allocate with the GC and throw as well. 
(They'll GC allocate an exception and throw it if they encounter an invalid UTF 
sequence. The adapters use the more common method of inserting a substitution 
character and continuing on.) This makes it harder to make GC-free Phobos code.




Re: Creeping Bloat in Phobos

2014-09-28 Thread bearophile via Digitalmars-d

Walter Bright:

I'm painfully aware of what a large change removing 
autodecoding is. That means it'll take a long time to do it. In 
the meantime, we can stop adding new code to Phobos that does 
autodecoding. We have taken the first step by adding the 
.byDchar and .byCodeUnit adapters.


We have .representation and .assumeUTF, I am using it to avoid 
most autodecoding problems. Have you tried to use them in your D 
code?


The changes you propose seem able to break almost every D program 
I have written (most or all code that uses strings with Phobos 
ranges/algorithms, and I use them everywhere). Compared to this 
change, disallowing comma operator to implement nice built-in 
tuples will cause nearly no breakage in my code (I have done a 
small analysis of the damages caused by disallowing the tuple 
operator in my code). It sounds like a change fit for a D3 
language, even more than the introduction of reference counting. 
I think this change will cause some people to permanently stop 
using D.


In the end you are the designer and the benevolent dictator of D, 
I am not qualified to refuse or oppose such changes. But before 
doing this change I suggest to study how many changes it causes 
in an average small D program that uses strings and 
ranges/algorithms.


Bye,
bearophile


Re: Creeping Bloat in Phobos

2014-09-28 Thread bearophile via Digitalmars-d

Walter Bright:

but do want to stop adding more autodecoding functions like the 
proposed std.path.withExtension().


I am not sure that can work. Perhaps you need to create a range2 
and algorithm2 modules, and keep adding some autodecoding 
functions to the old modules.


Bye,
bearophile


Re: Creeping Bloat in Phobos

2014-09-28 Thread Walter Bright via Digitalmars-d

On 9/28/2014 11:39 AM, bearophile wrote:

Walter Bright:


I'm painfully aware of what a large change removing autodecoding is. That
means it'll take a long time to do it. In the meantime, we can stop adding new
code to Phobos that does autodecoding. We have taken the first step by adding
the .byDchar and .byCodeUnit adapters.


We have .representation and .assumeUTF, I am using it to avoid most autodecoding
problems. Have you tried to use them in your D code?


Yes. They don't work. Well, technically they do work, but your code gets 
filled with explicit casts, which is awful.


The problem is the representation of char[] is type char, not type ubyte.



The changes you propose seem able to break almost every D program I have written
(most or all code that uses strings with Phobos ranges/algorithms, and I use
them everywhere). Compared to this change, disallowing comma operator to
implement nice built-in tuples will cause nearly no breakage in my code (I have
done a small analysis of the damages caused by disallowing the tuple operator in
my code). It sounds like a change fit for a D3 language, even more than the
introduction of reference counting. I think this change will cause some people
to permanently stop using D.


It's quite possible we will be unable to make this change. But the question that 
started all this would be what would I change if breaking code was allowed.


I suggest that in the future write code that is explicit about the intention - 
by character or by decoded character - by using adapters .byChar or .byDchar.




Re: Creeping Bloat in Phobos

2014-09-28 Thread Uranuz via Digitalmars-d

I totally agree with all of that.

It's one of those cases where correct by default is far too 
slow (that would have to be graphemes) but fast by default is 
far too broken. Better to force an explicit choice.


There is no magic bullet for unicode in a systems language such 
as D. The programmer must be aware of it and make choices about 
how to treat it.


I see didn't know about difference between byCodeUnit and
byGrapheme, because I speak Russian and it is close to English,
because it doesn't have diacritics. As far as I remember German,
that I learned at school have diacritics. So you opened my eyes
in this question. My position as usual programmer is that I
speaking language which graphemes coded by 2 bytes and I alwas
need to do decoding otherwise my programme will be broken. Other
possibility is to use wstring or dstring, but it is less memory
efficient. Also UTF-8 is more commonly used in the Internet so I
don't want to do some conversions to UTF-32, for example.

Where I could read about byGrapheme? Isn't this approach
overcomplicated? I don't want to write Dostoevskiy's book War
and Peace in order to write some parser for simple DSL.


Re: Creeping Bloat in Phobos

2014-09-28 Thread Walter Bright via Digitalmars-d

On 9/28/2014 11:51 AM, bearophile wrote:

Walter Bright:


but do want to stop adding more autodecoding functions like the proposed
std.path.withExtension().


I am not sure that can work. Perhaps you need to create a range2 and algorithm2
modules, and keep adding some autodecoding functions to the old modules.


It can work just fine, and I wrote it. The problem is convincing someone to pull 
it :-( as the PR was closed and reopened with autodecoding put back in.


As I've explained many times, very few string algorithms actually need decoding 
at all. 'find', for example, does not. Trying to make a separate universe out of 
autodecoding algorithms is missing the point.


Certainly, setExtension() does not need autodecoding, and in fact all the 
autodecoding in it does is slow it down, allocate memory on errors, make it 
throwable, and produce dchar output, meaning at some point later you'll need to 
put it back to char.


I.e. there are no operations on paths that require decoding.

I know that you care about performance - you post about it often. I would expect 
that unnecessary and pervasive decoding would be of concern to you.


Re: Creeping Bloat in Phobos

2014-09-28 Thread Dmitry Olshansky via Digitalmars-d

28-Sep-2014 23:44, Uranuz пишет:

I totally agree with all of that.

It's one of those cases where correct by default is far too slow (that
would have to be graphemes) but fast by default is far too broken.
Better to force an explicit choice.

There is no magic bullet for unicode in a systems language such as D.
The programmer must be aware of it and make choices about how to treat
it.


I see didn't know about difference between byCodeUnit and
byGrapheme, because I speak Russian and it is close to English,
because it doesn't have diacritics. As far as I remember German,
that I learned at school have diacritics. So you opened my eyes
in this question. My position as usual programmer is that I
speaking language which graphemes coded by 2 bytes


In UTF-16 and UTF-8.


and I alwas
need to do decoding otherwise my programme will be broken. Other
possibility is to use wstring or dstring, but it is less memory
efficient. Also UTF-8 is more commonly used in the Internet so I
don't want to do some conversions to UTF-32, for example.

Where I could read about byGrapheme?


std.uni docs:
http://dlang.org/phobos/std_uni.html#.byGrapheme


Isn't this approach
overcomplicated? I don't want to write Dostoevskiy's book War
and Peace in order to write some parser for simple DSL.


It's Tolstoy actually:
http://en.wikipedia.org/wiki/War_and_Peace

You don't need byGrapheme for simple DSL. In fact as long as DSL is 
simple enough (ASCII only) you may safely avoid decoding. If it's in 
Russian you might want to decode. Even in this case there are ways to 
avoid decoding, it may involve a bit of writing in as for typical short 
novel ;)


In fact I did a couple of such literature exercises in std library.

For codepoint lookups on non-decoded strings:
http://dlang.org/phobos/std_uni.html#.utfMatcher

And to create sets of codepoints to detect with matcher:
http://dlang.org/phobos/std_uni.html#.CodepointSet

--
Dmitry Olshansky


Re: Creeping Bloat in Phobos

2014-09-28 Thread Andrei Alexandrescu via Digitalmars-d

On 9/28/14, 11:36 AM, Walter Bright wrote:

Currently, the autodecoding functions allocate with the GC and throw as
well. (They'll GC allocate an exception and throw it if they encounter
an invalid UTF sequence. The adapters use the more common method of
inserting a substitution character and continuing on.) This makes it
harder to make GC-free Phobos code.


The right solution here is refcounted exception plus policy-based 
functions in conjunction with RCString. I can't believe this focus has 
already been lost and we're back to let's remove autodecoding and ban 
exceptions. -- Andrei


Re: Creeping Bloat in Phobos

2014-09-28 Thread bearophile via Digitalmars-d

Walter Bright:

It can work just fine, and I wrote it. The problem is 
convincing someone to pull it :-( as the PR was closed and 
reopened with autodecoding put back in.


Perhaps you need a range2 and algorithm2 modules. Introducing 
your changes in a sneaky way may not produce well working and 
predictable user code.



I know that you care about performance - you post about it 
often. I would expect that unnecessary and pervasive decoding 
would be of concern to you.


I care first of all about program correctness (that's why I 
proposed unusual things like optional strong typing for built-in 
array indexes, or I proposed the enum preconditions). Secondly 
I care for performance in the functions or parts of code where 
performance is needed. There are plenty of code where performance 
is not the most important thing. That's why I have tons of 
range-base code. In such large parts of code having short, 
correct, nice looking code that looks correct is more important. 
Please don't assume I am simple minded :-)


Bye,
bearophile


Re: Creeping Bloat in Phobos

2014-09-28 Thread H. S. Teoh via Digitalmars-d
On Sun, Sep 28, 2014 at 12:57:17PM -0700, Walter Bright via Digitalmars-d wrote:
 On 9/28/2014 11:51 AM, bearophile wrote:
 Walter Bright:
 
 but do want to stop adding more autodecoding functions like the
 proposed std.path.withExtension().
 
 I am not sure that can work. Perhaps you need to create a range2 and
 algorithm2 modules, and keep adding some autodecoding functions to
 the old modules.
 
 It can work just fine, and I wrote it. The problem is convincing
 someone to pull it :-( as the PR was closed and reopened with
 autodecoding put back in.

The problem with pulling such PRs is that they introduce a dichotomy
into Phobos. Some functions autodecode, some don't, and from a user's
POV, it's completely arbitrary and random. Which leads to bugs because
people can't possibly remember exactly which functions autodecode and
which don't.


 As I've explained many times, very few string algorithms actually need
 decoding at all. 'find', for example, does not. Trying to make a
 separate universe out of autodecoding algorithms is missing the point.
[...]

Maybe what we need to do, is to change the implementation of
std.algorithm so that it internally uses byCodeUnit for narrow strings
where appropriate. We're already specialcasing Phobos code for narrow
strings anyway, so it wouldn't make things worse by making those special
cases not autodecode.

This doesn't quite solve the issue of composing ranges, since one
composed range returns dchar in .front composed with another range will
have autodecoding built into it. For those cases, perhaps one way to
hack around the present situation is to use Phobos-private enums in the
wrapper ranges (e.g., enum isNarrowStringUnderneath=true; in struct
Filter or something), that ranges downstream can test for, and do the
appropriate bypasses.

(BTW, before you pick on specific algorithms you might want to actually
look at the code for things like find(), because I remember there were a
couple o' PRs where find() of narrow strings will use (presumably) fast
functions like strstr or strchr, bypassing a foreach loop over an
autodecoding .front.)


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: Creeping Bloat in Phobos

2014-09-28 Thread Uranuz via Digitalmars-d

It's Tolstoy actually:
http://en.wikipedia.org/wiki/War_and_Peace

You don't need byGrapheme for simple DSL. In fact as long as 
DSL is simple enough (ASCII only) you may safely avoid 
decoding. If it's in Russian you might want to decode. Even in 
this case there are ways to avoid decoding, it may involve a 
bit of writing in as for typical short novel ;)


Yes, my mistake ;) I was thinking about *Crime and Punishment* 
but writen *War and Peace*. Don't know why. May be because it is 
longer.


Thanks for useful links. As far as we are talking about standard 
library I think that some stanard aproach should be provided to 
solve often tasks: searching, sorting, parsing, splitting 
strings. I see that currently we have a lot of ways of doing 
similar things with strings. I think this is a problem of 
documentation at some part. When I parsing text I can't 
understand why I need to use all of these range interfaces 
instead of just manipulating on raw narrow string. We have 
several modules about working on strings: std.range, 
std.algorithm, std.string, std.array, std.utf and I can't see how 
they help me to solve my problems. In opposite they just creating 
me new problem to think of them in order to find *right* way. So 
most of my time I spend on thinking about it but not solving my 
task.


It is hard for me to accept that we don't need to decode to do 
some operations. What is annoying is that I always need to think 
of codelength that I should show to user and byte length that is 
used to slice char array. It's very easy to be confused with them 
and do something wrong.


I see that all is complicated we have 3 types of character and 
more than 5 modules for trivial manipulations on strings with 
10ths of functions. It all goes into hell. But I don't even 
started to do my job. And we don't have *standard* way to deal 
with it in std lib. At least this way in not documented enough.


Re: Creeping Bloat in Phobos

2014-09-28 Thread Andrei Alexandrescu via Digitalmars-d

On 9/28/14, 1:39 PM, H. S. Teoh via Digitalmars-d wrote:

On Sun, Sep 28, 2014 at 12:57:17PM -0700, Walter Bright via Digitalmars-d wrote:

On 9/28/2014 11:51 AM, bearophile wrote:

Walter Bright:


but do want to stop adding more autodecoding functions like the
proposed std.path.withExtension().


I am not sure that can work. Perhaps you need to create a range2 and
algorithm2 modules, and keep adding some autodecoding functions to
the old modules.


It can work just fine, and I wrote it. The problem is convincing
someone to pull it :-( as the PR was closed and reopened with
autodecoding put back in.


The problem with pulling such PRs is that they introduce a dichotomy
into Phobos. Some functions autodecode, some don't, and from a user's
POV, it's completely arbitrary and random. Which leads to bugs because
people can't possibly remember exactly which functions autodecode and
which don't.


I agree. -- Andrei




Re: Creeping Bloat in Phobos

2014-09-28 Thread Dmitry Olshansky via Digitalmars-d

29-Sep-2014 00:39, H. S. Teoh via Digitalmars-d пишет:

On Sun, Sep 28, 2014 at 12:57:17PM -0700, Walter Bright via Digitalmars-d wrote:

On 9/28/2014 11:51 AM, bearophile wrote:

Walter Bright:


but do want to stop adding more autodecoding functions like the
proposed std.path.withExtension().


I am not sure that can work. Perhaps you need to create a range2 and
algorithm2 modules, and keep adding some autodecoding functions to
the old modules.


It can work just fine, and I wrote it. The problem is convincing
someone to pull it :-( as the PR was closed and reopened with
autodecoding put back in.


The problem with pulling such PRs is that they introduce a dichotomy
into Phobos. Some functions autodecode, some don't, and from a user's
POV, it's completely arbitrary and random. Which leads to bugs because
people can't possibly remember exactly which functions autodecode and
which don't.



Agreed.




As I've explained many times, very few string algorithms actually need
decoding at all. 'find', for example, does not. Trying to make a
separate universe out of autodecoding algorithms is missing the point.

[...]

Maybe what we need to do, is to change the implementation of
std.algorithm so that it internally uses byCodeUnit for narrow strings
where appropriate. We're already specialcasing Phobos code for narrow
strings anyway, so it wouldn't make things worse by making those special
cases not autodecode.

This doesn't quite solve the issue of composing ranges, since one
composed range returns dchar in .front composed with another range will
have autodecoding built into it. For those cases, perhaps one way to
hack around the present situation is to use Phobos-private enums in the
wrapper ranges (e.g., enum isNarrowStringUnderneath=true; in struct
Filter or something), that ranges downstream can test for, and do the
appropriate bypasses.



We need to either generalize the hack we did for char[] and wchar[] or 
start creating a whole new phobos without auto-decoding.


I'm not sure what's best but the latter is more disruptive.


(BTW, before you pick on specific algorithms you might want to actually
look at the code for things like find(), because I remember there were a
couple o' PRs where find() of narrow strings will use (presumably) fast
functions like strstr or strchr, bypassing a foreach loop over an
autodecoding .front.)



Yes, it has fast path.


--
Dmitry Olshansky


Re: Creeping Bloat in Phobos

2014-09-28 Thread Dmitry Olshansky via Digitalmars-d

29-Sep-2014 00:33, Andrei Alexandrescu пишет:

On 9/28/14, 11:36 AM, Walter Bright wrote:

Currently, the autodecoding functions allocate with the GC and throw as
well. (They'll GC allocate an exception and throw it if they encounter
an invalid UTF sequence. The adapters use the more common method of
inserting a substitution character and continuing on.) This makes it
harder to make GC-free Phobos code.



The right solution here is refcounted exception plus policy-based
functions in conjunction with RCString. I can't believe this focus has
already been lost and we're back to let's remove autodecoding and ban
exceptions. -- Andrei


I've already stated my perception of the no stinking exceptions, and 
no destructors 'cause i want it fast elsewhere.


Code must be correct and fast, with correct being a precondition for any 
performance tuning and speed hacks.


Correct usually entails exceptions and automatic cleanup. I also do not 
believe the exceptions have to be slow motto, they are costly but 
proportion of such costs was largely exaggerated.


--
Dmitry Olshansky


Re: Creeping Bloat in Phobos

2014-09-28 Thread Dmitry Olshansky via Digitalmars-d

29-Sep-2014 00:44, Uranuz пишет:

It's Tolstoy actually:
http://en.wikipedia.org/wiki/War_and_Peace

You don't need byGrapheme for simple DSL. In fact as long as DSL is
simple enough (ASCII only) you may safely avoid decoding. If it's in
Russian you might want to decode. Even in this case there are ways to
avoid decoding, it may involve a bit of writing in as for typical
short novel ;)


Yes, my mistake ;) I was thinking about *Crime and Punishment* but
writen *War and Peace*. Don't know why. May be because it is longer.



Admittedly both are way too long for my taste :)


Thanks for useful links. As far as we are talking about standard library
I think that some stanard aproach should be provided to solve often
tasks: searching, sorting, parsing, splitting strings. I see that
currently we have a lot of ways of doing similar things with strings. I
think this is a problem of documentation at some part.


Some of this is historical, in particular std.string is way older then 
std.algorithm.



When I parsing
text I can't understand why I need to use all of these range interfaces
instead of just manipulating on raw narrow string. We have several
modules about working on strings: std.range, std.algorithm, std.string,
std.array,


std.range publicly imports std.array thus I really do not see why we 
still have std.array as standalone module.


 std.utf and I can't see how they help me to solve my

problems. In opposite they just creating me new problem to think of them
in order to find *right* way.


There is no *right* way, every level of abstraction has its uses. Also 
there is a bit of trade-off on performance vs easy/obvious/nice code.



So most of my time I spend on thinking
about it but not solving my task.


Takes time to get accustomed with a standard library. See also std.conv 
and std.format. String processing is indeed shotgun-ed across entire phobos.



It is hard for me to accept that we don't need to decode to do some
operations. What is annoying is that I always need to think of
codelength that I should show to user and byte length that is used to
slice char array. It's very easy to be confused with them and do
something wrong.


As long as you use decoding primitives you keep getting back proper 
indices automatically. That must be what some folks considered correct 
way to do Unicode until it was apparent to everybody that Unicode is way 
more then this.




I see that all is complicated we have 3 types of character and more than
5 modules for trivial manipulations on strings with 10ths of functions.
It all goes into hell.


There are many tools, but when I write parsers I actually use almost 
none of them. Well, nowdays I'm going to use the stuff in std.uni like 
CodePointSet, utfMatcher etc. std.regex makes some use of these already, 
but prior to that std.utf.decode was my lone workhorse.



But I don't even started to do my job. And we
don't have *standard* way to deal with it in std lib. At least this way
in not documented enough.


Well on the bright side consider that C has lots of broken functions in 
stdlib, and even some that are _never_ safe like gets ;)


--
Dmitry Olshansky


Re: Creeping Bloat in Phobos

2014-09-28 Thread Walter Bright via Digitalmars-d

On 9/28/2014 1:38 PM, bearophile wrote:

Walter Bright:


It can work just fine, and I wrote it. The problem is convincing someone to
pull it :-( as the PR was closed and reopened with autodecoding put back in.


Perhaps you need a range2 and algorithm2 modules. Introducing your changes in a
sneaky way may not produce well working and predictable user code.


I'm not suggesting sneaky ways. setExt() was a NEW function.



I know that you care about performance - you post about it often. I would
expect that unnecessary and pervasive decoding would be of concern to you.


I care first of all about program correctness (that's why I proposed unusual
things like optional strong typing for built-in array indexes, or I proposed the
enum preconditions).


Ok, but you implied at one point that you were not aware of which parts of your 
string code decoded and which did not. That's not consistent with being very 
careful about correctness.


Note that autodecode does not always happen - it doesn't happen for ranges of 
chars. It's very hard to look at piece of code and tell if autodecode is going 
to happen or not.



Secondly I care for performance in the functions or parts
of code where performance is needed. There are plenty of code where performance
is not the most important thing. That's why I have tons of range-base code. In
such large parts of code having short, correct, nice looking code that looks
correct is more important. Please don't assume I am simple minded :-)


It's very hard to disable the autodecode when it is not needed, though the new 
.byCodeUnit has made that much easier.




Re: Creeping Bloat in Phobos

2014-09-28 Thread Walter Bright via Digitalmars-d

On 9/28/2014 1:39 PM, H. S. Teoh via Digitalmars-d wrote:

It can work just fine, and I wrote it. The problem is convincing
someone to pull it :-( as the PR was closed and reopened with
autodecoding put back in.


The problem with pulling such PRs is that they introduce a dichotomy
into Phobos. Some functions autodecode, some don't, and from a user's
POV, it's completely arbitrary and random. Which leads to bugs because
people can't possibly remember exactly which functions autodecode and
which don't.


That's ALREADY the case, as I explained to bearophile.

The solution is not to have the ranges autodecode, but to have the ALGORITHMS 
decide to autodecode (if they need it) or not (if they don't).




As I've explained many times, very few string algorithms actually need
decoding at all. 'find', for example, does not. Trying to make a
separate universe out of autodecoding algorithms is missing the point.

[...]

Maybe what we need to do, is to change the implementation of
std.algorithm so that it internally uses byCodeUnit for narrow strings
where appropriate. We're already specialcasing Phobos code for narrow
strings anyway, so it wouldn't make things worse by making those special
cases not autodecode.


Those special cases wind up going everywhere and impacting everyone who attempts 
to write generic algorithms.




This doesn't quite solve the issue of composing ranges, since one
composed range returns dchar in .front composed with another range will
have autodecoding built into it. For those cases, perhaps one way to
hack around the present situation is to use Phobos-private enums in the
wrapper ranges (e.g., enum isNarrowStringUnderneath=true; in struct
Filter or something), that ranges downstream can test for, and do the
appropriate bypasses.


More complexity :-( for what should be simple tasks.



(BTW, before you pick on specific algorithms you might want to actually
look at the code for things like find(), because I remember there were a
couple o' PRs where find() of narrow strings will use (presumably) fast
functions like strstr or strchr, bypassing a foreach loop over an
autodecoding .front.)


Oh, I know that many algorithms have such specializations. Doesn't it strike you 
as sucky to have to special case a whole basket of algorithms when the 
InputRange does not behave in a reliable manner?


It's very simple for an algorithm to decode if it needs to, it just adds in a 
.byDchar adapter to its input range. Done. No special casing needed. The lines 
of code written drop in half. And it works with both arrays of chars, arrays of 
dchars, and input ranges of either.


---

The stalling of setExt() has basically halted my attempts to adjust Phobos so 
that one can write nothrow and @nogc algorithms that work on strings.


Re: Creeping Bloat in Phobos

2014-09-28 Thread Walter Bright via Digitalmars-d

On 9/28/2014 1:33 PM, Andrei Alexandrescu wrote:

On 9/28/14, 11:36 AM, Walter Bright wrote:

Currently, the autodecoding functions allocate with the GC and throw as
well. (They'll GC allocate an exception and throw it if they encounter
an invalid UTF sequence. The adapters use the more common method of
inserting a substitution character and continuing on.) This makes it
harder to make GC-free Phobos code.


The right solution here is refcounted exception plus policy-based functions in
conjunction with RCString. I can't believe this focus has already been lost and
we're back to let's remove autodecoding and ban exceptions. -- Andrei


Or setExt() can simply insert .byCodeUnit as I suggested in the PR, and it's 
done and working correctly and doesn't throw and doesn't allocate and goes fast.


Not everything in Phobos can be dealt with so easily, of course, but there's 
quite a bit of low hanging fruit of this nature we can just take care of now.


Re: Creeping Bloat in Phobos

2014-09-28 Thread Walter Bright via Digitalmars-d

On 9/28/2014 2:00 PM, Dmitry Olshansky wrote:

I've already stated my perception of the no stinking exceptions, and no
destructors 'cause i want it fast elsewhere.

Code must be correct and fast, with correct being a precondition for any
performance tuning and speed hacks.


Sure. I'm not arguing for preferring incorrect code.



Correct usually entails exceptions and automatic cleanup. I also do not believe
the exceptions have to be slow motto, they are costly but proportion of such
costs was largely exaggerated.


I think it was you that suggested that instead of throwing on invalid UTF, that 
the replacement character be used instead? Or maybe not, I'm not quite sure.


Regardless, the replacement character method is widely used and accepted 
practice. There's no reason to throw.




Re: Creeping Bloat in Phobos

2014-09-28 Thread ketmar via Digitalmars-d
On Sun, 28 Sep 2014 19:44:39 +
Uranuz via Digitalmars-d digitalmars-d@puremagic.com wrote:

 I speaking language which graphemes coded by 2 bytes
UCS-4? KOI8? my locale is KOI8, and i HATE D for assuming that everyone
one the planet using UTF-8 and happy with it. from my POV, almost all
string decoding is broken. string i got from filesystem? good god, lest
it not contain anything out of ASCII range! string i got from text
file? the same. string i must write to text file or stdout? oh, 'cmon,
what do you mean telling me п©я─п╦п╡п╣я┌?! i can't read that!


signature.asc
Description: PGP signature


Re: Creeping Bloat in Phobos

2014-09-28 Thread Martin Nowak via Digitalmars-d

On 09/28/2014 02:23 AM, Andrei Alexandrescu wrote:

front() should follow a simple pattern that's been very successful in
HHVM: small inline function that covers most cases with if (c  0x80)
followed by an out-of-line function on the multicharacter case. That
approach would make the cost of auto-decoding negligible in the
overwhelming majority of cases.

Andrei


Well, we're using the same trick for already 3 years now :).
https://github.com/D-Programming-Language/phobos/pull/299


Re: Creeping Bloat in Phobos

2014-09-28 Thread Martin Nowak via Digitalmars-d

On 09/28/2014 01:02 AM, Walter Bright wrote:


It's the autodecode'ing front(), which is a fairly complex function.


At least for dmd it's caused by a long-standing compiler bug.
https://issues.dlang.org/show_bug.cgi?id=7625

https://github.com/D-Programming-Language/phobos/pull/2566


Creeping Bloat in Phobos

2014-09-27 Thread Walter Bright via Digitalmars-d
From time to time, I take a break from bugs and enhancements and just look at 
what some piece of code is actually doing. Sometimes, I'm appalled. Phobos, for 
example, should be a lean and mean fighting machine:



http://www.nbcnews.com/id/38545625/ns/technology_and_science-science/t/king-tuts-chariots-were-formula-one-cars/#.VCceNmd0xjs

Instead, we have something more akin to:


http://untappedcities.com/2012/10/31/roulez-carrosses-carriages-of-versailles-arrive-in-arras/

More specifically, I looked at std.file.copy():

  https://github.com/D-Programming-Language/phobos/blob/master/std/file.d

Which is 3 lines of code:

  void copy(in char[] from, in char[] to) {
immutable result = CopyFileW(from.tempCStringW(), to.tempCStringW(), 
false);

if (!result)
throw new FileException(to.idup);
  }

Compiling this code for Windows produces the rather awful:

_D3std4file4copyFxAaxAaZv   comdat
assume  CS:_D3std4file4copyFxAaxAaZv
L0: pushEBP
mov EBP,ESP
mov EDX,FS:__except_list
push0h
lea EAX,-0220h[EBP]
pushoffset _D3std4file4copyFxAaxAaZv[0106h]
pushEDX
mov FS:__except_list,ESP
sub ESP,8
sub ESP,041Ch
push0
pushdword ptr 0Ch[EBP]
pushdword ptr 8[EBP]
callnear ptr 
_D3std8internal7cstring21__T11tempCSÇàÆTuTaZÇìÆFNbNixAaZSÇ┬├3Res

mov dword ptr -4[EBP],0
lea EAX,-0220h[EBP]
callnear ptr 
_D3std8internal7cstring21__T11tempCStringTuTaZ11tempCStringFNbNixAaZ3Res3ptrMxFNaNbNdNiNfZPxu

pushEAX
lea EAX,-0430h[EBP]
pushdword ptr 014h[EBP]
pushdword ptr 010h[EBP]
callnear ptr 
_D3std8internal7cstring21__T11tempCSÇàÆTuTaZÇìÆFNbNixAaZSÇ┬├3Res

mov dword ptr -4[EBP],1
lea EAX,-0430h[EBP]
callnear ptr 
_D3std8internal7cstring21__T11tempCStringTuTaZ11tempCStringFNbNixAaZ3Res3ptrMxFNaNbNdNiNfZPxu

pushEAX
calldword ptr __imp__CopyFileW@12
mov -01Ch[EBP],EAX
mov dword ptr -4[EBP],0
callnear ptr L83
jmp short   L8F
L83:lea EAX,-0220h[EBP]
callnear ptr 
_D3std8internal7cstring21__T11tempCStringTuTaZ11tempCStringFNbNixAaZ3Res6__dtorMFNbNiZv

ret
L8F:mov dword ptr -4[EBP],0h
callnear ptr L9D
jmp short   LA9
L9D:lea EAX,-0430h[EBP]
callnear ptr 
_D3std8internal7cstring21__T11tempCStringTuTaZ11tempCStringFNbNixAaZ3Res6__dtorMFNbNiZv

ret
LA9:cmp dword ptr -01Ch[EBP],0
jne LF3
mov ECX,offset FLAT:_D3std4file13FileException7__ClassZ
pushECX
callnear ptr __d_newclass
add ESP,4
pushdword ptr 0Ch[EBP]
mov -018h[EBP],EAX
pushdword ptr 8[EBP]
callnear ptr _D6object12__T4idupTxaZ4idupFNaNbNdNfAxaZAya
pushEDX
pushEAX
calldword ptr __imp__GetLastError@0
pushEAX
pushdword ptr _D3std4file13FileException6__vtblZ[02Ch]
pushdword ptr _D3std4file13FileException6__vtblZ[028h]
push095Dh
mov EAX,-018h[EBP]
callnear ptr 
_D3std4file13FileException6__ctorMFNfxAakAyakZC3std4file13FileException

pushEAX
callnear ptr __d_throwc
LF3:mov ECX,-0Ch[EBP]
mov FS:__except_list,ECX
mov ESP,EBP
pop EBP
ret 010h
mov EAX,offset 
FLAT:_D3std4file13FileException6__vtblZ[0310h]
jmp near ptr __d_framehandler

which is TWICE as much generated code as for D1's copy(), which does the same 
thing. No, it is not because D2's compiler sux. It's because it has become 
encrustified with gee-gaws, jewels, decorations, and other crap.


To scrape the barnacles off, I've filed:

https://issues.dlang.org/show_bug.cgi?id=13541
https://issues.dlang.org/show_bug.cgi?id=13542
https://issues.dlang.org/show_bug.cgi?id=13543
https://issues.dlang.org/show_bug.cgi?id=13544

I'm sure there's much more in std.file (and elsewhere) that can be done. Guys, 
when developing Phobos/Druntime code, please look at the assembler once in a 
while and see what is being wrought. You may be appalled, too.






Re: Creeping Bloat in Phobos

2014-09-27 Thread Peter Alexander via Digitalmars-d
On Saturday, 27 September 2014 at 20:57:53 UTC, Walter Bright 
wrote:
From time to time, I take a break from bugs and enhancements 
and just look at what some piece of code is actually doing. 
Sometimes, I'm appalled.


Me too, and yes it can be appalling. It's pretty bad for even 
simple range chains, e.g.


import std.algorithm, std.stdio;
int main(string[] args) {
  return cast(int)args.map!(a.length).reduce!a+b();
}

Here's what LDC produces (with -O -inline -release -noboundscheck)

__Dmain:
00011480pushq   %r15
00011482pushq   %r14
00011484pushq   %rbx
00011485movq%rsi, %rbx
00011488movq%rdi, %r14
0001148b	callq	0x10006df10 ## symbol stub for: 
__D3std5array14__T5emptyTAyaZ5emptyFNaNbNdNfxAAyaZb

00011490xorb$0x1, %al
00011492movzbl  %al, %r9d
00011496	leaq	_.str12(%rip), %rdx ## literal pool for: 
/Users/pja/ldc2-0.14.0-osx-x86_64/bin/../import/std/algorithm.d
0001149d	movq	0xcbd2c(%rip), %r8 ## literal pool symbol 
address: 
__D3std9algorithm24__T6reduceVAyaa3_612b62Z124__T6reduceTS3std9algorithm85__T9MapResultS633std10functional36__T8unaryFunVAyaa8_612e6c656e677468Z8unaryFunTAAyaZ9MapResultZ6reduceFNaNfS3std9algorithm85__T

000114a4movl$0x2dd, %edi
000114a9movl$0x3f, %esi
000114aexorl%ecx, %ecx
000114b0	callq	0x10006e0a2 ## symbol stub for: 
__D3std9exception14__T7enforceTbZ7enforceFNaNfbLAxaAyamZb

000114b5movq(%rbx), %r15
000114b8leaq0x10(%rbx), %rsi
000114bcleaq-0x1(%r14), %rdi
000114c0	callq	0x10006df10 ## symbol stub for: 
__D3std5array14__T5emptyTAyaZ5emptyFNaNbNdNfxAAyaZb

000114c5testb   $0x1, %al
000114c7jne 0x114fa
000114c9addq$-0x2, %r14
000114cdaddq$0x20, %rbx
000114d1nopw%cs:(%rax,%rax)
000114e0addq-0x10(%rbx), %r15
000114e4movq%r14, %rdi
000114e7movq%rbx, %rsi
000114ea	callq	0x10006df10 ## symbol stub for: 
__D3std5array14__T5emptyTAyaZ5emptyFNaNbNdNfxAAyaZb

000114efdecq%r14
000114f2addq$0x10, %rbx
000114f6testb   $0x1, %al
000114f8je  0x114e0
000114famovl%r15d, %eax
000114fdpopq%rbx
000114fepopq%r14
00011500popq%r15
00011502ret

and for:

import std.algorithm, std.stdio;
int main(string[] args) {
  int r = 0;
  foreach (i; 0..args.length)
r += args[i].length;
  return r;
}

__Dmain:
000115c0xorl%eax, %eax
000115c2testq   %rdi, %rdi
000115c5je  0x115de
000115c7nopw(%rax,%rax)
000115d0movl%eax, %eax
000115d2addq(%rsi), %rax
000115d5addq$0x10, %rsi
000115d9decq%rdi
000115dcjne 0x115d0
000115deret

(and sorry, don't even bother looking at what dmd does...)

I'm not complaining about LDC here (although I'm surprised 
array.empty isn't inlined). The way ranges are formulated make 
them difficult to optimize. I think there's things we can do here 
in the library. Maybe I'll write up something about that at some 
point.


I think the takeaway here is that people should be aware of (a) 
what kind of instructions their code is generating, (b) what kind 
of instructions their code SHOULD be generating, and (c) what is 
practically possible for present-day compilers. Like you say, it 
helps to look at the assembled code once in a while to get a feel 
for this kind of thing. Modern compilers are good, but they 
aren't magic.




Re: Creeping Bloat in Phobos

2014-09-27 Thread H. S. Teoh via Digitalmars-d
On Sat, Sep 27, 2014 at 09:59:17PM +, Peter Alexander via Digitalmars-d 
wrote:
 On Saturday, 27 September 2014 at 20:57:53 UTC, Walter Bright wrote:
 From time to time, I take a break from bugs and enhancements and just
 look at what some piece of code is actually doing. Sometimes, I'm
 appalled.
 
 Me too, and yes it can be appalling. It's pretty bad for even simple
 range chains, e.g.
 
 import std.algorithm, std.stdio;
 int main(string[] args) {
   return cast(int)args.map!(a.length).reduce!a+b();
 }

I vaguely recall somebody mentioning a while back that range-based code
is poorly optimized because compilers weren't designed to recognize
such patterns before. I wonder if there are ways for the compiler to
recognize range primitives and apply special optimizations to them.

I do find, though, that gdc -O3 generally tends to do a pretty good job
of reducing range-based code to near-minimal assembly. Sadly, dmd is
changing too fast for gdc releases to catch up with the latest and
greatest, so I haven't been using gdc very much recently. :-(


T

-- 
If Java had true garbage collection, most programs would delete
themselves upon execution. -- Robert Sewell


Re: Creeping Bloat in Phobos

2014-09-27 Thread Brad Roberts via Digitalmars-d
What we're seeing here is pretty much the same problem that early c++ 
suffered from: abstraction penalty.  It took years of work to help 
overcome it, both from the compiler and the library.  Not having trivial 
functions inlined and optimized down through standard techniques like 
dead store elimination, value range propagation, various loop 
restructurings, etc means that code will look like what Walter and you 
have shown.  Given DMD's relatively weak inliner, I'm not shocked by 
Walter's example.  I am curious why ldc failed to inline those functions.


On 9/27/2014 2:59 PM, Peter Alexander via Digitalmars-d wrote:

On Saturday, 27 September 2014 at 20:57:53 UTC, Walter Bright wrote:

From time to time, I take a break from bugs and enhancements and just
look at what some piece of code is actually doing. Sometimes, I'm
appalled.


Me too, and yes it can be appalling. It's pretty bad for even simple
range chains, e.g.

import std.algorithm, std.stdio;
int main(string[] args) {
   return cast(int)args.map!(a.length).reduce!a+b();
}

Here's what LDC produces (with -O -inline -release -noboundscheck)

__Dmain:
00011480pushq%r15
00011482pushq%r14
00011484pushq%rbx
00011485movq%rsi, %rbx
00011488movq%rdi, %r14
0001148bcallq0x10006df10 ## symbol stub for:
__D3std5array14__T5emptyTAyaZ5emptyFNaNbNdNfxAAyaZb
00011490xorb$0x1, %al
00011492movzbl%al, %r9d
00011496leaq_.str12(%rip), %rdx ## literal pool for:
/Users/pja/ldc2-0.14.0-osx-x86_64/bin/../import/std/algorithm.d
0001149dmovq0xcbd2c(%rip), %r8 ## literal pool symbol
address:
__D3std9algorithm24__T6reduceVAyaa3_612b62Z124__T6reduceTS3std9algorithm85__T9MapResultS633std10functional36__T8unaryFunVAyaa8_612e6c656e677468Z8unaryFunTAAyaZ9MapResultZ6reduceFNaNfS3std9algorithm85__T

000114a4movl$0x2dd, %edi
000114a9movl$0x3f, %esi
000114aexorl%ecx, %ecx
000114b0callq0x10006e0a2 ## symbol stub for:
__D3std9exception14__T7enforceTbZ7enforceFNaNfbLAxaAyamZb
000114b5movq(%rbx), %r15
000114b8leaq0x10(%rbx), %rsi
000114bcleaq-0x1(%r14), %rdi
000114c0callq0x10006df10 ## symbol stub for:
__D3std5array14__T5emptyTAyaZ5emptyFNaNbNdNfxAAyaZb
000114c5testb$0x1, %al
000114c7jne0x114fa
000114c9addq$-0x2, %r14
000114cdaddq$0x20, %rbx
000114d1nopw%cs:(%rax,%rax)
000114e0addq-0x10(%rbx), %r15
000114e4movq%r14, %rdi
000114e7movq%rbx, %rsi
000114eacallq0x10006df10 ## symbol stub for:
__D3std5array14__T5emptyTAyaZ5emptyFNaNbNdNfxAAyaZb
000114efdecq%r14
000114f2addq$0x10, %rbx
000114f6testb$0x1, %al
000114f8je0x114e0
000114famovl%r15d, %eax
000114fdpopq%rbx
000114fepopq%r14
00011500popq%r15
00011502ret

and for:

import std.algorithm, std.stdio;
int main(string[] args) {
   int r = 0;
   foreach (i; 0..args.length)
 r += args[i].length;
   return r;
}

__Dmain:
000115c0xorl%eax, %eax
000115c2testq%rdi, %rdi
000115c5je0x115de
000115c7nopw(%rax,%rax)
000115d0movl%eax, %eax
000115d2addq(%rsi), %rax
000115d5addq$0x10, %rsi
000115d9decq%rdi
000115dcjne0x115d0
000115deret

(and sorry, don't even bother looking at what dmd does...)

I'm not complaining about LDC here (although I'm surprised array.empty
isn't inlined). The way ranges are formulated make them difficult to
optimize. I think there's things we can do here in the library. Maybe
I'll write up something about that at some point.

I think the takeaway here is that people should be aware of (a) what
kind of instructions their code is generating, (b) what kind of
instructions their code SHOULD be generating, and (c) what is
practically possible for present-day compilers. Like you say, it helps
to look at the assembled code once in a while to get a feel for this
kind of thing. Modern compilers are good, but they aren't magic.


Re: Creeping Bloat in Phobos

2014-09-27 Thread Walter Bright via Digitalmars-d

On 9/27/2014 2:59 PM, Peter Alexander wrote:

On Saturday, 27 September 2014 at 20:57:53 UTC, Walter Bright wrote:

From time to time, I take a break from bugs and enhancements and just look at
what some piece of code is actually doing. Sometimes, I'm appalled.


Me too, and yes it can be appalling. It's pretty bad for even simple range
chains, e.g.

import std.algorithm, std.stdio;
int main(string[] args) {
   return cast(int)args.map!(a.length).reduce!a+b();
}

Here's what LDC produces (with -O -inline -release -noboundscheck)


Part of this particular case problem is not a compiler optimizer weakness, but 
that autodecode problem I've been throwing (!) chairs through windows on.




Re: Creeping Bloat in Phobos

2014-09-27 Thread H. S. Teoh via Digitalmars-d
On Sat, Sep 27, 2014 at 03:26:35PM -0700, Walter Bright via Digitalmars-d wrote:
 On 9/27/2014 2:59 PM, Peter Alexander wrote:
 On Saturday, 27 September 2014 at 20:57:53 UTC, Walter Bright wrote:
 From time to time, I take a break from bugs and enhancements and
 just look at what some piece of code is actually doing. Sometimes,
 I'm appalled.
 
 Me too, and yes it can be appalling. It's pretty bad for even simple
 range chains, e.g.
 
 import std.algorithm, std.stdio;
 int main(string[] args) {
return cast(int)args.map!(a.length).reduce!a+b();
 }
 
 Here's what LDC produces (with -O -inline -release -noboundscheck)
 
 Part of this particular case problem is not a compiler optimizer
 weakness, but that autodecode problem I've been throwing (!) chairs
 through windows on.

If we can get Andrei on board, I'm all for killing off autodecoding.


T

-- 
MAS = Mana Ada Sistem?


Re: Creeping Bloat in Phobos

2014-09-27 Thread bearophile via Digitalmars-d

Walter Bright:


import std.algorithm, std.stdio;
int main(string[] args) {
  return cast(int)args.map!(a.length).reduce!a+b();
}

Here's what LDC produces (with -O -inline -release 
-noboundscheck)


Part of this particular case problem is not a compiler 
optimizer weakness, but that autodecode problem I've been 
throwing (!) chairs through windows on.


There is no char auto decoding in this program, right?

Note: in Phobos now we have std.algorithm.sum, that is better 
than reduce!a+b().


Bye,
bearophile


Re: Creeping Bloat in Phobos

2014-09-27 Thread Walter Bright via Digitalmars-d

On 9/27/2014 3:26 PM, Brad Roberts via Digitalmars-d wrote:

What we're seeing here is pretty much the same problem that early c++ suffered
from: abstraction penalty.  It took years of work to help overcome it, both from
the compiler and the library.  Not having trivial functions inlined and
optimized down through standard techniques like dead store elimination, value
range propagation, various loop restructurings, etc means that code will look
like what Walter and you have shown.  Given DMD's relatively weak inliner, I'm
not shocked by Walter's example.  I am curious why ldc failed to inline those
functions.


Again, this accumulation of barnacles is not a failure of the optimizer. It's a 
failure of adding gee-gaws to the source code without checking their effect.




Re: Creeping Bloat in Phobos

2014-09-27 Thread Brad Roberts via Digitalmars-d

On 9/27/2014 3:54 PM, Walter Bright via Digitalmars-d wrote:

On 9/27/2014 3:26 PM, Brad Roberts via Digitalmars-d wrote:

What we're seeing here is pretty much the same problem that early c++
suffered
from: abstraction penalty.  It took years of work to help overcome it,
both from
the compiler and the library.  Not having trivial functions inlined and
optimized down through standard techniques like dead store
elimination, value
range propagation, various loop restructurings, etc means that code
will look
like what Walter and you have shown.  Given DMD's relatively weak
inliner, I'm
not shocked by Walter's example.  I am curious why ldc failed to
inline those
functions.


Again, this accumulation of barnacles is not a failure of the optimizer.
It's a failure of adding gee-gaws to the source code without checking
their effect.


Look at Peter's example, it's better for this, I believe.  Why isn't 
empty being inlined?  That's a tiny little function with a lot of impact.


Of course there's more than just optimization, but it's a big player in 
the game too.


Re: Creeping Bloat in Phobos

2014-09-27 Thread Walter Bright via Digitalmars-d

On 9/27/2014 3:52 PM, bearophile wrote:

There is no char auto decoding in this program, right?


Notice the calls to autodecoding 'front' in the assembler dump.



Re: Creeping Bloat in Phobos

2014-09-27 Thread Walter Bright via Digitalmars-d

On 9/27/2014 3:59 PM, Brad Roberts via Digitalmars-d wrote:

Look at Peter's example, it's better for this, I believe.  Why isn't empty being
inlined?  That's a tiny little function with a lot of impact.


It's the autodecode'ing front(), which is a fairly complex function.



Re: Creeping Bloat in Phobos

2014-09-27 Thread bearophile via Digitalmars-d

H. S. Teoh:

If we can get Andrei on board, I'm all for killing off 
autodecoding.


Killing auto-decoding for std.algorithm functions will break most 
of my D2 code... perhaps we can do that in a D3 language.


Bye,
bearophile


Re: Creeping Bloat in Phobos

2014-09-27 Thread Peter Alexander via Digitalmars-d
On Saturday, 27 September 2014 at 23:04:00 UTC, Walter Bright 
wrote:

On 9/27/2014 3:52 PM, bearophile wrote:

There is no char auto decoding in this program, right?


Notice the calls to autodecoding 'front' in the assembler dump.


I think you're imagining things Walter!

There's no auto-decoding my example, it's just adding up the 
lengths.


Re: Creeping Bloat in Phobos

2014-09-27 Thread David Nadlinger via Digitalmars-d
On Saturday, 27 September 2014 at 23:00:20 UTC, Brad Roberts via 
Digitalmars-d wrote:
Look at Peter's example, it's better for this, I believe.  Why 
isn't empty being inlined?  That's a tiny little function with 
a lot of impact.


This is most likely due to an issue with how the new DMD template 
emission strategy (needsCodegen() et al.) was integrated into 
LDC: https://github.com/ldc-developers/ldc/issues/674


The issue in question was fixed recently in LDC Git master, but 
regressed again when 2.066 was merged.


David


Re: Creeping Bloat in Phobos

2014-09-27 Thread H. S. Teoh via Digitalmars-d
On Sat, Sep 27, 2014 at 11:00:16PM +, bearophile via Digitalmars-d wrote:
 H. S. Teoh:
 
 If we can get Andrei on board, I'm all for killing off autodecoding.
 
 Killing auto-decoding for std.algorithm functions will break most of
 my D2 code... perhaps we can do that in a D3 language.
[...]

Well, obviously it's not going to be done in a careless, drastic way!

There will be a proper migration path and deprecation cycle. We already
have byCodeUnit and byCodePoint, and the first step is probably to
migrate towards requiring usage of one or the other for iterating over
strings, and only once all code is using them, we will get rid of
autodecoding (the job now being done by byCodePoint). Then, the final
step would be to allow the direct use of strings in iteration constructs
again, but this time without autodecoding by default. Of course,
.byCodePoint will still be available for code that needs to use it.


T

-- 
Ph.D. = Permanent head Damage


Re: Creeping Bloat in Phobos

2014-09-27 Thread Walter Bright via Digitalmars-d

On 9/27/2014 4:06 PM, Peter Alexander wrote:

On Saturday, 27 September 2014 at 23:04:00 UTC, Walter Bright wrote:

On 9/27/2014 3:52 PM, bearophile wrote:

There is no char auto decoding in this program, right?


Notice the calls to autodecoding 'front' in the assembler dump.


I think you're imagining things Walter!

There's no auto-decoding my example, it's just adding up the lengths.


oh crap, I misread empty as front!


Re: Creeping Bloat in Phobos

2014-09-27 Thread Andrei Alexandrescu via Digitalmars-d

On 9/27/14, 3:40 PM, H. S. Teoh via Digitalmars-d wrote:

If we can get Andrei on board, I'm all for killing off autodecoding.


That's rather vague; it's unclear what would replace it. -- Andrei



Re: Creeping Bloat in Phobos

2014-09-27 Thread Andrei Alexandrescu via Digitalmars-d

On 9/27/14, 1:57 PM, Walter Bright wrote:

To scrape the barnacles off, I've filed:

https://issues.dlang.org/show_bug.cgi?id=13541
https://issues.dlang.org/show_bug.cgi?id=13542
https://issues.dlang.org/show_bug.cgi?id=13543
https://issues.dlang.org/show_bug.cgi?id=13544

I'm sure there's much more in std.file (and elsewhere) that can be done.


Noice. Should be told, though, that reading the actual file will 
dominate execution time. -- Andrei


Re: Creeping Bloat in Phobos

2014-09-27 Thread Andrei Alexandrescu via Digitalmars-d

On 9/27/14, 3:54 PM, Walter Bright wrote:

Again, this accumulation of barnacles is not a failure of the optimizer.
It's a failure of adding gee-gaws to the source code without checking
their effect.


The Go project has something nice set up - easy-to-run benchmarks that 
are part of the acceptance testing. That's good prevention against 
creeping inefficiencies. -- Andrei


Re: Creeping Bloat in Phobos

2014-09-27 Thread Andrei Alexandrescu via Digitalmars-d

On 9/27/14, 4:02 PM, Walter Bright wrote:

On 9/27/2014 3:59 PM, Brad Roberts via Digitalmars-d wrote:

Look at Peter's example, it's better for this, I believe.  Why isn't
empty being
inlined?  That's a tiny little function with a lot of impact.


It's the autodecode'ing front(), which is a fairly complex function.


front() should follow a simple pattern that's been very successful in 
HHVM: small inline function that covers most cases with if (c  0x80) 
followed by an out-of-line function on the multicharacter case. That 
approach would make the cost of auto-decoding negligible in the 
overwhelming majority of cases.


Andrei


Re: Creeping Bloat in Phobos

2014-09-27 Thread deadalnix via Digitalmars-d
On Saturday, 27 September 2014 at 22:11:39 UTC, H. S. Teoh via 
Digitalmars-d wrote:
I vaguely recall somebody mentioning a while back that 
range-based code
is poorly optimized because compilers weren't designed to 
recognize
such patterns before. I wonder if there are ways for the 
compiler to
recognize range primitives and apply special optimizations to 
them.


I do find, though, that gdc -O3 generally tends to do a pretty 
good job
of reducing range-based code to near-minimal assembly. Sadly, 
dmd is
changing too fast for gdc releases to catch up with the latest 
and

greatest, so I haven't been using gdc very much recently. :-(



That was me, specifically for LLVM (I don't know much about GCC's 
innards). Hopefully, this is being worked (as it also impact 
C++'s stdlib).