LINUX.ORG.RU

Какие есть годные языки с производительностью на уровне C?

 ,


3

7

Какие есть языки, в которых производительности и потребление памяти близки к таковым для кода на C (разница не более чем в 2-3 раза, а не в десятки и сотни раз как на всяких питонах), но без извращений с ручным выделением памяти и поддержкой функций как значений переменной, оптимизации хвостовой рекурсии и тд?

Желательна строгая типизация.

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

★★★★★

Последнее исправление: Xenius (всего исправлений: 4)
Ответ на: комментарий от roof

оптимизации хвостовой рекурсии

Тут вопрос к знатокам компиляторов, сам врать не буду.

в C++ есть. Работает. Но не гарантированна, потому как оно не всегда профит приносит, и не всегда оно возможно (это всё-таки не LISP).

Тут очень умная формулировка, я не совсем понял. Разве не любой язык можно выучить за ограниченное время?

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

emulek
()
Ответ на: комментарий от anonymous

Да даже C++ не 11 подходит по всем пунктам требований ТС.

ТС ФП просил. Т.ч. без 11 не очень.

emulek
()
Ответ на: комментарий от forCe

Не хочешь, не извращайся, умные указатели сделают все за тебя

Ручной разбор циклических зависимостей - это таки извращение.

он везде «ручной». В CPU никаких зависимостей нет.

В С++ типизация не строгая.

тебе шашачки или ехать?

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

+1

emulek
()
Ответ на: комментарий от emulek

он везде «ручной». В CPU никаких зависимостей нет.

Из всех используемых на практике стратегий сборки только подсчет ссылок заставляет руками отслеживать циклические ссылки. Любой нормальный GC умеет с ними правильно работать.

forCe
()
Ответ на: комментарий от dizza

Пруфы?

тысячи их. Ну попробуй IDE например. На жабе это жеж ППЦ, а не IDE.

Напиши сам на том и на том и сравни.

да я жабку не очень хорошо знаю. Но вот код тестов смотрел. Я не знаю, что там с жабкой, но вот код на C++ меня расстроил. Так никто на C++ не делает. Это как если сравнивать молоток vs микроскоп, в деле забивания гвоздей. Ну да, микроскоп — говно. Особенно меня поразил тест с множественным выделением/освобождением памяти. Ну типичная жеж задача для GC, ясное дело, что ::new с этим справился хуже. Сложно GC написать под ЭТУ задачу? В C++ это можно, а вот в жабке... Сомневаюсь. У вас ведь нельзя new перезагрузить?

emulek
()
Ответ на: комментарий от forCe

Из всех используемых на практике стратегий сборки только подсчет ссылок заставляет руками отслеживать циклические ссылки. Любой нормальный GC умеет с ними правильно работать.

1. не совсем понял, зачем применять подсчёт ссылок там, где это не нужно?

2. не понял, почему нельзя применить любую другую стратегию GC?

PS: сейчас вот пилю реализацию GC, там у меня подсчёт ссылок, но циклических не может быть архитектурно. ЧЯДНТ?

emulek
()
Ответ на: комментарий от emulek

Ну а та строчка, про которую я говорю, она совсем неграмотная

Мало ли какой крайний случай ты хочешь подсунуть: (предположительно) твои два filter вполне заменяются на where (ys,zs) = partition .. без существенного удлиннения.

anonymous
()
Ответ на: комментарий от anonymous

Мало ли какой крайний случай ты хочешь подсунуть

да зачем мне вообще такой ЯП, на котором я на такие грабли могу наступить? C++ у меня уже есть. (:

emulek
()
Ответ на: комментарий от emulek

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

Это как? Один объект может ссылаться на другой, другой на второй, ... n-1'ый на n'ый, а n'ый ссылается на первый.

У вас там или специальный случай(тогда это реализация GC именно для этого странного случая) или вы ошиблись в архитектуре.

anonymous
()
Ответ на: комментарий от dizza

Проблемы с жавой віжу такіе

  • array access index range checking
  • нет value types
  • нет указателей на функцію (передаются обьекты із кучі)
  • небесплатный дінаміческій type case
  • способ мышленія «best practices» (interfaces/patterns)
  • вера в то, что JVM сделает всё за тебя
dzidzitop ★★
()
Ответ на: комментарий от anonymous

Это как? Один объект может ссылаться на другой, другой на второй, ... n-1'ый на n'ый, а n'ый ссылается на первый.

есть два класса, виден только S. Ещё есть M, но он скрыт.

Внутри M есть подсчёт ссылок. Когда создаётся S, он создаёт M. Ещё есть конструктор копий S, когда создаётся копия S2=S1, то то в S2 получается ссылка на S1.M (счётчик M увеличивается)

Когда S удаляется, то и его S.M тоже удаляется, если счётчик ==1, иначе из счётчика вычитается 1.

M невозможно создать никак, кроме как через создание S.

Внутри одного S только один M(или ссылка на другой M)

S1 не может ссылаться на другой S2. Можно сделать только копию S2. Если делать копию S1=S2, то перед этим старый S1.M удаляется(его счётчик уменьшается на 1)

Можно изменить S. Есть два случая:

1. S меняется так, что M не меняется («константное изменение»)

2. S меняется так, что M меняется. Тогда старое M «удаляется»(ну действительно оно удаляется только если больше никому не нужно), и создаётся новое M.

У вас там или специальный случай(тогда это реализация GC именно для этого странного случая) или вы ошиблись в архитектуре.

Вот и мне интересно, где я ошибся?

emulek
()
Ответ на: комментарий от dzidzitop

array access index range checking

в C++ реализовано перезагрузкой operator[]. Хоть только нечётные индексы...

нет value types

WTF?

нет указателей на функцію (передаются обьекты із кучі)

ИМХО и не нужно.

вера в то, что JVM сделает всё за тебя

везде своя вера. В сишечке вера в компилятор, в LISP вера в скобки и хвостовую рекурсию, в питоне/bash'е вера в то, что это будет достаточно быстро работать, в sed/perl вера в то, что завтра это можно будет прочитать и исправить если-что. (:

emulek
()
Ответ на: комментарий от emulek

В терминологии. Это не реализация GC. Это ваш специальный случай и специальный алгоритм удаления строго определенного вида объектов.

anonymous
()
Ответ на: комментарий от anonymous

В терминологии. Это не реализация GC. Это ваш специальный случай и специальный алгоритм удаления строго определенного вида объектов.

хм... А чего у меня не хватает до «полноценного» в вашем понимании GC?

emulek
()
Ответ на: комментарий от emulek

array access index range checking

в C++ реализовано перезагрузкой operator[]. Хоть только нечётные индексы...

это оверхэд, который JІТ не всегда может вырезать (напрімер, віртуальный вызов CharSequence#charAt(int))

нет value types

WTF?

создать массів структур невозможно. Возможно создать массів обьектов, которые лежат в куче. Эффектівность CPU cache & memory footprint - под вопросом.

нет указателей на функцію (передаются обьекты із кучі)

ИМХО и не нужно.

Пішут anonymous classes (аллокація в куче + віртуальные вызовы)

везде своя вера

доходіт до (образно) «напішу бубльсорт, а мудрая JVM сделает із этого O(nlogn)

dzidzitop ★★
()
Ответ на: комментарий от dzidzitop

Пішут anonymous classes (аллокація в куче + віртуальные вызовы)

+ храненіе обьекта Class (овэрхэд на memory footprint & garbage collection)

dzidzitop ★★
()

Очевидный Haskell настолько очевиден, что я даже поражён 4 страницами срача на эту тему.

mix_mix ★★★★★
()
Ответ на: комментарий от dzidzitop

это оверхэд, который JІТ не всегда может вырезать

значит JIT == говно. (:

Да и вообще, проверка индексов не нужна.

создать массів структур невозможно. Возможно создать массів обьектов, которые лежат в куче. Эффектівность CPU cache & memory footprint - под вопросом.

не, ну точно — говно.

доходіт до (образно) «напішу бубльсорт, а мудрая JVM сделает із этого O(nlogn)

ну это уже не проблема ЯП.

emulek
()
Ответ на: комментарий от emulek

Haskell — стандартизованный чистый функциональный язык программирования общего назначения
зачем он нужен-то?

Так как же ты, Петька, дошел до такой жизни, что спрашиваешь меня, своего боевого командира, для чего программисту нужен язык программирования?

mix_mix ★★★★★
()
Ответ на: комментарий от mix_mix

для чего программисту нужен язык программирования?

ещё один?!

emulek
()
Ответ на: комментарий от dzidzitop

это оверхэд, который JІТ не всегда может вырезать (напрімер, віртуальный вызов CharSequence#charAt(int))

Вроде их хваленый JIT умеет инлайнить виртуальные вызовы, т.е. собирается статистика о том, что постоянно используется один и тот же dispatch и генерируется код с проверкой класса и инлайном виртуального вызова. Это не работает с CharSequence#charAt(int)?

создать массів структур невозможно. Возможно создать массів обьектов, которые лежат в куче. Эффектівность CPU cache & memory footprint - под вопросом

Это вообще конкретный fail в JVM, в C# и .NET все правильно сделали в отличии от.

Пішут anonymous classes (аллокація в куче + віртуальные вызовы)

Есть MethodHandle и специальная его поддержка в JVM. Это не помогает?

kamre ★★★
()
Ответ на: комментарий от emulek

не факт. Та реализация qsort, что на хаскеле и из одной строчки, по скорости примерно как пузырёк на сишечке, а по памяти сливает на много порядков.

а ничего, что пузырек так и останется n^2, а qsort таки в среднем n logn ?

Waterlaz ★★★★★
()
Ответ на: комментарий от emulek

Работы с произвольными объектами(ну или хотя бы с произвольными объектами, аллоцированными в куче этого gc).

anonymous
()
Ответ на: комментарий от Xenius

Ну, тут по крайней мере легко различить отдельные операции. Кстати, j, если его попросить, может расставить пробелы в выражении. Явное преимущество перед Perl'ом!
Вообще, забавное выражение. Полное пренебрежение к возможности определить функцию и признание только бесточечного стиля как единственно верного. Но этот код работает. Сам писал?

quantum-troll ★★★★★
()
Ответ на: комментарий от Waterlaz

а ничего, что пузырек так и останется n^2, а qsort таки в среднем n logn ?

ничего. Все чего-то не знают. Например того, что О-большое ОнО имеет смысл не здесь, не там, а только в прекраснОм далёкО (:

Во вторых, мало кто знает, что О большое описывает только _рост_ функции, а совсем не время работы. Это вообще говоря разные вещи.

Также, мало кто знает, что O(N*log(N)) это только при выполнении некоторых допущений, которые вообще говоря НЕ выполняются IRL, особенно, если аффтор про них не знает. А ваще у qsort ровно столько же O(N*N), как у пузырька, если положить болт(зависит от выбора медианы, а эта задача нетривиальна, и иногда даже в принципе не разрешима).

Естественно, мало кому известно, что 95% работы qsort тратит не на больших массивах, а на маленьких. И естественно, никому невдомёк, что как раз на маленьких(<10) qsort сливает практически любому другому алгоритму, в т.ч. и пузырьку (все стандартные реализации используют НЕ qsort когда дробление достигнет ~10, обычно простые вставки)

Но вот что самое интересное, все знают про N*log(N), но практически никто не понимает, ЧТО за число, выдаёт эта формула. А выдаёт она число ПЕРЕСТАНОВОК, БЛДЖАД! Да, берём X, сохраняем в tmp, Пишем X<-Y, а потом tmp->X. Это такая фигня, которая называется НА МЕСТЕ! Не... В этом вашем хаскеле сливаются списки. Это, блжад, ДРУГОЙ алгоритм. Яхз, какая у него ваще асимптота и время выполнения. Знаю только, что только полный идиот будет пытаться сортировать списки неким подобием qsort'а, ибо для списков имеется всем известная merge-sort, которая мало того что устойчивая, дык ещё и выполняется _всегда_ с асимптотой O(N*log(N)), а не только в лучшем случае. Также у merge-sort нет затыка на маленьких массивах. Короче — сплошные профиты. Вот только «на месте» не получится. Извините, только списком.

Вот этот код:

qsort [] = [] qsort (x:xs) = qsort [ u |
    u<-xs, u<x ] ++ [ x ] ++ qsort [ u | u<-xs, u>=x
    ]

А вот настоящий qsort на этот вашем хаскеле http://www.mail-archive.com/haskell-cafe@haskell.org/msg63381.html

import Data.Array.Base (unsafeRead, unsafeWrite)
import Data.Array.ST
import Control.Monad.ST

myqsort :: STUArray s Int Int -> Int -> Int -> ST s ()
myqsort a lo hi
    | lo < hi   = do
        let lscan p h i
                | i < h = do
                    v <- unsafeRead a i
                    if p < v then return i else lscan p h (i+1)
                | otherwise = return i
            rscan p l i
                | l < i = do
                    v <- unsafeRead a i
                    if v < p then return i else rscan p l (i-1)
                | otherwise = return i
            swap i j = do
                v <- unsafeRead a i
                unsafeRead a j >>= unsafeWrite a i
                unsafeWrite a j v
            sloop p l h
                | l < h = do
                    l1 <- lscan p h l
                    h1 <- rscan p l1 h
                    if (l1 < h1) then (swap l1 h1 >> sloop p l1 h1) else return 
l1
                | otherwise = return l
        piv <- unsafeRead a hi
        i <- sloop piv lo hi
        swap i hi
        myqsort a lo (i-1)
        myqsort a (i+1) hi
    | otherwise = return ()
----------------------------------------------------------------------------------------

для сравнения сишечка http://ru.wikibooks.org/wiki/Примеры_реализации_быстрой_сортировки

int n, a[n]; //n - количество элементов
void qs(int* s_arr, int first, int last)
{
    int i = first, j = last, x = s_arr[(first + last) / 2];
 
    do {
        while (s_arr[i] < x) i++;
        while (s_arr[j] > x) j--;
 
        if(i <= j) {
            if (i < j) swap(s_arr[i], s_arr[j]);
            i++;
            j--;
        }
    } while (i <= j);
 
    if (i < last)
        qs(s_arr, i, last);
    if (first < j)
        qs(s_arr, first,j);
}
ну а здесь замеры времени: http://users.livejournal.com/wu_/132187.html (там более грамотный хаскель-код, но он всё равно сливает в 17 с лишнем раз сишке по времени на маленьком массивчике в 10К(блжад, что там сортировать-то?!). Замеров потребляемой памяти аффтор не привёл, что символизирует)

emulek
()
Ответ на: комментарий от anonymous

Работы с произвольными объектами(ну или хотя бы с произвольными объектами, аллоцированными в куче этого gc).

не, это есть. Класс M на самом деле выделяет кусок памяти в 2^n байт из одного из 32х списков (т.к. мне не нужны куски больше 4Гб), ну и возвращает их туда же(может потом близнецов запилю, а может и нет). По условиям задачи эти M динамически могут расти, потому резерв в среднем 25% там нужен. Т.е. т.к. выделяется только 2^n байт, в среднем заполнено всего 75%, но это пустое место нужно для того, что-бы достаточно быстро приляпать ещё данных к этому M. Причём это «константная операция», т.е. после добавления к одному M, ссылки на этот M сохраняются.

Собственно и нужен этот M для того, что-бы разруливать конфликты, когда к ссылке M1 прибавляется «а», а к ссылке M2 прибавляется «б» (такое редко, но бывает. Приходится делать новый M2, что-бы туда закатать «б» на том месте, где в M1 уже «а»)

Вот только по моему мнению, аллокатор памяти слабо связан с GC.

emulek
()
Ответ на: комментарий от quantum-troll

qsort вообще не тот алгоритм, который хорошо сочетается с иммутабельностью.

ну как и любая сортировка «на месте». Она по определению не иммутабельна. А зачем её везде пихают как пример крутизны хаскеля?

emulek
()
Ответ на: комментарий от emulek

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

quantum-troll ★★★★★
()
Ответ на: комментарий от dzidzitop

array access index range checking

Оптимизатор как правило выкидывает во время исполнения.

нет value types

Зато есть escape analysis

нет указателей на функцію (передаются обьекты із кучі)

В 8-й яве будут.

небесплатный дінаміческій type case

А он где-то бесплатный? Не знал.

способ мышленія «best practices» (interfaces/patterns)

Проблема программиствов

вера в то, что JVM сделает всё за тебя

Проблема программистов

dizza ★★★★★
()
Ответ на: комментарий от emulek

тысячи их. Ну попробуй IDE например. На жабе это жеж ППЦ, а не IDE.

Я пользуюсь Java IDE уже лет 6. Софт уровня сложности Intellij IDEA практически не реально написать на С++. Соответственно и работает оно тормознуто потому, что сверхсложно.

У вас ведь нельзя new перезагрузить?

Нельзя. Но выделение памяти - херовый бенчмарк. Слишком синтетический.

Вот хороший бенчмарк: http://www.h2database.com/html/performance.html

dizza ★★★★★
()
Ответ на: комментарий от Temp

Что у них с GUI?

Есть привязки для второго гтк, у хаскелля вроде даже третьего.

olibjerd ★★★★★
()
Последнее исправление: olibjerd (всего исправлений: 1)
Ответ на: комментарий от emulek

зачем писать про языки о которых не знаешь по результатам запросов в гугле? Ты даже не можешь понять, где что происходит и почему...

лучше бы из бана не вылезал :/

qnikst ★★★★★
()
Последнее исправление: qnikst (всего исправлений: 1)
Ответ на: комментарий от Xenius

Гм... Когда я начинал писать на плюсах, со мной именно так и получилось. Плюсы не принуждают сразу начинать пользоваться всеми сложными вещами, в отличие, например, от Хаскеля, который почти сразу требует понять что такое монада и зачем она нужна.

roof ★★
()
Ответ на: комментарий от forCe

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

roof ★★
()
Ответ на: комментарий от roof

монада это точка с запятой. всё.. никого матана, никакого бурито!

Ладно, наврал, в модане ещё и значение передается, т.е. это x = foo ; bar x, что тут понимать то? Далее этот «оператор» можно перегрузить, т.е. (псевдокод на си-подобном языке):

; ((Maybe a) value, *(Maybe b)(a) next) {
  if (value->empty == false) {
     return Nothing;
  } else {
     return next(value->value);
  }
}

struct (Maybe_a) {
   int empty,
   a*  value,
} (Maybe a);

При этом хацкель не заставляет сразу пользоваться всеми фичами CPS,Iteratee/Conduit/Pipes,стрелками,использовать FRP, typefamilies, gadt, знать про primitive, c--. Так что дурацкое сравнение.

qnikst ★★★★★
()
Последнее исправление: qnikst (всего исправлений: 4)
Ответ на: комментарий от quantum-troll

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

вы на них что, дрочите? (прошу прощения за грубость, но как иначе тебя понимать?)

По мне сортировка слиянием выглядит изумительно. На любом нормальном ЯП. Если слияние выглядит уродливо, то это ЯП уродливый.

emulek
()
Ответ на: комментарий от qnikst

Добавлю это объяснение в мою коллекцию объяснений о монадах, спасибо. Интуитивно, что это такое я понимаю. Но меня не оставляет ощущение, что чтобы понимать полностью, мне-таки надо прочитать книжку по теории категорий, которая стоит у меня на полочке уже второй год.

roof ★★
()
Ответ на: комментарий от dizza

Я пользуюсь Java IDE уже лет 6. Софт уровня сложности Intellij IDEA практически не реально написать на С++. Соответственно и работает оно тормознуто потому, что сверхсложно.

не верю. И да, мне хватает VIM'а

Нельзя. Но выделение памяти - херовый бенчмарк. Слишком синтетический.

я тут уже задолбался ругаться с сонмом анонимусов, которые доказывали, какой идеальный в яве GC и new.

Вот хороший бенчмарк: http://www.h2database.com/html/performance.html

а при чём тут СУБД?

emulek
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.