powered by simpleCommunicator - 2.0.52     © 2025 Programmizd 02
Форумы / WinForms, .Net Framework [игнор отключен] [закрыт для гостей] / Впечатления от собеседования (связано с .Net)
83 сообщений из 83, показаны все 4 страниц
Впечатления от собеседования (связано с .Net)
    #39466682
Супер_Пав
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
На днях ходил на встречу, где был заданы всего два вопроса:
автор1) Что Вам не нравится в приведенном коде:
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
private readonly Dictionary<string, Guid> dict = new Dictionary<string, Guid>();

public Guid GetValue(stringkey)
{
    if (dict.ContainsKey(key))
        return dict[key];
    var newValue = Guid.NewGuid();
    dict.Add(key, newValue);
    return newValue;
}


автор2) Как организовать доступ к объекту (dict, из примера выше, надо поправить тело метода GetValue) несколькими потоками?
Ответ на первый вопрос заключался в том, что вместо
Код: c#
1.
2.
if (dict.ContainsKey(key))
    return dict[key];


нужно использовать
Код: c#
1.
2.
3.
Guid value;
if (dict.TryGetValue(key, out value))
    return dict[key];


Если честно, я всегда использовал 1й вариант и по 2му у меня какие-то сомнения возникли, я не понял выгоды, чем 1й вариант, хуже 2го. Написал небольшую утилиту чтобы проверить время выполнения первого и второго куска. В словарь было добавлено 40 млн записей, разницы в производительности никакой, вообще. Возможно на слабом железе что-то и проявится, но в моем случае поиск в обоих случаях выполняется за одинаковое кол-во временных единиц. Кто-то может объяснить преимущество одного варианта над другим?
По второму вопросу ответ дам чуть позже, хочется услышать ваши решения. Я так же озвучу, какой вариант я предложил. Он был неправильным, мне сказали, что существует только одно решение задачи.
...
Рейтинг: 0 / 0
Впечатления от собеседования (связано с .Net)
    #39466700
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ИМХО первый вариант от второго ничем не отличается. Два поиска key в dict
Может правильно все-таки
Код: c#
1.
2.
3.
Guid value;
if (dict.TryGetValue(key, out value))
    return value;


так один поиск будет.
...
Рейтинг: 0 / 0
Впечатления от собеседования (связано с .Net)
    #39466703
Супер_Пав
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dima TИМХО первый вариант от второго ничем не отличается. Два поиска key в dict
Может правильно все-таки
Код: c#
1.
2.
3.
Guid value;
if (dict.TryGetValue(key, out value))
    return value;


так один поиск будет.
да, value. Это очепятка, код тут набивал
...
Рейтинг: 0 / 0
Впечатления от собеседования (связано с .Net)
    #39466709
Roman Mejtes
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Супер_Пав,

Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
public bool ContainsKey(TKey key)
{
	return this.FindEntry(key) >= 0;
}

public bool TryGetValue(TKey key, out TValue value)
{
	int num = this.FindEntry(key);
	if (num >= 0)
	{
		value = this.entries[num].value;
		return true;
	}
	value = default(TValue);
	return false;
}


как видишь, разница по сути 0вая, просто с TryGetValue код "удобочитамее". Но как по мне, пофигу вообще, не принципиально.
хотя с учётом современных версий C# код должен выглядеть след. образом:
Код: c#
1.
2.
            if (dict.TryGetValue(key, out Guid value))
                return value;


+ если данный в многопоточной среде лучше не применять
...
Рейтинг: 0 / 0
Впечатления от собеседования (связано с .Net)
    #39466713
Супер_Пав
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вот результат поиска
GetValueI start at:06-06-2017 10:14:26.330
Guid = 0df051e7-c221-468b-aca6-85f514a723dd
GetValueI end at:06-06-2017 10:14:26.332

GetValueII start at:06-06-2017 10:14:26.333
Guid = 0df051e7-c221-468b-aca6-85f514a723dd
GetValueII end at:06-06-2017 10:14:26.333
Continue test? (Y/N) :>Y

GetValueI start at:06-06-2017 10:14:35.483
Guid = 9b88cf75-64fa-4297-98e8-00a85cf67863
GetValueI end at:06-06-2017 10:14:35.484

GetValueII start at:06-06-2017 10:14:35.484
Guid = 9b88cf75-64fa-4297-98e8-00a85cf67863
GetValueII end at:06-06-2017 10:14:35.484
Continue test? (Y/N) :>Y

GetValueI start at:06-06-2017 10:14:36.459
Guid = 4b0b3251-32ad-4f94-857a-9185635aedbe
GetValueI end at:06-06-2017 10:14:36.460

GetValueII start at:06-06-2017 10:14:36.460
Guid = 4b0b3251-32ad-4f94-857a-9185635aedbe
GetValueII end at:06-06-2017 10:14:36.460
Continue test? (Y/N) :>Y

GetValueI start at:06-06-2017 10:14:37.499
Guid = 40f25a6f-5e68-496d-9e68-b7aca8e02a71
GetValueI end at:06-06-2017 10:14:37.500

GetValueII start at:06-06-2017 10:14:37.500
Guid = 40f25a6f-5e68-496d-9e68-b7aca8e02a71
GetValueII end at:06-06-2017 10:14:37.501
Continue test? (Y/N) :>Y

GetValueI start at:06-06-2017 10:14:38.620
Guid = 929bd12d-bd1f-4d8e-8d0a-1e87e981c14b
GetValueI end at:06-06-2017 10:14:38.621

GetValueII start at:06-06-2017 10:14:38.622
Guid = 929bd12d-bd1f-4d8e-8d0a-1e87e981c14b
GetValueII end at:06-06-2017 10:14:38.623
Continue test? (Y/N) :>Y

GetValueI start at:06-06-2017 10:14:39.445
Guid = 53144be1-66f3-4266-bcda-9fb7acb00086
GetValueI end at:06-06-2017 10:14:39.446

GetValueII start at:06-06-2017 10:14:39.448
Guid = 53144be1-66f3-4266-bcda-9fb7acb00086
GetValueII end at:06-06-2017 10:14:39.448
Continue test? (Y/N) :>Y

GetValueI start at:06-06-2017 10:14:40.630
Guid = 061bcf94-3bdb-4fc8-b100-2220f0c8547f
GetValueI end at:06-06-2017 10:14:40.631

GetValueII start at:06-06-2017 10:14:40.632
Guid = 061bcf94-3bdb-4fc8-b100-2220f0c8547f
GetValueII end at:06-06-2017 10:14:40.632
Continue test? (Y/N) :>Y

GetValueI start at:06-06-2017 10:15:16.180
Guid = 07587b42-2937-4d01-afbb-27efa1f61059
GetValueI end at:06-06-2017 10:15:16.180

GetValueII start at:06-06-2017 10:15:16.181
Guid = 07587b42-2937-4d01-afbb-27efa1f61059
GetValueII end at:06-06-2017 10:15:16.182
Continue test? (Y/N) :>N
Press Enter

GetValueI - это первый вариант поиска, GetValueII - это второй. Как видно, разницы нет
...
Рейтинг: 0 / 0
Впечатления от собеседования (связано с .Net)
    #39466718
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Супер_Пававтор2) Как организовать доступ к объекту (dict, из примера выше, надо поправить тело метода GetValue) несколькими потоками?
Блокировкой
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
private readonly Dictionary<string, Guid> dict = new Dictionary<string, Guid>();

public Guid GetValue(stringkey)
{
 lock(dict) {
    if (dict.ContainsKey(key))
        return dict[key];
    var newValue = Guid.NewGuid();
    dict.Add(key, newValue);
    return newValue;
 }
}
...
Рейтинг: 0 / 0
Впечатления от собеседования (связано с .Net)
    #39466722
Супер_Пав
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Roman Mejtesудобочитамее
по мне, так дело вкуса. Мне больше первый вариант нравится: проверил, выполнил. Во втором случает лишняя переменная появляется. Имхо, дело вкуса.
Я просто под небольшим впечатлением от того, что мне говорили, мол второй вариант лучше.
...
Рейтинг: 0 / 0
Впечатления от собеседования (связано с .Net)
    #39466723
Супер_Пав
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dima TСупер_Павпропущено...

Блокировкой
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
private readonly Dictionary<string, Guid> dict = new Dictionary<string, Guid>();

public Guid GetValue(stringkey)
{
 lock(dict) {
    if (dict.ContainsKey(key))
        return dict[key];
    var newValue = Guid.NewGuid();
    dict.Add(key, newValue);
    return newValue;
 }
}


Это был мой вариант. Блокировка им не понравилась.
...
Рейтинг: 0 / 0
Впечатления от собеседования (связано с .Net)
    #39466732
Pallaris
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
В первом варианте метод GetValue меняет состояние коллекции, что печально. Либо переназвать, либо не добавлять элемент в коллекцию
...
Рейтинг: 0 / 0
Впечатления от собеседования (связано с .Net)
    #39466733
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Супер_ПавGetValueI - это первый вариант поиска, GetValueII - это второй. Как видно, разницы нет
Кривой замер. Чтобы разницу заметить общее время теста должно быть хотя бы сотни миллисекунд, лучше несколько секунд.

Также вопрос какие значения искались, если GetValue() вызывалось каждый с новым значением, т.е. происходило добавление, то разницы не будет.

Как уже написал - разница в количестве поисков по dict
Код: c#
1.
2.
    if (dict.ContainsKey(key)) // Первый поиск
        return dict[key];  // Второй поиск


Код: c#
1.
2.
if (dict.TryGetValue(key, out value)) // Первый поиск
    return value;
...
Рейтинг: 0 / 0
Впечатления от собеседования (связано с .Net)
    #39466743
Супер_Пав
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dima TСупер_ПавGetValueI - это первый вариант поиска, GetValueII - это второй. Как видно, разницы нет
Кривой замер. Чтобы разницу заметить общее время теста должно быть хотя бы сотни миллисекунд, лучше несколько секунд.

Также вопрос какие значения искались, если GetValue() вызывалось каждый с новым значением, т.е. происходило добавление, то разницы не будет.

Как уже написал - разница в количестве поисков по dict
Код: c#
1.
2.
    if (dict.ContainsKey(key)) // Первый поиск
        return dict[key];  // Второй поиск


Код: c#
1.
2.
if (dict.TryGetValue(key, out value)) // Первый поиск
    return value;


Разница понятна, но по мне, так оба варианта приемлемы. Не могу понять, зачем об этом спрашивать, коль 2 вариант правильные.
GetValueI и GetValueII вызывались с одним ключом по разу, ключе менялся, снова был вызов. Я не вижу смысла менять замер, коль разницы нет, оба куска кода отрабатывают очень быстро.
...
Рейтинг: 0 / 0
Впечатления от собеседования (связано с .Net)
    #39466745
Супер_Пав
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
По поводу второго вопроса. lock забраковали, мол блокирует потоки. Единственное решение задачи - это класс ReaderWriterLockSlim
...
Рейтинг: 0 / 0
Впечатления от собеседования (связано с .Net)
    #39466762
Фотография Где-то в степи
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dima T,
авторКак уже написал - разница в количестве поисков по dict
дануна....
по кишкам имхо однохуйственно ( гляньте ктнонитьрефлекторм)
первый имхо даже живее будет ?
...
Рейтинг: 0 / 0
Впечатления от собеседования (связано с .Net)
    #39466770
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Где-то в степиDima T,
авторКак уже написал - разница в количестве поисков по dict
дануна....
Кишки уже привели выше 20543115
в дополнение
Код: c#
1.
2.
3.
4.
5.
        public TValue this[TKey key] {
            get {
                int i = FindEntry(key);
                if (i >= 0) return entries[i].value;
...


два вызова FindEntry() для исходного кода и один для TryGetValue()
...
Рейтинг: 0 / 0
Впечатления от собеседования (связано с .Net)
    #39466778
Супер_Пав
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dima TГде-то в степиDima T,
пропущено...

дануна....
Кишки уже привели выше 20543115
в дополнение
Код: c#
1.
2.
3.
4.
5.
        public TValue this[TKey key] {
            get {
                int i = FindEntry(key);
                if (i >= 0) return entries[i].value;
...


два вызова FindEntry() для исходного кода и один для TryGetValue()
Не могу понять Вас, вы просто объясняете различия или утверждаете, что второй способ лучше?
...
Рейтинг: 0 / 0
Впечатления от собеседования (связано с .Net)
    #39466786
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Супер_ПавDima Tпропущено...

Кишки уже привели выше 20543115
в дополнение
Код: c#
1.
2.
3.
4.
5.
        public TValue this[TKey key] {
            get {
                int i = FindEntry(key);
                if (i >= 0) return entries[i].value;
...


два вызова FindEntry() для исходного кода и один для TryGetValue()
Не могу понять Вас, вы просто объясняете различия или утверждаете, что второй способ лучше?
Второй - быстрее, т.к. поиск (вызов FindEntry()) достаточно тяжелая операция.
...
Рейтинг: 0 / 0
Впечатления от собеседования (связано с .Net)
    #39466789
Супер_Пав
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dima TСупер_Павпропущено...

Не могу понять Вас, вы просто объясняете различия или утверждаете, что второй способ лучше?
Второй - быстрее, т.к. поиск (вызов FindEntry()) достаточно тяжелая операция.
А я утверждаю, что нет разницы. Проверил на 40 млн записях.
...
Рейтинг: 0 / 0
Впечатления от собеседования (связано с .Net)
    #39466793
Фотография Где-то в степи
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dima T,
тогда да, но надо смотреть чистый код, имхо в первом случае оптимизатор может порвать этот примитив на раз с двумя вызовами -
хотя к делу мало относится.
...
Рейтинг: 0 / 0
Впечатления от собеседования (связано с .Net)
    #39466836
Фотография Изопропил
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Roman Mejtesпросто с TryGetValue код "удобочитамее"
код с параметрами out - сомнительная удобночитаемость
...
Рейтинг: 0 / 0
Впечатления от собеседования (связано с .Net)
    #39466843
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Супер_ПавDima Tпропущено...

Второй - быстрее, т.к. поиск (вызов FindEntry()) достаточно тяжелая операция.
А я утверждаю, что нет разницы. Проверил на 40 млн записях.
Хреново ты проверял
Исходник
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
namespace Test {

	class TestDict {
		private readonly Dictionary<string, Guid> dict = new Dictionary<string, Guid>();

		public Guid GetValue1(string key)
		{
			if (dict.ContainsKey(key))
				return dict[key];
			var newValue = Guid.NewGuid();
			dict.Add(key, newValue);
			return newValue;
		}

		public Guid GetValue2(string key)
		{
			Guid value;
			if (dict.TryGetValue(key, out value))
				return value;
			var newValue = Guid.NewGuid();
			dict.Add(key, newValue);
			return newValue;
		}
	}

	static class Test {

		static string[] test_value;

		static void Init(int size) {
			Console.WriteLine($"Init {size} values");
			test_value = new string[size];
			for(int i = 0; i < test_value.Length; i++) test_value[i] = Guid.NewGuid().ToString();
		}

		static void Test1() {
			var td = new TestDict();
			Console.WriteLine("Test GetValue1() ...");
			var sw = Stopwatch.StartNew();
			for(int i = 0; i < test_value.Length; i++) {
				for(int j = i; j < test_value.Length; j += 100) {
					var guid = td.GetValue1(test_value[j]);
				}
			}
			Console.WriteLine($"Elapsed {sw.ElapsedMilliseconds} ms");
		}

		static void Test2() {
			var td = new TestDict();
			Console.WriteLine("Test GetValue2() ...");
			var sw = Stopwatch.StartNew();
			for(int i = 0; i < test_value.Length; i++) {
				for(int j = i; j < test_value.Length; j += 100) {
					var guid = td.GetValue2(test_value[j]);
				}
			}
			Console.WriteLine($"Elapsed {sw.ElapsedMilliseconds} ms");
		}

		static void Main(string[] args) {
			Init(100000);
			Test1();
			Test2();
			return;
		}
	}
}


Результат
Код: plaintext
1.
2.
3.
4.
Init 100000 values
Test GetValue1() ...
Elapsed 5721 ms
Test GetValue2() ...
Elapsed 4039 ms

Второй вариант на 30% быстрее.
...
Рейтинг: 0 / 0
Впечатления от собеседования (связано с .Net)
    #39466846
Фотография Cat2
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Модератор форума
Если несколько потоков, то надо использовать ConcurrentDictionary
https://msdn.microsoft.com/ru-ru/library/dd287191(v=vs.110).aspx
...
Рейтинг: 0 / 0
Впечатления от собеседования (связано с .Net)
    #39466940
Супер_Пав
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dima TСупер_Павпропущено...

А я утверждаю, что нет разницы. Проверил на 40 млн записях.
Хреново ты проверял
Исходник
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
namespace Test {

	class TestDict {
		private readonly Dictionary<string, Guid> dict = new Dictionary<string, Guid>();

		public Guid GetValue1(string key)
		{
			if (dict.ContainsKey(key))
				return dict[key];
			var newValue = Guid.NewGuid();
			dict.Add(key, newValue);
			return newValue;
		}

		public Guid GetValue2(string key)
		{
			Guid value;
			if (dict.TryGetValue(key, out value))
				return value;
			var newValue = Guid.NewGuid();
			dict.Add(key, newValue);
			return newValue;
		}
	}

	static class Test {

		static string[] test_value;

		static void Init(int size) {
			Console.WriteLine($"Init {size} values");
			test_value = new string[size];
			for(int i = 0; i < test_value.Length; i++) test_value[i] = Guid.NewGuid().ToString();
		}

		static void Test1() {
			var td = new TestDict();
			Console.WriteLine("Test GetValue1() ...");
			var sw = Stopwatch.StartNew();
			for(int i = 0; i < test_value.Length; i++) {
				for(int j = i; j < test_value.Length; j += 100) {
					var guid = td.GetValue1(test_value[j]);
				}
			}
			Console.WriteLine($"Elapsed {sw.ElapsedMilliseconds} ms");
		}

		static void Test2() {
			var td = new TestDict();
			Console.WriteLine("Test GetValue2() ...");
			var sw = Stopwatch.StartNew();
			for(int i = 0; i < test_value.Length; i++) {
				for(int j = i; j < test_value.Length; j += 100) {
					var guid = td.GetValue2(test_value[j]);
				}
			}
			Console.WriteLine($"Elapsed {sw.ElapsedMilliseconds} ms");
		}

		static void Main(string[] args) {
			Init(100000);
			Test1();
			Test2();
			return;
		}
	}
}


Результат
Код: plaintext
1.
2.
3.
4.
Init 100000 values
Test GetValue1() ...
Elapsed 5721 ms
Test GetValue2() ...
Elapsed 4039 ms

Второй вариант на 30% быстрее.
Хорош. Вы суммарное время работы со 100к элементов указали, разница в 1.5 секунды не впечатляет.
А если сперва заполнить словари (о чем говорилось на собеседовании, было условие, что 99% записей существуют в словаре), то поиск не отличается.
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
class Program
{
    private static readonly TestClass TestClass1 = new TestClass();
    private static readonly TestClass TestClass2 = new TestClass();
    private static void Main()
    {
        const int count = 10000000;
        for (var i = 0; i < count; i++)
        {
            StartTest1(i);
            StartTest2(i);
        }

        Console.WriteLine("Press Enter");
        Console.ReadLine();
    }

    private static void StartTest1(int key)
    {
        var sw = Stopwatch.StartNew();
        TestClass1.GetValueI(key);
        var ms = sw.ElapsedMilliseconds;

        if (ms > 100)
        {
            Console.WriteLine($"Key: {key}");
            Console.WriteLine($"GetValueI: {ms} ms.");
            Console.WriteLine();
        }
    }

    private static void StartTest2(int key)
    {
        var sw = Stopwatch.StartNew();
        TestClass2.GetValueI(key);
        var ms = sw.ElapsedMilliseconds;

        if (ms > 100)
        {
            Console.WriteLine($"Key: {key}");
            Console.WriteLine($"GetValueII: {ms} ms.");
            Console.WriteLine();
        }
    }
}

class TestDict
{
    private readonly Dictionary<string, Guid> dict = new Dictionary<string, Guid>();

    public Guid GetValue1(string key)
    {
        if (dict.ContainsKey(key))
            return dict[key];
        var newValue = Guid.NewGuid();
        dict.Add(key, newValue);
        return newValue;
    }

    public Guid GetValue2(string key)
    {
        Guid value;
        if (dict.TryGetValue(key, out value))
            return value;
        var newValue = Guid.NewGuid();
        dict.Add(key, newValue);
        return newValue;
    }
}

...
Рейтинг: 0 / 0
Впечатления от собеседования (связано с .Net)
    #39466941
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Супер_ПавПо поводу второго вопроса. lock забраковали, мол блокирует потоки. Единственное решение задачи - это класс ReaderWriterLockSlim
Блокирует не надолго, поэтому засомневался что тут поможет ReaderWriterLockSlim, RW блокировки на самом деле достаточно тормозные.
Делал по примеру из хэлпа .
Исходник
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
namespace Test {

	class TestDict {
		private Dictionary<string, Guid> dict;

		ReaderWriterLockSlim rwsl = new ReaderWriterLockSlim();

		public void Init() {
			dict = new Dictionary<string, Guid>();
		}

		public Guid GetValue_lock(string key)
		{
			lock(dict) {
				Guid value;
				if (dict.TryGetValue(key, out value))
					return value;
				var newValue = Guid.NewGuid();
				dict.Add(key, newValue);
				return newValue;
			}
		}

		public Guid GetValue_RWSL(string key)
		{
			rwsl.EnterUpgradeableReadLock();
			try {
				Guid value;
				if (dict.TryGetValue(key, out value)) {
					return value;
				}
				rwsl.EnterWriteLock();
				try {
					var newValue = Guid.NewGuid();
					dict.Add(key, newValue);
					return newValue;
				} finally {
					rwsl.ExitWriteLock();
				}
			} finally {
				rwsl.ExitUpgradeableReadLock();
			}
		}
	}

	class TestDictConcurrent {
		private ConcurrentDictionary<string, Guid> dict = new ConcurrentDictionary<string, Guid>();

		public Guid GetValue(string key)
		{
			return dict.GetOrAdd(key, (k) => Guid.NewGuid());
		}
	}

	static class Test {

		static string[] test_value;

		static void Init(int size) {
			Console.WriteLine($"Init {size} values");
			test_value = new string[size];
			for(int i = 0; i < test_value.Length; i++) test_value[i] = Guid.NewGuid().ToString();
		}

		static TestDict td = new TestDict();

		static void Task1() {
			for(int i = 0; i < test_value.Length; i++) {
				for(int j = i; j < test_value.Length; j += 100) {
					var guid = td.GetValue_lock(test_value[j]);
				}
			}
		}

		static void Test1() {
			td.Init();
			Console.WriteLine("Test lock() ...");
			var sw = Stopwatch.StartNew();
			var tasks = new Task[3];
			for(int i = 0; i < tasks.Length; i++) {
				tasks[i] = Task.Run(() => Task1());
			}
			Task.WaitAll(tasks);
			Console.WriteLine($"Elapsed {sw.ElapsedMilliseconds} ms");
		}

		static void Task2() {
			for(int i = 0; i < test_value.Length; i++) {
				for(int j = i; j < test_value.Length; j += 100) {
					var guid = td.GetValue_RWSL(test_value[j]);
				}
			}
		}

		static void Test2() {
			td.Init();
			Console.WriteLine("Test ReaderWriterLockSlim() ...");
			var sw = Stopwatch.StartNew();
			var tasks = new Task[3];
			for(int i = 0; i < tasks.Length; i++) {
				tasks[i] = Task.Run(() => Task2());
			}
			Task.WaitAll(tasks);
			Console.WriteLine($"Elapsed {sw.ElapsedMilliseconds} ms");
		}

		static TestDictConcurrent tdc = new TestDictConcurrent();

		static void Task3() {
			for(int i = 0; i < test_value.Length; i++) {
				for(int j = i; j < test_value.Length; j += 100) {
					var guid = tdc.GetValue(test_value[j]);
				}
			}
		}

		static void Test3() {
			td.Init();
			Console.WriteLine("Test ConcurrentDictionary() ...");
			var sw = Stopwatch.StartNew();
			var tasks = new Task[3];
			for(int i = 0; i < tasks.Length; i++) {
				tasks[i] = Task.Run(() => Task3());
			}
			Task.WaitAll(tasks);
			Console.WriteLine($"Elapsed {sw.ElapsedMilliseconds} ms");
		}

		static void Main(string[] args) {
			Init(100000);
			Test1();
			Test2();
			Test3();
			return;
		}
	}
}


Результат
Код: plaintext
1.
2.
3.
4.
5.
6.
Init 100000 values
Test lock() ...
Elapsed 13309 ms
Test ReaderWriterLockSlim() ...
Elapsed 16477 ms
Test ConcurrentDictionary() ...
Elapsed 4922 ms

lock() на 20% быстрее оказался.
И как правильно замечено выше: надо использовать ConcurrentDictionary(), но в той постановке вопроса это не разрешается.
...
Рейтинг: 0 / 0
Впечатления от собеседования (связано с .Net)
    #39466943
Фотография ЕвгенийВ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Супер_ПавОтвет на первый вопрос заключался в том, что вместо
Код: c#
1.
2.
if (dict.ContainsKey(key))
    return dict[key];


нужно использовать
Код: c#
1.
2.
3.
Guid value;
if (dict.TryGetValue(key, out value))
    return dict[key];



Молотком по пальцам таким собеседователям.
Логика разная у кода, второй всегда что то вернет, как минимум default(Guid).
...
Рейтинг: 0 / 0
Впечатления от собеседования (связано с .Net)
    #39466953
Супер_Пав
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dima TСупер_ПавПо поводу второго вопроса. lock забраковали, мол блокирует потоки. Единственное решение задачи - это класс ReaderWriterLockSlim
Блокирует не надолго, поэтому засомневался что тут поможет ReaderWriterLockSlim, RW блокировки на самом деле достаточно тормозные.
Делал по примеру из хэлпа .
Исходник
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
namespace Test {

	class TestDict {
		private Dictionary<string, Guid> dict;

		ReaderWriterLockSlim rwsl = new ReaderWriterLockSlim();

		public void Init() {
			dict = new Dictionary<string, Guid>();
		}

		public Guid GetValue_lock(string key)
		{
			lock(dict) {
				Guid value;
				if (dict.TryGetValue(key, out value))
					return value;
				var newValue = Guid.NewGuid();
				dict.Add(key, newValue);
				return newValue;
			}
		}

		public Guid GetValue_RWSL(string key)
		{
			rwsl.EnterUpgradeableReadLock();
			try {
				Guid value;
				if (dict.TryGetValue(key, out value)) {
					return value;
				}
				rwsl.EnterWriteLock();
				try {
					var newValue = Guid.NewGuid();
					dict.Add(key, newValue);
					return newValue;
				} finally {
					rwsl.ExitWriteLock();
				}
			} finally {
				rwsl.ExitUpgradeableReadLock();
			}
		}
	}

	class TestDictConcurrent {
		private ConcurrentDictionary<string, Guid> dict = new ConcurrentDictionary<string, Guid>();

		public Guid GetValue(string key)
		{
			return dict.GetOrAdd(key, (k) => Guid.NewGuid());
		}
	}

	static class Test {

		static string[] test_value;

		static void Init(int size) {
			Console.WriteLine($"Init {size} values");
			test_value = new string[size];
			for(int i = 0; i < test_value.Length; i++) test_value[i] = Guid.NewGuid().ToString();
		}

		static TestDict td = new TestDict();

		static void Task1() {
			for(int i = 0; i < test_value.Length; i++) {
				for(int j = i; j < test_value.Length; j += 100) {
					var guid = td.GetValue_lock(test_value[j]);
				}
			}
		}

		static void Test1() {
			td.Init();
			Console.WriteLine("Test lock() ...");
			var sw = Stopwatch.StartNew();
			var tasks = new Task[3];
			for(int i = 0; i < tasks.Length; i++) {
				tasks[i] = Task.Run(() => Task1());
			}
			Task.WaitAll(tasks);
			Console.WriteLine($"Elapsed {sw.ElapsedMilliseconds} ms");
		}

		static void Task2() {
			for(int i = 0; i < test_value.Length; i++) {
				for(int j = i; j < test_value.Length; j += 100) {
					var guid = td.GetValue_RWSL(test_value[j]);
				}
			}
		}

		static void Test2() {
			td.Init();
			Console.WriteLine("Test ReaderWriterLockSlim() ...");
			var sw = Stopwatch.StartNew();
			var tasks = new Task[3];
			for(int i = 0; i < tasks.Length; i++) {
				tasks[i] = Task.Run(() => Task2());
			}
			Task.WaitAll(tasks);
			Console.WriteLine($"Elapsed {sw.ElapsedMilliseconds} ms");
		}

		static TestDictConcurrent tdc = new TestDictConcurrent();

		static void Task3() {
			for(int i = 0; i < test_value.Length; i++) {
				for(int j = i; j < test_value.Length; j += 100) {
					var guid = tdc.GetValue(test_value[j]);
				}
			}
		}

		static void Test3() {
			td.Init();
			Console.WriteLine("Test ConcurrentDictionary() ...");
			var sw = Stopwatch.StartNew();
			var tasks = new Task[3];
			for(int i = 0; i < tasks.Length; i++) {
				tasks[i] = Task.Run(() => Task3());
			}
			Task.WaitAll(tasks);
			Console.WriteLine($"Elapsed {sw.ElapsedMilliseconds} ms");
		}

		static void Main(string[] args) {
			Init(100000);
			Test1();
			Test2();
			Test3();
			return;
		}
	}
}


Результат
Код: plaintext
1.
2.
3.
4.
5.
6.
Init 100000 values
Test lock() ...
Elapsed 13309 ms
Test ReaderWriterLockSlim() ...
Elapsed 16477 ms
Test ConcurrentDictionary() ...
Elapsed 4922 ms

lock() на 20% быстрее оказался.
И как правильно замечено выше: надо использовать ConcurrentDictionary(), но в той постановке вопроса это не разрешается.

Ничего с потолка не взял. О чем сказали на собеседовании, то и привел. Я обычно забываю такие встречи, но тут прям сомнения закрались, что мне воду в уши льют. Удивило еще, что обошлись одним вопросом.
Вакансию нашел в разделе Вакансии сего сайта
...
Рейтинг: 0 / 0
Впечатления от собеседования (связано с .Net)
    #39466959
Фотография ЕвгенийВ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Молотком по пальцам таким собеседователям.
Супер_ПавПо поводу второго вопроса. lock забраковали, мол блокирует потоки. Единственное решение задачи - это класс ReaderWriterLockSlim
А если один резво пишет, другие никогда не прочитают.

Вообще каждый случай должен разбираться отдельно, но лучший вариант из коробки
Cat2Если несколько потоков, то надо использовать ConcurrentDictionary
https://msdn.microsoft.com/ru-ru/library/dd287191(v=vs.110).aspx
...
Рейтинг: 0 / 0
Впечатления от собеседования (связано с .Net)
    #39466962
Фотография Нахлобуч
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Супер_Пав,

1. Метод GetValue(), который модифицирует коллекцию -- вот, что должно не нравиться в этом коде. GetOrAddValue() -- куда ни шло. Ну и TryGetValue() внутри, да.
2. Порочный вопрос. Нужно использовать ConcurrentDictionary, а не переизобретать колесо.
...
Рейтинг: 0 / 0
Впечатления от собеседования (связано с .Net)
    #39466970
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Супер_ПавХорош. Вы суммарное время работы со 100к элементов указали, разница в 1.5 секунды не впечатляет.
А если сперва заполнить словари (о чем говорилось на собеседовании, было условие, что 99% записей существуют в словаре), то поиск не отличается.
Внимательнее смотри. Основной цикл
Код: c#
1.
2.
3.
4.
5.
			for(int i = 0; i < test_value.Length; i++) {
				for(int j = i; j < test_value.Length; j += 100) {
					var guid = tdc.GetValue(test_value[j]);
				}
			}


словарь изначально пустой, в процессе работы наполняется 100к элементами, но итераций цикла 50 050к, т.е. в 99.8% случаев записи были найдены.

Разницу надо не в секундах смотреть, а в процентах. Но не забывать погрешность таймера учитывать. Там 1 мс погрешность, поэтому твои замеры с результатом 0-2 мс это погрешность.
...
Рейтинг: 0 / 0
Впечатления от собеседования (связано с .Net)
    #39466971
Супер_Пав
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
НахлобучСупер_Пав,

1. Метод GetValue(), который модифицирует коллекцию -- вот, что должно не нравиться в этом коде. GetOrAddValue() -- куда ни шло. Ну и TryGetValue() внутри, да.
2. Порочный вопрос. Нужно использовать ConcurrentDictionary, а не переизобретать колесо.

1. Название метода не важно.
2. Потоки появились во втором вопросе, в первом случает вопрос был больше по поиску.
...
Рейтинг: 0 / 0
Впечатления от собеседования (связано с .Net)
    #39466982
Фотография buser
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Супер_Пав1. Название метода не важно.
Не о названии речь
...
Рейтинг: 0 / 0
Впечатления от собеседования (связано с .Net)
    #39467200
Фотография Изопропил
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
автор1) Что Вам не нравится в приведенном коде:
название метода
...
Рейтинг: 0 / 0
Впечатления от собеседования (связано с .Net)
    #39467325
Фотография RocknRolla
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ЕвгенийВМолотком по пальцам таким собеседователям.
Супер_ПавПо поводу второго вопроса. lock забраковали, мол блокирует потоки. Единственное решение задачи - это класс ReaderWriterLockSlim
А если один резво пишет, другие никогда не прочитают.

Вообще каждый случай должен разбираться отдельно, но лучший вариант из коробки
Cat2Если несколько потоков, то надо использовать ConcurrentDictionary
https://msdn.microsoft.com/ru-ru/library/dd287191(v=vs.110).aspx
+1
ТС не расстраивайтесь, клоунада полнейшая. Очередные математеги, хорошо что про расчет цикломатической сложности неспрашивали.
...
Рейтинг: 0 / 0
Впечатления от собеседования (связано с .Net)
    #39467383
Фотография skyANA
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Супер_ПавПо поводу второго вопроса. lock забраковали, мол блокирует потоки. Единственное решение задачи - это класс ReaderWriterLockSlim
Если это единственное решение, то Вы походу нам условия задачи озвучили не полностью. Опустили важный момент :)
...
Рейтинг: 0 / 0
Впечатления от собеседования (связано с .Net)
    #39467398
Roman Mejtes
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
skyANAСупер_ПавПо поводу второго вопроса. lock забраковали, мол блокирует потоки. Единственное решение задачи - это класс ReaderWriterLockSlim
Если это единственное решение, то Вы походу нам условия задачи озвучили не полностью. Опустили важный момент :)
я вообще не понял, вот этой фразы "блокируются потоки". Какие потоки и где блокируется. Типа при RWLS и ConcurentDictionary они не блокируются и все операции атомарны :)
...
Рейтинг: 0 / 0
Впечатления от собеседования (связано с .Net)
    #39467407
Фотография skyANA
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Roman MejtesskyANAпропущено...

Если это единственное решение, то Вы походу нам условия задачи озвучили не полностью. Опустили важный момент :)
я вообще не понял, вот этой фразы "блокируются потоки". Какие потоки и где блокируется. Типа при RWLS и ConcurentDictionary они не блокируются и все операции атомарны :)
В документации жеж все расписано...
...
Рейтинг: 0 / 0
Впечатления от собеседования (связано с .Net)
    #39467411
Фотография skyANA
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Если коротко, то ReaderWriterLockSlim рекомендуется когда до фига чейтателей и один чукча :)
...
Рейтинг: 0 / 0
Впечатления от собеседования (связано с .Net)
    #39467418
Фотография skyANA
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Супер_ПавВакансию нашел в разделе Вакансии сего сайта
А дайте тынц..
...
Рейтинг: 0 / 0
Впечатления от собеседования (связано с .Net)
    #39467426
Фотография LR
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Здесь сравниваются обычный лок, ReadWriteLockSlim, ConcurrentDictionary в двух граничных ситуациях Mostly Misses/Mostly Hits. По результатам получается, что для "Mostly Misses" лучше обычный лок, а для "Mostly Hits" - ConcurrentDictionary.
...
Рейтинг: 0 / 0
Впечатления от собеседования (связано с .Net)
    #39467471
Фотография Алексей К
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Супер_ПавПо поводу второго вопроса. lock забраковали, мол блокирует потоки. Единственное решение задачи - это класс ReaderWriterLockSlimReaderWriterLockSlim потоки не блокирует?
...
Рейтинг: 0 / 0
Впечатления от собеседования (связано с .Net)
    #39467486
kealon(Ruslan)
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Алексей КСупер_ПавПо поводу второго вопроса. lock забраковали, мол блокирует потоки. Единственное решение задачи - это класс ReaderWriterLockSlimReaderWriterLockSlim потоки не блокирует?если нет писателей, то не должен, вернее вероятность этого очень близка к нулю

ЕвгенийВ,
на одном проце разницы почти нет, ну а вообще на другом вдруг будет - потому идиологически, конечно, 2-й вариант правильнее

я memorize в питоне вообще через обработку исключений делал и это было быстрее
...
Рейтинг: 0 / 0
Впечатления от собеседования (связано с .Net)
    #39467505
Фотография Алексей К
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kealon(Ruslan)Алексей Кпропущено...
ReaderWriterLockSlim потоки не блокирует? если нет писателей, то не должен, вернее вероятность этого очень близка к нулюЯ в курсе, только в утверждении не было никаких если.
...
Рейтинг: 0 / 0
Впечатления от собеседования (связано с .Net)
    #39467540
Фотография skyANA
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Алексей Кkealon(Ruslan)пропущено...
если нет писателей, то не должен, вернее вероятность этого очень близка к нулюЯ в курсе, только в утверждении не было никаких если.
А разве где-то выше утверждалось, что ReaderWriterLockSlim не блокирует потоки? :)
Не тратьте время на домыслы...
...
Рейтинг: 0 / 0
Впечатления от собеседования (связано с .Net)
    #39467573
Супер_Пав
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
skyANAСупер_ПавВакансию нашел в разделе Вакансии сего сайта
А дайте тынц..
тынц

З.Ы. по поводу доп условия....ну если только, что 99% ключей, передаваемых в метод, существуют. Больше никаких.
...
Рейтинг: 0 / 0
Впечатления от собеседования (связано с .Net)
    #39467601
Siemargl
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Все верно что не взяли. Судя по обсуждению, знания у соискателя слабые.

Ну и что, что тестирование содержит провокационный вопрос?
...
Рейтинг: 0 / 0
Впечатления от собеседования (связано с .Net)
    #39467621
yabs
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Супер_Павпо мне, так дело вкуса. Мне больше первый вариант нравится: проверил, выполнил. Во втором случает лишняя переменная появляется.
так тебе эта переменная все равно нужна
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
public Guid GetValue(string key)
        {
            Guid value;
            if (dict.TryGetValue(key, out value))
                return value;

            value = Guid.NewGuid();
            dict.Add(key, value);

            return value;
        }



или, кому религия запрещает больше одного return'а
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
        public Guid GetValue(string key)
        {
            Guid value;
            if (dict.TryGetValue(key, out value) == false)
            {
                value = Guid.NewGuid();
                dict.Add(key, value);
            }
            return value;
        }



а вообще, хорошая тема
благодаря твоему собеседованию много для себя узнал
у меня завтра очередное ))
...
Рейтинг: 0 / 0
Впечатления от собеседования (связано с .Net)
    #39467628
Супер_Пав
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
yabsСупер_Павпо мне, так дело вкуса. Мне больше первый вариант нравится: проверил, выполнил. Во втором случает лишняя переменная появляется.
так тебе эта переменная все равно нужна
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
public Guid GetValue(string key)
        {
            Guid value;
            if (dict.TryGetValue(key, out value))
                return value;

            value = Guid.NewGuid();
            dict.Add(key, value);

            return value;
        }



или, кому религия запрещает больше одного return'а
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
        public Guid GetValue(string key)
        {
            Guid value;
            if (dict.TryGetValue(key, out value) == false)
            {
                value = Guid.NewGuid();
                dict.Add(key, value);
            }
            return value;
        }



а вообще, хорошая тема
благодаря твоему собеседованию много для себя узнал
у меня завтра очередное ))
Собеседования вообще полезные мероприятия, иногда, что-то новое узнаешь =)
...
Рейтинг: 0 / 0
Впечатления от собеседования (связано с .Net)
    #39467638
Фотография ЕвгенийВ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
А что вам не нравиться в этом коде?
Код: c#
1.
 if (dict.TryGetValue(key, out value) == false)
...
Рейтинг: 0 / 0
Впечатления от собеседования (связано с .Net)
    #39467644
Супер_Пав
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ЕвгенийВА что вам не нравиться в этом коде?
Код: c#
1.
 if (dict.TryGetValue(key, out value) == false)


Если вопрос мне, то ничего против не имею.
А что вам не нравится в?
Код: c#
1.
2.
 if (dict.ContainsKey(key))
     return dict[key];
...
Рейтинг: 0 / 0
Впечатления от собеседования (связано с .Net)
    #39467688
Siemargl
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ЕвгенийВА что вам не нравиться в этом коде?
Код: c#
1.
 if (dict.TryGetValue(key, out value) == false)

Для того булевы придумали, чтобы на равенство не проверять.

Кстати, я бы "зарезал" только за утверждение
ТС1. Название метода не важно. И еще потребовал документировать заголовок в стиле Доксигена итп

На практике это получается потом гораздо важнее говнокода внутри.
...
Рейтинг: 0 / 0
Впечатления от собеседования (связано с .Net)
    #39467741
Супер_Пав
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SiemarglЕвгенийВА что вам не нравиться в этом коде?
Код: c#
1.
 if (dict.TryGetValue(key, out value) == false)

Для того булевы придумали, чтобы на равенство не проверять.

Кстати, я бы "зарезал" только за утверждение
ТС1. Название метода не важно. И еще потребовал документировать заголовок в стиле Доксигена итп

На практике это получается потом гораздо важнее говнокода внутри.
пытаетесь казаться умным? Название не важно было в приведенном примере. В тесте, который давали, имя метода было другое, какое, я не помню.
...
Рейтинг: 0 / 0
Впечатления от собеседования (связано с .Net)
    #39467756
Pallaris
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Супер_ПавНазвание не важно было в приведенном примере.

Вопрос был: "что вам не нравится в приведенном коде".
Ответ: название метода не соответствует его действиям.

Если бы было: "что вам не нравится, кроме названия", тогда ок
...
Рейтинг: 0 / 0
Впечатления от собеседования (связано с .Net)
    #39467766
Супер_Пав
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
PallarisСупер_ПавНазвание не важно было в приведенном примере.

Вопрос был: "что вам не нравится в приведенном коде".
Ответ: название метода не соответствует его действиям.

Если бы было: "что вам не нравится, кроме названия", тогда ок
Я буквально сразу указал на то, что названия метода в данном вопросе не играет роли. Но почему-то особо тугие пытаются казаться очень умными.
...
Рейтинг: 0 / 0
Впечатления от собеседования (связано с .Net)
    #39467769
Pallaris
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Супер_ПавЯ буквально сразу указал на то, что названия метода в данном вопросе не играет роли.

Ажно на второй странице. Ладно, пофиг тащемта
...
Рейтинг: 0 / 0
Впечатления от собеседования (связано с .Net)
    #39467791
petalvik
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Супер_Пававтор1) Что Вам не нравится в приведенном коде:
Код: c#
1.
private readonly Dictionary<string, Guid> dict = new Dictionary<string, Guid>();




Инициализация поля на самом деле будет осуществлена в конструкторе. Компилятор, видя такой код, переместит код инициализации во все конструкторы. Если конструкторов не один, а много и если иницииализируемых полей много, то это приведёт к распуханию кода.

Конечно, это не имеет значения, если конструктор всего один. Но в общем случае, как завещал Рихтер, следует код инициализации выносить в конструктор, инициализирующий поля по умолчанию. А потом вызывать его из всех других конструкторов.
...
Рейтинг: 0 / 0
Впечатления от собеседования (связано с .Net)
    #39467802
petalvik
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
По поводу тормознутости ReaderWriterLockSlim не высказывался только ленивый. Уж сколько было тестов, замеров и бенчмарков, в которых наивный lock побивал его. Поэтому, имхо, работодатели не совсем правы, что это единственный вариант.

Опять же, можно реализовать ручную блокировку (вернее, ожидание) на спинах, что будет быстрее лока (не всегда, но во многих случаях). Впрочем, это уже реализовано в ConcurrentDictionary, который тут уже предлагали. Вот в первую очередь его и взять.
...
Рейтинг: 0 / 0
Впечатления от собеседования (связано с .Net)
    #39467814
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
petalvikОпять же, можно реализовать ручную блокировку (вернее, ожидание) на спинах, что будет быстрее лока (не всегда, но во многих случаях).
lock() реализован на Critical Section , это комбинация спинлока и мутекса. Поэтому чистые спины будут чуть быстрее пока работающих потоков не станет больше чем ядер.
...
Рейтинг: 0 / 0
Впечатления от собеседования (связано с .Net)
    #39467861
Фотография ЕвгенийВ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dima TpetalvikОпять же, можно реализовать ручную блокировку (вернее, ожидание) на спинах, что будет быстрее лока (не всегда, но во многих случаях).
lock() реализован на Critical Section , это комбинация спинлока и мутекса. Поэтому чистые спины будут чуть быстрее пока работающих потоков не станет больше чем ядер.
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
   public class BI 
    {
        static object Locker = new object();
        public BI() 
        {
 
        }
        public double Sin()
        {
            lock(Locker)
            {
                return Math.Sin(12.3);
            }
        }
    }


Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
.method public hidebysig 
	instance float64 Sin () cil managed 
{
	// Method begins at RVA 0x2484
	// Code size 55 (0x37)
	.maxstack 2
	.locals init (
		[0] bool '<>s__LockTaken0',
		[1] float64 CS$1$0000,
		[2] object CS$2$0001,
		[3] bool CS$4$0002
	)

	IL_0000: nop
	IL_0001: ldc.i4.0
	IL_0002: stloc.0
	.try
	{
		IL_0003: ldsfld object Test.BI::Locker
		IL_0008: dup
		IL_0009: stloc.2
		IL_000a: ldloca.s '<>s__LockTaken0'
		IL_000c: call void [mscorlib]System.Threading.Monitor::Enter(object, bool&)
		IL_0011: nop
		IL_0012: nop
		IL_0013: ldc.r8 12.3
		IL_001c: call float64 [mscorlib]System.Math::Sin(float64)
		IL_0021: stloc.1
		IL_0022: leave.s IL_0034
	} // end .try
	finally
	{
		IL_0024: ldloc.0
		IL_0025: ldc.i4.0
		IL_0026: ceq
		IL_0028: stloc.3
		IL_0029: ldloc.3
		IL_002a: brtrue.s IL_0033

		IL_002c: ldloc.2
		IL_002d: call void [mscorlib]System.Threading.Monitor::Exit(object)
		IL_0032: nop

		IL_0033: endfinally
	} // end handler

	IL_0034: nop
	IL_0035: ldloc.1
	IL_0036: ret
} // end of method BI::Sin
...
Рейтинг: 0 / 0
Впечатления от собеседования (связано с .Net)
    #39467901
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ЕвгенийВ, это к чему?

Надо не IL-код смотреть, а реальную реализацию System.Threading.Monitor::Enter, какое WinAPI он вызывает.
Не помню где я вычитал что критические секции используются, т.е. вызов EnterCriticalSection()

Погуглил, возможно я ошибаюсь и тут просто игра слов, т.к. в документации критической секцией называют блок кода внутри lock()
https://msdn.microsoft.com/ru-ru/library/system.threading.monitor(v=vs.110).aspx#CriticalSection The critical section

Use the Enter and Exit methods to mark the beginning and end of a critical section.
...

Не знаю можно ли считать достоверным источником, но вот что пишут
https://stackoverflow.com/questions/14156349/critical-section-in-c-sharp Why you want to use WinAPI Critical section? In .NET there are class Monitor which encapsulates WinAPI Critical section – Hamlet Hakobyan
...
Рейтинг: 0 / 0
Впечатления от собеседования (связано с .Net)
    #39467992
Фотография Denis.
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Супер_Пав,
не читал тред.
1 очевидно трайгетвалью, но метод(public Guid GetValue(stringkey)) сам по себе убог так как семантически предполагает обязательное возвращение значения, так что совсем тру - просто дикт[] и падать при отсутствии, заодно лямбдой запишешь.
2 все кроме конкарентдикта не жизненно, возможно хотели услышать ридер райтер лок, но ни разу не встречал в проде чтоб он обгонял обычный лок, так что или конкарентдикт, или, как говорил солист группы Бредер...:)
...
Рейтинг: 0 / 0
Впечатления от собеседования (связано с .Net)
    #39467995
Фотография ЕвгенийВ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dima T,
Я тоже иногда вангую, но лучше прочитать документ из первых рук и посмотреть реальный код.
...
Рейтинг: 0 / 0
Впечатления от собеседования (связано с .Net)
    #39467996
Фотография Denis.
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Супер_Пав...я не понял выгоды, чем 1й вариант, хуже 2го
ну там скорее всего возвращался валю и выгода довольно очевидная, а в последнем шарпе еще и пишется симпатично.
...
Рейтинг: 0 / 0
Впечатления от собеседования (связано с .Net)
    #39468030
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ЕвгенийВDima T,
Я тоже иногда вангую, но лучше прочитать документ из первых рук и посмотреть реальный код.
Собственно вот что там пишут
авторMonitor is implemented as a "hybrid lock;" it has features of both a spin-lock and a kernel-based lock like a Mutex. The idea is that most locks are held only briefly, so it takes less time to simply spin-wait for the lock to be released, than it would to make a call into the kernel to block the thread. It is important not to waste CPU cycles spinning, so if the lock has not been acquired after a brief period of spinning, the implementation falls back to blocking in the kernel.
Вот что пишут про критические секции
https://msdn.microsoft.com/ru-ru/library/windows/desktop/ms682530(v=vs.85).aspx A thread uses the InitializeCriticalSectionAndSpinCount or SetCriticalSectionSpinCount function to specify a spin count for the critical section object. Spinning means that when a thread tries to acquire a critical section that is locked, the thread enters a loop, checks to see if the lock is released, and if the lock is not released, the thread goes to sleep.
Тот же самый подход: некоторое количество спинлоков затем освобождение проца, если установить блокировку не удалось.
...
Рейтинг: 0 / 0
Впечатления от собеседования (связано с .Net)
    #39468071
mikron
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
PallarisСупер_ПавНазвание не важно было в приведенном примере.

Вопрос был: "что вам не нравится в приведенном коде".
Ответ: название метода не соответствует его действиям.

Какие мелочи.

А если метод назвать GetUniqueValue вам всё нравится?
А если метод называется GetValue и принадлежит классу UniqueValueFactory ?
...
Рейтинг: 0 / 0
Впечатления от собеседования (связано с .Net)
    #39468118
Pallaris
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
mikronА если метод назвать GetUniqueValue вам всё нравится?
А если метод называется GetValue и принадлежит классу UniqueValueFactory ?

1. Нет
2. Нет
...
Рейтинг: 0 / 0
Впечатления от собеседования (связано с .Net)
    #39468213
yabs
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ЕвгенийВА что вам не нравиться в этом коде?
Код: c#
1.
 if (dict.TryGetValue(key, out value) == false)


Я от него наоборот тащусь ))

И чтобы два раза не вставать товарищу, который против сравнения с false, отвечу
На мой взгляд восклицательный знак в начале очень легко не заметить, поэтому я пишу так
...
Рейтинг: 0 / 0
Впечатления от собеседования (связано с .Net)
    #39468219
Фотография Shocker.Pro
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
yabsНа мой взгляд восклицательный знак в начале очень легко не заметить, поэтому я пишу тактогда лайфхак: пиши !=true - так еще заметнее
...
Рейтинг: 0 / 0
Впечатления от собеседования (связано с .Net)
    #39468261
Фотография Алексей К
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
petalvikСупер_Павпропущено...

Код: c#
1.
private readonly Dictionary<string, Guid> dict = new Dictionary<string, Guid>();




Инициализация поля на самом деле будет осуществлена в конструкторе. Компилятор, видя такой код, переместит код инициализации во все конструкторы. Если конструкторов не один, а много и если иницииализируемых полей много, то это приведёт к распуханию кода.

Конечно, это не имеет значения, если конструктор всего один. Но в общем случае, как завещал Рихтер, следует код инициализации выносить в конструктор, инициализирующий поля по умолчанию. А потом вызывать его из всех других конструкторов.Отключать "инлайнинг" методов Рихтер тоже завещал?
...
Рейтинг: 0 / 0
Впечатления от собеседования (связано с .Net)
    #39468425
Arm79
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
НахлобучМетод GetValue(), который модифицирует коллекцию -- вот, что должно не нравиться в этом коде
+1


НахлобучНужно использовать ConcurrentDictionary
+1, но он потормознее ИМХО варианта с lock

Супер_ПавЕдинственное решение задачи - это класс ReaderWriterLockSlim
Это будет верно только если а) многопоточные обращения к методу действительно интенсивные б) обращения в основном читающие, и изредка пишущие.
В вашем случае одновременно проводится и чтение и запись, в таком случае lock по любому будет выстрее
...
Рейтинг: 0 / 0
Впечатления от собеседования (связано с .Net)
    #39468459
Фотография ЕвгенийВ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Arm79+1, но он потормознее ИМХО варианта с lock

Не заморачивались бы с ним тогда. Кстати ConcurrentDictionary использует lock внутри но лочит только часть данных, которые удовлетворяют значению хеша.
...
Рейтинг: 0 / 0
Впечатления от собеседования (связано с .Net)
    #39468500
Roman Mejtes
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
if (condition == false), с точки зрения получаемого кода, после оптимизации, вряд ли будет чем то отличаться от if (!condition)

Denis. все кроме конкарентдикта не жизненно, возможно хотели услышать ридер райтер лок, но ни разу не встречал в проде чтоб он обгонял обычный лок, так что или конкарентдикт, или, как говорил солист группы Бредер...:)
всё зависит от задачи, если операции очень короткие, то будет медленее, если операции чтения и записи длительные, то будет лучше.
этот как и с Parallels, далеко не всегда будет прирост, а если операция очень короткая, будет только тормознее.
...
Рейтинг: 0 / 0
Впечатления от собеседования (связано с .Net)
    #39468523
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Arm79НахлобучНужно использовать ConcurrentDictionary
+1, но он потормознее ИМХО варианта с lock
Я намерил в 2+ раза побыстрее 20543813
...
Рейтинг: 0 / 0
Впечатления от собеседования (связано с .Net)
    #39468530
Фотография ЕвгенийВ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dima TArm79пропущено...

+1, но он потормознее ИМХО варианта с lock
Я намерил в 2+ раза побыстрее 20543813
Сценарии для ReaderWriterLockSlim - один пишет, 100500 читают!
...
Рейтинг: 0 / 0
Впечатления от собеседования (связано с .Net)
    #39468548
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ЕвгенийВDima Tпропущено...

Я намерил в 2+ раза побыстрее 20543813
Сценарии для ReaderWriterLockSlim - один пишет, 100500 читают!
ReaderWriterLockSlim там тоже был в замере. Тормознее всех оказался.

Проблема одной общей блокировки в том что идет постоянное перекидывание кэш-линии проца между разными ядрами, в итоге тормоза. Тут замерял 20429620
...
Рейтинг: 0 / 0
Впечатления от собеседования (связано с .Net)
    #39468649
Arm79
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dima TArm79пропущено...

+1, но он потормознее ИМХО варианта с lock
Я намерил в 2+ раза побыстрее 20543813 '
Сколько там потоков для теста?)))) 100? Да, в условиях большого количества потоков по любому ConcurrentDictionary получше будет за счет снижения блокировок. Но там прикладная логика, которая будет неактуальна, когда потоков всего 2-3. Lock построен на критической секции, и в условиях отсутствия конкуренции за ресурсы практически ничего не стоит.
...
Рейтинг: 0 / 0
Впечатления от собеседования (связано с .Net)
    #39468672
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Arm79Dima Tпропущено...

Я намерил в 2+ раза побыстрее 20543813 '
Сколько там потоков для теста?)))) 100? Да, в условиях большого количества потоков по любому ConcurrentDictionary получше будет за счет снижения блокировок. Но там прикладная логика, которая будет неактуальна, когда потоков всего 2-3. Lock построен на критической секции, и в условиях отсутствия конкуренции за ресурсы практически ничего не стоит.
3 потока.
В исходник под спойлером можно было заглянуть
Код: c#
1.
2.
3.
4.
5.
			var tasks = new Task[3];
			for(int i = 0; i < tasks.Length; i++) {
				tasks[i] = Task.Run(() => Task1());
			}
			Task.WaitAll(tasks);
...
Рейтинг: 0 / 0
Впечатления от собеседования (связано с .Net)
    #39468685
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Как уже выше написали
ЕвгенийВКстати ConcurrentDictionary использует lock внутри но лочит только часть данных, которые удовлетворяют значению хеша.
За счет этого он быстрее, т.к. это тот же lock() но на часть данных.
...
Рейтинг: 0 / 0
Впечатления от собеседования (связано с .Net)
    #39468739
Arm79
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dima T3 потока.
В исходник под спойлером можно было заглянуть
Точно, недосмотрел. Увидел краем глаза j += 100 и поспешил
...
Рейтинг: 0 / 0
Впечатления от собеседования (связано с .Net)
    #39469061
Фотография Cat2
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Модератор форума
Программирование потому и является искусством, по крайней мере пока, что нет четких правил, когда что применять нужно.

К решению ведет тысяча путей, но надо выбрать лучший. Ну хотя бы не худший.

Насчет того, что потенциальные работодатели считали лучшим решением использование ReadWriteLockSlim.
Это часто бывает. Кто-то однажды решил частную задачу красивым способом и горд им. Те, кто решает ее не так - лохи.

Только вот все меняется с бешеной скоростью. Вчерашнее отличное решение для Windows XP становится отстоем на вин 10-64 со 128 гигов оперативы и 16 ядерным процессором.
Ну, вчерашнее - это для меня. Для кого-то XP - глубокая древность
===================
И еще одно мое мнение. Если алгоритм не удается надежно реализовать - надо менять алгоритм.

Если нет хорошего решения с использованием Словаря - надо искать решение без Словаря
...
Рейтинг: 0 / 0
Впечатления от собеседования (связано с .Net)
    #39469122
Фотография Алексей К
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Cat2Для кого-то XP - глубокая древность Суровая реальность.
...
Рейтинг: 0 / 0
Впечатления от собеседования (связано с .Net)
    #39469210
Фотография ЕвгенийВ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Алексей КCat2Для кого-то XP - глубокая древность Суровая реальность.
Ты еще счастливчик! Тут парни на .NET делают ПО для управления своими железками. Там реально покоцанный Linux и скудные возможности по вычислительным ресурсам и памяти.
...
Рейтинг: 0 / 0
Впечатления от собеседования (связано с .Net)
    #39469212
Фотография ЕвгенийВ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Cat2Насчет того, что потенциальные работодатели считали лучшим решением использование ReadWriteLockSlim.

Если обладать знанием и опытом, то можно обрисовать многопоточные сценарии, когда они окажутся правы, когда нет. Рассказать про возможные альтернативы и т. д.
Но знание увеличивает грусть.
...
Рейтинг: 0 / 0
Впечатления от собеседования (связано с .Net)
    #39469296
Фотография Antonariy
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Алексей КCat2Для кого-то XP - глубокая древность Суровая реальность. светлое будущее!

YouTube Video
...
Рейтинг: 0 / 0
Впечатления от собеседования (связано с .Net)
    #39469311
Gluck_13
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ЕвгенийВЯ намерил в 2+ раза побыстрее 20543813
Сценарии для ReaderWriterLockSlim - один пишет, 100500 читают![/quot]

И когда код, находящийся под локом, выполняется существенно дольше, чем вызов Enter/Exit ReadLock
...
Рейтинг: 0 / 0
83 сообщений из 83, показаны все 4 страниц
Форумы / WinForms, .Net Framework [игнор отключен] [закрыт для гостей] / Впечатления от собеседования (связано с .Net)
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]