Pull to refresh
90
0

Пользователь

Send message
Вот, например, если я знаю, что последний элемент типа T это массив, то могу ли я добавить в malloc некоторое количество элементов для него?

Можно глянуть на код для С?


Мощь Rust я понимаю больше как гарантию отсутствия race conditions в сложном многопоточном коде.

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


КМК и вне рамок многопоточности тут много "плюшек".

На какой-то платформе соберется и будет нормально работать, на какой-то взорвется нафиг.

Вот это взорвется? https://www.onlinegdb.com/vmdoJZFgL


Поясните, из-за чего?


Мы ж про плюсы говорим

Вообще меня интересовали примеры нестабильного C++ в стандартной библиотеке C++.


Пока рассматриваем стабильный из С.

Пример по ссылке компилируется.


Нестабильный компилироваться не должен.

Quod licet Iovi, non licet bovi

В целом мотивация упрятать нестабильный box внутрь Box понятна, тут вопросов нет.


Нет возражений также считать код Box "надёжным", в том смысле, в каком "надёжен" код на любом ЯП — не меньше, но и не больше.


PS. Для саморазвития — можно глянуть на примеры нестабильного C++ в стд C++?

Гм, а как вы в таком случае доверяете функциям выделения памяти в других языках?

Приходится именно что доверять, "гарантий" компилятора же нет. Понятно, что даже в случае наличия таковых встает вопрос о доверии самому компилятору, но тем не менее...

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

На картинке скорее односвязный список с локальными "побегами" одиночной длины.


Разумеется, все гарантии компилятора на него распространяются независимо от того что там внутри.

Как могут гарантии стабильного компилятора распространяться на то, что не компилируется?

Вижу там агрегацию нескольких malloc в один, вижу там двусвязныё двусвязные циклические списки, где элемент может и не знать, в каком он контейнере расположен, или можно сказать, что он сам по себе контейнер.

Работу с памятью можно практически не менять, malloc — нет проблем.


res = libc::malloc(std::mem::size_of::<T>()) as *mut T;

И понимаю, что это надо переписывать как-то совершенно по-другому.

Чтобы задействовать всю мощь Rust надо, действительно, писать несколько иначе. Но можно оставаться и во вполне "сишных" рамках, почему нет. Бонусом будет кросс-компиляция "из-коробки", для embedded скорее всего надо будет побороться с размером исполняемого модуля, недавно была статья по этой теме.

Возможно я чего-то не понимаю но если я правильно понимаю зачем написаны previous и next то предполагается сделать как раз цикл, если конечно в списке планируется более чем 1 элемент.

Как же может получиться цикл, если список, как бы это… односвязный, т.е. узлы связаны только через previous. Понятно, ребра в некоторомы смысле моделируются еще и через next, но там нет ссылок на другие узлы (т.е. значения типа Node).


Есть определенная загадка в том, как автор инициализирует ЭТО без Option, и зачем ему ЭТО. Возможно, это был некий черновичок.


Каких гарантий?

Гарантий, предоставляемых стабильным компилятором Rust.


Во всех остальных случаях Box::new для всего подходит.

Подходит-то он подходит, но речь ведь не об этом.

Код, что написан на картинке ниже этого предложения — образец того как нельзя писать код. Ну нельзя делать циклы из Rc, это не имеет смысла.

На картинке нет цикла из Rc


Что там внутри — не важно совершенно, сама функция Box::new стабильна и безопасна.

Предлагается считать функцию Box безопасной, но гарантий, в данном случае, нет. Целиком полагаемся на разработчика. Мало ли что он там поместил внутрь, на то и служат маркеры version=nightly/unsafe чтобы не доверять, а проверять.

Я показывал упрощенные модели оригинальных трейтов замыканий (FnOnce и т.д.), которые тоже не "настоящие" (как мне кажется). "Не настоящие" в том смысле, что они обрабатываются компилятором особым образом. Я считаю, что реализовать их самостоятельно нельзя, компилятор не поймет, ибо это его сугубо "внутреннее дело". А если и поймет, то нельзя будет вернуть, а если можно вернуть, то что-то еще пойдет не так.


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

После слов:


Правда, реализовать такой типаж не так-то просто, и если нет желания раскрывать реализацию замыкания вручную…

я ожидал, что таки в рамках Stable channel можно предложить сложную реализацию ("замыкания вручную"), которая возвращает замыкание не через кучу. Cобственно именно это и интересует.


Вы же предложили (для Stable channel) вернуться к Box+dyn. Ну т.е. таки "в кучу, товарищи".


В общем, смысл Вашего комментария по отношению к стабильной ветке (про что я, собственно, рассказываю) не очень понятен мне.


К слову, можно ведь и так определить тип, подающий надежды на то, что можно вернуть замыкание:


trait Summer<Closure: FnMut(i32, i32) -> i32> {
    fn get_sum(mult: i32) -> Closure;
}

Но толку-то...

Вы забыли про такую возможность как type alias

Здесь не просто type alias, еще нужны associated types, которые требуют отдельного описания. Это в планах.


Правда, реализовать такой типаж не так-то просто

Если это возможно, приведите пример?

Не совсем понятно, что писать собираетесь. Вызовы С<=>Go занимают около сотни наносекунд, что почти на два порядка больше, чем C<=>Rust.


Для некоторых применений это фатально, для других вполне норм.

я могу назвать минимум 5 приложений видео для iPhone, которые раскрывают возможности аппарата, и максимум 2 более менее достойных для Android

Очень интересно! Озвучьте, пожалуйста, хотя бы для Android.

Примерно так выглядит типичный мастер-узел:
image

Это то же самое, что и в документации:
image


"На самом деле", если ставить по инструкции при помощи kubeadm, получается как-то так:
image

Да, пожалуй. Полемически заострил, слишком сильно. Сглажу.

func BenchmarkMemoryHeap2(b *testing.B) {

    f, err := os.Create("heap.out")
    if err != nil {
        panic(err)
    }
    defer f.Close()

    err = trace.Start(f)
    if err != nil {
        panic(err)
    }

    for i := 0; i < b.N; i++ {
        s := byPointer()
        if s.a != 1 {
            panic("a!=1")
        }
    }

    trace.Stop()
    b.StopTimer()

}

BenchmarkMemoryStack-4 193849980 6.160 ns/op
BenchmarkMemoryHeap-4 18460486 62.46 ns/op
BenchmarkMemoryHeap2-4 195428566 6.141 ns/op


Собственно, уже было

САП, согласно историческим данным, мог обработать в штатном режиме до 12 тысяч заказов за день. Новая WMS, по нашим оценкам, легко справится с 40–50 тысячами.

Не уловил, зачем индивидуальный ЦОД для такой нагрузки?

Я обычно удивляюсь, когда кто-то ArchiMate нотацию узнает, так как ее применение не так популярно, как тот же UML.

Встретились два одиночества...


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

Непонятна связь этой метрики с требованиями к системе: "С учетом географии «Магнита» – это более 420 000 изменений в минуту". Можете пояснить?

Ого, схема на ArchiMate​ modelling language.


На текущий момент мы обрабатываем более 150 000 изменений в минуту.

А можно узнать сколько и какого виртуального железа стоит за этим в облаке?

Information

Rating
Does not participate
Location
Санкт-Петербург, Санкт-Петербург и область, Россия
Date of birth
Registered
Activity