Помощь новичкам

При выполнение строки dataGridView2.Sort(0, ListSortDirection.Descending) даёт ошибку - Неизвестное имя ‘ListSortDirection’. Помогите пожалуйста, как разбираться?

Этот класс - он тоже далеко не во всем подарок. На Хабре есть достаточно подробная статья, и мне не совсем понравилось нынешнее (т.е начиная с .NET 4.0) состояние вопроса. Особенно расстроило вот это: %D0%A1%D0%BD%D0%B8%D0%BC%D0%BE%D0%BA

Мне в голову приходит что-то типа такого:

var s := Range('a','z').JoinIntoString;
ArrGen(15,i->s[Random(1,26)]).JoinIntoString.Print;

Я также подумываю заменить расширение JoinIntoString на просто Join, хотя там будет путаница с Join со второй последовательностью

1 лайк

Нет, это плохо. У вас .JoinIntoString не пытается вычислить готовую длину строки, поэтому это будет медленно.

Зато так:

var s := Range('a','z').JoinIntoString;
var s2 := new string(ArrGen(15,i->s[Random(1,26)]));
s2.Print;

Будет наверняка даже быстрее чем в моём примере.

Но я у себя в примере использовал только множество .Append и 1 .ToString. Это если делать что то более сложное - работа стринг билдера может стать медленной.

begin
  var k, t: integer;
  var n := 1000000;
  Milliseconds;
  loop n do
  begin
    var s := Range('a', 'z').JoinIntoString;
    k := s.Length;
    ArrGen(15, i -> s[Random(1, k)]).JoinIntoString //.Println
  end;
  t := MillisecondsDelta;
  Println(t);
  Milliseconds;
  loop n do
  begin
    var c := Range('a', 'z').ToArray;
    k := c.Count - 1;
    ArrGen(15, i -> c[Random(0, k)]).JoinIntoString //.Println
  end;
  t := MillisecondsDelta;
  Println(t);
  Milliseconds;
  loop n do
  begin
    var s := Range('a', 'z').JoinIntoString;
    k := s.Length;
    var s2 := new string(ArrGen(15, i -> s[Random(1, k)]));
    //s2.Print;
  end;
  t := MillisecondsDelta;
  Println(t)
end.

Результаты

4262 
3779 
3638 

На миллионе вызовов - 0.6 с максимум. Мышиная возня.

1 лайк

И будет этих Join аж три - статический метод для класса string, сливающий строки через разделитель, метод для слияния пары последовательностей по ключам и метод для слияния последовательности символов в строку…

1 лайк
  1. Длина строки тоже влияет на результаты.
  2. Range('a', 'z').JoinIntoString и Range('a', 'z').ToArray работают не одинаково. Поэтому их не нужно считать при вычислении времени.
  3. Stopwatch считает время более точно.
begin
  var k: integer;
  var s: string;
  var c: array of char;
  var n := 100000;
  var l := 1000;
  var sw := new System.Diagnostics.Stopwatch;
  var seed := 0;
  
  Randomize(seed);
  s := Range('a', 'z').JoinIntoString;
  k := s.Length;
  sw.Restart;
  loop n do ArrGen(l, i -> s[Random(k)+1]).JoinIntoString;
  sw.Stop;
  sw.Elapsed.ToString.Println;
  
  Randomize(seed);
  c := Range('a', 'z').ToArray;
  k := c.Length;
  sw.Restart;
  loop n do ArrGen(l, i -> c[Random(k)]).JoinIntoString;
  sw.Stop;
  sw.Elapsed.ToString.Println;
  
  Randomize(seed);
  s := Range('a', 'z').JoinIntoString;
  k := s.Length;
  sw.Restart;
  loop n do new string(ArrGen(l, i -> s[Random(k)+1]));
  sw.Stop;
  sw.Elapsed.ToString.Println;
  
  Randomize(seed);
  c := Range('a', 'z').ToArray;
  k := c.Length;
  sw.Restart;
  loop n do new string(ArrGen(l, i -> c[Random(k)]));
  sw.Stop;
  sw.Elapsed.ToString.Println;
  
  readln;
end.

image

1 лайк

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

  1. Про это уже столько раз писали… в том числе, разработчики. Коим я привык доверять.

Stopwatch умеет использовать встроенные в железо таймеры, которые на много точнее чем DateTime. Их существование на компьютере можно проверить так:

begin
  System.Diagnostics.Stopwatch.IsHighResolution.Print;
end.

А Milliseconds ещё и использует DateTime.Now, которое берёт DateTime.UtcNow и выполняет дополнительные действия чтоб учесть часовой пояс, сезонный перевод часов и т.п.

Про это говорили давно, и после этого я новую инфу откопал. Ещё, недавно, статью с хабра, вроде, на куберфоруме кто то кидал.

Доверять и верить как в бога это не одно и то же. Разработчики тоже умеет говорить глупости.
Кроме того, я не помню чтоб они утверждали что Milliseconds лучше. Я помню чтоб они спрашивали почему кто то из форумчан решил что оно хуже. Хотя найти тот разговор не смог, так что это не точно.

Да мы ж не возражаем.

А как с помощью Stopwatch написать Milliseconds?

Оу, с помощью Stopwatch можно замерить интервал в 5 секунд точнее на 0.01% ? Да ради бога…

В PABCSystem строчки 6837-6851:

var
  curr_time := DateTime.Now;

function Milliseconds: integer;
begin
  curr_time := DateTime.Now;
  Milliseconds := Convert.ToInt32((curr_time - StartTime).TotalMilliseconds);
end;

function MillisecondsDelta: integer;
begin
  var t := DateTime.Now;  
  Result := Convert.ToInt32((t - curr_time).TotalMilliseconds);
  curr_time := DateTime.Now;
end;

Надо заменить на:

var msTimer := new System.Diagnostics.Stopwatch;
var msdTimer := new System.Diagnostics.Stopwatch;

function Milliseconds: integer;
begin
  Result := msTimer.ElapsedMilliseconds;
  msdTimer.Restart;
end;

function MillisecondsDelta: integer;
begin
  Result := msdTimer.ElapsedMilliseconds;
  msdTimer.Restart;
end;

Правда, свойство ElapsedMilliseconds имеет тип int64. Можно ещё изменить возвращаемое значение этих 2 функций с integer на int64, если это не сломает совместимость.


Так же надо убрать строчку 2214:

  StartTime: DateTime;// Для Milliseconds

И строчку 11491:

  StartTime := DateTime.Now;

Заменить на:

  msTimer.Start;
  msdTimer.Start;
1 лайк

Сергей, Алекс, Админ – благодарю. Хотя ответы обычно касаются нескольких аспектов, именно благодаря вам узнаю важные (для себя) нюансы

А зачем два таймера???

Milliseconds отсчитывает от запуска, а MillisecondsDelta от последнего вызова любой из этих 2 функций.

А одним таймером нельзя обойтись? И целой глобальной переменной. Два таймера - это ресурсы

У вас так же было. StartTime и curr_time тратят абсолютно столько же ресурсов. Ну, разве что curr_time инициализировалось в статичном конструкторе, но я сомневаюсь что это сильно большая разница.

Кроме того, Stopwatch, как и DateTime, не тратит время процессора пока не вызовешь какую то из функций выше.

При выполнение строки dataGridView2.Sort(0, ListSortDirection.Descending) даёт ошибку - Неизвестное имя ‘ListSortDirection’. Помогите пожалуйста, как разбираться?

  1. Забиваем в поиск на msdn

  2. Видим:

То есть надо или прописать uses System.ComponentModel; в начале программы, или писать каждый раз System.ComponentModel.ListSortDirection.