Re[7]: Линус о языке Си++
От: Cyberax Марс  
Дата: 15.12.07 04:21
Оценка: +1
Здравствуйте, Pzz, Вы писали:

C>>Как нет?!?! Очень даже есть! Посмотри на GObject'ы в GTK, например.

Pzz>В Си нет такой вещи, как иерархоя классов. Ее можно при желании сделать ручками, но значительно меньше хочется, чем воспользоваться встроенной в C++. Поэтому без большой нужды делать не будешь.
И что? Если нужна иерархия — то и на С придется ее делать, или расставлять switch'и. Ну не вижу я тут проблемы.

Pzz>GTK писали студенты, это надо понимать. Им было прикольно.

Ну и?

C>>Эээ... Вообще-то, я лично переписывал драйвер с C-шного стиля на С++-ный — благодаря RAII код уменьшился в два раза.

Pzz>Эээ. А я лично (командой из 3-х человек) выразил в 60К строк на Си примерно то, что команда из 6-и человек до меня выразила в 300К строк кода на C++. Поэтому у меня другой опыт.
Интересно, за счет чего? За счет оптимизации алгоритмов/структуры? Мы получили выигрыш просто за счет изменения стиля кода.
Sapienti sat!
Re[3]: Линус о языке Си++
От: hexis  
Дата: 15.12.07 07:15
Оценка:
Cyberax wrote:
>
> Здравствуйте, hexis, Вы писали:
>
> Не согласен абсолютно. Одним из главных принципов при разработке С++
> было: "you don't pay for what you don't use". Этот принцип вполне
> нормально соблюдается почти всеми реализациями С++. В результате, на С++
> можно писать так же быстро (и даже быстрее — благодаря исключениями,
> например) как и на С. Более того, можно вообще писать точно так же как и
> на С (за исключением мелких различий в синтаксисе).
>

Ну с этим я и не пытался спорить — конечно, на C++ можно разрабатывать
столь-же эффективные программы, что и на C. И часто — гораздо быстрее,
чем на C и с меньшим количеством ошибок. Но вы забываете, что у этого
принципа есть и обратная сторона — you pay for what you use. И цена эта
— разная, но в каждой фиче она присутствует (there is no free lunch).
Например, использование виртуальных функций в C++ — повсеместная
практика. А в C — редкость. Использование таблиц виртуальных функций в C
я не разу не встречал. А в C++ — это типичная реализация. Цена —
дополнительный уровень разименования указателя при обращении к функции.
Активное использование шаблонов в некоторых случаях улучшает
производительность, и, как правило, приводит к увеличению объема кода.

У исключений тоже есть своя цена. Попробуйте скомпилировать следующую
программу в ассемблер любимым компилятором с включенной поддержкой
исключений и с выключенной и сравните результаты:

class A
{
public:
    A();
    ~A();
};

void funcb(A *);

void func()
{
    A a;

    funcb(&a);
}


И так далее. Конечно, на C++ можно писать так-же как на C. На практике
это проделывается редко. Можно в C писать как на C++, что тоже делается
редко. Насколько я понимаю, Линус говорит о том, что C делает эту цену
явной — программисту придется самостоятельно написать весь этот код. В
то время, как в C++, за кажущейся простотой исходного текста, порой
прячется очень много машинного кода — цена становится неявной, и нужно
очень хорошо знать реализацию, чтобы оптимизировать производительность и
размер кода.
Posted via RSDN NNTP Server 2.1 beta
Re[4]: Линус о языке Си++
От: Cyberax Марс  
Дата: 15.12.07 07:29
Оценка: 1 (1) +1
Здравствуйте, hexis, Вы писали:

H>Например, использование виртуальных функций в C++ — повсеместная

H>практика. А в C — редкость.
В нормальном коде на С++ — они используются только для классов, которые реально могут быть полиморфными.

H>Использование таблиц виртуальных функций в C я не разу не встречал.

В С — это повседневная практика. Для GTK смотри GObject, для Линукса — тот же интерфейс модулей или VFS и т.п.

H>Активное использование шаблонов в некоторых случаях улучшает

H>производительность, и, как правило, приводит к увеличению объема кода.
Объем кода — это фигня, в разумных пределах.

H>
class A
H>{
H>public:
H>    A();
H>    ~A();
H>};
H>void funcb(A *);
H>void func()
H>{
H>    A a;
H>    funcb(&a);
H>}

Для табличной обработки исключений — цена будет равна нулю на путях, которые не бросают исключения. Благодаря этому, программы, которые используют исключения для обозначения ошибок, могут работать быстрее программ с тупой проверкой кодов возврата. Не веришь?

H>Насколько я понимаю, Линус говорит о том, что C делает эту цену

H>явной — программисту придется самостоятельно написать весь этот код.
Угу, именно в этом и проблемы. Каждый раз тупо писать кучу кода.
Sapienti sat!
Re[5]: Линус о языке Си++
От: hexis  
Дата: 15.12.07 08:07
Оценка: 6 (1)
Pzz wrote:
>
> H>Ну, тогда мы явно заблуждаемся вместе. Что такое "индустриальный"
> H>стиль программирования, как не эффективность на этапе разработки?
>
> Для начала надо определить понятие эффективности. Но как бы не была

Не претендуя на всеобъемлющее, абсолютно точное или каноническое
определение, я бы сказал так: эффективность, в широком смысле, — это
соответствие объема потребляемых ресурсов (или других параметров)
заданным (приемлемым в данных условиях). Под ресурсами (параметрами)
могут пониматься разные вещи — время разработки, качество разработки,
управляемость (расширяемость) кода, объем исходного текста, читаемость
(понимаемость) текста программистами определенного уровня, время
исполнения, объем машинного кода, объем памяти и т.д и т.п.
Решение эффективно, если позволяет оставаться в рамках заданных
параметров. Например требование масштабируемости и возможность
распараллеливания — это тоже один из критериев эффективности самого
процесса разработки.

> определена эффективность, ясно, что она является дробью, в числителе у

> которой то, что мы преобрели, а в знаменателе — то, что потратили.

Да, согласен. Конечно, хотелось бы достичь лучших показателей по всем
параметрам одновременно. Но, на практике это возможно только для
программ класса "hello world". Уже в более-менее крупных проектах,
приходится балансировать, исходя из разных показателей. И критерии
эффективности по каждому параметру выбираются для каждого проекта.
Например, типичными требованиями являются: при первичной разработке
оптимизировать время разработки (быстрее получить продукт), при
вторичной — время исполнения (повысить качество реализации). Вообще,
вторичные реализации обычно дают существенно другую картину — и по
объемам исходного текста, и по качеству реализации, и по времени
исполнения. Все это — совершенно нормально и обычно говорит не о
качестве исполнителей в первой и второй команде, а о том, что в
результате первой реализации было получено более глубокое понимание
задачи (разработчиками и заказчиком) и изменились критерии эффективности.
Posted via RSDN NNTP Server 2.1 beta
Re[5]: Линус о языке Си++
От: hexis  
Дата: 15.12.07 09:06
Оценка:
Cyberax wrote:
>
>
> H>Например, использование виртуальных функций в C++ — повсеместная
> H>практика. А в C — редкость.
> В нормальном коде на С++ — они используются только для классов, которые
> реально могут быть полиморфными.

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

>

> H>Использование таблиц виртуальных функций в C я не разу не встречал.
> В С — это повседневная практика. Для GTK смотри GObject, для Линукса —
> тот же интерфейс модулей или VFS и т.п.

Да, пожалуй про это я забыл. Хотя я бы не сказал, что это — повседневная
практика в C. Зато в C++ создание интерфейсов действительно повседневная
практика. Причем часто это делается не из существующих потребностей, а
из соображений возможных будущих расширений.

>

> H>Активное использование шаблонов в некоторых случаях улучшает
> H>производительность, и, как правило, приводит к увеличению объема кода.
> Объем кода — это фигня, в разумных пределах.

Но тем не менее все это — цена, которую приходится платить. И она не
равна нулю. Понятно, что в некоторых условиях получаемый выигрыш
существенно перевешивает затраты.

>

> Для табличной обработки исключений — цена будет равна *нулю* на путях,
> которые не бросают исключения. Благодаря этому, программы, которые
> используют исключения для обозначения ошибок, могут работать *быстрее*
> программ с тупой проверкой кодов возврата. Не веришь?

Я же написал о другом — об объеме требуемого машинного кода. В
приведенном примере компилятор не знает, может ли funcb генерировать
исключения, поэтому обязан всегда обрабатывать исключения чтобы
корректно отработал деструктор. Насчет скорости — да, могут. Не всегда,
конечно, но могут. Тем не менее — оптимизация производительности не
единственный и далеко не универсальный критерий разработки.
Posted via RSDN NNTP Server 2.1 beta
Re[6]: Линус о языке Си++
От: Cyberax Марс  
Дата: 15.12.07 09:40
Оценка:
Здравствуйте, hexis, Вы писали:

H>Конечно. Но вот насчет "реально могут быть" — я бы так не сказал. Это

H>зависит от проектировщика, от его опыта, и его видения задачи.
При чем тут видение? Нет необходимости делать методы виртуальными просто так.

H>Да, пожалуй про это я забыл. Хотя я бы не сказал, что это — повседневная

H>практика в C. Зато в C++ создание интерфейсов действительно повседневная
H>практика. Причем часто это делается не из существующих потребностей, а
H>из соображений возможных будущих расширений.
Если делается "просто так" — то пинать таких программистов ногами. Если же расширения будут — то и в С придется делать виртуальные интерфейсы.

H>Но тем не менее все это — цена, которую приходится платить. И она не

H>равна нулю. Понятно, что в некоторых условиях получаемый выигрыш
H>существенно перевешивает затраты.
Так ведь в чистом С затраты будут тоже, и зачастую ну точно такие же, как и в С++.

H>Я же написал о другом — об объеме требуемого машинного кода. В

H>приведенном примере компилятор не знает, может ли funcb генерировать
H>исключения, поэтому обязан всегда обрабатывать исключения чтобы
H>корректно отработал деструктор.
Нет. Тебе стоит узнать как работают исключения. Ладно, делаем тест:

test.cpp:
#include <stdio.h>
int somefunc();
class A
{
public:
    A() {printf("Cons\n");}
    ~A() {printf("~Cons\n");}
};
int main()
{
    try
    {
        A obj;
        somefunc();
    } catch(...)
    {
        printf("Excpt!\n");
    }
    return 0;
}


func.cpp
#include <stdio.h>
#include <exception>
#include <stdexcept>

int somefunc()
{
    printf("Hello!\n");
    throw std::logic_error("Gotcha!");
}


Компилируем и выполняем:
devsrv% g++ test.cpp func.cpp
devsrv% ./a.out
Cons
Hello!
~Cons
Excpt!


Работает все правильно. Теперь начнем разбирать на кусочки:
devsrv% g++ -S test.cpp func.cpp


Вот дизассемблированая функция main():
; Обычный пролог функции
main:
.LFB8:
        pushq   %rbp
.LCFI6:
        movq    %rsp, %rbp
.LCFI7:
        pushq   %rbx

; Конструкция объекта
.LCFI8:
        subq    $24, %rsp
.LCFI9:
        leaq    -9(%rbp), %rdi
.LEHB0:
        call    _ZN1AC1Ev ; Вызов конструктора (1)
.LEHE0:
.LEHB1:
        call    _Z8somefuncv ; Вызов функции (2)

.LEHE1:
        leaq    -9(%rbp), %rdi ; Загрузка адреса объекта (3)
.LEHB2:
        call    _ZN1AD1Ev ; Вызов деструктора (4)
.LEHE2:
        jmp     .L9 ; Переход на конец функции (с оператором "return 0") (5)

; ОБРАБОТКА ИСКЛЮЧЕНИЙ
.L15:
        movq    %rax, -32(%rbp)
.L8:
        movq    -32(%rbp), %rbx
        leaq    -9(%rbp), %rdi
        call    _ZN1AD1Ev ; Вызов деструктора объекта A
        movq    %rbx, -32(%rbp)
        jmp     .L10
.L16:
        movq    %rax, -32(%rbp)
.L10:
        movq    -32(%rbp), %rdi
        call    __cxa_begin_catch
        movl    $.LC2, %edi
.LEHB3:
        call    puts ; Вызов printf
.LEHE3:
.LEHB4:
        call    __cxa_end_catch
.LEHE4:
        jmp     .L9 ; Переход на конец функции (с оператором "return 0")
.L14:
        movq    %rax, -32(%rbp)
.L11:
        movq    -32(%rbp), %rbx
        call    __cxa_end_catch
        movq    %rbx, -32(%rbp)
        movq    -32(%rbp), %rdi
.LEHB5:
        call    _Unwind_Resume
.LEHE5:

; Реализация "return 0" и эпилога функции
.L9:
        movl    $0, %eax
        addq    $24, %rsp
        popq    %rbx
        leave
        ret


Заметь, что между (1) и (5) нет никакого кода обработки исключений. Это обычный код, который идентичен тому, который генерируется с отключеными исключениями (за исключением последнего jmp).

Такая магия делается с помощью табличной обработки исключений — в секции .gcc_except_table находятся списки адресов, при броске исключения эти списки используются для сопоставления значения указателя команд с текущим блоком и поиска нужного обработчика.

Так что у нас обработка исключений получается всегда полностью бесплатной по скорости в случае, если нет бросков. Это достигается небольшим (порядка 10-15%) увеличением объема исполняемого файла за счет таблиц.
Sapienti sat!
Re[14]: Линус о языке Си++
От: Pzz Россия https://github.com/alexpevzner
Дата: 15.12.07 10:36
Оценка:
Здравствуйте, Cyberax, Вы писали:

C>Ну как бы все стандартные функции работы со строками до некоторого времени принимали "char*", например.


void    *_Cdecl memccpy (void *dest, const void *src, int c, size_t n);
void    *_Cdecl memchr  (const void *s, int c, size_t n);
int      _Cdecl memcmp  (const void *s1, const void *s2, size_t n);
void    *_Cdecl memcpy  (void *dest, const void *src, size_t n);
int      _Cdecl memicmp (const void *s1, const void *s2, size_t n);
void    *_Cdecl memmove (void *dest, const void *src, size_t n);
void    *_Cdecl memset  (void *s, int c, size_t n);
void     _Cdecl movedata(unsigned srcseg, unsigned srcoff, unsigned dstseg,
                         unsigned dstoff, size_t n);
char    *_Cdecl stpcpy  (char *dest, const char *src);
char    *_Cdecl strcat  (char *dest, const char *src);
char    *_Cdecl strchr  (const char *s, int c);
int      _Cdecl strcmp  (const char *s1, const char *s2);
char    *_Cdecl strcpy  (char *dest, const char *src);


Это из Turbo C 2.0, борландского компилятора 1988-го года выпуска. Язык, который он реализует, это даже не c89, а драфт c89. Я что-то не заметил пока никакой разницы с современным положением вещей...
Re[7]: Линус о языке Си++
От: dupamid Россия  
Дата: 15.12.07 10:41
Оценка: +2
Здравствуйте, Cyberax, Вы писали:

H>>Я же написал о другом — об объеме требуемого машинного кода. В

H>>приведенном примере компилятор не знает, может ли funcb генерировать
H>>исключения, поэтому обязан всегда обрабатывать исключения чтобы
H>>корректно отработал деструктор.
C>Нет. Тебе стоит узнать как работают исключения. Ладно, делаем тест:

Это ты привел пример того, как работает обработка исключений на Linux — там используется табличный подход. Для Windows 32-бита, будет сгенерирован код для прологи и эпилога функции и он будет отличаться того, который будет без исключений. Оба подхода имеют свои плюсы и минусы. Плюс табличного подхода ты привел — почти нет дополнительного сгенерированного кода. Минус — объем таблиц, когда областей видимости, временных объектов и т.п. объем таблиц может быть огромен. Так как каждое создание объекта и его уничтожение создает новый контекст обработки исключений. Подход с генераций кода более компактен, но всегда дает накладные расходы. Кроме того, наличие возможности исключений подавляет некоторые оптимизации компилятора (исключения создают дополнительные переходы к коде, например любая функция может не вернуться — бросить исключение), так что не весь эффект от исключений выражен в новом коде или таблицах.
Re[15]: Линус о языке Си++
От: Roman Odaisky Украина  
Дата: 15.12.07 12:07
Оценка:
Здравствуйте, Pzz, Вы писали:

C>>Ну как бы все стандартные функции работы со строками до некоторого времени принимали "char*", например.


Pzz>char * _Cdecl strchr(const char * s, int c);


Это что, поддержка const?!

Pzz>Это из Turbo C 2.0, борландского компилятора 1988-го года выпуска. Язык, который он реализует, это даже не c89, а драфт c89. Я что-то не заметил пока никакой разницы с современным положением вещей...


strchr на C как следует не сделать из-за отсутствия перегрузки.
До последнего не верил в пирамиду Лебедева.
Re[8]: Линус о языке Си++
От: Cyberax Марс  
Дата: 15.12.07 12:19
Оценка:
Здравствуйте, dupamid, Вы писали:

C>>Нет. Тебе стоит узнать как работают исключения. Ладно, делаем тест:

D>Это ты привел пример того, как работает обработка исключений на Linux — там используется табличный подход. Для Windows 32-бита, будет сгенерирован код для прологи и эпилога функции и он будет отличаться того, который будет без исключений. Оба подхода имеют свои плюсы и минусы. Плюс табличного подхода ты привел — почти нет дополнительного сгенерированного кода. Минус — объем таблиц, когда областей видимости, временных объектов и т.п. объем таблиц может быть огромен.
По реальным данным 10-20% оверхеда по объему. Оно все достаточно компактно получается. На Windows в GCC, кстати, можно тоже табличные исключения использовать

D>Так как каждое создание объекта и его уничтожение создает новый контекст обработки исключений. Подход с генераций кода более компактен, но всегда дает накладные расходы. Кроме того, наличие возможности исключений подавляет некоторые оптимизации компилятора (исключения создают дополнительные переходы к коде, например любая функция может не вернуться — бросить исключение), так что не весь эффект от исключений выражен в новом коде или таблицах.

Ну и что, что функция может не вернуться? В этом случае, у нас будут выполнена размотка стека, и все будет нормально обработано. Если же делается inline — то у компилятора есть все данные о местах бросания исключений, так что тоже никаких проблем.
Sapienti sat!
Re[8]: Линус о языке Си++
От: Сергей  
Дата: 15.12.07 12:20
Оценка:
Здравствуйте, dupamid, Вы писали:

D>Это ты привел пример того, как работает обработка исключений на Linux — там используется табличный подход.


Думаю, это специфика компилятора, линукс здесь ни при чём.
Re[8]: Линус о языке Си++
От: Roman Odaisky Украина  
Дата: 15.12.07 13:26
Оценка: -1
Здравствуйте, Maxim S. Shatskih, Вы писали:

RO>>Вообще, грустно в Windows без нормальных файловых систем. Например, FAT на флешках — это же издевательство над микросхемой…


MSS>А что, на флешке нужны симлинки? или rwxrwxrwx?


Нет, именно над микросхемой. У нее есть некое ограниченное, и не такое уж и большое, количество циклов чтения-записи (а точнее, стирания) на каждую ячейку. FAT использует пространство очень неравномерно, соответственно, когда она протрет дыру в начале раздела, где хранится собственно таблица, наступит виндекапец. Юниксукапец наступит значительно позже, потому что там есть JFFS2, специально созданная для флеш-памяти. Это особенно важно для новомодных безвинчестерных устройств вроде Asus Eee, где сама ОС живет на флешке. (NTFS/ext3/reiserfs ситуацию не исправят, потому что тоже рассчитаны на винчестеры.)

Симлинки нужны, rwxrwxrwx не нужны в том смысле, что юзер/группа всё равно будут другими на другом компьютере, в который флешка воткнута, и нужны в том, что потерять эти режимы при переносе даных с одного юникса на другой малоприятно (впрочем, здесь tar спасает отца русской демократии).
До последнего не верил в пирамиду Лебедева.
Re[7]: Линус о языке Си++
От: Roman Odaisky Украина  
Дата: 15.12.07 13:32
Оценка:
Здравствуйте, Pzz, Вы писали:

Pzz>Эээ. А я лично (командой из 3-х человек) выразил в 60К строк на Си примерно то, что команда из 6-и человек до меня выразила в 300К строк кода на C++. Поэтому у меня другой опыт.


Pzz>P.S. Их C++'ный код был очень хорош, как и мой Сишный.


Если твой код на C хорош (например, кастит результаты malloc), то он с тем же успехом представляет из себя хороший код на C++.
До последнего не верил в пирамиду Лебедева.
Re[13]: Линус о языке Си++
От: jazzer Россия Skype: enerjazzer
Дата: 15.12.07 13:42
Оценка:
Здравствуйте, Cyberax, Вы писали:

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


J>>Ну т.е. Торвальдс — это менеджер. Чего он полез с менеджерской колокольни судить о языке, которого он не знает — не очень понятно.

C>Нет, Торвальдс — очень хороший программист. Но! Он системный программист, часто работающий на уровне ассемблера (он писал, что GDB в качестве дизассемблера чаще всего использует).

C>В результате — у него стандартная болезнь системщиков. Т.е. неприятие чего-либо кроме С.


О чем я и говорю. С++ он не знает.
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re[9]: Линус о языке Си++
От: dupamid Россия  
Дата: 15.12.07 13:50
Оценка:
Здравствуйте, Cyberax, Вы писали:

C>>>Нет. Тебе стоит узнать как работают исключения. Ладно, делаем тест:

D>>Это ты привел пример того, как работает обработка исключений на Linux — там используется табличный подход. Для Windows 32-бита, будет сгенерирован код для прологи и эпилога функции и он будет отличаться того, который будет без исключений. Оба подхода имеют свои плюсы и минусы. Плюс табличного подхода ты привел — почти нет дополнительного сгенерированного кода. Минус — объем таблиц, когда областей видимости, временных объектов и т.п. объем таблиц может быть огромен.
C>По реальным данным 10-20% оверхеда по объему. Оно все достаточно компактно получается. На Windows в GCC, кстати, можно тоже табличные исключения использовать

Я видел реальные программы, которые распухали почти в два раза Так что это очень индивидуально и зависит от того сколько объектов создатеся и разрушается, включая все локальный, временые переменные и временные переменные создающиеся под условием типа "some_cond ? A() : f(B())", здесь будет созадана или временная переменная типа A или B и в конце вычисления полного выражения так переменная которая была созданна должна быть разрешена. Такого рода вещи создают очень много EH контекстов.

D>>Так как каждое создание объекта и его уничтожение создает новый контекст обработки исключений. Подход с генераций кода более компактен, но всегда дает накладные расходы. Кроме того, наличие возможности исключений подавляет некоторые оптимизации компилятора (исключения создают дополнительные переходы к коде, например любая функция может не вернуться — бросить исключение), так что не весь эффект от исключений выражен в новом коде или таблицах.

C>Ну и что, что функция может не вернуться? В этом случае, у нас будут выполнена размотка стека, и все будет нормально обработано. Если же делается inline — то у компилятора есть все данные о местах бросания исключений, так что тоже никаких проблем.

Разница может быть в том, что компилятор будет учитывать дополнительный переход от места вызова к выходу из функции на графе потока управления (CFG) функции. Пример когда это может иметь значение, статическая переменная была поднята в регистр, значит перед вызовом функции ее предется опустить обратно в пямять (хотя может быть известно что внутри функции она не используется), так как функция может не вернуться. Кроме того в С++ намного больше вызово функций чем в обычном коде на С++ — это просто статистика. Исключения в стиле С setjmp/longjmp еще хуже в этом смысле, но они реже используются в коде на С, чем исключения в коде на С++.
Re[16]: Линус о языке Си++
От: Pzz Россия https://github.com/alexpevzner
Дата: 15.12.07 14:01
Оценка:
Здравствуйте, Roman Odaisky, Вы писали:

Pzz>>char * _Cdecl strchr(const char * s, int c);


RO>Это что, поддержка const?!


Нет, это попытка оспорить ту точку зрения, что семантика const в ANSI C существенно изменилась за время жизни линуха.

Я пока не вижу никаких изменений со времен драфта c89 — т.е., примерно за 20 лет.
Re[9]: Линус о языке Си++
От: Pzz Россия https://github.com/alexpevzner
Дата: 15.12.07 14:06
Оценка:
Здравствуйте, Roman Odaisky, Вы писали:

RO>Нет, именно над микросхемой. У нее есть некое ограниченное, и не такое уж и большое, количество циклов чтения-записи (а точнее, стирания) на каждую ячейку. FAT использует пространство очень неравномерно, соответственно, когда она протрет дыру в начале раздела, где хранится собственно таблица, наступит виндекапец. Юниксукапец наступит значительно позже, потому что там есть JFFS2, специально созданная для флеш-памяти. Это особенно важно для новомодных безвинчестерных устройств вроде Asus Eee, где сама ОС живет на флешке. (NTFS/ext3/reiserfs ситуацию не исправят, потому что тоже рассчитаны на винчестеры.)


В принципе, с протиранием дырок на флешке можно бороться не в файловой системе, а на уровне драйвера блочного устройства. Или даже вовсе запихнуть эту логику в контроллер, который делает из флешки иллюзию IDE-диска. Тем более, что какой-то интеллект на этом уровне все равно нужен, т.к. типичный размер "сектора" (минимального куска, который можно стереть и переписать за раз) на флешке — 8-16 килобайт, а традиционные файловые системы рассчитаны на 512-байтный сектор.

Я удивляюсь, неужели в реальности этого не было сделано?
Re[10]: Линус о языке Си++
От: remark Россия http://www.1024cores.net/
Дата: 15.12.07 14:11
Оценка: 3 (1)
Здравствуйте, dupamid, Вы писали:


D>Так что это очень индивидуально и зависит от того сколько объектов создатеся и разрушается, включая все локальный, временые переменные и временные переменные создающиеся под условием типа "some_cond ? A() : f(B())", здесь будет созадана или временная переменная типа A или B и в конце вычисления полного выражения так переменная которая была созданна должна быть разрешена. Такого рода вещи создают очень много EH контекстов.



EH контекстов (фреймов) такие вещи обычно не создают. EH фрейм обычно создаётся один на функцию. Все создания объектов с деструкторами (в т.ч. "some_cond ? A() : f(B())") просто инкрементируют неявный счётчик — некий аналог счётчика команд IP. По значению этого счётчика обработчик исключения (в т.ч. неявный, который генерируется компилятором и рушит объекты) может точно сказать какие объекты сейчас живы на стеке (т.е. какие надо разрушить).
Поэтому создания локальных объектов в функции зачастую приводят лишь к одной машинной инструкции add (когда неявный счётчик лежит в регистре).
В С коде так же зачастую поддерживается аналогичный счётчик, что бы можно было вынести код разрушения ресурсов в единое место. Однако в С коде этот счётчик так же зачастую совмещается с самими объектами. Например, значение 0 для указателя — это пример счётчика объектов, совмещённого с самим объектом. Но по сути это ничего не меняет, т.к. всё равно нужна одна дополнительная инструкция для инициализации этого указателя в 0 вначале функции.
Т.е. получается практически полностью аналогичный код. Только в С++ он создаётся неявно компилятором.



1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[6]: Линус о языке Си++
От: Ka3a4oK  
Дата: 15.12.07 14:15
Оценка:
AA>Нет силы разрушительной страшнее,
AA>Чем кода стиль "Я-Прочитал-Александреску"...

Буст не в таком ли стиле написан ?
... << RSDN@Home 1.1.4 stable rev. 510>>
Re[8]: Линус о языке Си++
От: Pzz Россия https://github.com/alexpevzner
Дата: 15.12.07 14:17
Оценка:
Здравствуйте, Cyberax, Вы писали:

Pzz>>Эээ. А я лично (командой из 3-х человек) выразил в 60К строк на Си примерно то, что команда из 6-и человек до меня выразила в 300К строк кода на C++. Поэтому у меня другой опыт.

C>Интересно, за счет чего? За счет оптимизации алгоритмов/структуры? Мы получили выигрыш просто за счет изменения стиля кода.

Отчасти за счет того, что в C++'ном коде были очень дотошно расписаны правила игры в терминах интерфейсов — в Си так не сделаешь, поэтому и сделано не было. Отчасти же за счет того, что C++'ный код был более абстрактным и заточенным на дальнейшее развитие в неизвестно какую сторону, а Сишный был более сконцентрирован на решении практической задачи.

Любопытно при этом, что хотя C++'ный код был сознательно спроектирован гибким, реально гнуть быстрее получалось Сишный код, в силу его обозримости и относительной простоты.

А причиной переписывания, между прочим, было то, что с размахом написанный C++'ный код оказалось очень трудно перенести из той среды, для которой он изначально предназначался (железка) в драйвер для линуха и вендов — никто не подумал о том, что в драйвере стек очень маленький, и слишком много говна заводилось прямо на стеке, по всему коду. Вычистить это из 300К строк кода оказалось неподъемной задачей. Ну и плюс к тому, в вендовом NDIS'овском драйвере нет честного способа организовать ядерный поток (WHQL на NDIS'овские драйвера прямо проверяет, что Вы этого не делаете).
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.