Страницы

Поиск по вопросам

вторник, 17 марта 2020 г.

Как найти open source проект под себя [закрыт]

#java_ee #java #opensource


        
             
                
                    
                        
                            Закрыт. Этот вопрос не по теме. Ответы на него в данный
момент не принимаются.
                            
                        
                    
                
                            
                                
                
                        
                            
                        
                    
                        
                            Хотите улучшить этот вопрос? Переформулируйте вопрос,
чтобы он соответствовал тематике «Stack Overflow на русском».
                        
                        Закрыт 4 года назад.
                                                                                
           
                
        
Здравствуйте, помогите, пожалуйста, найти не большой и не слишком сложный open source
проект на java. Я хочу получить опыт, перед тем как устраиватся на джуниора, и считаю,
что open source лучшее решение. Но, к сожалению, никак не могу найти проект, который
мне бы подошел. Желательно, чтобы там был спринг и мавен. Извините за столь глупый
вопрос)    


Ответы

Ответ 1



Пробовали искать на GitHub? Что-нибудь вроде вот этого.

Ответ 2



Можете попробовать на JavaTalks стукнуться. Там пишут форум. Со спрингом и мавеном, как вы хотите )

Как отсортировать массив объектов по их свойствам?

#javascript


var a = {prop: 3, name: 'a'},
    b = {prop: 2, name: 'b'},
    c = {prop: 1, name: 'c'};

var array = [ a, b, c ],
    result = null;

result = array.sort(function(a, b){
    var c = a.prop,
        d = b.prop;

    if( c < b ){
        return -1;
    }else if( c > b ){
        return 1;
    }

    return 0;
});

for(var i in result){
    console.log(result[i].name); // a, b, c
}

Так не работает...
Добавлено:
А в js так нельзя сортировать?? А какая разница сорту, что двигать местами?    


Ответы

Ответ 1



У вас две ошибки: Метод sort сортирует массив на месте, т.е. изменяет массив, к которому он применен. Если вы хотите сохранить исходный массив, сделайте копию перед сортировкой: result = array.slice().sort() Вы используете b в сравнениях (c < b) и (c > b), хотя хотели d. Исправленная программа работает как надо.

Ответ 2



В принципе многомерные сортировки решаются с помощью написания сложных функций для sort(), но это сложно, поэтому можно воспользоваться какой-нибудь библиотекой, например, эта функция может быть реализована с помощью библиотеки Alasql, которая предназначена для обработки массивов как в SQL. var a = {prop: 3, name: 'a'}, b = {prop: 2, name: 'b'}, c = {prop: 1, name: 'c'}; var array = [ a, b, c ]; var result = alasql('SELECT * FROM ? ORDER BY name',[array]); Порядок и количество полей можно варьировать с помощью ключевых слов ASC (по возрастанию)/DESC (по убыванию), например, так: var result = alasql('SELECT * FROM ? ORDER BY name DESC, prop ASC',[array]); Ваш пример на jsFiddle.

Ответ 3



var a = {prop: 3, name: 'a'}, b = {prop: 2, name: 'b'}, c = {prop: 1, name: 'c'}, array = [ a, b, c ]; for (var i=0; i < array.sort(function(obj1, obj2){ return obj1.prop-obj2.prop; }).length; i++) { console.log(array[i].prop); }

ООП ради ООП

#ооп #классы


Доброго времени суток!
Есть, к примеру, класс Cat, который реализует интерфейс Movable, инкапсулирует цвет
и прочее.    Имеет ли смысл создавать подклассы BlackCat, WhiteCat и т.д., которые,
по сути дела, ничего нового не привносят? Правильно ли в таком случае создавать enum
Сats и уже конкретный экземпляр enum'а (со своими полями) передавать в конструктор
класса Cat, а там присваивать значения полей?    


Ответы

Ответ 1



Переменные аспекты (условия/реализации или как удобней их называть) лучше всего всегда отделять от тех, которые являются постоянными. Это правило как один из принципов проектирования. Если следовать ему, то тут уж надо выделять отдельный интерфейс с реализациями цвета или, как предложили, создать перечисление. Например, если цвет будет переливающимся и становиться другим в зависимости от условий (допустим, от освещенности комнаты, где находится кошка), то уже перечислением не обойтись, а надо делать интерфейс и реализовывать отдельное поведение для отдельных цветов кошки. В итоге у нас может получиться один абстрактный класс или интерфейс Cat с реализацией, например, BadCat и GoodCat. Также будет интерфейс Colorable и конкретные реализации, например, WhiteColor, BlackColor.

Ответ 2



Говорить о сферических котах Шредингера в вакууме довольно сложно, поскольку не факт, что удастся перенести полученный в этом вопросе опыт в реальное приложение. Есть ряд простых, которые могут сказать, стоит или нет использовать наследование, или некоторый аспект должен быть лишь свойством. Отношение "Является" против отношения "является свойством". Итак, можно ли сказать, что черный кот является котом в том же смысле, что и "кот является млекопитающим"? Т.е. является ли цвет некоторой характеристиков поведения моделируемой сущности, которая является неизменной во времени? Можно ли сказать, что "черные коты" образуют определенную группу животных (котов), принадлежность к которым существенно меняет их собственное поведение? Или же можно сказать, что цвет - это один из атрибутов конкретного экземпляра, который, к тому же, может поменяться со временем? Поскольку второе высказывание кажется более логичным, то и предпочтение стоит отдать свойству Color, а не подклассам BlackCat, RedCat и т.д. У этого подхода есть ряд очень важных следствий. Когда что-то моделируется с помощью класса, то созданный объект намертво к нему привязывается. У созданного объекта кот нельзя поменять цвет, что вполне может быть реальным при моделировании некоторого поведения (например, кот постарел, его обрили). К тому же, иерархии плохо расширяются. Это значит, что для добавления нового цвета придется изменять иерархию, что существенно сложнее добавления нового перечисления или путем просто использования другого значения из стандартного перечисления Color. Наследование предназначено для моделирования некоторого подмножества в общем семействе объектов. Также, наследование является очень жесткой связью, которую невозможно изменить после создания объекта, а также сложно расширять. Большинство современных языков не обладают множественным наследованием реализации, что не позволит в случае наследования цветастости котов, добавить другую "проекцию" наследования, например, по породе котов или другому признаку.

Замена данных в TCP пакете

#java #замена #tcp


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

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

То есть что получается: мне нужно поднять сервер, получить пакет, убрать из него
содержимое и вставить своё. Отправить пакет дальше. Даже схемка есть: 

Вот - N - это количество "D".



Не понимаю, с чего начинать, т.к. с этим сталкиваюсь в первый раз. И хотелось бы
понять, что нарисовано на картинке.
    


Ответы

Ответ 1



Тут вроде ничего сложного. На картинке показана структура 2-х пакетов: Сообщение, которое к вам приходит. Сообщение, которое вы должны отослать. По каждому сообщению подробно расписана структура следования байтов (Б1, Б2 и т.д.), также показано, какую часть и куда нужно переносить. Тело исходного сообщения состоит из массива данных структуры "D", каждый элемент по 6 байт. Но я сейчас какие-то прописные истины перечислил)), которые вы и сами, наверное, поняли) Но вот что мне не понятно по этому рисунку: Во-первых, "Измерительное сообщение 98 байт максимум" - следовательно, пакет нефиксированной длины, а как мы узнаем об окончании пакета? + не хватает 10 байт в описании, максимум 98, а на картинке расписано только 88 байт. Может, еще есть какая-нибудь информация? Во-вторых, тело исходного сообщения на картинке 84 байта, а уместить его нужно в 103 байта, с ним производятся какие-то манипуляции? Или нужно добивать нулями до определенной длинны? =============================================== Все еще остаются вопросы) вот смотрите примерный алгоритм На вашем сервере(на рис - прибор 2), считываем поток байт, для начала берем первый байт и сверяем заголовок, судя по рисунку заголовок всегда 23 если да то продолжаем читать, если нет то нужно больше информации о других пакетах и дальнейших действиях Теперь когда мы поняли что за пакет, нам нужно узнать остальные данные, для этого нужно понять длинну пакета, и тут опять непонятно как ее вычислить она всегда фиксирована и равна = 113 байт ( тогда вам нужно считать еще 110 байт + crc(2 байта) ), или "N" - это количество D, как говорил @avp, тогда вам нужно считать еще один байт, будем считать что это count, тогда формула будет такая count * 6 + crc( 2 байта ) Когда вы получили тело сообщения, нужно сверить crc ( последние 2 байта), но тут не написано для какой части сообщения его сверять? Если crc совпал то теперь можно формировать новый пакет, но как его формировать тоже не совсем понятно

Ответ 2



Короче, вот что я сумел настрогать: Вот прибор 1: import java.io.*; import java.net.*; import java.util.*; import java.nio.ByteBuffer; import java.math.BigInteger; class TCPClient { public static void main(String argv[]) throws Exception { Random rand = new Random(); int[] keys = {20, 1480, 70, 1520, 1470, 60, 0, -16, -15, -14}; float[] values = {0.000f, 0.000f, 0.000f, 0.000f, 0.006f, 0.000f, 0f, 22.150f, 744.301f, 41.136f}; byte[] bots = new byte[88]; byte[] one_byte = new byte[4]; //one_byte = intToByteArray(023, 1); bots[0] = intToByteArray(23, 1)[0]; bots[1] = intToByteArray(14, 1)[0]; for(int i=2, key_store = 0; i < 81; i++, key_store++) { one_byte = intToByteArray(keys[key_store], 2); // код ЗХВ bots[i++] = one_byte[0]; bots[i++] = one_byte[1]; one_byte = FloatToByteArray(values[key_store]); // отчет float bots[i++] = one_byte[0]; bots[i++] = one_byte[1]; bots[i++] = one_byte[2]; bots[i++] = one_byte[3]; } one_byte = intToByteArray(rand.nextInt(), 2); // код CRC 16 bots[86] = one_byte[0]; bots[87] = one_byte[1]; for(int i=0; i < 88; i++) { System.out.print(bots[i] + " "); } Socket socket = new Socket("localhost", 6789); DataOutputStream outToServer = new DataOutputStream(socket.getOutputStream()); BufferedReader inFromServer = new BufferedReader(new InputStreamReader(socket.getInputStream())); outToServer.write(bots); int bytesWritten = outToServer.size(); System.out.println("Total " + bytesWritten + " bytes are written to stream."); String modifiedSentence = inFromServer.readLine(); System.out.println("FROM SERVER: " + modifiedSentence); socket.close(); } public static byte[] FloatToByteArray(float value) { int bits = Float.floatToIntBits(value); byte[] bytes = new byte[4]; bytes[0] = (byte)(bits & 0xff); bytes[1] = (byte)((bits >> 8) & 0xff); bytes[2] = (byte)((bits >> 16) & 0xff); bytes[3] = (byte)((bits >> 24) & 0xff); return bytes; } public static byte[] intToByteArray(int value, int length) { if(length == 2) { byte[] data = new byte[2]; data[0] = (byte) (value & 0xFF); data[1] = (byte) ((value >> 8) & 0xFF); return data; } else { BigInteger bigInt = BigInteger.valueOf(value); return bigInt.toByteArray(); } } static int crc16(final byte[] buffer) { int crc = 0xFFFF; for (int j = 0; j < buffer.length ; j++) { crc = ((crc >>> 8) | (crc << 8) )& 0xffff; crc ^= (buffer[j] & 0xff);//byte to int, trunc sign crc ^= ((crc & 0xff) >> 4); crc ^= (crc << 12) & 0xffff; crc ^= ((crc & 0xFF) << 5) & 0xffff; } crc &= 0xffff; return crc; } } Как я думаю, как оно работает: первые 2 байта - кодирую int в byte и записываю. Дальше идут структуры "D", содержащие по 6 байт, где первые 2 байта ключ, а остальные 4 - значение. Ну и в конце код CRC. Но что получается, на устройстве 2 я принимаю запрос так: Socket connectionSocket = welcomeSocket.accept(); BufferedReader inFromClient = new BufferedReader(new InputStreamReader(connectionSocket.getInputStream())); DataOutputStream outToClient = new DataOutputStream(connectionSocket.getOutputStream()); while ((i = inFromClient.read()) != -1) { } и получаю int значение, когда должно приходить byte, отправлял же в byte. Что делать? Вообще правильно?

Как правильно вычислить или вывести малое число?

#visual_cpp


Пытаюсь вычислить частичную сумму знакопеременного ряда К/ (M*M),  где К=1,-1,1,-1...
Известно, что если М стремится к бесконечности, то сумма ряда равна (Пи*Пи)/12=0.8224670334241132...
(точное значение невозможно, так как есть число Пи.)
И даже получились очень симпатишные результаты! 
Но почему-то точность падает на два порядка после 10 в -11 степени. По точности Пи
и по разрядности переменных вроде есть запас.
В чем может быть моя ошибка - в типах переменных, в ключах вывода или в методе вычисления?
Как это определить?
#include 
#include 
#define _USE_MATH_DEFINES  // M_PI = 3.14159265358979323846
#include 
#include 

int main()
{

    int N=1, M;
    double Summa, Error, Limit, One;

    cout << "Вычисление частичной суммы ряда и сравнение её с пределом.\n\n" << endl
<< endl;

    Limit = (M_PI*M_PI)/12;

    while (N < 65000)
    {
        Summa=0; 
        Error=0;
        One=1;
        for ( M = 1; M < N; M++) 
        {
            Summa += ( One / (M*M) ); // здесь вычисляем сумму первых членов
            One=-One; // ряд знакопеременный
        }
        Error = Limit - Summa;

        cout << "Cумма " << N << " членов ряда = " << setprecision(10) << Summa <<
"\t Ошибка = " << setprecision(3) << abs(Error) << endl;
    N=N+1000; // шаг изменения кол-ва членов частичной суммы
    }
    cout << "    Предел суммы ряда: " << setprecision(16) << Limit << endl;

}

Cумма   1001 членов ряда = 0.8224665339  Ошибка =     5e-007 - больше членов - меньше
ошибка
Cумма   2001 членов ряда = 0.8224669085  Ошибка =  1.25e-007
Cумма   3001 членов ряда = 0.8224669779  Ошибка =  5.55e-008
Cумма   4001 членов ряда = 0.8224670022  Ошибка =  3.12e-008
Cумма   5001 членов ряда = 0.8224670134  Ошибка =     2e-008
Cумма   6001 членов ряда = 0.8224670195  Ошибка =  1.39e-008
Cумма   7001 членов ряда = 0.8224670232  Ошибка =  1.02e-008
Cумма   8001 членов ряда = 0.8224670256  Ошибка =  7.81e-009
Cумма   9001 членов ряда = 0.8224670273  Ошибка =  6.17e-009
Cумма  10001 членов ряда = 0.8224670284  Ошибка =     5e-009
...
Cумма  53001 членов ряда = 0.8224670333  Ошибка =  1.29e-010
Cумма  54001 членов ряда = 0.8224670333  Ошибка =  1.03e-010
Cумма  55001 членов ряда = 0.8224670334  Ошибка =   7.2e-011
Cумма  56001 членов ряда = 0.8224670334  Ошибка =  3.42e-011
Cумма  57001 членов ряда = 0.8224670334  Ошибка =  1.24e-011
Cумма  58001 членов ряда = 0.8224670335  Ошибка =  7.14e-011
Cумма  59001 членов ряда = 0.8224670336  Ошибка =  1.49e-010   <- и вдруг...
Cумма  60001 членов ряда = 0.8224670337  Ошибка =  2.54e-010
Cумма  61001 членов ряда = 0.8224670338  Ошибка =  4.06e-010
Cумма  62001 членов ряда = 0.8224670341  Ошибка =  6.43e-010
Cумма  63001 членов ряда = 0.8224670345  Ошибка =  1.07e-009  <- падает точность...
Cумма  64001 членов ряда = 0.8224670355  Ошибка =  2.05e-009
    Предел суммы ряда: 0.8224670334241132
    


Ответы

Ответ 1



В принципе, ничего неожиданного нет. Вы вычисляете с типом double, который имеет около 16 значащих цифр. Теперь, если само слагаемое имеет порядок 1e-5 * 1e-5 = 1e-10, а вы складываете его с частичной суммой, которая имеет величину порядка единицы, дальнейшие разряды теряются, и реально прибавляются лишь последние 6 десятичных цифр: част. сумма: x.xxxxxxxxxxxxxxxx слагаемое: 0.0000000000xxxxxxxxxxxxxxxx ------------------------------------------ результат: x.xxxxxxxxxxxxxxxx То есть, точность слагаемого при таком вычислении фактически ограничена 1e-16. Когда у вас количество слагаемых порядка 1e+5, суммарная точность получается порядка 1e-11. Попробуйте вычислять с конца: сначала наименьшие слагаемые. Тогда частичная сумма будет, возможно, не так сильно понижать точность. (Не уверен, что это поможет.) Обновление: на самом деле тут были две проблемы. Первая — переполнение int: произведение M * M не помещалось в 32-битный int, поэтому вычислялось по модулю 2^32, что, конечно, давало неправильный результат. Ликвидировав это проблему и подняв количество слагаемых, стало возможно добраться до такой точности, где и порядок слагаемых играет роль. Здесь вычисление от маленьких к большим наконец-то дало положительный эффект. Ещё по теме: Алгоритм Кэхэна (здесь на русском).

Ответ 2



@qqqq1961, боюсь тут все сложнее, чем Вам кажется. Внимательно посмотрите на простую программу, ее результаты и сравненние их с подсчетом в bc с точностью 40 знаков. #include #include #include #define __S_PI(x) # x #define _S_PI(x) __S_PI(x) #define S_PI _S_PI(M_PI) int main(int ac, char *av[]) { printf ("M_PI = %.16f M_PI ** 2 = %.16f (math.h: %s)\n", M_PI, M_PI * M_PI, S_PI); return puts("End") == EOF; } avp@avp-xub11:hashcode$ gcc c.c avp@avp-xub11:hashcode$ ./a.out M_PI = 3.1415926535897931 M_PI ** 2 = 9.8696044010893580 (math.h: 3.14159265358979323846) End avp@avp-xub11:hashcode$ bc bc 1.06.95 Copyright 1991-1994, 1997, 1998, 2000, 2004, 2006 Free Software Foundation, Inc. This is free software with ABSOLUTELY NO WARRANTY. For details type `warranty'. scale=40 3.1415926535897931 * 3.1415926535897931 9.86960440108935774884804450080761 3.14159265358979323846 * 3.14159265358979323846 9.8696044010893586188178821328931344231716 avp@avp-xub11:hashcode$ Заметили, что доверять можно только 16 десятичным знакам (15 после запятой)? Особо посмотрите, как падает точность после умножения (M_PI * M_PI). Другими словами, точность вычислений с double на самом-то деле ограничена точностью аппаратуры. Отсутсвие ПРАВИЛЬНОГО ОКРУГЛЕНИЯ и приводит к странным результатам (особенно при подсчете суммы, начиная с больших членов).

Ответ 3



Суммировать следует с наименьших чисел, чтобы свести к минимуму накапливаемую погрешность. Посмотри мою небольшую лекцию. Следующая задачка: подсчитать сумму 10 000 000 элементов ряда: S = 1 + 1/2 + 1/3 + 1/4 + 1/5 + 1/6 + . . . + 1/10000000. По идее от перемены слагаемых сумма не меняется, т.е. если буду складывать в обратном порядке: S = 1/10000000 + 1/9999999 + 1/9999998 + . . . + 1/3 + 1/2 + 1 то сумма должна быть такой же. Это верно для классической арифметики. Но мы имеем дело с компами, в которых заложена дискретная арифметика. Напишем нижеследующий код и скомпилируем его: program Summa; var s:single; i:longint; begin s:=0.0; for i:=1 to 10000000 do s:=s+1.0/i; //подсчет суммы S = 1 + 1/2 +...+ 1/10000000 Writeln(s:0:2); //вывод результата на экран s:=0.0; for i:=10000000 downto 1 do s:=s+1.0/i; //подсчет суммы S = 1/10000000 +...+ 1/2 + 1 Writeln(s:0:2) //вывод результата на экран end. На экране будут такие результаты: 15.40 16.69 Результаты разные. В чем дело? Какая сумма из них более достоверна? И какая отсюда мораль? Проблема заключается в конечности представления чисел в компе. Для данных типа single отводится 4 байта, в которых 1 бит отведен под знак, 8 бит – под двоичную степень, а оставшиеся 23 бита – под мантиссу ==> точность представления чисел ограничена 23 битами или 7-8 значащими десятичными цифрами. Т.е. в комп можно еще записать число 7.7777777 или 7.7777778, но никак не 7.7777777000000000007777777 – такое число просто округляется/обрезается до 23 бит для мантиссы. Для того, чтобы проще объяснить работу нашего вышеприведенного примера, допустим, что точность чисел ограничена 2 значащими числами. Тогда в цикле подсчета суммы в прямом направлении имеем: Проход 1: s := 0.0 + 1.0/1.0 = 1.0 Проход 2: s := 1.0 + 1.0/2.0 = 1.5 Проход 3: s := 1.5 + 1.0/3.0 = 1.5 + 0.33333333… --> 1.8 (округление до 2 цифр) . . . Проход 100: s := s + 1.0/100.0 = s + 0.01… --> s (округление и потеря младших цифр) Проход 101: s := s + 1.0/101.0 = s + 0.0099… --> s (округление и потеря младших цифр) . . . При такой точности после 100-го прохода (фактически еще раньше) сумма в цикле будет адекватной s := s + 0.0 из-за выбрасывания младших цифр в накапливаемой сумме. Если же проделывать в обратном направлении: Проход 1: s := 0.0 + 1.0/10000000.0 = 0.0000001 (результат сохраняется до 2 значащих цифр) Проход 2: s := 0.0000001 + 1.0/9999999.0 = 0.0000001+ 0.00000010000001…--> 0.0000002 Проход 3: s := 0.0000002 + 1.0/9999998.0 = 0.0000001+ 0.00000010000002…--> 0.0000003 . . . то мы получим более достоверную сумму. Кстати, если декларировать для s тип уже не single (одинарной точности), а double (двойной точности – 8 байт), то на экран будет выведено следующее: 16.70 16.70. Но если же суммировать для бOльшего числа элементов (к примеру, до 100000000000000 элементов), то опять могут возникнуть искажения. Мораль: для суммирования данных с большим разбросом значений подсчет суммы следует начинать с наименьших элементов, для того чтобы свести к минимуму потерю информации из-за дискретной природы данных, представляемых в компе. И еще что бы посоветовал - раз ряд знакопеременный, то обычно стоило бы суммировать разности соседних элементов, так будет аккуратнее. Но для 1/(m*m) это, наверное, неактуально.

Android orientation & DialogFragment

#java #android #android_fragment #android_edittext


Добрый день!
Проблема: при открытом DialogFragment при смене ориентации вылетает исключение. Сталкивался
ли кто-нибудь с подобным и есть ли методы решения? 
Также интересует: как отследить изменения в EditText не через TextWatcher? (Требуется
отловить лишь события набора текста, без события программного изменения.)
С уважением, Игорь.    


Ответы

Ответ 1



По поводу того, что вылетает exception при смене ориентации. Какое именно исключение? Покажите stacktrace. Попробуйте сделать следующее: добавьте setRetainInstance(true) в методе onCreateDialog(). Насчет того как отловить изменения в EditText, есть несколько способов. Можно сделать класс адаптер, который будет просто оберткой (заглушкой) методов интерфейса TextWatcher, соответственно вы сможете просто переопределить нужный Вам метод. Вообще вам нужно все равно будет использовать какой-то интерфейс слушателя. Возможен еще такой вариант с OnFocusChangeListener. Данный интерфейс имеет только один метод onFocusChange(View v, boolean hasFocus), сюда передается булевая переменная, которая показывает, был ли измен фокус данного View.

Скрипт вывода товаров, очень долго грузится

#mysqli #while #php #foreach


Функции выборки товаров из базы:
function result_to_array($result) {
    $res_array = array();
    $count = 0;
    while( $row = $result->fetch_assoc() ) {
        $res_array[$count] = $row;
        $count++;
    }
    return $res_array;
}

function get_product() {
    connect_db();
    global $mysqli;
    $result = $mysqli->query("SELECT *FROM `product` ORDER by `id` DESC");
    $result = result_to_array($result);
    return $result;
}

На самой странице все товары выводятся циклом foreach:
$products = get_product();



html код



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


Ответы

Ответ 1



А много ли товаров? И можно оптимизировать конструкцию, убрав $count: while( $row = $result->fetch_assoc() ) { $res_array[] = $row; } Перед выполнением кода и после выполнения добавьте microtime(): function result_to_array($result) { $ra_start = microtime(); $res_array = array(); $count = 0; while( $row = $result->fetch_assoc() ) { $res_array[$count] = $row; $count++; } $ra_end = microtime(); echo $ra_end - $ra_start; return $res_array; } function get_product() { $gp_start = microtime(); connect_db(); global $mysqli; $result = $mysqli->query("SELECT *FROM `product` ORDER by `id` DESC"); $result = result_to_array($result); $gp_end = microtime(); echo $gp_end - $gp_start; return $result; } На самой странице все товары выводятся циклом foreach: $products = get_product(); html код: По результатам сможете увидеть, какой кусок у Вас долго выполняется.

Ответ 2



Идите поэтапно: 1) Смотрим, а не тупит ли mysql: $result = $mysqli->query("SELECT *FROM `product` ORDER by `id` DESC"); exit(); $result = result_to_array($result); 2) Как быстр while: while( $row = $result->fetch_assoc() ) { $res_array[$count] = $row; $count++; } exit(); return $res_array; 3) Как быстр вызов $products = get_product(); $products = get_product(); exit(); 4) Убираем и смотрим, как работает без него. Если долго выполняеться этап 1, оптимизируем mysql запрос (табличка возможно очень большая). Если долго выполняеться этап 2, используем ответ выше. Если долго выполняеться этап 3 (без двух предыдущих ) - что-то очень странное. Если долго выполняеться этап 4, то используем for вместо foreach (https://stackoverflow.com/questions/3430194/performance-of-for-vs-foreach-in-php). Если ничего не помогает и вызовы повторяються, то пихаем все в мемкэш (вплоть до html).