August 24, 2021 Re: Sometimes 100 lines of code can fix your ctfe perf | ||||
---|---|---|---|---|
| ||||
Posted in reply to Paul Backus | On 8/24/21 1:14 PM, Paul Backus wrote: >> On Tuesday, 24 August 2021 at 16:58:26 UTC, Adam D Ruppe wrote: >>> On Tuesday, 24 August 2021 at 16:52:30 UTC, Ali Çehreli wrote: >>>> auto s = format!"hello %s world %s"(a, b); >>> >>> yikes that's like the worst thing in the whole D world. brutally slow >>> by all metrics. [...] > Internally, `format` uses `formattedWrite` > with an `Appender` as the output range [1] That's what I thought. Additionally, some of my structs define toString() functions that work with a "sink" so they would be written into the buffer of an appender without extra string creation: https://dlang.org/library/std/format/write.html To do even better, we could write the following function that reuses a static Appender object: auto appendingFormatter(string fmt, string file = __FILE__, size_t line = __LINE__, Args...)(Args args) { import std.array : Appender; import std.format : formattedWrite; static Appender!(char[]) buffer; buffer.clear(); buffer.formattedWrite!fmt(args); return buffer.data; } import std.stdio; void main() { size_t total; enum N = 100; foreach (i; 0 .. N) { foreach (d; 0 .. N) { total += appendingFormatter!"hello %s world %s"(i, d).length; total += appendingFormatter!"goodbye %s moon %s"(i * 10, d / 7).length; } } writeln(appendingFormatter!"An arbitrary value: %s"(total)); const a = appendingFormatter!"%s"(42); const b = appendingFormatter!"%s"(43); // BUG: Fails. assert((a == "42") && (b == "43")); } Performance is awesome because there is almost no memory allocation. Unfortunately, there is that bug on the last line of main because there is no __COLUMN__ or __ID__ or __COUNTER__ or etc. that would differ per __LINE__. Or, is there? Please? :) Do you know a trick that would pass that assertion? Ali |
August 25, 2021 __COUNTER__ (was: Sometimes 100 lines of code can fix your ctfe perf) | ||||
---|---|---|---|---|
| ||||
Posted in reply to Ali Çehreli | On 8/24/21 3:33 PM, Ali Çehreli wrote: > there is no __COLUMN__ or __ID__ or __COUNTER__ or etc. that would differ per __LINE__. I found the following two closed PRs that tried to implement C's __COUNTER__ macro: https://github.com/dlang/dmd/pull/10093 https://github.com/dlang/dmd/pull/10131 As mentioned in the second PR, the semantics can be confusing especially with separate compilation. (I wonder how C works out the semantics.) (And 'static foreach' may be sufficient to handle C's __COUNTER__ for us in a way that leaves the semantics to the user. (I am not sure about that...)) Actually, for this particular use case, I would be happy with a __COLUMN__ counter that would resolve to the location on the line e.g. exactly where the first '_' character of __COLUMN__ appeared. Combined with __FILE_FULL_PATH__ and __LINE__, this would allow us produce unique positions. Does that make sense? Ali |
August 26, 2021 Re: __COUNTER__ (was: Sometimes 100 lines of code can fix your ctfe perf) | ||||
---|---|---|---|---|
| ||||
Posted in reply to Ali Çehreli | On Thursday, 26 August 2021 at 05:41:17 UTC, Ali Çehreli wrote:
> On 8/24/21 3:33 PM, Ali Çehreli wrote:
>
> > there is no __COLUMN__ or __ID__ or __COUNTER__ or etc. that
> would differ per __LINE__.
>
> I found the following two closed PRs that tried to implement C's __COUNTER__ macro:
>
> https://github.com/dlang/dmd/pull/10093
>
> https://github.com/dlang/dmd/pull/10131
>
> As mentioned in the second PR, the semantics can be confusing especially with separate compilation. (I wonder how C works out the semantics.) (And 'static foreach' may be sufficient to handle C's __COUNTER__ for us in a way that leaves the semantics to the user. (I am not sure about that...))
>
> Actually, for this particular use case, I would be happy with a __COLUMN__ counter that would resolve to the location on the line e.g. exactly where the first '_' character of __COLUMN__ appeared. Combined with __FILE_FULL_PATH__ and __LINE__, this would allow us produce unique positions.
>
> Does that make sense?
>
> Ali
The linked `__COUNTER__` (10131) is actually fine.
I think it does to work inside a static foreach as well.
whereas `__COLUMN__` would not give you unique identifiers in a static foreach.
|
August 26, 2021 Re: __COUNTER__ (was: Sometimes 100 lines of code can fix your ctfe perf) | ||||
---|---|---|---|---|
| ||||
Posted in reply to Ali Çehreli | On Thursday, 26 August 2021 at 05:41:17 UTC, Ali Çehreli wrote:
> On 8/24/21 3:33 PM, Ali Çehreli wrote:
>
> > there is no __COLUMN__ or __ID__ or __COUNTER__ or etc. that
> would differ per __LINE__.
>
> I found the following two closed PRs that tried to implement C's __COUNTER__ macro:
>
> https://github.com/dlang/dmd/pull/10093
>
> https://github.com/dlang/dmd/pull/10131
>
> As mentioned in the second PR, the semantics can be confusing especially with separate compilation. (I wonder how C works out the semantics.) (And 'static foreach' may be sufficient to handle C's __COUNTER__ for us in a way that leaves the semantics to the user. (I am not sure about that...))
>
> Actually, for this particular use case, I would be happy with a __COLUMN__ counter that would resolve to the location on the line e.g. exactly where the first '_' character of __COLUMN__ appeared. Combined with __FILE_FULL_PATH__ and __LINE__, this would allow us produce unique positions.
>
> Does that make sense?
Yes, dmd uses something similar to generate unittests names.
__COUNTER__ would have been fine to name symbols because the mangles start with the module name so separate compilation would not have caused multiple definitions errors.
|
Copyright © 1999-2021 by the D Language Foundation