При выполнение строки dataGridView2.Sort(0, ListSortDirection.Descending) даёт ошибку - Неизвестное имя ‘ListSortDirection’. Помогите пожалуйста, как разбираться?
Этот класс - он тоже далеко не во всем подарок. На Хабре есть достаточно подробная статья, и мне не совсем понравилось нынешнее (т.е начиная с .NET 4.0) состояние вопроса. Особенно расстроило вот это:
Мне в голову приходит что-то типа такого:
var s := Range('a','z').JoinIntoString;
ArrGen(15,i->s[Random(1,26)]).JoinIntoString.Print;
Я также подумываю заменить расширение JoinIntoString на просто Join, хотя там будет путаница с Join со второй последовательностью
Нет, это плохо. У вас .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 с максимум. Мышиная возня.
И будет этих Join аж три - статический метод для класса string, сливающий строки через разделитель, метод для слияния пары последовательностей по ключам и метод для слияния последовательности символов в строку…
- Длина строки тоже влияет на результаты.
-
Range('a', 'z').JoinIntoString
иRange('a', 'z').ToArray
работают не одинаково. Поэтому их не нужно считать при вычислении времени. -
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.
Мне совершенно неинтересно, насколько быстро работает тот или иной элемент в программе. Меня интересует, насколько отличается время получения конечного результата, т.е. поставленной задачи.
- Про это уже столько раз писали… в том числе, разработчики. Коим я привык доверять.
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;
Сергей, Алекс, Админ – благодарю. Хотя ответы обычно касаются нескольких аспектов, именно благодаря вам узнаю важные (для себя) нюансы
А зачем два таймера???
Milliseconds
отсчитывает от запуска, а MillisecondsDelta
от последнего вызова любой из этих 2 функций.
А одним таймером нельзя обойтись? И целой глобальной переменной. Два таймера - это ресурсы
У вас так же было. StartTime
и curr_time
тратят абсолютно столько же ресурсов. Ну, разве что curr_time
инициализировалось в статичном конструкторе, но я сомневаюсь что это сильно большая разница.
Кроме того, Stopwatch
, как и DateTime
, не тратит время процессора пока не вызовешь какую то из функций выше.
При выполнение строки dataGridView2.Sort(0, ListSortDirection.Descending) даёт ошибку - Неизвестное имя ‘ListSortDirection’. Помогите пожалуйста, как разбираться?
-
Видим:
То есть надо или прописать uses System.ComponentModel;
в начале программы, или писать каждый раз System.ComponentModel.ListSortDirection
.