`in` C# 7
От: #John Европа https://github.com/ichensky
Дата: 04.12.18 10:37
Оценка:
Здравствуйте,
В каких случая лучше использовать `in`?
Напр. есть класс:
public static class CipherUtility
    {
        public static string Encrypt<T>(in string value, in string password, in string salt)
        {
            ..
            return str;
        }

        public static string Decrypt<T>(this string text, string password, string salt)
        {
            ..
            return str;
        }
    }

Если использовать `in` — экономится память при передачи строк в методы и трата CPU на лишнее копирование,
особенно если входящий параметр — очень большая строка.
Но с другой стороны, без `in` вызов метода `Decrypt` в длинной цепочке вызовов будет выглядеть более читаемым/эстетичным:
"some_str".SomeOtherMethod().Decrypt<object>("pass","salt").SomeOtherMethod2()...
И нет опасности, что в каком-нибудь другом потоке value/password/salt поменяются пока будет выполнятся метод `Encrypt`
Підтримати Україну у боротьбі з країною-терористом.

https://prytulafoundation.org/
https://u24.gov.ua/

Слава Збройним Силам України!!! Героям слава!!!
Re: readonly struct
От: Qbit86 Кипр
Дата: 04.12.18 10:46
Оценка: 78 (2) +1
Здравствуйте, #John, Вы писали:

J>В каких случая лучше использовать `in`?


В случае, когда у тебя передаётся в метод значимый тип, который: 1) `readonly struct`, 2) большой: https://docs.microsoft.com/en-us/dotnet/csharp/write-safe-efficient-code

J>Если использовать `in` — экономится память при передачи строк в методы и трата CPU на лишнее копирование,


Нет, в обоих случаях передаётся ссылка на данные строки, потому что строка — ссылочный тип. Только в первом случае ссылка передаётся по ссылке, во втором — ссылка передаётся по значению.
Глаза у меня добрые, но рубашка — смирительная!
Re: `in` C# 7
От: Sinclair Россия https://github.com/evilguest/
Дата: 04.12.18 13:57
Оценка:
Здравствуйте, #John, Вы писали:
J>И нет опасности, что в каком-нибудь другом потоке value/password/salt поменяются пока будет выполнятся метод `Encrypt`
Уровень опасности совершенно одинаковый. Без жосткого использования unsafe или рефлексии поменять значение строки в дотнете нельзя.
Так что если вы получаете в метод Encrypt строковый параметр, то значение этой строки можно ожидать неизменным. Даже если вы его сохраните в поле объекта, и будете обращаться к нему раз в полгода — всё равно, строка останется той же самой.
А вот если злоумышленно написанный код лезет внутрь строкового буфера и меняет его, то метод encrypt сломается независимо от наличия декоратора in в аргументе.
Потому что единственный способ от этого защититься — принудительно сделать глубокую копию строки (например, через StringBuilder), которая невидима для внешнего кода.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re: `in` C# 7
От: _NN_ www.nemerleweb.com
Дата: 04.12.18 19:03
Оценка:
Здравствуйте, #John, Вы писали

Немного деталей про производительность.
https://blogs.msdn.microsoft.com/seteplia/2018/03/07/the-in-modifier-and-the-readonly-structs-in-c/
https://blogs.msdn.microsoft.com/seteplia/2018/04/11/performance-traps-of-ref-locals-and-ref-returns-in-c/
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re: `in` C# 7
От: Igorxz  
Дата: 05.12.18 23:13
Оценка:
Здравствуйте, #John, Вы писали:

J>Здравствуйте,

J>В каких случая лучше использовать `in`?

есть ещё один повод использовать `in`-модификатор, а именно в связке с value-tuple's.
т.е. не
public static string Encrypt<T>(in string value, in string password, in string salt)

а
public static string Encrypt<T>(in (string value, string password, string salt) t)

что это дает: в первом случае передается три указателя в метод, а во втором — только один.
особенно критично для hot-path кода. value-tuple's замечательная весчь (как оно сделано) — модифицировать сущ. код легко, не надо описывать бесчисленные структуры параметров, названия им придумывать. счастье.
Re[2]: Value tuples
От: Qbit86 Кипр
Дата: 06.12.18 00:21
Оценка: +2
Здравствуйте, Igorxz, Вы писали:

I>что это дает: в первом случае передается три указателя в метод, а во втором — только один.


Но value tuple — это мутабельная структура, так ведь? Передавать такие с модификатором in не рекомендуется.

I>особенно критично для hot-path кода.


В hot-path я бы такое поостерёгся. У меня микробенчмарк показал падение производительности при передаче кортежа с модификатором in.
Глаза у меня добрые, но рубашка — смирительная!
Re[3]: Value tuples
От: Igorxz  
Дата: 06.12.18 00:57
Оценка:
Здравствуйте, Qbit86, Вы писали:

Q>Здравствуйте, Igorxz, Вы писали:


I>>что это дает: в первом случае передается три указателя в метод, а во втором — только один.


Q>Но value tuple — это мутабельная структура, так ведь? Передавать такие с модификатором in не рекомендуется.

это все общие слова. типа как лозунги — "лучше быть здоровым и богатым, чем наоборот" — кто бы с этим спорил, токо это ни о чем.

I>>особенно критично для hot-path кода.


Q>В hot-path я бы такое поостерёгся. У меня микробенчмарк показал падение производительности при передаче кортежа с модификатором in.

не может этого быть, ибо, известно что напр. в x64 архитектуре параметры в метод передаются так: два первых через регистры, остальные через стек.
для члена-функции первый всегда скрытый экземпляр.
если 5-10 параметров против 1-2. не может оно падать в производительности.
Re[4]: Value tuples
От: romangr Россия  
Дата: 06.12.18 03:37
Оценка: +1
Здравствуйте, Igorxz, Вы писали:

I>не может этого быть, ибо, известно что напр. в x64 архитектуре параметры в метод передаются так: два первых через регистры, остальные через стек.


Не 2, а 4 — rcx, rdx, r8, r9. И еще 4 аргумента с плавающей запятой передаются через xmm0-xmm3.
Microsoft x64 calling convention
Re[4]: Микробенчмарк
От: Qbit86 Кипр
Дата: 06.12.18 06:26
Оценка: 44 (1)
Здравствуйте, Igorxz, Вы писали:

I>это все общие слова. типа как лозунги


Не слова, а реальность, данная нам в ощущениях. И измерениях.

I>не может этого быть, ибо…


BenchmarkDotNet=v0.11.3, OS=Windows 10.0.17763.134 (1809/October2018Update/Redstone5)
Intel Core i5-4690K CPU 3.50GHz (Haswell), 1 CPU, 4 logical and 4 physical cores
.NET Core SDK=2.1.500
  [Host]     : .NET Core 2.1.6 (CoreCLR 4.6.27019.06, CoreFX 4.6.27019.05), 64bit RyuJIT
  Job-RVABUB : .NET Core 2.1.6 (CoreCLR 4.6.27019.06, CoreFX 4.6.27019.05), 64bit RyuJIT

Jit=RyuJit  Platform=X64  Runtime=Core  
IterationCount=3  LaunchCount=1  WarmupCount=3  

            Method |      Mean |     Error |    StdDev | Ratio |
------------------ |----------:|----------:|----------:|------:|
 SeparateArguments |  2.481 ns | 0.2602 ns | 0.0143 ns |  1.00 |
           AsTuple | 10.061 ns | 0.7534 ns | 0.0413 ns |  4.06 |

// * Legends *
  Mean   : Arithmetic mean of all measurements
  Error  : Half of 99.9% confidence interval
  StdDev : Standard deviation of all measurements
  Ratio  : Mean of the ratio distribution ([Current]/[Baseline])
  1 ns   : 1 Nanosecond (0.000000001 sec)


Код бенчмарка:
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Configs;
using BenchmarkDotNet.Environments;
using BenchmarkDotNet.Jobs;

namespace Spontaneous
{
    public class ValueTupleBenchmark
    {
        private static readonly string s_one = "one";
        private static readonly string s_two = "two";
        private static readonly string s_three = "three";

        [Benchmark(Baseline = true)]
        public int SeparateArguments()
        {
            return SeparateArgumentsCore(s_one, s_two, s_three);
        }

        [Benchmark]
        public int AsTuple()
        {
            return AsTupleCore((s_one, s_two, s_three));
        }

        private int SeparateArgumentsCore(string one, string two, string three)
        {
            return unchecked(one.Length + two.Length * three.Length);
        }

        private int AsTupleCore(in (string one, string two, string three) t)
        {
            return unchecked(t.one.Length + t.two.Length * t.three.Length);
        }

        internal static IConfig CreateDefaultConfig()
        {
            Job coreRyuJitJob = new Job(Job.Default)
                .With(Runtime.Core)
                .With(Platform.X64)
                .With(Jit.RyuJit)
                .ApplyAndFreeze(RunMode.Short);

            IConfig result = ManualConfig.Create(DefaultConfig.Instance)
                .With(coreRyuJitJob);

            return result;
        }
    }
}
Глаза у меня добрые, но рубашка — смирительная!
Re[5]: Микробенчмарк
От: Igorxz  
Дата: 06.12.18 11:02
Оценка: 1 (1)
Здравствуйте, Qbit86, Вы писали:

Q>Не слова, а реальность, данная нам в ощущениях. И измерениях.

ощущения бывают разные, в разных местах. путать их с какими-то а-ля концепциями-понятиями не стоит. ты о чем рассказываешь: об ощущениях своих или об осмысленной позиции? разберись.

пришлось мерить самому... вот что намерилось у меня. думаю тенденция понятна, а её причина была объяснена выше.
BenchmarkDotNet=v0.11.3, OS=Windows 7 SP1 (6.1.7601.0)
Intel Core i5-4690 CPU 3.50GHz (Haswell), 1 CPU, 4 logical and 4 physical cores
Frequency=3417988 Hz, Resolution=292.5698 ns, Timer=TSC
  [Host]     : .NET Framework 4.7.2 (CLR 4.0.30319.42000), 64bit RyuJIT-v4.8.3646.0
  DefaultJob : .NET Framework 4.7.2 (CLR 4.0.30319.42000), 64bit RyuJIT-v4.8.3646.0


            Method |     Mean |     Error |    StdDev | Ratio |
------------------ |---------:|----------:|----------:|------:|
 SeparateArguments | 3.691 ns | 0.0238 ns | 0.0223 ns |  1.00 |
           AsTuple | 3.468 ns | 0.0386 ns | 0.0361 ns |  0.94 |


код:
    /// <summary>
    /// 
    /// </summary>
    public class ValueTupleBenchmark
    {
        private const string ONE   = "one";
        private const string TWO   = "two";
        private const string THREE = "three";
        private const string _4 = "4-three";
        private const string _5 = "5-three";
        private const string _6 = "6-three";
        private const string _7 = "7-three";
        private const string _8 = "8-three";
        private const string _9 = "9-three";
        private const string _10 = "10-three";
        private (string one, string two, string three, string _4, string _5, string _6, string _7, string _8, string _9, string _10) _Tuple = (ONE, TWO, THREE, _4, _5, _6, _7, _8, _9, _10);

        [MethodImpl(MethodImplOptions.NoInlining)]
        [Benchmark(Baseline = true)] public int SeparateArguments() => SeparateArgumentsCore( ONE, TWO, THREE, _4, _5, _6, _7, _8, _9, _10 );

        [MethodImpl(MethodImplOptions.NoInlining)]
        [Benchmark] public int AsTuple() => AsTupleCore( in _Tuple );

        [MethodImpl(MethodImplOptions.NoInlining)]
        private int SeparateArgumentsCore( string one, string two, string three, string _4, string _5, string _6, string _7, string _8, string _9, string _10 )
            => unchecked(one.Length + two.Length * three.Length + _4.Length + _5.Length + _6.Length + _7.Length + _8.Length + _9.Length + _10.Length);

        [MethodImpl(MethodImplOptions.NoInlining)]
        private int AsTupleCore( in (string one, string two, string three, string _4, string _5, string _6, string _7, string _8, string _9, string _10) t ) 
            => unchecked(t.one.Length + t.two.Length * t.three.Length + t._4.Length + t._5.Length + t._6.Length + t._7.Length + t._8.Length + t._9.Length + t._10.Length);

        internal static IConfig CreateDefaultConfig()
        {
            var job = new Job( Job.Default )
                .With( Runtime.Core )
                .With( Platform.X64 )
                .With( Jit.RyuJit )
                .ApplyAndFreeze( RunMode.Short );

            IConfig result = ManualConfig.Create( DefaultConfig.Instance )
                .With( job );

            return (result);
        }
    }
Re[6]: Микробенчмарк
От: Qbit86 Кипр
Дата: 06.12.18 13:03
Оценка:
Здравствуйте, Igorxz, Вы писали:

I>пришлось мерить самому... вот что намерилось у меня.


Так а почему намерялось на десяти строках? Выше ты предлагал топикстартеру передавать кортежи из трёх строк, «особенно критично для hot-path кода».

I>что это дает: в первом случае передается три указателя в метод, а во втором — только один.


Но добавляется лишний уровень косвенности в адресации.
Глаза у меня добрые, но рубашка — смирительная!
Re[6]: Микробенчмарк
От: rameel https://github.com/rsdn/CodeJam
Дата: 06.12.18 13:05
Оценка: 11 (1) +1
Здравствуйте, Igorxz, Вы писали:

I>пришлось мерить самому... вот что намерилось у меня. думаю тенденция понятна, а её причина была объяснена выше.


Ты в тесте на сконструированный тупл ссылку передаешь, что читерство, мог бы сразу константу подставлять
... << RSDN@Home 1.0.0 alpha 5 rev. 0>>
Re[4]: Value tuples
От: #John Европа https://github.com/ichensky
Дата: 06.12.18 13:11
Оценка: 1 (1)
Здравствуйте, Igorxz, Вы писали:

Q>>В hot-path я бы такое поостерёгся. У меня микробенчмарк показал падение производительности при передаче кортежа с модификатором in.

I>не может этого быть, ибо, известно что напр. в x64 архитектуре параметры в метод передаются так: два первых через регистры, остальные через стек.
I>для члена-функции первый всегда скрытый экземпляр.
I>если 5-10 параметров против 1-2. не может оно падать в производительности.

Когда мы передаем в функцию переменные через Tuple, то .net сначала запихивает эти переменные из регистров/другой памяти в объект tuple (если еще не создан, то создает такой объект), а потом передает ссылку на этот объект(qword ptr [rbp+48h]) через регистр в функцию (данном примере через `rcx`).

Когда мы передаем просто переменные в функцию, то .net передает эти переменные как через регистры, так и через стек.
Но что странно, что в начале функции .net сначала выгружает данные из этих регистров в стек, потом делает какую-то проверку(какую??) и уже потом проводит операцию сложения. Для tuples нет такого оверхеда по выгрузке данных из регистров в стек, но есть оверхед перед вызовом функции: создание объекта.

    class Program 
    {
        #region
//00007FFF6E6B1AA0 push        rbp  
//00007FFF6E6B1AA1 push        rdi  
//00007FFF6E6B1AA2 push        rsi  
//00007FFF6E6B1AA3 sub         rsp,30h  
//00007FFF6E6B1AA7 mov         rbp,rsp  
//00007FFF6E6B1AAA xor         eax,eax  
//00007FFF6E6B1AAC mov         qword ptr[rbp + 28h], rax  
//00007FFF6E6B1AB0 mov         dword ptr[rbp + 50h], ecx  
//00007FFF6E6B1AB3 cmp         dword ptr[7FFF6E5949C8h],0  
//00007FFF6E6B1ABA je          00007FFF6E6B1AC1  
//00007FFF6E6B1ABC call        00007FFFCE2E39D0  
//00007FFF6E6B1AC1 mov         eax,dword ptr[rbp + 50h]  
//00007FFF6E6B1AC4 mov         dword ptr[rbp + 24h], eax  
//00007FFF6E6B1AC7 mov         eax,dword ptr[rbp + 50h]  
//00007FFF6E6B1ACA inc         eax  
//00007FFF6E6B1ACC mov         dword ptr[rbp + 50h], eax  
//00007FFF6E6B1ACF mov         eax,dword ptr[rbp + 24h]  
//00007FFF6E6B1AD2 lea         rsp,[rbp+30h]  
//00007FFF6E6B1AD6 pop         rsi  
//00007FFF6E6B1AD7 pop         rdi  
//00007FFF6E6B1AD8 pop         rbp  
//00007FFF6E6B1AD9 ret
        #endregion
        static int ecx(int x) =>x++;

        #region
//00007FFF6E6B1B60 push        rbp  
//00007FFF6E6B1B61 push        rdi  
//00007FFF6E6B1B62 push        rsi  
//00007FFF6E6B1B63 sub         rsp,30h  
//00007FFF6E6B1B67 mov         rbp,rsp  
//00007FFF6E6B1B6A xor         eax,eax  
//00007FFF6E6B1B6C mov         qword ptr[rbp + 28h], rax  
//00007FFF6E6B1B70 mov         dword ptr[rbp + 50h], ecx  
//00007FFF6E6B1B73 mov         dword ptr[rbp + 58h], edx  
//00007FFF6E6B1B76 cmp         dword ptr[7FFF6E5949C8h],0  
//00007FFF6E6B1B7D je          00007FFF6E6B1B84  
//00007FFF6E6B1B7F call        00007FFFCE2E39D0  
//00007FFF6E6B1B84 mov         eax,dword ptr[rbp + 50h]  
//00007FFF6E6B1B87 add         eax,dword ptr[rbp + 58h]  
//00007FFF6E6B1B8A lea         rsp,[rbp+30h]  
//00007FFF6E6B1B8E pop         rsi  
//00007FFF6E6B1B8F pop         rdi  
//00007FFF6E6B1B90 pop         rbp  
//00007FFF6E6B1B91 ret
        #endregion
        static int ecx_edx(int x, int y) => x + y;
        static int ecx_edx_rd8(int x, int y, int z) => x + y + z;
        static int ecx_edx_rd8_rd9(int x, int y, int z, int a) => x + y + z + a;
        static int ecx_edx_rd8_rd9_stack(int x, int y, int z, int a, int b) => x + y + z + a + b;

        #region
//00007FFF6E691D80 push        rbp  
//00007FFF6E691D81 push        rdi  
//00007FFF6E691D82 push        rsi  
//00007FFF6E691D83 sub         rsp,30h  
//00007FFF6E691D87 mov         rbp,rsp  
//00007FFF6E691D8A xor         eax,eax  
//00007FFF6E691D8C mov         qword ptr[rbp + 28h], rax  
//00007FFF6E691D90 mov         qword ptr[rbp + 50h], rcx  
//00007FFF6E691D94 cmp         dword ptr[7FFF6E5749C8h],0  
//00007FFF6E691D9B je          00007FFF6E691DA2  
//00007FFF6E691D9D call        00007FFFCE2E39D0  
//00007FFF6E691DA2 mov         rax,qword ptr[rbp + 50h]  
//00007FFF6E691DA6 mov         eax,dword ptr[rax]  
//00007FFF6E691DA8 mov         rdx,qword ptr[rbp + 50h]  
//00007FFF6E691DAC add         eax,dword ptr[rdx + 4]  
//00007FFF6E691DAF lea         rsp,[rbp+30h]  
//00007FFF6E691DB3 pop         rsi  
//00007FFF6E691DB4 pop         rdi  
//00007FFF6E691DB5 pop         rbp  
//00007FFF6E691DB6 ret
        #endregion
        static int tuple_over_heap_rcx(in (int x, int y)t) => t.x + t.y;


        static void Main()
        {
            // 00007FFF6E6A14C6 mov         ecx,5  
            var val = ecx(5);

            // 00007FFF6E6914D9 mov         ecx,2  
            // 00007FFF6E6914DE mov         edx,4
            val = ecx_edx(2,4);

            // 00007FFF6E6B14F1 mov         ecx,1  
            // 00007FFF6E6B14F6 mov         edx,2
            // 00007FFF6E6B14FB mov         r8d,3
            val = ecx_edx_rd8(1, 2, 3);


            // 00007FFF6E6A1922 mov         ecx,9  
            // 00007FFF6E6A1927 mov         edx,8
            // 00007FFF6E6A192C mov         r8d,7
            // 00007FFF6E6A1932 mov         r9d,6
            ecx_edx_rd8_rd9(9,8,7,6);

            // 00007FFF6E681944  mov         dword ptr [rsp+20h],5  
            // 00007FFF6E68194C mov         ecx,1
            // 00007FFF6E681951 mov         edx,2
            // 00007FFF6E681956 mov         r8d,3
            // 00007FFF6E68195C mov         r9d,4
            ecx_edx_rd8_rd9_stack(1, 2, 3, 4, 5);


            // 00007FFF6E6B1974 xor         ecx,ecx
            // 00007FFF6E691976  mov         qword ptr [rbp+48h],rcx  
            // 00007FFF6E69197A lea         rcx,[rbp+48h]  
            // 00007FFF6E69197E mov         edx,2  
            // 00007FFF6E691983 mov         r8d,3  
            // 00007FFF6E691989 call        00007FFF6E6914A0  
            // 00007FFF6E69198E mov         rcx,qword ptr[rbp + 48h]  
            // 00007FFF6E691992 mov         qword ptr[rbp + 78h], rcx  
            // 00007FFF6E691996 lea         rcx,[rbp+78h]
            tuple_over_heap_rcx((2,3));

          

        }
    }
Підтримати Україну у боротьбі з країною-терористом.

https://prytulafoundation.org/
https://u24.gov.ua/

Слава Збройним Силам України!!! Героям слава!!!
Re[5]: Value tuples
От: rameel https://github.com/rsdn/CodeJam
Дата: 06.12.18 13:16
Оценка:
Здравствуйте, #John, Вы писали:

J>Когда мы передаем просто переменные в функцию, то .net передает эти переменные как через регистры, так и через стек.

J>Но что странно, что в начале функции .net сначала выгружает данные из этих регистров в стек, потом делает какую-то проверку(какую??) и уже потом проводит операцию сложения.

Ты уверен, что не в Debug смотришь? Не похоже на релизный выхлоп.
... << RSDN@Home 1.0.0 alpha 5 rev. 0>>
Re[7]: Конструирование кортежа
От: Qbit86 Кипр
Дата: 06.12.18 13:20
Оценка:
Здравствуйте, rameel, Вы писали:

R>Ты в тесте на сконструированный тупл ссылку передаешь, что читерство, мог бы сразу константу подставлять :-\


Вернулся в тред, чтобы дописать этот комментарий, а ты его уже добавил.
Глаза у меня добрые, но рубашка — смирительная!
Re[5]: Value tuples
От: rameel https://github.com/rsdn/CodeJam
Дата: 06.12.18 13:28
Оценка:
Здравствуйте, #John, Вы писали:

К тому же для простых структур (до 4 полей) есть соответствующая оптимизация (lowering) и в твоем примере
tuple_over_heap_rcx((2,3));


метод будет заинлайнен, вычислен, а потом вообще будет выкинут Пруф

Для
public static class Program
{
    public static void Main()
    {
        tuple_over_heap_rcx((2, 3));
    }
    
    public static int tuple_over_heap_rcx(in (int x, int y) t) => t.x + t.y;
    public static int ecx_edx(int x, int y) => x + y;
    public static int ecx_edx_rd8(int x, int y, int z) => x + y + z;
    public static int ecx_edx_rd8_rd9(int x, int y, int z, int a) => x + y + z + a;
    public static int ecx_edx_rd8_rd9_stack(int x, int y, int z, int a, int b) => x + y + z + a + b;
}

получается вот такой код
Program.Main()
    L0000: ret

Program.tuple_over_heap_rcx(System.ValueTuple`2<Int32,Int32> ByRef)
    L0000: mov eax, [rcx]
    L0002: add eax, [rcx+0x4]
    L0005: ret

Program.ecx_edx(Int32, Int32)
    L0000: lea eax, [rcx+rdx]
    L0003: ret

Program.ecx_edx_rd8(Int32, Int32, Int32)
    L0000: add ecx, edx
    L0002: lea eax, [rcx+r8]
    L0006: ret

Program.ecx_edx_rd8_rd9(Int32, Int32, Int32, Int32)
    L0000: add ecx, edx
    L0002: add ecx, r8d
    L0005: lea eax, [rcx+r9]
    L0009: ret

Program.ecx_edx_rd8_rd9_stack(Int32, Int32, Int32, Int32, Int32)
    L0000: add ecx, edx
    L0002: add ecx, r8d
    L0005: add ecx, r9d
    L0008: mov eax, ecx
    L000a: add eax, [rsp+0x28]
    L000e: ret
... << RSDN@Home 1.0.0 alpha 5 rev. 0>>
Re[7]: Микробенчмарк
От: Igorxz  
Дата: 06.12.18 14:42
Оценка:
Здравствуйте, Qbit86, Вы писали:

Q>Так а почему намерялось на десяти строках? Выше ты предлагал топикстартеру передавать кортежи из трёх строк, «особенно критично для hot-path кода».

потому что это подтверждает то, о чем я говорил. а говорил я следующее: передача 1-2 параметра не может быть медленнее, чем передача 5-10 параметров.
если это вдруг не так, уж не знаю по какой причине (компилятор/оптимизатор кривой, ещё чего), то что-то не так в _твоем_ датском королевстве.
Re[7]: Микробенчмарк
От: Igorxz  
Дата: 06.12.18 14:51
Оценка:
Здравствуйте, rameel, Вы писали:

R>Ты в тесте на сконструированный тупл ссылку передаешь, что читерство, мог бы сразу константу подставлять

в тесте я подтверждаю именно то, что утверждал: передача 1-2 параметра быстрее чем 5-10.
сконструированние туплов зависит от контекста/ситуации — где-то нужно, где-то нет.

(насчет "читерство" — советую с мало знакомыми людьми быть вежливым и проявлять сдержанность)
Re[8]: Реальность
От: Qbit86 Кипр
Дата: 06.12.18 14:51
Оценка: +3
Здравствуйте, Igorxz, Вы писали:

Q>>Так а почему намерялось на десяти строках? Выше ты предлагал топикстартеру передавать кортежи из трёх строк, «особенно критично для hot-path кода».

I>потому что это подтверждает то, о чем я говорил. а говорил я следующее...

А говорил ты следующее: «что это дает: в первом случае передается три указателя в метод, а во втором — только один. особенно критично для hot-path кода»

I>передача 1-2 параметра не может быть медленнее, чем передача 5-10 параметров.

I>если это вдруг не так, уж не знаю по какой причине

Чтоб передать этот один параметр — кортеж — тебе его надо ещё сконструировать. На руках-то у тебя отдельные value, password и salt. Поэтому помимо измерения времени вызова нужно ещё учитывать время подготовки перед этим вызовом.

I>то что-то не так в _твоем_ датском королевстве.


«Реальность — это то, что продолжает существовать, даже когда ты перестаёшь в неё верить.»
Глаза у меня добрые, но рубашка — смирительная!
Re[9]: Реальность
От: Igorxz  
Дата: 06.12.18 14:58
Оценка: -2
Здравствуйте, Qbit86, Вы писали:

Q>Чтоб передать этот один параметр — кортеж — тебе его надо ещё сконструировать. На руках-то у тебя отдельные value, password и salt. Поэтому помимо измерения времени вызова нужно ещё учитывать время подготовки перед этим вызовом.

Q>«Реальность — это то, что продолжает существовать, даже когда ты перестаёшь в неё верить.»

ты либо молодой/зеленый, либо прекрасно понял то, о чем я говорю, но прикидываешься.
в первом случае ты понять ничего не сможешь, во втором не захочешь.
в обоих случаях дискутировать бессмысленно...)))
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.