LINUX.ORG.RU

Сравнение производительности доступа к полям структур в Python, Common Lisp и С++

 , cоmmon lisp, , ,


0

2

Помните, я сказал, что постараюсь не писать до конца сентября? Так вот: у меня не получилось :) Кому не нравится тут тег Яр - заверяю, что он не для рекламы (и так все уже знают), а исключительно для удобства: мне по нему удобно искать, а вам его удобно заигнорить. Отношение к Яру здесь такое: я мучаюсь, как мне реализовать объекты Яра. Склоняюсь к тому, что сделать их с опцией «реализовать как defstruct/clos». Но дальше идут тонкости, в которые сейчас не лезу.

Итак, я нашёл тред пиписькометрии 7 - летней давности: https://www.linux.org.ru/forum/development/4535326, и там сравнивалась скорость каких-то циклов. но это неинтересно. Интересно сравнивать скорость доступа к полям объектов хотя бы. Я попробовал. Вот что в итоге вышло (платформа 64 разрядная).

С++

// cpp-benchmark.cpp
#include "stdio.h"
#include <cstdlib>

class test_class {
public:
	int fld1, fld2, fld3, fld4, fld5;
        test_class *next;
};


int inner(test_class *o,int bound) {
    int res=0;
    for (int i=0;i<bound;i++) {
        res += o->fld1;
        o->fld2 = o->fld1;
        o->fld3 = o->fld2;
        o->fld4 = o->fld3;
        o->fld5 = o->fld4;
        o->fld1 = res - 1;
        o = o->next;
        res = res % 16;

    }    
    return res;
}

int main(int argc, char* argv[])
{
    test_class o1;
    test_class o2;
    o1.fld1=1;
    o2.fld1=1;
    o1.next=&o2;
    o2.next=&o1;
    int n = 100*1000*1000;
    int result=inner(&o1,n);
    printf("%d %d\n",o1.fld5,result); // проверяем корректность и чтобы оптимизатор
    // не выкинул неиспользуемый код
    return 0;
}
// EOF
// запускаем:
g++ -O2 -o cpp-benchmark cpp-benchmark.cpp ; echo disassemble inner | gdb cpp-benchmark ; time ./cpp-benchmark 
// листинг пропускаю.

real	0m0.225s
user	0m0.216s
sys	0m0.004s

Лисп на структурах:

;; struct-benchmark.lisp
(in-package :cl-user)

(list
 '#.(restrict-compiler-policy 'safety)
 '#.(restrict-compiler-policy 'debug))
 
(declaim
 (optimize (speed 3) (safety 0) (debug 0)
           (space 0) (compilation-speed 0)))

(defparameter *times* (* 100 1000 1000))

(defstruct test-struct 
  (next nil :type (or null test-struct))
  (fld1 0 :type fixnum)
  (fld2 0 :type fixnum)
  (fld3 0 :type fixnum)
  (fld4 0 :type fixnum)
  (fld5 0 :type fixnum)
  )

(declaim (inline test-struct-fld1 test-struct-fld2 test-struct-fld3 test-struct-fld4 test-struct-fld5 (setf test-struct-fld1) (setf test-struct-fld2) (setf test-struct-fld3) (setf test-struct-fld4) (setf test-struct-fld5)
                    test-struct-next))

(defun inner (o n)
  (declare (type test-struct o))
  (declare (type fixnum n))
  (let ((res 0))
    (declare (type fixnum res))
    (dotimes (i n)
      (incf res (the fixnum (test-struct-fld1 o)))
      (setf (test-struct-fld2 o) (test-struct-fld1 o)
            (test-struct-fld3 o) (test-struct-fld2 o)
            (test-struct-fld4 o) (test-struct-fld3 o)
            (test-struct-fld5 o) (test-struct-fld4 o)
            (test-struct-fld1 o) (- res 1)
            o (test-struct-next o)
            res (mod res 16)))
    res))

(defun main ()
  (let* ((o1 (make-test-struct :fld1 1))
         (o2 (make-test-struct :fld1 1 :next o1))
         res)
    (setf (test-struct-next o1) o2)
    (setf res (inner o1 *times*))
    (format t "~S~%~S~%" (test-struct-fld5 o1) res)))

(let ((*trace-output* *standard-output*))
  (time (main)))
;;;; EOF
;; запускаем
>(load (compile-file "~/py/struct-benchmark.lisp"))
  0.394 seconds of real time
  0.436000 seconds of total run time (0.436000 user, 0.000000 system)
Лисп, но вместо inline ставим notinline - все аксессоры превращаются в полноценные функции. Получаем
real time 3.879 seconds
Лисп на CLOS:
;; clos-benchmark-with-types.lisp
(in-package :cl-user)

(list
 '#.(restrict-compiler-policy 'safety)
 '#.(restrict-compiler-policy 'debug))
 
(declaim
 (optimize (speed 3) (safety 0) (debug 0)
           (space 0) (compilation-speed 0)))

(defparameter *times* (* 100 1000 1000))

(defclass test-class-3 ()
  ((fld1 :initarg :fld1 :accessor test-class-3-fld1)
   (fld2 :accessor test-class-3-fld2)
   (fld3 :accessor test-class-3-fld3)
   (fld4 :accessor test-class-3-fld4)
   (fld5 :accessor test-class-3-fld5)
   (next :initarg :next :accessor test-class-3-next)))

(defun inner (o n)
  (declare (type fixnum n))
  (declare (type test-class-3 o))
  (let ((res 0))
    (declare (type fixnum res))
    (dotimes (i n)
      (incf res (the fixnum (test-class-3-fld1 o)))
      (setf (test-class-3-fld2 o) (the fixnum (test-class-3-fld1 o))
            (test-class-3-fld3 o) (the fixnum (test-class-3-fld2 o))
            (test-class-3-fld4 o) (the fixnum (test-class-3-fld3 o))
            (test-class-3-fld5 o) (the fixnum (test-class-3-fld4 o))
            (test-class-3-fld1 o) (the fixnum (- res 1))
            o (test-class-3-next o)
            res (mod res 16)))
    (print res)
    res))

(defun main()
  (let* (
         (o1 (make-instance 'test-class-3 :fld1 1))
         (o2 (make-instance 'test-class-3 :fld1 1 :next o1))
         res)
    (setf (test-class-3-next o1) o2)
    (setf res (inner o1 *times*))
    (format t "~S~%~S~%" (test-class-3-fld5 o1) res)))

(let ((*trace-output* *standard-output*))
  (time (main)))
#|
6.115секунд
|#

python:

# ~/py/oop-benchmark.py
import time

__times__ = 100*1000*1000

class TestClass3(object):
  
    def __init__(self):
        self.fld1 = 1
        self.fld2 = 0
        self.fld3 = 0
        self.fld4 = 0
        self.fld5 = 0
        self.next = self

def inner(o,count):
    res = 0
    for i in xrange(count):
        res += o.fld1
        o.fld2 = o.fld1
        o.fld3 = o.fld2
        o.fld4 = o.fld3
        o.fld5 = o.fld4
        o.fld1 = res - 1
        o = o.next;
        res = res % 16
    return res

def my_main():
    o1 = TestClass3()
    o2 = TestClass3()
    o1.next = o2
    o2.next = o1
    res = inner(o1,__times__)
    print '%s' % o1.fld5
    print '%s' % res

my_main()

# запуск:
#time python oop-benchmark.py 
#266666656
#3
#real	0m51.031s
#user	0m50.696s
#sys	0m0.052s
FreePascal
{oop-benchmark.fpc}
{$mode ObjFPC}
const n=100*1000*1000;
type
  PTest = ^TTest;
  TTest = object
  public
    fld1, fld2, fld3, fld4, fld5: Integer;
    next: PTest;
  end;

function inner(o: PTest; bound: Integer): Integer;
var i: Integer;
begin
  Result:=0;
  for i:=0 to bound-1 do with o^ do begin
    Result:=Result+fld1;
    fld2:=fld1;
    fld3:=fld2;
    fld4:=fld3;
    fld5:=fld4;
    fld1:=Result-1;
    o:=next;
    Result:=Result mod 16;
  end;
end;

var
  o1, o2: TTest;
  b: Integer;
begin
  o1.fld1:=1; o1.next:=@o2;
  o2.fld1:=1; o2.next:=@o1;
  b:=inner(@o1,n);
  WriteLn(o1.fld5,' ',b);
end.
{

fpc -O3 oop-benchmark.fpc
Free Pascal Compiler version 2.6.4+dfsg-4 [2014/10/14] for x86_64
Copyright (c) 1993-2014 by Florian Klaempfl and others
Target OS: Linux for x86-64
Compiling oop-benchmark.fpc
Linking oop-benchmark
/usr/bin/ld.bfd: warning: link.res contains output sections; did you forget -T?
36 lines compiled, 0.1 sec 
1 warning(s) issued
den73@deb8:~/py$ time ./oop-benchmark
266666656 3

real	0m1.810s
user	0m1.776s
sys	0m0.008s
}

cython, pypy

##########
# test.pyx file

import cython

cdef class TestClass:

    cdef public unsigned int fld1, fld2, fld3, fld4, fld5
    cdef public object next
    
    def __cinit__(self):
        self.fld1 = 1
        self.fld2 = 0
        self.fld3 = 0
        self.fld4 = 0
        self.fld5 = 0
        self.next = self

@cython.overflowcheck(False)
@cython.cdivision(True)
cdef inner(TestClass o, count):
    cdef unsigned int res = 0, i
    for i in range(count):
        res += o.fld1
        o.fld2 = o.fld1
        o.fld3 = o.fld2
        o.fld4 = o.fld3
        o.fld5 = o.fld4
        o.fld1 = res - 1
        o = o.next;
        res = res % 16
    return res

def main():
    cdef TestClass o1, o2
    o1 = TestClass()
    o2 = TestClass()
    o1.next = o2
    o2.next = o1
    res = inner(o1, 100_000_000)
    print('%s' % o1.fld5)
    print('%s' % res)

##########
# setup.py file

from distutils.core import setup
from distutils.extension import Extension
from Cython.Build import cythonize

# to compile a module:
# python setup.py build_ext --inplace

extensions = [
    Extension('test', ['test.pyx'],
              extra_compile_args=['-O3'])
]

setup(name = 'access attrs benchmark',
      ext_modules = cythonize(extensions, annotate=True),
)

#########
# main.py file

from test import *
main()

# Запуск с помощью pip 
# 1. Создать ТРИ файла, исходник которых дан выше
# 2. В этой директории:
python setup.py build_ext --inplace
time python main.py

# Результаты:
real	0m0.306s
user	0m0.304s
sys	0m0.004s

$ time pypy oop-benchmark.py 
266666656
3

real	0m0,761s
user	0m0,736s
sys	0m0,020s

EMACS Lisp - несколько быстрее Питона.

★★★★★

Последнее исправление: den73 (всего исправлений: 17)

Ответ на: комментарий от RazrFalcon

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

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

Честно говоря, сравнение ниочем. Для крестов доступ к полю - это всего лишь смещение в ассемблерной команде. А для python/lisp - это поиск.

anonymous
()

норовил закешировать в регистрах значения полей класса и записывать их только в конце цикла

Че, volatile нынче не в моде, обязательно надо printf городить?

maxis11
()

Сравнение производительности доступа к полям

class test_class {
public:
int fld1, fld2, fld3, fld4, fld5;
};

ТС явно наркоман. И ладно там Яр, человек в своё удовольствие пилит язык, но ЭТО.

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

Я слаб в сях. Мне казалось, что volatile - это несправедливо, т.к. результаты будут занижены. Я, кстати, забыл, для многопоточности ведь вроде не пользуются volatile. А вместо этого вроде бы компилятор сам выводит теорию о том, когда объект должен быть синхронизирован, исходя из того, где находятся обращения к примитивам синхронизации. Т.е. volatile - это некая экзотика для драйверов, для longjmp и для прочих хаков. Не?

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

Я слаб в сях. Мне казалось, что volatile - это несправедливо, т.к. результаты будут занижены.

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

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

Для многопоточности они не используются, и правильно, ибо для неё есть атомарные операции с их memory order.

А вместо этого вроде бы компилятор сам выводит теорию о том, когда объект должен быть синхронизирован, исходя из того, где находятся обращения к примитивам синхронизации.

НЕТ. НЕТ. НЕТ. Синхронизация - задача программиста, тут либо lock-free код(атомарные операции), либо явные синхронизации (блокировки). Читай Скотт Мейерс — Эффективный современный С++ (С++11/14) там по этой теме написано.

Т.е. volatile - это некая экзотика для драйверов, для longjmp и для прочих хаков.

Для хаков, но они экзотикой для драйверов и longjmp не ограничиваются

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

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

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

Синхронизация - задача программиста, тут либо lock-free код(атомарные операции), либо явные синхронизации (блокировки).

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

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

В C и плюсах доступ к полю - вопрос одной операции сложения, >поэтому и быстро.

Мммм. Ну как вопрос одной операции сложения. У тебя есть изначально указатель на структуру, а тебе нужно получить, допустим, int из поля со смещением эн, прибавить один и положить на место. В машине это будет значить довольно много действий: добавить к поинтеру эн, подтянуть в кеш то место, куда указывает поинтер, а затем подтянуть из кеша в регистр, потом прибавить, потом выложить обратно. Ну или может быть есть какая-то программа инкремента по месту прямо в памяти - это я не в курсе.

Как бы быстро это не происходило, нельзя считать, что это занимает время 0 - это будет неправдой.

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

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

Учись читать и правильно задавать вопросы. Ты спросил про доступ - я ответил про доступ: это сложение и втягивание в регистр того что лежало по адресу, ни про какие «сложить и положить обратно» речи не шло. Где ты увидел чтобы я говорил что это выполняется за 0 времени? Я лишь сказал что быстрее ты сделать не сможешь, что подразумевает O(1) и O(N) в случае со слоями индирекции, где N - их количество.

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

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

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

volatile компилятор вывести не может. Иначе это был бы ИИ, а не компилятор

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

А можно добавить Free Pascal?

{$mode ObjFPC}
type
  TTest = object
  public
    fld1, fld2, fld3, fld4, fld5: Integer;
  end;

function inner(var ii: TTest; bound: Integer): Integer;
var i: Integer;
begin
  Result:=0;
  for i:=0 to bound-1 do with ii do begin
    Result:=Result+fld1;
    fld2:=fld1;
    fld3:=fld2;
    fld4:=fld3;
    fld5:=fld4;
    fld1:=Result-1;
  end;
end;

var
  t: TTest;
  b: Integer;
begin
  t.fld1:=ParamCount;
  Val(ParamStr(1),b);
  b:=inner(t,b);
  Write(t.fld5,b);
end.
bormant ★★★★★
()
Ответ на: комментарий от bormant

А можно добавить Free Pascal?

.section .text.n_p$program_$$_inner$ttest$longint$$longint,"x"
	.balign 16,0x90
.globl	P$PROGRAM_$$_INNER$TTEST$LONGINT$$LONGINT
P$PROGRAM_$$_INNER$TTEST$LONGINT$$LONGINT:
# [a.pas]
# [10] begin
	pushl	%ebx
	pushl	%esi
# Var ii located in register ecx
# Var bound located in register edx
# Var $result located in register eax
# Var i located in register esi
	movl	%eax,%ecx
# Var $result located in register eax
# [11] Result:=0;
	movl	$0,%eax
# [12] for i:=0 to bound-1 do with ii do begin
	subl	$1,%edx
# Var i located in register esi
	movl	$0,%esi
	cmpl	%esi,%edx
	jl	.Lj10
	subl	$1,%esi
	.balign 4,0x90
.Lj11:
	addl	$1,%esi
# [13] Result:=Result+fld1;
	movl	(%ecx),%ebx
	leal	(%ebx,%eax),%ebx
	movl	%ebx,%eax
# [14] fld2:=fld1;
	movl	(%ecx),%ebx
	movl	%ebx,4(%ecx)
# [15] fld3:=fld2;
	movl	%ebx,8(%ecx)
# [16] fld4:=fld3;
	movl	%ebx,12(%ecx)
# [17] fld5:=fld4;
	movl	%ebx,16(%ecx)
# [18] fld1:=Result-1;
	leal	-1(%eax),%ebx
	movl	%ebx,(%ecx)
	cmpl	%esi,%edx
	jg	.Lj11
.Lj10:
# [20] end;
	popl	%esi
	popl	%ebx
	ret
bormant ★★★★★
()
Ответ на: комментарий от bormant

Погодь. Я собирался переделать бенчмарк.

den73 ★★★★★
() автор топика

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

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

Угу. Ну уж чем богаты, тем и балуемся.

den73 ★★★★★
() автор топика
Ответ на: комментарий от den73
{$mode ObjFPC}
const n=100*1000*1000;
type
  PTest = ^TTest;
  TTest = object
  public
    fld1, fld2, fld3, fld4, fld5: Integer;
    next: PTest;
  end;

function inner(o: rPTest; bound: Integer): Integer;
var i: Integer;
begin
  Result:=0;
  for i:=0 to bound-1 do with o^ do begin
    Result:=Result+fld1;
    fld2:=fld1;
    fld3:=fld2;
    fld4:=fld3;
    fld5:=fld4;
    fld1:=Result-1;
    o:=next;
    Result:=Result mod 16;
  end;
end;

var
  o1, o2: TTest;
  b: Integer;
begin
  o1.fld1:=1; o1.next:=@o2;
  o2.fld1:=1; o2.next:=@o1;
  b:=inner(@o1,n);
  WriteLn(o1.fld5,' ',b);
end.
$ fpc -O3 testpas.pas
$ time ./testpas
bormant ★★★★★
()
Последнее исправление: bormant (всего исправлений: 1)
Ответ на: комментарий от Deleted

То что он там изобрел даже на велик не похоже. Этот чел совершенно не понимает, что он делает. Даже боюсь представить, что он там за лисп попова велосипедит.

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

дык, велосипедит и велосипедит. никому от этого никакого вреда. иногда велосипедостроение даже идёт на пользу. в процессе набивания шишек на собственном опыте познаётся мудрость бытия :)

так что велосипеды ради любопытства - это хорошо. вот велосипеды в продакшне - это зло. а дома, на коленке - да хоть восьмиколёсный! :)

Iron_Bug ★★★★★
()
Ответ на: комментарий от den73
g++ -march=native ....

должен сожрать.

а если ещё с профилированием (-fprofile-generate и -fprofile-use) собрать - вообще будет летать. правда, для этого нужна glibc. на musl нет счётчика для такого профилирования и эта фича недоступна.

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

вот велосипеды в продакшне - это зло.

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

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

Учиться на собственных ошибках очень дорого. Время - самый ценный ресурс в этом мире. Поэтому разумно иногда прислушиваться к тому, что говорят другие. Ему в этом треде уже раз 5 написали, что нет никаких структур и объектов на уровне машинного кода. Нечего там замерять. А вот поиск по stl контейнерам еще был бы смысл сравнивать со всякими питонами...

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

нет. продакшн - это не место для игр. в продакшн грязными руками лазить нельзя. а то офигевшие юзеры обрывают телефоны техподдержки, а потом злые и голодные саппорты придут за этим программистом :)

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

Бошки полетят когда, тогда может и придёт в сознание. Немножко. А на следующей работе... Ну, надеюсь, хватит ума не вздумать «тряхнуть стариной».

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

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

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

достаточно разъярённого суппорта :) когда суппорт появляется в отделе программистов - значит, что-то случилось. и если он не спал всю ночь - он очень злой :)

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

-march=native дало менее 5% прироста. С профайлером не знаю, как собирать, попробовал эти опции последовательно (сначала generate, потом use), а также вместе - ничего не изменилось.

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

Ну достали вы уже. Я начинал программировать на калькуляторе БЗ-34 в уме, потом немного ассемблер БК-0010. Что же это за мода такая повальная считать себя умными, а остальных дурачками и школотой. Себе же вредите такой позицией.

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

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

Iron_Bug ★★★★★
()

зачем делать тест, если результаты известны заранее?

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

Я отвечаю себе на очень простой вопрос: есть тип данных «структура». Понятно, как он работает в Си. Насколько быстро его можно заставить работать в Лиспе, насколько медленно он работает в Питоне и каковы конкурентные преимущества. Т.е. у меня была изначально задача, реализовывать ли объекты в Яре через struct-ы или через CLOS, и что мы потеряем против Си и выиграем против Питона. Ответы я уже получил. Для полноты картины нужно ещё посмотреть на скомпилированный Питон, но товарищ пропал, а сам я вряд ли осилю.

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

В си этот «тип данных» просто адрес в памяти.

struct SuperSpecialDataType {
    int a;
    int b;
} data { 13, 666 }, *pdata = &data;
mov  (pdata), %eax  // eax = 13
mov 4(pdata), %ebx  // ebx = 666

Вот тебе и доступ к полям структуры. Что тут замерять? Взвешивание воздуха...

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

Ну достали вы уже. Я начинал программировать на калькуляторе БЗ-34 в уме, потом немного ассемблер БК-0010.

Ну я допустим с тех времен. И программировал на БЗ-34 и других калькуляторах,БК-0010,ДВК-2М,Мир-2,агатах,ямахах,спектрумах, на всем что движется, и до чего я мог дотянуться в СССР-е.

Но я не лезу КАЖДЫЙ БОЖИЙ ДЕНЬ на все форумы, с запросами чтобы мне все объяснили или сделали за меня. При этом с явным отношением ко всем как к быдлу.

Себе же вредите такой позицией.

Каким макаром «они вредят себе». Будь вообще благодарен, что тебе кто-то вообще отвечает с таким отношением к людям.

Я за бан. Но тут модерация походу только поверхностная.

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

Как можно сравнивать компилируемое и интерпретируемое ? Или просто для прикола ?

Кстати, поговаривают, что lua с jit не хуже С по скорости, а это интерпретируемый

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

Смотря как писать. В идеальных условиях сишку может обогнать только ассемблерщик гений-оптимизатор, пишущий под конкретный проц. Чем более безопасен и наворочен язык, тем больше он несет оверхеда. А эти ваши пистоны и луы ввобще на сях написаны, т.е. являются фактически сишными фреймворками. Обгонять си они не могут. Это как заявить, что либсишные обертки работают шустрее системных вызовов, которые они оборачивают.

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

И вообще - си сям рознь. Смотря каким компилятором пользоваться и какие оптимизации включать. Я как-то собирал прошивку для древнего девайса при помощи древнего гцц, глянул в objdump и офигел от обилия бессмысленных операций...

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

сделай -march и PGO и будет в 10k раз :)

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

Iron_Bug ★★★★★
()
Последнее исправление: Iron_Bug (всего исправлений: 2)
Ответ на: комментарий от anonymous

тем не менее, lua по сравнению с пистоном - это просто стероидный монстр. во-первых, он шустрее раз в цать, как минимум. во-вторых, футпринт при установке мизерный по сравнению с невероятно развестистой и несовместимой с FHS клюквой, которая тащится с установкой пистона. и поэтому lua можно использовать в embedded. и, если нужно, на нём же можно сварганить относительно маложручую веб-морду для девайса. у него также есть luajit, который можно легко интегрировать в сишные проекты (например, для динамической замены какой-то логики, которая не слишком критична к оптимизации, но может быть прописана даже юзером). так что если вообще брать скриптовый язык - то это luа.

Iron_Bug ★★★★★
()
Последнее исправление: Iron_Bug (всего исправлений: 1)

А ничего, что в python структур нет? Синтаксис с точкой - всего лишь синтаксический сахар для доступа к элементам словаря объекта. И в результате сравнивается производительность структур с производительностью хэш таблицы. Напиши расширение для python, внутри которого будут структуры, и тогда сравнивай. Скорее всего python все равно проиграет, но перестанешь теплое с мягким сравнивать

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

Вот такой «динамический» класс уже будет похож по свистелкам на питон/лисп.

починил

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