1. ActionScript / Говнокод #12040

    −115

    1. 01
    2. 02
    3. 03
    4. 04
    5. 05
    6. 06
    7. 07
    8. 08
    9. 09
    10. 10
    11. 11
    12. 12
    13. 13
    14. 14
    15. 15
    16. 16
    17. 17
    18. 18
    19. 19
    20. 20
    21. 21
    22. 22
    23. 23
    24. 24
    25. 25
    // =================================================================================================
    //
    //	Starling Framework
    //	Copyright 2011 Gamua OG. All Rights Reserved.
    //
    //	This program is free software. You can redistribute and/or modify it
    //	in accordance with the terms of the accompanying license agreement.
    //
    // =================================================================================================
    
    package starling.utils
    {
        /** Returns the next power of two that is equal to or bigger than the specified number. */
        public function getNextPowerOfTwo(number:int):int
        {
            if (number > 0 && (number & (number - 1)) == 0) // see: http://goo.gl/D9kPj
                return number;
            else
            {
                var result:int = 1;
                while (result < number) result <<= 1;
                return result;
            }
        }
    }

    Для кого-то и логарифм - высшая математика... :(

    Запостил: wvxvw, 01 Ноября 2012

    Комментарии (122) RSS

    • Кот тех же авторов:
      mWidth = Math.pow(2, data[7]); 
      mHeight = Math.pow(2, data[8]);

      ширина / высота - целые числа. :)
      Ответить
      • Ну это говно. Вряд ли это один и тот же человек.
        Он бы сдвиг сделал. Инфа 100%.
        Ответить
    • Ты уверен, что логарифм будет лучше, точнее?
      Кстати, зря в языках нету bsr
      Ответить
      • Точнее чем что? Тут все что нужно сделать Math.floor(Math.log(x) / Math.log(2)) в чем тут можно ошибиться?
        Тем более, функция используется в атласе текстур, где все измерения целочисленные и неотрицательные.
        Ответить
        • Подозреваю, что целочисленный цикл (довольно короткий, кстати) порвёт два вызова логарифма как нефиг делать, но нужны бенчмарки.
          Ответить
          • Вызов логарифма - один, Math.log(2) - константа, как бе...

            Если для этого логарифм не использовать, то для чего же тогда? Тут прямо и само название говорит об этом.
            Ответить
            • Да даже один, логарифмы сходятся плохо. Плюс преобразование из целого в число с плавающей точкой и обратно, нужно fpu подключать.
              Ответить
        • >Тут все что нужно сделать Math.floor(Math.log(x) / Math.log(2)) в чем тут можно ошибиться?
          Код автора - лучше. Сдвиговая арифметика.
          А дорогое деление и логарифм, а также перессылка в st0 и обратно съедят скорость.
          Есть более быстрые способы, но они юзают битовую магию и неочевидны для читателей.

          >где все измерения целочисленные и неотрицательные.
          Тем более.

          Минус.
          Ответить
          • http://pastebin.com/k1HHf1tk

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

              P.S. Вот всяко на нормальном компилируемом языке он еще и быстрее.
              Ответить
              • Как чем? Больше места занимает. Не использует специально предназначенные для этого функции. Т.е. пытается сэкономить там, где это не нужно, и в итоге мало того, что не экономит, так еще и добавляет всяких странностей.
                Ответить
            • http://pastebin.com/dff0SRHv

              Кстати, если уж речь о байтолюбстве, то есть еще такие варианты:
              Как оказалось, бинарный поиск - в пролете, а обычный if-else всех победил.
              Ответить
              • Проверьте, пожалуйста, еще версию от 3.14159265, которую он приводил вчера:
                --i;
                i |= i >> 1;
                i |= i >> 2;
                i |= i >> 4;
                i |= i >> 8;
                i |= i >> 16;
                return ++i;
                Ответить
                • http://pastebin.com/4tLMsGuY

                  Да, получится чуть быстрее.
                  Но, тут еще такой момент: самый первый тест я сделал в более старой версии плеера, где логарифм вообще выигал, а в более новой - он безнадежно проигрывает. Т.е. видимо где-то в JIT компиляции научились лучше понимать байткод.
                  Кроме того, бинарный поиск можно оптимизировать, но для этого нужно будет переписать это на HaXe, или использовать какой-нибудь "оптимизатор", который бы переделал чтение / запись из флешевого вектора в обычный Си-шный массив. Скорее всего время тратится именно там в бинарном поиске.
                  Ответить
              • if-else всех победил потому, что с вероятностью 1/2 у тебя будет число от 2^(N-1) до 2^N, то есть перебор закончится на первой же ветке. А будет ли такое же распределение в реальной жизни?
                Ответить
                • В реальной жизни там никогда не будет чисел больше чем 2^11, ну, не знаю, может на каких-то видеокарточках до 2^13... Но если ориентироваться на реальные требования, то и остальное тоже можно было на это ориентировать. Можно было вообще энумератор какой-нибудь для популярных значений сделать, их вцелом не так много получится (по 4-8 пикселов текстуры тоже редкость).
                  Ответить
                  • Так вот перепиши рандомайзер так, чтобы его распределение было как можно ближе к реальной жизни.
                    Ответить
          • > Есть более быстрые способы, но они юзают битовую магию и неочевидны для читателей.

            Есть одна асмокоманда. Но она не поддерживается ни в одном известном мне ЯВУ.
            Ответить
            • Ну в гцц кстати есть костылик:
              http://ideone.com/vODZhq

              На соответствующих процах компилится именно в bsr. На тех где нету - видимо в цикл.
              Ответить
              • Круть, а в стандарт добавят? А в LLVM запилят?
                Ещё байтоёбский вопрос: запилят ли в стандарт mul_int_int_to_double_int и div_double_int_on_int?
                Ответить
                • > Круть, а в стандарт добавят?
                  > запилят ли в стандарт
                  146%, что нет.

                  > А в LLVM запилят?
                  __builtin_ia32_bsrdi. Х.з. если честно как с ним не на интелях.

                  > mul_int_int_to_double_int и div_double_int_on_int
                  Если я правильно понял, что double int это тупо два инта - то тут gcc и так отлично справляется. Где-то я уже кидал пример
                  int a, b; // input
                  long long r = (long long)a * (long long)b;
                  int hi = (r >> 32) & 0xFFFFFFFF;
                  unsigned int lo = r & 0xFFFFFFFF;
                  который превращается в одинокий imul.
                  Ответить
                  • Ну это да, но это на уровне оптимизаций компилятора, а не конструкций языка. Не по-сишному.
                    Ответить
                  • >который превращается в одинокий imul.
                    Чудеса конечно. Но asmовставка очевидней будет.
                    Ответить
              • Давно тоже вроде обсуждали. Там дохера всякого такого:
                int __builtin_popcount (unsigned int x)
                Ответить
            • >Есть одна асмокоманда.
              Ну то давно известно. На многие случаи жизни, особенно когда дело касается работы с битами есть "одна асмокомманда".
              Например еще есть popcnt и lzcnt. Последняя суть аналог bsr, но вроде побыстрее.

              Я же о реализации без них.

              Вот реально жаль что в языках нету команды которая делит число и одновременно находит его остаток. Всё какие-то проценты сраные.

              Кстати мне раньше нравилась старая winApi функция mulDiv, которую дельфятники даже в язык встроили. Но это немного не то.
              Ответить
              • Да, надо бы все такие хаки запилить в сишку. По крайней мере всё равно самые попсовые процессоры их поддерживают.
                Ответить
                • Дждесять лет жду.
                  А они всякое не особо нужное говно добавляют.
                  Ответить
              • > Вот реально жаль что в языках нету команды которая делит число и одновременно находит его остаток.

                Умножение по модулю? Ну да, для той же криптографии полезно.
                Ответить
                • Не-не.
                  div когда делит, то результат деления в eax, а остаток в edx.
                  Обожаю эту фичу.
                  Потому что обычно когда делишь, то нужен и остаток. А везде надо 2 деления делать. Это говно.

                  >Умножение по модулю?
                  Это mulDiv. Или не то выделил когда цитировал?
                  Ответить
                  • Да тоже небось компиляторы распознают, не? Но всё равно не по-сишному.
                    Ответить
                  • > А везде надо 2 деления делать.
                    (multiple-value-bind (a b) (floor  7 / 5) (format t "a: ~d, b: ~d~&"))
                    Ответить
                    • Не компилицо. И вообще как чуда-макрос работает?
                      Делает список из 2-х значений?
                      Где первый элемент - частное, а второе остаток?
                      Ответить
                      • Не, второе - остаток, делить у вас уже как бы есть... или это мой русский?
                        Ответить
                        • >или это мой русский
                          Это моя очепятка :)
                          >чуда-макрос
                          чудо-макрос
                          Ответить
                      • wvxvw имел в виду вот так: http://ideone.com/7yIG5O
                        Ответить
                        • О. Большое Спасибо.
                          А то как я только не пробовал
                          (format t "a: ~d, b: ~d~&" (a, b) ))
                          (format t "a: ~d, b: ~d~&" a, b ))
                          А там оказывается хуйня с делением.
                          Ответить
                      • Ну там не совсем список. Если поюзать функцию, возвращающую несколько результатов в обычном контексте - будет использоваться только первый (в данном случае частное). Если же отдать ее в multiple-value-bind - можно получить доступ ко всем остальным результатам.

                        P.S. За название multiple-value-bind мне хочется взять-и-уебать того кто ее так назвал. Довольно удобная и полезная фича, которую тем не менее противно юзать из-за длинного имени.
                        Ответить
                        • (defmacro mvb (vars value-form &body body)
                            `(multiple-value-bind ,vars ,value-form ,@body))
                          Ответить
                          • Да, вот чем рулит лисп - так это тем, что любое говнецо в нем можно замакрить. Правда, при неудачном выборе имени макроса это совсем не лучшим образом сказывается на читабельности.
                            Ответить
                  • a, b = divmod(7, 5)
                    print 'a: %d, b: %d' % (a, b)

                    (multiple-value-bind (a b) (floor  7 5) (format t "a: ~d, b: ~d~&"))

                    fixed :)
                    Ответить
                    • В clisp не пашет. Кто будет формату аргументы передавать?
                      Ответить
                      • Эх, вот так всегда, когда пишешь без редактора :)
                        Ответить
                  • В хаскеле есть divMod

                    > Это mulDiv. Или не то выделил когда цитировал?
                    Да, на mulDiv отвечал.
                    Ответить
                    • Хацкель с лиспом снова показали свою божественную природу.
                      Но, блядь, почему в лоу-левельной сишке и прочих языках такого нет?
                      Ладно - они не могут в кортежи, списки и возвращать несколько значений.
                      Но ведь есть же передача по ссылке.
                      Ответить
                      • или rvo\nrvo при возврате структуры
                        ну а ссылок в сишке нет, указатели только
                        Ответить
      • >Кстати, зря в языках нету bsr
        Да. Асм безусловно рулит в таких вопросах. Быстро и красиво.
        Кстати тут очень давно это обсуждали.
        Ответить
    • Нормальный код. Я пока не дошел до предложения про логарифмы сомневался:
      "суть наверное в том чел написал одну годную оптимизацию
      > (number & (number - 1))
      Но не написал другую
      --i;
      i |= i >> 1;
      i |= i >> 2;
      i |= i >> 4;
      i |= i >> 8;
      i |= i >> 16;
      return ++i;

      Но когда я дошел до Math.floor(Math.log(x) / Math.log(2)) понял что код абсолютно адекватен.

      Вот буквально только что смотрел. Из сырцов жабы (довольно свежих):
      ConcurrentHashMap.class - очень годная, скоростная мапа, если что.
      // Find power-of-two sizes best matching arguments
              int sshift = 0;        int ssize = 1;
              while (ssize < concurrencyLevel) {
                  ++sshift;
                  ssize <<= 1;
              }
      Ответить
      • >concurrencyLevel
        За что эта константа отвечает?
        Ответить
        • Уровень конкуренции
          Ответить
          • показать все, что скрытоололо. инглиш знаешь или в гуглотранслейт забил?
            а вот жабу не знаешь, раз ответить не смог
            Ответить
            • - Слышь, пацанчик, Жабу знаешь?
              - Неа.
              - Нет? А на си-решетке сидел?
              - Нет.
              - Че, крестоблядь что-ли?

              Одно дело знать жабу, другое знать все кишки реализации ее хешмапов.
              Ответить
    • Ха, самое интересное, что я этого вначале не заметил даже... но вообще, в коде другая проблема :) Первая "оптимизация" возвращает текущую степень двойки, а не следующую, как было торжественно заявлено.
      Битовая магия, не?
      Ответить
      • > Первая "оптимизация"
        Можно номер строки в которой она находится?
        Ответить
        • getNextPowerOfTwo(256) = 256
          Ответить
          • Ну да. А што еще должно вернуть return number;
            Дело в том что нам надо "округлять вверх" до ближайшего сдвига. То есть задача следующая
            min(x,y where y=2^n and y>x)
            Ответить
            • Я вообще не обратил сначала внимания, что возвращается аргумент функции, а не результат. При том, что в функции фигурирует переменная с названием "результат"... как-то просто даже не посмотрел.
              Ответить
          • А что должно быть? Для текстуры вполне кошерного размера 256х256 захуячить огромное полотно 512х512 и без пользы потратить вчетверо больше памяти?

            Работа кода вполне соответствует комменту:
            /** Returns the next power of two that is equal to or bigger than the specified number. */

            P.S. Ну правда next можно было и убрать.
            Ответить
            • Тогда функцию нужно было по-другому называть. Я же не говорю, что нужно в четыре раза большую текстуру создавать :/
              Ответить
              • > Тогда функцию нужно было по-другому называть.
                Да, согласен.
                Ответить
          • Код из ConcurrentHashMap приведенный мною выше работает точно так же. На 256 он вернет 256.

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

            Так вот нам надо найти минимальную степень двойки, которая покроет нужный concurrencyLevel
            Потому берем либо точно, либо немного с избытком. BUT NOT ANYMORE BABY!!!

            Это ж должно быть очевидно - почему так.
            Edit. Вон и bormand чуть выше толкует об том же.
            Ответить
            • Спасибо.
              Блять. И вот после они говорят, что в кресты добавили поддержку многопоточности в новом стандарте С++11. Даже в бородавках жабы есть потокобезопасные контейнеры
              Ответить
              • Ну одно дело "потокобезопасный контейнер", это не трудно и ума много не требует. Мьютекс на каждый метод и вперед.
                Другое дело быстрый, потокобезопастный контейнер, который умеет раssпаралеливаться - то есть можно одновременно добавлять значения, с другого треда читать, а с третьего удалять. Разработка такой штуки - дело непростое.

                Потому кстати это одно из немногих мест где шарп отстал от жабы - в до-диезе только с 4-ой версии добавили ConcurrentDictionary. А до этого у них был только тормозной Hashtable.Synchronised, который работал в однопоточном режиме. Нахуй так жить?
                Ответить
                • Два чаю этому господину. В крестах даже тормозного потокобезопасного контейнера нет.
                  Ответить
                  • ну есть интел tbb и мсдн подсказывает, что в новой студии в коробке свои аналоги - http://msdn.microsoft.com/en-us/library/dd504906.aspx
                    а парни из интела даже пропозицию делали в стандарт по поводу concurrent_* контейнеров
                    Ответить
                    • >пропозицию
                      proposal?
                      Ответить
                    • Я не знаю о чем думает комитет стандартизации, но он почемуто решил не принимать всякие полезные штуки, зато принимать всё остальное.
                      Ответить
                      • Хорошо, что не приняли. Но это всерьёз рассматривалось, чтобы принять. Пару тыс страниц говорят одно только, то что будет показано ниже. В первую очередь меня удивили Аксиомы. Из крестов захотели сделать Agda или ещё какоето задротство:

                        Концепты

                        «Концепты» (concepts) – это механизм, описывающий требования для типов, комбинаций типов или комбинаций типов и целых чисел. Эта возможность особенно полезна для ранней проверки использования шаблонов. И наоборот, она также помогает находить ошибки в теле шаблона на ранней стадии. Давайте рассмотрим алгоритм fill из стандартной библиотеки:
                        // типы типов
                        template<ForwardIterator Iter, class V>
                        // взаимоотношения между аргументами типов
                        requires Assignable<Iter::value_type,V>
                        // лишь объявление, а не определение
                        void fill(Iter first, Iter last, const V& v);


                        // Iter имеет тип int; ошибка: int не является ForwardIterator-ом
                        // int не содержит *
                        fill(0, 9, 9.9);

                        // Iter имеет тип int; ok: int* является ForwardIterator-ом
                        fill(&v[0], &v[9], 9.9);
                        Ответить
                        • Обратите внимание, что мы только объявили метод fill(); мы не определяли его реализацию. С другой стороны, мы точно определили, что метод fill() требует от аргументов:

                          · Аргументы first и last должны быть типом ForwardIterator (и они должны быть одного типа).

                          · Третий аргумент v должен быть типом, который можно присвоить типу value_type типа ForwardIterator.

                          Конечно, мы все это знаем, ведь мы читали стандарт. Однако, компиляторы не умеют читать документы с требованиями, поэтому мы должны сказать ему в коде, в виде концептов ForwardIterator и Assignable. В результате ошибки использования метода fill() могут быть пойманы в месте использования, и текст ошибок может быть значительно яснее. Теперь у компилятора есть информация о намерениях программиста, что позволяет обеспечить хороший уровень проверок и диагностических сообщений.
                          Ответить
                          • Концепты также помогают в реализации шаблонов. Давайте рассмотрим пример:
                            template<ForwardIterator Iter, class V>
                            	requires Assignable<Iter::value_type,V>
                            	void fill(Iter first, Iter last, const V& v)
                            	{
                            		while (first!=last) {
                            			*first = v;
                            			// ошибка: + не определен для Forward_iterator
                            			// (нужно использовать ++first)
                            			first=first+1;	
                            		}
                            	}


                            Эта ошибка будет отловлена сразу же, устраняя необходимость трудоемкого тестирования (хотя и не избавляет от тестирования полностью).

                            С возможностью классифицировать и различать разные типы типов, мы можем перегружать методы, основываясь на виде передаваемых типов. Например:
                            // стандартный алгоритм сортировки, на основе 
                            	// итераторов (с концептами):
                            	template<Random_access_iterator Iter>
                            		requires Comparable<Iter::value_type>
                            	// используем обычную реализацию
                            	void sort(Iter first, Iter last); 
                            
                            	// container-based sort:
                            	template<Container Cont>
                            		requires Comparable<Cont::value_type>
                            	void sort(Cont& c)
                            	{
                            		// просто вызываем версию на основе итераторов
                            		sort(c.begin(),c.end());    
                            	}
                            
                            	void f(vector<int>& v)
                            	{
                            		sort(v.begin(), v.end());   // один способ
                            		sort(v);                    // еще один способ
                            		// ...
                            	}


                            Вы можете определить свои собственные концепты, но для начала, в стандартной библиотеке определен большой набор полезных концептов, таких как ForwardIterator, Collable, LessThanComparable и Regular.


                            Обратите внимание, стандартные библиотеки С++11 предусматривают использование концептов.

                            См. также:
                            the C++ draft 14.10 Concepts
                            [N2617=08-0127] Douglas Gregor, Bjarne Stroustrup, James Widman, and Jeremy Siek: Proposed Wording for Concepts (Revision 5) (Final proposal).
                            Douglas Gregor, Jaakko Jarvi, Jeremy Siek, Bjarne Stroustrup, Gabriel Dos Reis, and Andrew Lumsdaine: Concepts: Linguistic Support for Generic Programming in C++. OOPSLA'06, October 2006.
                            Ответить
                            • Отображения концептов

                              int* является ForwardIterator; мы сказали об этом при обсуждении концептов, и в стандартной библиотеке это всегда было именно так; даже в первой версии STL указатели использовались в качестве итераторов. Однако, мы также говорили о члене value_type типа ForwardIterator. Но int* не содержит члена с именем value_type; на самом деле, он вообще не содержит никаких членов. Так как int* может быть ForwardIterator? Поскольку мы сами это указали. С помощью concept_map мы можем сказать, что при использовании T*, где требуется ForwardIterator, мы будем рассматривать T в качестве value_type:
                              template<Value_type T> 
                              	// value_type типа T* - это T
                              	concept_map ForwardIterator<T*> {	  
                              		typedef T value_type;
                              	};


                              concept_map позволяет указать способ представления нашего типа, предотвращая от модификации существующий тип или от создания нового типа в качестве обертки. «Отображения концептов» (concept maps) являются гибким и обобщенным механизмом для адаптации независимо разработанных программ для совместного использования.
                              Ответить
                              • См. также:
                                the C++ draft 14.10.2 Concept maps
                                [N2617=08-0127] Douglas Gregor, Bjarne Stroustrup, James Widman, and Jeremy Siek: Proposed Wording for Concepts (Revision 5) (Final proposal).
                                Douglas Gregor, Jaakko Jarvi, Jeremy Siek, Bjarne Stroustrup, Gabriel Dos Reis, Andrew Lumsdaine: Concepts: Linguistic Support for Generic Programming in C++. OOPSLA'06, October 2006.
                                Ответить
                                • Аксиомы

                                  Аксиома (axiom) – это набор предикатов, определяющих семантику концепта. Главным сценарием использование аксиом являются внешние инструменты (например, действия, нетипичные для компилятора), такие как, инструменты для предметно-ориентированных оптимизаций (domain-specific optimizations) (языки для описания программных изменений стали важным поводом появления аксиом). Аксиомы также могут быть полезны для некоторых оптимизаций (выполняемых компилятором и обычными оптимизаторами), но компиляторы не должны обращать внимания на пользовательские аксиомы; их работа основана на семантиках, определенных в стандарте.

                                  Аксиомы перечисляют пару вычислений, которые могут трактоваться как эквивалентные. Например:
                                  concept
                                  Semigroup<typename Op, typename T> : CopyConstructible<T> {
                                  		T operator()(Op, T, T);
                                  		axiom Associativity(Op op, T x, T y, T z) {
                                  			// можно предположить, что оператор типа T
                                  			// является ассоциативным
                                  			op(x, op(y, z)) <=> op(op(x, y), z);	
                                  		}
                                  	}
                                  
                                  	// monoid – это полугруппа с единичным элементом
                                  	concept Monoid<typename Op, typename T> : Semigroup<Op, T> {	
                                  		T identity_element(Op);
                                  		axiom Identity(Op op, T x) {
                                  			op(x, identity_element(op)) <=> x;
                                  			op(identity_element(op), x) <=> x;
                                  		}
                                  	}


                                  <=> - это оператор эквивалентности, используемый только в аксиомах. Обратите внимание, что вы не можете (в общем случае) доказать аксиому; мы используем аксиомы для указания того, что мы не можем доказать, но что программист может назвать приемлемым допущением. Обратите внимание, что обе стороны оператора эквивалентности могут быть некорректными для некоторых значений, например использование NaN (not a number) для типов с плавающей запятой: если обе стороны эквивалентности используют NaN, то обе стороны (явно) некорректны и эквивалентны (независимо от того, что говорится в аксиоме), но если NaN используется только с одной стороны, то существует возможность получить выгоды от использования аксиомы.
                                  Ответить
                                  • Аксиома это последовательность выражений эквивалентности (<=>) и условных выражений (вида “if (something) тогда мы можем предполагать следующую эквивалентность”):
                                    // в концепте TotalOrder:
                                    axiom Transitivity(Op op, T x, T y, T z)
                                    {
                                    // условная эквивалентность
                                    if (op(x, y) && op(y, z)) op(x, z) <=> true;
                                    }

                                    См. также:
                                    the C++ draft 14.9.1.4 Axioms
                                    ???.
                                    Ответить
                    • Вот если честно, лучшебы они приняли в стандарт, как этот сделали в том же стандарте шарпа (более высокоуровнего языка) MemoryBarrier разных видов и интресики типа add_and_fetch, atomic_increment и тд.
                      Зато они приняли std::atomic, который в нормальных локфри алгоритмах и не поиспользуешь нормально.
                      Ответить
                      • ну дак процесс внесения в стандарт новых фич - не быстрое дело
                        в частности, последние proposalы по интересующей тебя теме датируются сентябрем 2012 (кстати, в авторах числится А. Малахов - может поэтому не принимают?) http://bit.ly/SgjoTp

                        а вообще в целом интересная страничка:
                        http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/
                        Ответить
                      • Да это реально полезные фичи для мультитрейдинга.
                        А не AssParallel() #pragma omp parallel for для быдла которое возомнило что может в многопоточность.
                        Ответить
                      • Вот даже в высокоуровневую жабу добавили AtomicIntegerFieldUpdater, AtomicLongFieldUpdater, и AtomicReferenceFieldUpdater. Кресты вы мои кресты...
                        Ответить
                        • А AtomicReferenceFieldUpdaterFactoryBuilder там есть?
                          Ответить
                          • Приходится самому писать.
                            Я серъезно.
                            Ответить
                            • А в чем разница между AtomicIntegerArray и AtomicInteger[] ?
                              Ответить
                              • Говнокод.ру - учим жабу вместе?
                                Ладно. Я сегодня добрый.
                                Примерно такая же как между мутабельной ссылкой на массив констант, и константым массивом мутабельных переменных.
                                Ответить
                                • То есть AtomicIntegerArray - ссылка на массив, а AtomicInteger[] - массив ссылок?
                                  Ответить
                                  • Я просто оставлю это здесь:
                                    http://stackoverflow.com/questions/692677/atomicintegerarray-vs-atomicinteger

                                    AtomicInteger[] is an array of thread safe integers.
                                    AtomicIntegerArray is a thread-safe array of integers.
                                    Ответить
                                    • >AtomicInteger[] is an array of thread safe integers.
                                      AtomicIntegerArray is a thread-safe array of integers.
                                      Похоже на записки из бортового журнала капитана-очевидность.
                                      Ответить
                                    • Ещё раз спрошу AtomicInteger - класс, а значит кладется в массив по ссылке. В то время как AtomicIntegerArray сам кладется по ссылке, но внутри храняться интежеры не по ссылке, а по значению. Right?
                                      Ответить
                                      • > Right?
                                        Yes.

                                        Поэтому AtomicIntegerArray быстрее, жрет меньше памяти, и его проще инициализировать.
                                        Ответить
                          • А вот в крестах даже AtomicPointerUpdater приходится писать под каждую платформу или копипастить готовые реализации под каждую платформу из тырнета и потом приводить их к общему интерфейсу.
                            Ответить
              • Жаба родилась головастиком с многопоточностью в зелёной крови: потоки были в самой первой версии (сначала, правда, были зелёные). До хорошей, годной поддержки многопоточности она прошла довольно длинный путь.
                Ответить
            • Кстати, по поводу велосипедных библиотек с супервизорами... Почему бы попробовать Akka? Я сам, к сожалению, ей не пользовался, но люди хвалят. Говорят, она даже эрланг уделывает по производительности (на синтетических тестах, конечно).
              У эрланга, правда, есть большое преимущество: посколько процессы не шарят память, можно осуществлять сборку мусора в софт-реалтайм режиме: собирать мусор в тех процессах, которые в данный момент не выполняются, позволяя активным процессам продолжать работу.
              Ответить
              • Как бы это все замечательно не звучало, есть фундаментальный недостаток - невозможность сохранять и модифицировать состояние программы, когда оно становится большим. Т.е. если нам нужно обмениваться небольшими сообщениями, то все нормально работает, как только начинаются манипуляции с данными врезультате которых изменяется маленькая часть огромного объекта (пользователь покинул комнату в чате -> всем, у кого были ссылки на комнату нужно передать новый список всех пользователей в этой комнате, со всеми их потрохами) для того, чтобы приложение вцелом могло функционировать.
                Можно все делать в одном модуле, в одном потоке, чтобы никуда ничего не передавать :) но это как-бы делает потоки и все что с ними связано бесполезным.
                И это приводит к неимоверно кривым решениям:
                - запись в файл и передача имени файла (так и то быстрее получается).
                - запись в базу данных, и передавать доступ к соединению с базой в разные потоки (ппц глючно).
                - держать открытый сокет с самопальным сервером, предназначенным для хранения информации (типа Memcached, например). Тоже решение так себе, т.как обычно уже лучше написать и обработку там же заодно.

                Есть другой, меньший недостаток. Все объекты представлены, как в жабоскрипте: список, а внутри еще список, а внутри еще список... и т.д. Когда объекты простенькие - все замечательно, а когда начинаются усложнения - records превращаются в страницы текста до боли похожие одна на другую. И тут паттерн-матчинг начинает работать против нас, т.как случайно ненужные объекты попадают не в те функции. Решение - люди начинают изобретать свои системы типизации, которые, как правило сводятся к тому, что первым елементом в списке идет какой-нибудь символ, по которому дальше уже выбирается, что нужно. Естесственно, проблемы с уникальностью таких символов, ну и куча бойлерплейта, который никак не скрыть.
                Ответить
                • >(пользователь покинул комнату в чате -> всем, у кого были ссылки на комнату нужно передать новый список всех пользователей в этой комнате, со всеми их потрохами)


                  Зачем передавать измененный список полностью, если можно передать комманду на изменение копии списка, находящегося в чужом экторе?
                  Ответить
                • >Все объекты представлены, как в жабоскрипте: список

                  Эм. А рекордов там нет?
                  Просто храни список экторов (они у нас будут заменять рекорды) и через сообщения выпытывай у них значения тех или иных полей.

                  Конечно, если программировать на эрланге, как на стандартных парадигмах - оно не будет работать.
                  Ответить
                  • Ну, предположим, у нас есть одна функция, которая оповещает "друзей" об изменении статуса клиента, а другая функция показывает количество человек в "комнате". Обеим функциям нужно, чтобы при изменении списка посетителей комнаты этот список как-то получить.
                    Можно конечно не посылать им весь спискок, а послать "что поменялось", и пусть сами разбираются как обновить список. Таким образом экономим память, но тратим время на то, что каждая функция выполнит ту же процедуру по изменению списка.
                    Т.е. получается, что проигрываем либо по памяти, либо по скорости.

                    > Стандартных парадигмах
                    Каких стандартов? :)
                    Работать, как уже было заявлено, будет в песочнице, по-настоящему - не будет.

                    > Рекорды
                    Ну вот они аналогичны жабоскриптовскому Object, в рантайме они неотличимы один от другого. Т.е. чтобы понять, что перед нами объект какого-то определенного типа нам нужно проверить, что все требования к типу соблюдены, при чем сделать это вручную. Т.е. если это пользователь чата, то нужно проверить, что у него есть имя, возраст, адресс и т.д. Даже всякие самодельные, не встроенные в язык системы типа той же eieio берут на себя этот тяжкий труд и предоставляют красивый способ решить эту проблему. В Эрланге, это все нужно делать самому, но в виду вышеописаных обстоятельств делать и не хочется особо, т.как никакой выгоды в перспективе не намечается.
                    Ответить
                  • Еще есть такой момент. В Эрланге есть "наследование", но это не то, о чем вы подумали. Это подмена одного модуля другим. (т.е. наследуются только функции, а "поля" в кортеже / рекорде (который тот же кортеж на самом деле) - это навсегда).
                    http://stackoverflow.com/questions/3746709/erlang-removing-fields-in-records
                    и удалить их никак нельзя. И, как обычно, в ответе фигурирует "но если полей не много то..."
                    Ответить
                  • Если честно, я не понимаю, в чем проблема с рассылкой статусов.
                    Заводим процесс на каждого клиента, процесс на каждый диалог (который привязан к процессам клиентов). При смене состояния клиента (поменялся статус/отвалился) процесс диалога получает оповещение, и рассылает всем остальным участникам диалога соответствующее сообщение.

                    Если нужно делать постоянные вычисления и выборки по условиям, можно не мучиться с ручным удалением из списков и хранить данные в in-memory таблицах mnesia.

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

                    От разделяемого состояния на самом деле профита немного. При любом раскладе всем клиентам (ICQ-клиентам, comet-страничкам, etc.) нужно рассылать нотификации об изменении статусов, и наличие глобального состояния на сервере тут ничем не поможет. Оно также помешает распределению сервера по нескольким машинам.
                    Ответить
                    • Предположим, есть какая-то мультипользовательская рисовалка, общая планшетка на которой каждый может что-то нарисовать. И вот у нас есть процесс, который рисует графики, и процесс, который принимает от пользователей указания что рисовать (не только графики). Если эти две функции начнут обмениваться друг с другом картинками, каждый раз создавая их по-новой - никаких ресурсов не хватит. Мы не можем сразу во время получения новой информации от пользователя перерисовать картинку, т.как мы заблокируем все нафиг, поэтому графики рисуются в отдельном процессе, а функция пока принимает ввод от других пользователей.
                      Вывод: картинку нужно хранить где-то отдельно, и каким-то образом косвенно разрешать другим функциям с ней работать, так чтобы они эту картинку никогда по-настоящему не получали. Эта стратегия так быстро перерастает в неимоверное мозгоебство, с которым ну так не хочется бороться, особенно, когда рядом лежит нормальный инструмент, которы может это сделать вообще без затрачивания каких-либо усилий.
                      Возможно, если очень упорно стараться сделать то же самое на Эрланге, можно каким-то образом построить систему, которая не будет передавать ресурсы, а только записывать в них чего-то. Но зачем? Нет ничего, что бы Эрланг делал лучше чем аналоги. Издеваться над собой ради чего?
                      Сопоставление с образцом? Так оно и не нужно в 90% случаев, и еще в 9% случаев работает не так, как нужно.
                      Ключевые слова для создания процессов + ппц неудобная конструкция их обработки? - Офигенный бонус. Я прям зальюсь слезами и все брошу когда вместо receive мне нужно будет написать reactor.callLater(...)
                      Ответить
                      • >рисовалка
                        >Erlang
                        No way.
                        Ответить
                      • >Вывод: картинку нужно хранить где-то отдельно, и каким-то образом косвенно разрешать другим функциям с ней работать, так чтобы они эту картинку никогда по-настоящему не получали

                        Стандартная стратегия при работе с эктерами. Чего плохого то? Какие проблемы вызывает? Я бы так и на другом языке делал. Просто с этим эктером обменивался сообщениями.
                        Ответить
                        • О каких стандартах идет речь? Можно пожалуйста номер / ссылку / ISBN?
                          Или, просто, напишите фильтр "размывка", который усредняет значения цвета в пикселах без чтения из картинки.
                          Ответить
                          • Я бы даже сделал так, чтобы тот, эктор, о котором я говорил, владел не самим изображением, а эктарами, владеющими частью изображения, чтобы распараллелить процес рисования тех алгоритмов, что параллелятся.

                            А вот та идея, что обсуждается ниже (хранение кучи копий рисунков) - вообще не работоспособна. Это вместо единой работы, мы загружаем процессор кучой копий работы. А ведь это не единственная проблема. Результат некоторых алгоритмов рисования зависит от порядка рисования элементов. То есть если один человек закончил контур, а второй заливал этот контур (могло быть наоборот и команды пришли в обратном порядке), то залилось лишнее или один рисовал линию, а второй размытие (опять же в зависимости от порядка прихода команд), то линия получится размытой или нет. Порядок прихода сообщений в эрланге одному эктору от разных экторов не определен. Это значит что в каждой копии окажется свой рисунок, отличаюийся от других рисунков, если тебе не повезло. Делать так, чтобы один видел одно, а другой другое - глупо. Один говорит - ты все правильно сделал, а другой чатится с криками - ты упорот штоле? Лучше пусть они имеют единое мнение о упоротости или кутости параллельно рисующих. И отменят неудавшиеся операции.
                            Ответить
                            • Конечно же изображение с сервера в сжатом виде параллельными алгоритмами уже отправлять по сети клиентам многоадресной рассылкой.
                              Ответить
                              • На худой конец если хочется "тонкий" сервер, отправлять команды рисования обратно клиентам, но в правильном порядке, тк порядок отправки сообщений от одого эктора уже определен. Проблем с рассинхронизацией изображений не будет.
                                Ответить
                              • По тайлам гораздо сложнее фильтры прогонять, ведь каждый пиксель должен знать значения соседей. Если фильтровать тайлы независимо, получится не то.
                                Ответить
                                • Запросишь у эктора соседа
                                  Ответить
                                  • кол-во запросов растёт пропорционально квадрату кол-ва тайлов, да ещё и слайсы растра делать надо.
                                    Ответить
                                    • Зато параллельно обработается. Конечно тупо тут поступать нельзя. Пользоваться этим с осторожностью, но в идеале, если алгоритм разбивается, делать так:

                                      Первый этап делаем по технологии map-reduce, а второй на основе перового уже как финальная обработка. Конечно этапов можно завести и больше, если нужно.
                                      Ответить
                      • Ну, положим, независимо от языка реализации нужно будет передавать лишь обновления рисунка пользователями, т.е. команды: нарисовал такую-то линию там-то, а всё работу по рисованию должны делать клиентские программы. Исходное изображение должно полностью пройти по сети только один раз для каждого клиента.

                        Сервер, разумеется, ничего отрисовывать не должен, лишь заниматься маршрутизацией команд. Аналогично решается зача коллективного редактирования текста: между клиенскими машинами и сервером должны бегать только небольшие (но частые) патчи.
                        Ответить
                        • http://en.wikipedia.org/wiki/Operational_transformation
                          Ответить
                        • О, не должен? Это вы как определили? А кто должен? Расскажите, мне прям интересно стало...
                          Ответить
                        • Особенно интересует вариант, когда у клиента нет программы которая может нарисовать то, что нужно. Например, все тот же фильтр размытия. Вот нету у вас на клиенте такой возможности - че за патч такой чудесный вы ему пошлете?
                          Ответить
                          • Для таких клиентов можно попробовать предоставить процесс-прокси, который будет рендерить для него изображения, но лучше полагаться на то, что клиент достаточно толст, чтобы осуществлять бОльшую часть вычислительной нагрузки, ведь постоянная передача изображений более-менее приличного размера по сети взад-вперёд в теории должно порождать довольно убогое юзабилити, а нагрузка на сервер должна быть непомерно высокой (20 000 клиентов одновременно применяют фильтр к своим фотографиям 3000х2500 о_О).
                            Ответить
                            • > ведь постоянная передача изображений более-менее приличного размера по сети взад-вперёд в теории должно порождать довольно убогое юзабилити

                              chatroulette.com

                              В сервере написаном на Эрланге юзабилити будет не просто убогий, он вообще работать не будет :) даже проверять бессмысленно.
                              Ответить
                              • > chatroulette.com
                                пф, что это
                                Это совсем другая задача - не коллективное редактирование документов, а передача потока, и этим занимаются высокооптимизированные медиа-сервера, написанные на плюсах или на том же эрланге (http://erlyvideo.org/). Предварительной обработки там не требуется: получил поток, направь его в нужную соску. Сервер там ничего не рендерит, и никаких фильтров не применяет.

                                И тут на клиенте как раз стоит жирный Flash Player.
                                Ответить
                                • Вы так об этом заявляете, как будто хоть раз этим занимались. Правда что ли? А то, я как бы этим по жизни и занимаюсь. А вы такие интересные вещи рассказываете...

                                  Вот именно потому, что не применяет никаких фильтров, да и вообще ничего толком с видео сделать не может - и не нужен он по большому счету. Я же почему чатрултеку вспомнил. Там очень даже нужно с видео что-то делать.
                                  Например, там даже есть ИИ который пытается (но не очень успешно ;) угадать показывает ли абонент свои гениталии в камеру или это у него лицо такое. Но там еще много чего в том же духе.
                                  Ответить
                      • > и еще в 9% случаев работает не так, как нужно
                        А вот это интересно. Можно поподробнее?

                        Если рендерить всё на сервере, передавать изображения между разными процессами тоже практически не нужно.
                        На каждого клиента будет процесс, который принимает от него команды на редактирование; на каждое "коллективное" изображение будет процесс, который отвечает за последовательное применение команд, и практически не делит ни с кем изображение, разве что с процессом, отправляющим изображение обратно пользователям.

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

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

                        The most common class of 'less suitable' problems is characterised by performance being a prime requirement and constant-factors having a large effect on performance. Typical examples are image processing, signal processing, sorting large volumes of data and low-level protocol termination.
                        http://www.erlang.org/faq/introduction.html
                        Ответить
                        • Ну так поэтому дажа РНР его сделает за счет обязок к GD / Imagemagic. А такие задачи возникают всегда, даже в почти тривиальных ситуациях. Типа, на видео нужно приклеить водяной знак, чтобы не сперли, субтитры и т.п.

                          Когда сопоставление с образцом вредно:
                          - у нас есть кортеж, который представляет пользователя, мы написали функции которые на нем сепциализируется узнавая первый элемент коретжа как символ 'user'. Приложение монетизируют следующим образом: пользователи с "премиум" возможностями могут совершать какие-то операции, другие пользователи не могут (за эти возможности они чего-то заплатили).
                          Проблема: кортежи, которые представляют платных пользователей нужно как-то отличать от обычных пользователей.
                          Если мы переименуем первый тег в 'premium_user' - все функции, которые раньше специализировались на 'user' нужно либо переписать, либо они не будут рабоать. Иногда нам нужно / не важно будут ли они работать с новым типом пользователей, а может быть и важно. Другой вариант, оставляем и тех и других с тегом 'user' и добавляем еще один элемент в кортеж, в котором указываем тип пользователя - но проблему это не решает, т.как переписывать все равно нужно много. Можно еще использовать эрланговское наследование, при условии, что все функции работающие с пользователями были в одном модуле (а как же...) это будет немного лучше.
                          Вобщем, работа с похожими, но не одинаковыми объектами становится головной болью номер один, и выглядит как либо огромное количество if-ов, а учитывая не-ленивые if-ы, это цирк тот еще... Или в кучу служебных функций, которые пытаются как-то отфильтровать нужные типы объектов, или сигнатуры функций начинают выглядеть как доказательство последней теоремы Ферма.
                          Ответить
                          • > пользователи с "премиум" возможностями могут совершать какие-то операции, другие пользователи не могут

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

    Добавить комментарий